Patch an Existing NK.BIN
- by Kate Moss' Open Space
As you know, we can use MAKEIMG.EXE tool to create OS Image file, NK.BIN, or ROMIMAGE.EXE with a BIB for more accurate. But what if the image file is already created but need to be patched or you want to extract a file from NK.BIN?
The Platform Builder provide many useful command line utilities, and today I am going to introduce one, BINMOD.EXE.
http://msdn.microsoft.com/en-us/library/ee504622.aspx is the official page for BINMOD tool.
As the page says, The BinMod Tool (binmod.exe) extracts files from a run-time image, and replaces files in a run-time image and its usage
binmod [-i imagename] [-r replacement_filename.ext | -e extraction_filename.ext]
This is a simple tool and is easy to use, if we want to extract a file from nk.bin, just type
binmod –i nk.bin –e filename.ext
And that's it! Or use can try -r command to replace a file inside NK.BIN.
The small tool is good but there is a limitation; due to the files in MODULES section are fixed up during ROMIMAGE so the original file format is not preserved, therefore extract or replace file in MODULE section will be impossible.
So just like this small tool, this post supposed to be end here, right? Nah... It is not that easy.
Just try the above example, and you will find, the tool is not work! Double check the file is in FILES section and the NK.BIN is good, but it just quits. Before you throw away this useless toy, we can try to fix it! Yes, the source of this tool is available in your CE6, private\winceos\COREOS\nk\tools\romimage\binmod. As it is a tool run in your Windows so you need to Windows SDK or Visual Studio to build the code. (I am going to save you some time by skipping the detail as building a desktop console mode program is fairly trivial)
The cbinmod.cpp is the core logic for this program and follow up the error message we got, it looks like the following code is suspected.
//
// Extra sanity check...
//
if((DWORD)(HIWORD(pTOCLoc->dllfirst) << 16) <= pTOCLoc->dlllast &&
(DWORD)(LOWORD(pTOCLoc->dllfirst) << 16) <= pTOCLoc->dlllast)
{
dprintf("Found pTOC = 0x%08x\n", (DWORD)dwpTOC);
fFoundIt = true;
break;
}
else
{
dprintf("NOTICE! Record %d looked like a TOC except DLL first = 0x%08X, and DLL last = 0x%08X\r\n", i, pTOCLoc->dllfirst, pTOCLoc->dlllast);
}
The logic checks if dllfirst <= dlllast but look closer, the code only separated the high/low WORD from dllfirst but does not apply the same to dlllast, is that on purpose or a bug?
While the TOC is created by ROMIMAGE.EXE, so let's move to ROMIMAGE. In private\winceos\coreos\nk\tools\romimage\romimage\bin.cpp
Module::s_romhdr.dllfirst = (HIWORD(xip_mem->dll_data_bottom) << 16) | HIWORD(xip_mem->kernel_dll_bottom);
Module::s_romhdr.dlllast = (HIWORD(xip_mem->dll_data_top) << 16) | HIWORD(xip_mem->kernel_dll_top);
It is clear now, the high word of dll first is the upper 16 bits of XIP DLL bottom and the low word is the upper 16 bits of kernel dll bottom; also, the high word of dll last is the upper 16 bits of XIP DLL top and the low word is the upper 16 bits of kernel dll top. Obviously, the correct statement should be
if((DWORD)(HIWORD(pTOCLoc->dllfirst) << 16) <= (DWORD)(HIWORD(pTOCLoc->dlllast) << 16) &&
(DWORD)(LOWORD(pTOCLoc->dllfirst) << 16) <= (DWORD)(LOWORD(pTOCLoc->dlllast) << 16))
So update the code like this should fix this issue or just like the comment, it is an extra sanity check, you can just get rid of it, either way can make the code moving forward and everything worked as advertised. "Extracting out copies of files from the nk.bin... replacing files... etc."
Since the NK.BIN can be compressed, so the BinMod needs the compress.dll to decompress the data, the DLL can be found in C:\program files\microsoft platform builder\6.00\cepb\idevs\imgutils.