Monday, September 05, 2011 #

Use CE Debugger Extension (CeDebugX) to Find Stack Size

I have introduced a method to detect the stack size and other stack info during runtime in this article
http://geekswithblogs.net/KMOS/archive/2009/10/12/find-out-the-stack-size-in-ce-6.0.aspx

But what if we want to determine the stack size on arbitrary thread or for whatever reason, writing a code is not an option but wish to peek the stack size via debugger?
Fortunately, there is a debugger extension (CeDebugX) provides many power tools, such as !stacktrace or !stackeval to get the stack info for specific thread.
For detail please refer to http://msdn.microsoft.com/en-us/library/ee481348.aspx

Basically, you can roughly estimate the stack size by comparing the diff between last and first frame ptr from the output of !stacktrace.
For more accurate result, you can use !stackeval which shows you the stack low (current SP) and all of the contents in each frames.

Here is an example from the the output of CE7 to demostrate how parsing the stack size.
As this is a user thread and block in an API call, so we can see there are 2 stack, one for user mode, the other for kernel mode.
The current SP is 0xccfef9a8, so obviously, it is in kernel space which mean a Secure Stack.
The base of Secure Stack is 0xccfeff00, thus the use for secure stack part is 0xccfeff00 - 0xccfef968 = 0x598.
And for user mode stack, the base is 0x0002ff00, Stack low is 0x0002fae0, so 0x0002ff00 - 0x0002fae0 = 0x420.

Windows CE>!stackeval 0xC041D028
Stack Evaluate for thread 0xc041d028
 +============================+
 | pThread   : 0xc041d028
 | hThread   : 0x000000c8
 +============================+
  Stack ptr      : 0xccfef9a8
  Secure stack bound : 0xccfee000
  Secure stack base  : 0xccfeff00
  User stack bound  : 0x0002f000
  User stack base   : 0x0002ff00
  Stack frames:
   #  Frame Ptr  PC
  ============================
  [ 0] 0xccfef9a8, 0x00005263
  [ 1] 0xccfef9b4, 0x000147bd
  [ 2] 0xccfef9d4, 0x0000abd3
  [ 3] 0xccfefa88, 0x00014c31
  [ 4] 0xccfefbf4, 0x00014e72
  [ 5] 0x0002fb20, 0x00013f67
  [ 6] 0x0002fb30, 0x0000067b
  [ 7] 0x0002fb3c, 0x00000619
  [ 8] 0x0002fb84, 0x000003d1
  [ 9] 0x0002fb9c, 0x0000041d
  [10] 0x0002fc18, 0x0002331e
  Secure stack low : 0xccfef968
  Stack low     : 0x0002fae0


Posted On Monday, September 05, 2011 4:17 PM | Feedback (0)

Sunday, August 21, 2011 #

Patch Existing NK.BIN in Runtime

Usually, you need a permanently change to your ROM (recreate a NK.BIN or use BINFS/MultiBIN/IMGFS for partial region update) in order to change the content of the ROM..
What if for whatever reason, recreate a OS image is not an option but still need to patch the OS?
A possible hack is to patch the ROMHDR in early booting phase (says OEMInit or bootloader) to alter/remove the corresponding entry.
You can take a look at public\common\oak\inc\romldr.h for the structure of TOCentry (for module entry) and FILESentry (for FILES entry) and refer to private\winceos\coreos\nk\kernel\resource.c for how to traverse and parse the TOC.

Posted On Sunday, August 21, 2011 11:14 AM | Feedback (1)

Tuesday, July 26, 2011 #

How to Install Bootsector for Bootable CE Partition

To prepare a bootable CE disk for PC based system, you need to create the partition, format it and transfer the booting files.
CE provides a tool CESYS.EXE to transfer boot sector and copy bootloader to target volume for BIOSLOADER.
The tool is created since CE 4 and unfortunately, it is out dated and only support FAT12 or FAT16.
Modern storage devices have larger capacity and prefer or require to use FAT32/ExFAT.
For CE7, there is a new CESYS platform\CEPC\src\boot\tools\bin\i386\cesys.exe that support FAT32/ExFAT but it only works with the new boot loader framework.(platform\CEPC\src\boot\bldr\)
Refer to http://geekswithblogs.net/KMOS/archive/2011/06/30/introducing-the-new-boot-framework-in-ce-7.aspx for the introduction of new framework.


If you prefer to use BIOSLOADER or still work on a project that is pre-CE7, you could use 3rd party bootsector installer, such as http://www.nu2.nu/mkbt/ to transfer the boot sector.
And the DiskPart.exe utility in Windows can mark a MBR partition as active, more info please refer to http://msdn.microsoft.com/en-us/library/cc770877(WS.10).aspx

There is an alternative solution - use CE to prepare bootable CE partition - a CE version of DiskPart, allows you to create, set active a partition and prepare the boot sector as well, http://msdn.microsoft.com/en-us/library/ee478369(WinEmbedded.60).aspx

Posted On Tuesday, July 26, 2011 5:08 PM | Feedback (0)

Saturday, July 09, 2011 #

Passing a Buffer in User Mode Stack to Drivers

 

Consider the following code piece, it may look fine at the first glance but could pop out access violation under stress test

In the user mode applicatio



BYTE buffer[ 256 ]; // On stack
DWORD read;

while (<condition>) {

 if (ReadFile(hDriver, buffer, sizeof(buffer), &read, NULL) && (read > 0)){

   // Do something

 }

}

And inside the kernel mode driver:

 

ULONG
DRV_Read(
 HANDLE hOpen, //@parm [IN]  HANDLE returned by XXX_Open 
 PUCHAR pBuffer, //@parm [IN,OUT] Pointer to valid memory.  
 ULONG Count) //@parm [IN]  Size in bytes of pTargetBuffer.
{

  < Input params validation>

  // Read the data whatever available in the internal receive buffer
  // Occasionally, Data Abort happened at the following line
  *pBuffer = READ_REGISTER_UCHAR (DATA_PORT_ADDR);

  <etc>
}

So what's going on here?
Firstly, we must understand user mode stack is demand committed and since we allocate a relative large pool (256 bytes, compare the the page size, 4KB), there is a good chance the buffer may cross the page boundary. i.e. part or all of the memory for buffer is not yet committed.
As the driver is in kernel mode but the buffer address still in user mode, so when accessing this address, a page fault will be generated.
Normally, kernel can recover the stack page fault gracefully, but committing a user stack (untrusted stack) in kernel mode is likely to expose more risk, so kernel just fails it and let the access violation (data abort) happened naturally!

OK, so how do we fix it?
Since the data abort is due to uncommitted page in stack, a simple workaround is to foce page in the stack before pass to driver, for example

buffer[0] = 0;
if (ReadFile(hDriver, buffer, sizeof(buffer), &read, NULL) && (read > 0))
...

Assign data to start of buffer will force kernel to resolve the potential page fault and commit the page when needed. 
Apparently, it looks hacky and we should seek a solution to commit the page in driver.
And here is the answer,
LockPages.
Use LockPages to lock the buffer when entering the driver handlers, such as XXX_Read, and UnlockPages it before return to commit the user buffer in driver explicitly.

 

Posted On Saturday, July 09, 2011 6:21 PM | Feedback (0)

Saturday, July 02, 2011 #

Unaligned Access on ARM

ARM supports unaligned access and CE provides a kernel IOCTL_KLIB_UNALIGNENABLE (refer to http://msdn.microsoft.com/en-us/library/ee482755(WinEmbedded.60).aspx for details).
Application can use this IOCTL or its helper function, KLibUnalignedAccessEnable, to enable/disable unaligned access.
But for some reason, this IOCTL does not work in CE7 under user mode, a workaround is to delegate to a kernel mode library/driver to issue the IOCTL.
Or you can use following code to enable it on startup

#include <armintr.h>

OEMInit() {
...

ULONG SCTLR;

...

SCTLR = (ULONG)_MoveFromCoprocessor (15, 0, 1, 0, 0);
SCTLR &= ~0x2;  // disable the A bit
_MoveToCoprocessor (SCTLR, 15, 0, 1, 0, 0);

...

}

Posted On Saturday, July 02, 2011 5:31 PM | Feedback (0)

Thursday, June 30, 2011 #

Introducing the New Boot Framework in CE 7

CE 7 introduces a new boot loader framework, BLDR (platform\common\src\common\bldr\). Some people like its powerful and flexbility, others may feel its too complicate as a boot loader framework.

Despite to the favor, it is already there; so let's take a look at its features.
Unlike the previous BL framwork (CE7 still provides it in platform\common\src\common\boot\) is a monolithic library, the new framework has more architecture structure. It not only defines main body but also provides rich components, such as filesystem (BinFS/FAT), download transportations, display, logging and block devices: bios INT13, FAL, IDE, Flash ( and etc.
Note that in the block device category, the FAL is for legacy FMD/FAL, Flash is for latest MSFlash. Some of you may have encountered MSFlash MDD/PDD compatible partition is hard to created in bootloader and now it provides a clean solution! (Since this is a big topic, I will introduce it in future post)

Today, I am going to show you some basic helper components - Image Loading functions.
When OS image stored in the block device, it can be a file format, says your NK.BIN in the FAT volume or a RAW format, says the image is programmed to a BINFS partition.
For the first one you can use BootFileSystemReadBinFile (platform\common\src\common\bldr\fileSystem\utils\fileSystemReadBinFile.c) and use BootBlockLoadBinFsImage (platform\common\src\common\bldr\block\utils\loadBinFs.c) to load from a partition.

Need a sample code? No problem, the BootLoaderLoadOs in platform\cepc\src\boot\bldr\loados.c just provide a perfect example.

Posted On Thursday, June 30, 2011 9:01 AM | Feedback (0)

Wednesday, June 29, 2011 #

NEON Intrinsic Support in CE7

Just a side note for people who may be interested in creating high performance code to take advantage on NEON instruction set but wish to use NEON intrinsic instaed of coding assembly.
Compiler won't generate NEON opcode unless application use the NEON intrinsic explicitly.

Basically, you need ARMv7 build enviroment, so compiler can emit NEON opcode.
Intrinsic prototype can be found in public\COMMON\sdk\inc\arm_neon.h and that is all you got.
If you ever find an NEON opcode does not have corresponding intrinsic, you still need to use the old trick - write that part of code in assembly.

Posted On Wednesday, June 29, 2011 5:49 PM | Feedback (0)

BusEnum2 and a Minor Bug Fix

The default root bus driver, BusEnum, enumerate and active drivers one by one in synchronized manner. It is not only slowing the boot time but in the even if any of driver's init function (XXX_init) get hanged, the whole system won't boot at all.
There is a sample of enhanced root bus driver, BusEnum2, on the
http://msdn.microsoft.com/en-us/library/dd187254.aspx
The page provides the sample code and the detail explanation of the design concept.
With multi-threaded BusEnum2 on CE7 with SMP enabled system, the scalability is even more significant. Since you have more than one processor and it can load drivers in parallel!


Everything looks good so far, except to there is a small bug in the sample code.
Fortunately, it is easy to fix. But hard to trace if you ever enc outer it!
The BUSENUM2 flag only defined in BUSENUM2\BUSDEF\sources but not in BUSENUM2\BUSENUM\sources.
The DeviceFolder is implemented in BUSENUM2\BUSDEF but the instance is created in BUSENUM2\BUSENUM\busenum.cpp, so the result is it allocates less memory than actual need.
 
Add
 
CDEFINES=$(CDEFINES) -DBUSENUM2
 
into BUSENUM2\BUSENUM\sources and the problem fixed!

Posted On Wednesday, June 29, 2011 5:42 PM | Feedback (0)

Experience the new Bootloader of CE7 VirtualPC BSP - Display Resolution Override

The CE 7 (aka. Windows Embedded Compact) provides many new features, a new VirtualPC is one of them and as a replacement of Device Emulator in CE 6.
 
The bootloader of VPC BSP utilize a new introduced framework in CE7, the BLDR (not the BIOSLOADER!)
It provides many rich and advanced feature, I will introduce more detail in my future posts.
Today, I am going to introduce a basic usage: setting the display resolution.
One of the benefit os using the BLDR is it provides interactive user interface, no DOS enviroment required, so user can change the setting on the console. It is especially useful on VPC: if you are not using Win7, edit a file in VHD could take some effort!

In the Boot menu, you can select [5] Display Settings. There are a couples of sub menu allow you to change resolution, bpp and etc. As it is very straight forward, I won't go through each option except to the Option [3] "Change Viewable Display Region".
The resolution it provides depends on the BIOS (VPC is a PC compatible device), and the minimum resolution it provides is 640x480. But what if user need smaller resolution or any non-standard resolution for whatever reason, it comes the use of "Change Viewable Display Region". User can use it to create a reduced display region. e.g. 240x320 on 640x480 screen.
Also you can alter the platform\virtualpc\src\boot\bldr\config.c to add a non-standard resolution (e.g. 480x272) to displayMode array.

Another solution in case of you don't want to rebuilt and replace bootloader is to alter SaveVGAArgs in platform\common\src\x86\common\io\ioctl.c to overwrite cxDisplayScreen and cyDisplayScreen setting to whatever resolution you want.

 

Posted On Wednesday, June 29, 2011 5:04 PM | Feedback (0)

Wednesday, April 21, 2010 #

Building the Bootsector of BIOSLOADER

Windows CE is a 32 bits OS since day one, so it makes sense tools shipped with PB, compiler, linker, assembler and etc, are for targeting to 32 bits system.
But occasionally, if you are developing x86 based system and especially working on some boot code, such as boot sector of BIOSLOADER, that will be a problem.

Normally, as PB provides the prebuilt boot sector image but if you ever need to rebuilt it, what should you do? You may say as it's an x86, perhaps you can use VS or Windows SDK to build it. But unfortunately, today's desktop Windows tool chains are also 32 or even 64 bits only, you need to find something older. VC++ 6.0, but how can you find one?

This Website http://thestarman.pcministry.com/asm/masm.htm arranges some useful resources. Basically, you need 2 thing, the 16 bits MASM and 16 bits linker.
Just make it even easier for you

  1. Download http://download.microsoft.com/download/vb60ent/Update/6/W9X2KXP/EN-US/vcpp5.exe for Assembler (MASM).
  2. Download http://download.microsoft.com/download/vc15/Update/1/WIN98/EN-US/Lnk563.exe for the Linker.
  3. And then just extract the archives and what you need is ml.exe, ml.err and link.exe

Posted On Wednesday, April 21, 2010 4:37 PM | Feedback (0)