Log in

Mar. 18th, 2008



#define SDIMAGIC "$SDI0001"
#define SDIMAGICLEN (8)
#define SDITOCMAX (4)

enum MDB {
    MDBunknown = 0,

typedef struct _SDI_header {
    char    magic[8];
    QWORD   MDBtype;
    QWORD   BootCodeOffset;
    QWORD   BootCodeSize;
    QWORD   VendorID;       // 16-bit HEX value
    QWORD   DeviceID;       // 16-bit HEX value
    GUID    DeviceModel;
    QWORD   DeviceRole;     // int32 value
    QWORD   Reserved1;
    GUID    RuntimeGUID;
    QWORD   RuntimeOEMrev;  // int32 value
    QWORD   Reserved2;
    QWORD   PageAlignment;  // BLOB alignment value in pages
    QWORD   Reserved3[48];
    QWORD   Checksum;
} SDI_header;

typedef struct _SDI_TOC_record {
    char    BLOBtype[8];    // 3-4 bytes UPPERCASE value, 0-padded
    QWORD   Attr;           // uint32 value
    QWORD   Offset;
    QWORD   Size;
    QWORD   BaseAddress;
    // 0 for non-filesystem BLOBs, filesystem code for PART (as in MBR)
    // 7 for NTFS, 6 for BIGFAT, etc.
    QWORD   Reserved[3];
} SDI_TOC_record;

typedef struct _SDIpage0 {
    SDI_header      h;
    char            Reserved[512];
    SDI_TOC_record  TOC[48];
} SDIpage0;

#endif // _SDI_H_INCLUDED

You can download sdi.h by right-clicking.

Tags: ,

Mar. 17th, 2008

SDI file format specification

Windows (R) XP Embedded
SDI file format specification


Page as used in SDI file format is default i386 MMU page, 4096 bytes.
All numeric values in SDI file are stored in little-endian 64-bit format.
Empty (reserved) fields and space from a BLOB end to the beginning of next BLOB
are padded with 0-s.

SDI file is not padded at the end, so total length of an SDI file equals to
sum of aligned offset to last BLOB and exact (not aligned) length of that BLOB.

All BLOBs are aligned on boundary of alignment block.
Size of alignment block is specified as multiple of page size.
Size of SDI header alone is always 1 page, so if SDI consists of only a header,
its length is exactly 4096 bytes regardless of alignment block size.

First sector (512 bytes, the header) is checksummed, as described in previous article
For empty header with 1-page alignment the checksum value is 0x3A.

TOC begins at third sector (at 0x400 = 1K) (may be it can last until end of page ;-) )

Header format (offset 0)

char magic[4] (= '$SDI')
char ver[4]   (= '0001', you can define char magic[8] instead )
0 --- (Unspecified)

QWORD BootCodeOffset
QWORD BootCodeSize
Them are just copies of Offset and Size fields from the BOOT BLOB TOC record, if present.
QWORD VendorID (16-bit HEX value, PCI SIG?)
QWORD DeviceID (16-bit HEX value - what chip do you mean? Northbridge? Network?)

GUID DeviceModel
QWORD DeviceRole (int32 value)
QWORD Reserved1
QWORD RuntimeOEMrev (int32 value)
QWORD Reserved2
QWORD PageAlignment (BLOB alignment value in pages, as specified in /pack: )
QWORD Reserved3[48] (48=384/8; 384=0x80*3)
QWORD Checksum

TOC (Table-of-Content) record format (record size 64 bytes (0x40) ), offset of first record 0x400

char BLOBtype[8] (3-4 bytes UPPERCASE value, 0-padded)
QWORD Attr (uint32 value)
QWORD Offset
QWORD BaseAddress
(0 for non-filesystem BLOBs, filesystem code for PART (as in MBR) - 7 for NTFS, 6 for BIGFAT, etc)
QWORD Reserved[3]

end-of-TOC is just 0-record (may be detected by 0-blobtype)

known BLOB types:
BOOT (startrom.*, you could use server' hdlscom?.* for debug)
LOAD (osloader.exe, bootmgr.exe for PE 2.0)
You can unstub regular ntldr or setupldr.bin with oneliner from oss.netfarm.it
- get fixloader.py from here: http://oss.netfarm.it/guides/pxe.php

PART (Winimage .ima - just a filesystem, as old Linux initrd)
DISK (image with a MBR, you could import flat-VHD or *-flat.vmdk)
WIM (a new squashfs-style Windows Vista filesystem)

sdimgr /pack just needs to alphabetically sort BLOBs ('BOOT' < 'LOAD' < 'PART')

There are neither checksums for TOC and files (BLOB-s), nor sdimgr supports
signing of SDI file.

You should not make BootCodeOffset point to non-aligned-boundary
(for example to point into unused part of TOC in the first page),
some loaders can depend on it!

I hope this info is enough to write your own open-source version of sdimgr :-)

This post is discussed here:
Tags: , , ,

Feb. 8th, 2008


This is trivial. You can use SDI as flat VMDK image. (and use SDILoader to mount such images)

First, create new VMware hard drive, specifying it as flat (Allocate all disk space now) and independent/persistent (optional). You can also use your old flat VMDK.

Then create .sdi for it and import:
sdimgr.wsf /new *.sdi
sdimgr.wsf *.sdi /import:DISK,0,*-flat.vmdk
assuming that * is name of your virtual disk.

Now you can change the reference to BLOB in *.vmdk file. Open it with a text editor (wordpad, it uses Unix end-of-line!) and change extent description
RW ???? FLAT "*-flat.vmdk" 0
RW ???? FLAT "*.sdi" 8

FYI, 8 = 4096/512
Now you can remove original *-flat.vmdk:
del *-flat.vmdk

You did it!
Tags: , , ,

Feb. 5th, 2008

SDI checksum

SDI header has a checksum. Sum of all bytes from first sector (first 512 bytes) of .SDI file must be 0 modulo 256.

Please also check it, not only '$SDI' magic, when writing a custom SDI loader!

Being a totally 64-bit, an SDI file includes negated sum of all previous bytes at offset 512 - 8. (0x1f8)

Tags: , , ,

NTLDR for inclusion into an SDI

There are a lot of places citing http://msdn2.microsoft.com/en-us/library/ms838543.aspx for creation of loadable SDI. Some of them tell that NTLDR file must be from XP Embedded Remote Boot Service. http://remile.free.fr/syslinux/sdi.txt

But no one tells you that this file is exactly osloader.exe from retail XP. I compared SP1 and SP2 versions unpacked from retail service packs and XPe RBS, them match for both releases. (Really there is a Chinese source which tells).

On other hand, XP retail startrom.* are not SDI-capable, you can use WS2003 ones which are.

Tags: , , ,
skolk kolk

March 2008



RSS Atom
Powered by LiveJournal.com