NTBOOTDD.SYS or: booting NT/W2K/XP from CD (long)

Hi all,

the idea I’d like to discuss is based on Gary Nebbett’s article “Booting
NT from floppies” which I suggest you read before reading on, see
http://groups.google.com/groups?selm=01bd598b%244000c380%241eadf6a8%40caopi2
Also, Gary was kind enough to provide me with an updated version of the
article and the source code to his NTBOOTDD.SYS (basically ramboot.sys
is no longer needed). The updated article and the source code are
attached at the bottom of this message, please scroll down first and
read this too.

OK, the original approach is based on MS-DOS and does some tricky stuff
using DOS’ ramdrive.sys to create a RAM disk that stays intact across a
warm boot off of which NBOOTDD.SYS later “serves” the OS.

Well, my magic eight ball says that MS-DOS is not so good. So I was
thinking about how one could get rid of DOS and make the approach work
using NT technology only and have it work off of a bootable CD.

The following is a bit lengthy and I hope I can make it clear:

Let’s just assume I manage to create a much stripped down NT/W2K/XP on a
small, separate FAT partition, just enough to log somebody on and run a
custom shell and that this setup is reasonably small enough, say around
40-50 MB (I must admit that I never really tried even with NT4 what Gary
is describing, but I trust him enough).

Next I would create an 1:1 image of the partition this Mini-NT is
installed on. One would then need a small separate physical hard disk
(no larger than 640 MB), partition and format it to have a single,
active primary FAT partition, make sure it has the NT boot sector on it
and place a boot.ini (restricting NT’s memory to an amount that allows
to load the image of the mini NT partition into memory), NTLDR, a
customized version of Gary’s NTBOOTDD.SYS and the image of the Mini-NT
partition on that primary partition. Then I would create a bootable CD
emulating a hard disk (see
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q167685 ) from
that small hard disk.

Maybe a picture makes it clear:


/ <br>| ±---------+ |
| | boot.ini | |
| | NTLDR | |
| | NTBOOTDD.SYS | |
| | minint.img | |
| ±--------------------------+ |
_________________________ /

The basic idea is to have the contents of the RAM disk that Gary
populates “at DOS run time” fixed in a file.

So when the machine boots from this CD, the CD becomes drive C: (because
it emulates a hard disk), the NT boot code in the boot sector of the
“hard disk CD’s” primary partition fires up NTLDR and NTLDR launches
NTBOOTDD.SYS… and BSODs :slight_smile:

No, obviously what NTBOOTDD.SYS needs to do first of all is to read
minint.img into memory, basically creating a RAM disk “on the fly” and
then just (?) continue like the original “Nebbett” NTBOOTDD.SYS, serving
read/write requests to the boot volume from the RAM disk.

So the big question is if within the limited NTLDR environment, there is
any possibility to open and read a file on the boot volume. NTLDR seems
to export functions BlGetFileInformation, BlLoadImage, BlOpen, BlRead,
BlSetFileInformation, BlWrite, BlClose etc. which sound promising but
are of course undocumented.

I also seem to remember that the NTLDR environment is “real mode BIOS”,
would it be possible to issue INT13 calls from NTBOOTDD.SYS to read from
the bootable CD? (INT13 should work because we have a hard disk
emulation)

Does anybody happen to have some documentation on the Bl* functions in
NTLDR?

More importantly, does what I’m describing sound even remotely possible
or do I just waste my time, am I missing something basic?

I would be most happy if some of the experts on this list could share
their thoughts on this. I must admit that I’m neither an SCSI nor a
driver expert in particular but do know people who would probably be
willing to take the challenge provided they can be convinced that it’s
not a dead end.

Thanks a lot!

Ralf.


================================================

Booting NT from Floppies
========================

When Microsoft knowledge base speaks of booting NT from floppies, it is
normally referring only to the first phase of booting - the loading of ntldr
(and perhaps ntbootdd.sys) and reading of boot.ini. Once these components
have been loaded from floppy, the rest of the files needed to boot and start
NT are loaded from a hard disk. This article describes how to boot NT from
floppies alone - it is not even necessary for a hard disk to be present in
the PC. The mini NT system which is started is able to log users on/off and
uses cmd.exe as the user’s shell.

The basic process which will be described is:

- Boot MSDOS and create a RAM disk
- Unzip a stripped down NT system on the RAM disk
- Reboot from the RAM disk

Using this technique it is possible to boot Windows NT 4.0 SP5 from four
1.44MB floppy disks in about 5 minutes. The four floppy disks do not
include utilities such as regedt32, chkdsk or winfile which might be needed
to repair a system, but these can be loaded from other floppies after the
boot is complete; alternatively if the NT installation on the hard disk of
the PC is not too badly damaged, it might be possible to access these
utilities from there.

The position of the RAM disk in memory is stored in three places:

- MSDOS config.sys (creates the RAM disk)
- boot.ini (/maxmem flag stops NT using RAM disk memory)
- ntbootdd.sys (the RAM disk device driver)

It is relatively easy to change its position (three edits and one build would
be needed), but reserving the memory above 16MB for the RAM disk seems like a
reasonable choice.

Since the RAM disk must be at least 12MB in size, the hardware requirements
for the PC to be bootable from floppies are a floppy drive and at least 28MB
of RAM (24MB might just be enough, if only 10-12MB of RAM were to be reserved
for NT). The smallest configuration that I have tested is 16MB for NT and a
16MB RAM disk.

Creating the RAM disk
---------------------

The RAM disk can be created with the MSDOS ramdrive.sys. The following two
lines from config.sys reserve 16MB RAM for NT and create a 16MB RAM disk:

DEVICE=HIMEM.SYS /int15=15360
DEVICE=RAMDRIVE.SYS 16384 /e

Assuming that config.sys does not place any additional demands on extended
memory, the RAM disk created starts exactly at 0x1000000 (the 16MB
boundary). The MSDOS startup menu can be used to select larger RAM disk sizes
(up to the 32MB limit of ramdrive.sys) if the PC has enough memory.

Content of the RAM disk
-----------------------

The files which need to be loaded into the RAM disks are listed below. Some
of the smaller files may be unnecessary (I did not test whether NT would run
without null.sys, for example, although I expect that it would). The list
includes atdisk.sys and atapi.sys so that any IDE/EIDE disks (or CDROM
drives) can be accessed after the boot. If necessary, some SCSI miniports for
common SCSI disk devices could be added to the list.

Files used in approximate load order Reason for loading
------------------------------------ ------------------

\winnt\system32\ntoskrnl.exe Boot
\winnt\system32\hal.dll
\winnt\system32\config\system
\winnt\system32\l_intl.nls
\winnt\system32\c_1252.nls
\winnt\system32\c_850.nls
\winnt\system32\drivers\ntbootdd.sys Start = 0 (Boot) drivers
\winnt\system32\drivers\scsiport.sys
\winnt\system32\drivers\disk.sys
\winnt\system32\drivers\class2.sys
\winnt\system32\drivers\fastfat.sys

\winnt\system32\ntdll.dll

\winnt\system32\drivers\atapi.sys Start = 1 (System) drivers
\winnt\system32\drivers\atdisk.sys
\winnt\system32\drivers\floppy.sys
\winnt\system32\drivers\cdfs.sys
\winnt\system32\drivers\cdrom.sys
\winnt\system32\drivers\fs_rec.sys
\winnt\system32\drivers\i8042prt.sys
\winnt\system32\drivers\kbdclass.sys
\winnt\system32\drivers\ksecdd.sys
\winnt\system32\drivers\mouclass.sys
\winnt\system32\drivers\msfs.sys
\winnt\system32\drivers\npfs.sys
\winnt\system32\drivers\ntfs.sys
\winnt\system32\drivers\null.sys
\winnt\system32\drivers\vga.sys
\winnt\system32\drivers\videoprt.sys

\winnt\system32\smss.exe Started by ntoskrnl

\winnt\system32\advapi32.dll KnownDLLs
\winnt\system32\gdi32.dll
\winnt\system32\kernel32.dll
\winnt\system32\msvcrt.dll
\winnt\system32\rpcrt4.dll
\winnt\system32\user32.dll

\winnt\system32\config\sam
\winnt\system32\config\security
\winnt\system32\config\software

\winnt\system32\win32k.sys Kmode SubSystems

\winnt\system32\csrss.exe Required SubSystems
\winnt\system32\csrsrv.dll
\winnt\system32\basesrv.dll
\winnt\system32\winsrv.dll
\winnt\system32\unicode.nls
\winnt\system32\locale.nls
\winnt\system32\ctype.nls
\winnt\system32\sortkey.nls
\winnt\system32\sorttbls.nls

\winnt\system32\vga.dll
\winnt\system32\kbdus.dll

\winnt\system32\winlogon.exe Started by CSRSS
\winnt\system32\userenv.dll
\winnt\system32\shell32.dll
\winnt\system32\comctl32.dll
\winnt\system32\netapi32.dll
\winnt\system32\netrap.dll
\winnt\system32\samlib.dll
\winnt\system32\winmm.dll
\winnt\system32\msgina.dll
\winnt\system32\rpcltc1.dll
\winnt\system32\rpclts1.dll

\winnt\system32\services.exe Started by Winlogon
\winnt\system32\umpnpmgr.dll

\winnt\system32\lsass.exe Started by Winlogon
\winnt\system32\lsasrv.dll
\winnt\system32\samsrv.dll
\winnt\system32\msprivs.dll
\winnt\system32\netlogon.dll
\winnt\system32\msv1_0.dll
\winnt\system32\security.dll
\winnt\system32\wsock32.dll
\winnt\system32\ws2_32.dll
\winnt\system32\ws2help.dll

\winnt\system32\cmd.exe Started by Winlogon
\winnt\system32\mpr.dll (if Userinit = “cmd”)

The list includes four registry hives, some of which are often quite
large. Any source of these hives is acceptable and a good choice is the hives
created during a new installation of NT (the hives are still quite small at
this point). The drawbacks of using large hives are that more floppies may
be needed to contain them and the corresponding additional delay when
copying them to the RAM disk.

Assuming that the files listed above are zipped into a file called nt.zip,
then the contents of the four floppies are:

Disk1 Disk2 Disk3 Disk4

(MSDOS boot sector) (NT boot sector)
io.sys nt.zip nt.zip boot.ini
msdos.sys ntbootdd.sys
command.com ntdetect.com
config.sys ntldr
autoexec.bat reboot.com
himem.sys nt.zip
ramdrive.sys
unzip.exe
nt.zip

and boot.ini contains:

[boot loader]
default=scsi(0)disk(0)rdisk(0)partition(1)\winnt
[operating systems]
scsi(0)disk(0)rdisk(0)partition(1)\winnt=“Mini NT 4.0” /maxmem=16 /basevideo

Registry Settings
-----------------

There are a number of values in the system registry hive which need
modification:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit should be
set to “cmd” so that a command window will be started as the user’s shell.

HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage\ACP and
HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage\OEMCP should either
be set to 1252 and 850 respectively, or the files c_1252.nls and c_850.nls in
the zip file should be replaced by code page files which match the existing
registry values.

HKLM\SYSTEM\CurrentControlSet\Control\CrashControl\CrashDumpEnabled and
HKLM\SYSTEM\CurrentControlSet\Control\CrashControl\LogEvent should be
set to zero. This prevents the system from preparing for a crash dump. As a
side effect of making the RAM disk appear to the system as a hard disk,
“partition0” of the RAM disk appears to contain a FAT file system; ntoskrnl
expects this partition to contain a RAW file system and this mismatch leads
to a crash when preparing for a crash dump.

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PagingFiles
should be set to “C:\winnt\system32\temppf.sys 2 8”. This will prevent
winlogon from filling the RAM disk with a temporary paging file.

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\SystemPages
should be set to 0x3000. This will ensure that there are enough system PTEs
to map a 32MB RAM disk.

HKLM\SYSTEM\CurrentControlSet\Services should be checked for “Start=0”
services. Only ntbootdd and disk should start at boot time; other services
which have “Start=0” should be modified to “Start=1”. The entry for ntbootdd
can be created manually if necessary, taking another SCSI miniport as
template (e.g. Aha154x).

Booting from the RAM Disk
-------------------------

After the RAM disk has been loaded, the next step is to reboot the PC from a
“normal” NT boot floppy (Disk4 in the table above) whose boot.ini selects the
RAM disk as the boot disk. The only problem is that the normal Ctrl-Alt-Del
reboot zeros memory, erasing the contents of the RAM disk. Fortunately, there
is a method of rebooting without zeroing memory - by executing the Intel x86
instruction “int 19h” to invoke the bootstrap loader service; quoting from
Ralf Brown’s “Interrupt List”:

“This interrupt reboots the system without clearing memory or restoring
interrupt vectors.”

A two byte .com file containing the values 0xCD, 0x19 does the trick (these
values being the hexadecimal code for “int 19h”); a suitable name for this
file is reboot.com.

Ntbootdd
--------

If boot.ini selects a boot device whose ARC name starts with “scsi”, then
there must be a file in the same directory as boot.ini with the name
“ntbootdd.sys”. Normally ntbootdd.sys is a renamed copy of the appropriate
SCSI miniport driver for the hard disks of the system, but when booting from
the RAM disk, ntbootdd.sys is built from ntbootdd.cpp (Listing 1).

ntbootdd.sys appears twice on the boot floppies: once on the “normal” NT boot
floppy (where it is used by ntldr to load the initial system components) and
once in the zip file (from whence it is later loaded and used by ntoskrnl to
access the RAM disk). The same file is used in both places, but this is not
compulsory; there are some differences between the two environments into
which ntbootdd.sys is loaded and if necessary this could be compensated for
by alternative versions of the code.

Important environmental differences are that the ntldr implementation of
ScsiPortFreeDeviceBase() does nothing and the implementation of
ScsiPortGetDeviceBase() can map a maximum of 4MB and has problems mapping
non-paged aligned regions that straddle pages. The ntldr implementation of
ScsiPortGetDeviceBase() can be called from the HwScsiStartIo routine, but the
ntoskrnl implementation cannot (because of IRQL considerations).
ntbootdd.sys detects which environment it is in (by examining the first
sector of the RAM disk) and adapts its behaviour accordingly.

The 4MB mapping limit places an upper bound on how much data ntbootdd.sys can
load; excluding the system hive, about 1.3MB needs to be mapped so the system
hive can be as large as 2.5MB (the system hive can be reduced to about 64kB
by deleting unnecessary keys and values).

Ntbootdd was debugged by using the checked version of ntldr; when using the
checked version, the ScsiPort routine ScsiDebugPrint() is available and the
level of output is controlled by the [debug] section in boot.ini. Setting
scsidebug=3 produces a great deal of output; scsidebug=2 is much more
manageable. Since the debug output is only visible on the screen and scrolls
very quickly, it is often helpful to follow a ScsiDebugPrint() with code
like:

for (int i = 0; i < 2000; i++) ScsiPortStallExecution(1000);

Since the RAM disk does not contain a partition table, the initial version of
ntbootdd emulated a floppy device. This mostly worked, but attempts to create
paging files on the RAM disk failed with the error STATUS_FLOPPY_VOLUME (“The
paging file cannot be created on a floppy diskette”). The current version
emulates a hard disk and modifies the first sector of the RAM disk to include
a partition table. Another change is needed to the first sector of the RAM
disk because the MDDOS ramdrive.sys does not format the BIOS parameter blocks
in quite the same way as is expected of a FAT file system; it is necessary to
explicitly set the “Large Sectors” field (offset 0x20) to zero, otherwise the
RAM disk is not recognized as containing a FAT file system.

Drive Letters
-------------

The RAM disk is assigned the drive letter C:. Any other disks for which
drivers have been loaded are assigned drive letters, but these letters will
probably differ from the normal assignment for any particular PC. This is
because C: is already taken, there are no sticky drive letter assignments and
drivers for some disks are not loaded or are loaded in a different order.

Keyboard Layout
---------------

Information about the keyboard layout is stored in the registry on a per-user
basis. When no user is logged in or the logged in user’s hive is unavailable,
the keyboard layout information is retrieved from HKEY_USERS.Default (which
is stored in the hive named “default”). Since neither the default hive nor
any user hives are included in the zip file, the system defaults the keyboard
layout. Naturally, the default keyboard layout is a US keyboard layout. If
this is a problem, a suitable default hive could be included in the zip file.

=============================<ntbootdd.cpp>=============================

extern “C” {
#include “miniport.h”
#include “scsi.h”
}
#include <memory.h>

#pragma pack(push, 1)

typedef struct PTABLE {
UCHAR Flag;
UCHAR Chs1[3];
UCHAR Type;
UCHAR Chs2[3];
ULONG Start;
ULONG Size;
} *PPTABLE;

typedef struct FAT {
UCHAR Jump[3];
UCHAR System[8];
USHORT BytesPerSector;
UCHAR SectorsPerCluster;
USHORT ReservedSectors;
UCHAR FatCopies;
USHORT RootEntries;
USHORT SmallSectors;
UCHAR MediaType;
USHORT SectorsPerFat;
USHORT SectorsPerTrack;
USHORT Heads;
ULONG HiddenSectors;
ULONG LargeSectors;
UCHAR Disk;
UCHAR Flags;
UCHAR Signature;
ULONG SerialNumber;
UCHAR Label[11];
UCHAR Format[8];
UCHAR Code[0x17A];
ULONG DiskSignature;
UCHAR Reserved;
UCHAR BootPartition;
PTABLE Table[4];
USHORT BootSignature;
} *PFAT;

#pragma pack(pop)

typedef PVOID PPVOID;

const ULONG PageSize = 0x1000;
const ULONG DiskBase = 0x1000000;

ULONG BytesPerBlock, Blocks;
PCHAR MapBase;
BOOLEAN Boot;

ULONG ChunkSize(ULONG Offset, ULONG Length, ULONG Position)
{
ULONG X = PageSize - ((Offset + Position) & (PageSize - 1));
ULONG Y = Length - Position;

return X < Y ? X : Y;
}

PVOID MapPage(PVOID DeviceExtension, ULONG Address)
{
ULONG X = (Address - DiskBase) / PageSize;

if (PPVOID(DeviceExtension)[X] == 0)

(PPVOID(DeviceExtension) + X) =

ScsiPortGetDeviceBase(DeviceExtension, Internal, 0,
ScsiPortConvertUlongToPhysicalAddress(Address & ~(PageSize - 1)),
PageSize, FALSE);

return PCHAR(PPVOID(DeviceExtension)) + (Address & (PageSize - 1));
}

PVOID MapAddress(PVOID DeviceExtension, ULONG Address, ULONG Size)
{
return ScsiPortGetDeviceBase(DeviceExtension, Internal, 0,
ScsiPortConvertUlongToPhysicalAddress(Address), Size, FALSE);
}

BOOLEAN StartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
{
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
Srb->ScsiStatus = SCSISTAT_GOOD;

if (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Lun == 0) {

switch (Srb->Cdb[0]) {

case SCSIOP_INQUIRY:
{
memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
PINQUIRYDATA Inq = PINQUIRYDATA(Srb->DataBuffer);
Inq->DeviceType = DIRECT_ACCESS_DEVICE;
Inq->DeviceTypeQualifier = DEVICE_CONNECTED;
memcpy(Inq->VendorId, "NEBBETT ", sizeof Inq->VendorId);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_MODE_SENSE:
{
memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
PMODE_PARM_READ_WRITE_DATA Mode = PMODE_PARM_READ_WRITE_DATA(Srb->DataBuffer);
Mode->ParameterListHeader.ModeDataLength = sizeof *Mode - 1;
Mode->ParameterListHeader.BlockDescriptorLength = sizeof Mode->ParameterListBlock;
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_TEST_UNIT_READY:
case SCSIOP_MEDIUM_REMOVAL:
{
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_READ_CAPACITY:
{
ULONG X = BytesPerBlock;
REVERSE_BYTES(&PREAD_CAPACITY_DATA(Srb->DataBuffer)->BytesPerBlock, &X);
X = Blocks - 1;
REVERSE_BYTES(&PREAD_CAPACITY_DATA(Srb->DataBuffer)->LogicalBlockAddress, &X);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_READ:
{
ULONG X;
REVERSE_BYTES(&X, &PCDB(Srb->Cdb)->CDB10.LogicalBlockByte0);

if (Boot) {
X = X * BytesPerBlock + DiskBase;
for (ULONG Z, Y = 0; Y < Srb->DataTransferLength; Y += Z) {
Z = ChunkSize(X, Srb->DataTransferLength, Y);
memcpy(PCHAR(Srb->DataBuffer) + Y, MapPage(DeviceExtension, X + Y), Z);
}
}
else
memcpy(Srb->DataBuffer, MapBase + X * BytesPerBlock, Srb->DataTransferLength);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_WRITE:
{
ULONG X;
REVERSE_BYTES(&X, &PCDB(Srb->Cdb)->CDB10.LogicalBlockByte0);

if (Boot) {
X = X * BytesPerBlock + DiskBase;
for (ULONG Z, Y = 0; Y < Srb->DataTransferLength; Y += Z) {
Z = ChunkSize(X, Srb->DataTransferLength, Y);
memcpy(MapPage(DeviceExtension, X + Y), PCHAR(Srb->DataBuffer) + Y, Z);
}
}
else
memcpy(MapBase + X * BytesPerBlock, Srb->DataBuffer, Srb->DataTransferLength);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

default:
{
ScsiDebugPrint(1, “StartIo Function Execute %x, Flags %lx, Len %lx\n”,
int(Srb->Cdb[0]), Srb->SrbFlags, Srb->DataTransferLength);
// for (int i = 0; i < 2000; i++) ScsiPortStallExecution(1000);
}
break;
}
}

ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
ScsiPortNotification(NextRequest, DeviceExtension);

return TRUE;
}

ULONG FindAdapter(PVOID DeviceExtension, PVOID, PVOID, PCHAR,
PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
{
PFAT Fat = PFAT(MapAddress(DeviceExtension, DiskBase, sizeof (FAT)));

Boot = Fat->LargeSectors != 0;

BytesPerBlock = Fat->BytesPerSector;
Blocks = Fat->SmallSectors;

Fat->LargeSectors = 0;
Fat->BootSignature = 0xAA55;
Fat->Table[0].Type = 4;
Fat->Table[0].Start = 0;
Fat->Table[0].Size = Blocks;
Fat->Table[1].Type = Fat->Table[2].Type = Fat->Table[3].Type = 0;

ScsiPortFreeDeviceBase(DeviceExtension, Fat);

if (!Boot) MapBase = PCHAR(MapAddress(DeviceExtension, DiskBase, Blocks * BytesPerBlock));

ConfigInfo->NumberOfBuses = 1;
ConfigInfo->MaximumNumberOfTargets = 1;

*Again = FALSE;

return SP_RETURN_FOUND;
}

BOOLEAN ResetBus(PVOID DeviceExtension, ULONG PathId)
{
ScsiPortCompleteRequest(DeviceExtension, UCHAR(PathId), SP_UNTAGGED, SP_UNTAGGED,
SRB_STATUS_BUS_RESET);

return TRUE;
}

BOOLEAN Initialize(PVOID)
{
return TRUE;
}

extern “C”
ULONG DriverEntry(PVOID DriverObject, PVOID RegistryPath)
{
HW_INITIALIZATION_DATA Hid = {sizeof Hid};

Hid.AdapterInterfaceType = Isa;
Hid.DeviceExtensionSize = 0x2000 * sizeof (PVOID);
Hid.MapBuffers = TRUE;

Hid.HwFindAdapter = FindAdapter;
Hid.HwInitialize = Initialize;
Hid.HwResetBus = ResetBus;
Hid.HwStartIo = StartIo;

return ScsiPortInitialize(DriverObject, RegistryPath, &Hid, 0);
}</memory.h></ntbootdd.cpp>

It would be great to be able to boot from a 256Mb or 512Mb CompactFlash, if
nothing else, it fits in my wallet. It would also be great to be able to
Ghost a system in and out of a CompactFlash. Any takers ?

Alberto.

-----Original Message-----
From: Ralf Buschmann [mailto:xxxxx@backmagic.de]
Sent: Monday, May 06, 2002 5:03 PM
To: NT Developers Interest List
Subject: [ntdev] NTBOOTDD.SYS or: booting NT/W2K/XP from CD (long)

Hi all,

the idea I’d like to discuss is based on Gary Nebbett’s article “Booting
NT from floppies” which I suggest you read before reading on, see
http://groups.google.com/groups?selm=01bd598b%244000c380%241eadf6a8%40caopi2
Also, Gary was kind enough to provide me with an updated version of the
article and the source code to his NTBOOTDD.SYS (basically ramboot.sys
is no longer needed). The updated article and the source code are
attached at the bottom of this message, please scroll down first and
read this too.

OK, the original approach is based on MS-DOS and does some tricky stuff
using DOS’ ramdrive.sys to create a RAM disk that stays intact across a
warm boot off of which NBOOTDD.SYS later “serves” the OS.

Well, my magic eight ball says that MS-DOS is not so good. So I was
thinking about how one could get rid of DOS and make the approach work
using NT technology only and have it work off of a bootable CD.

The following is a bit lengthy and I hope I can make it clear:

Let’s just assume I manage to create a much stripped down NT/W2K/XP on a
small, separate FAT partition, just enough to log somebody on and run a
custom shell and that this setup is reasonably small enough, say around
40-50 MB (I must admit that I never really tried even with NT4 what Gary
is describing, but I trust him enough).

Next I would create an 1:1 image of the partition this Mini-NT is
installed on. One would then need a small separate physical hard disk
(no larger than 640 MB), partition and format it to have a single,
active primary FAT partition, make sure it has the NT boot sector on it
and place a boot.ini (restricting NT’s memory to an amount that allows
to load the image of the mini NT partition into memory), NTLDR, a
customized version of Gary’s NTBOOTDD.SYS and the image of the Mini-NT
partition on that primary partition. Then I would create a bootable CD
emulating a hard disk (see
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q167685 ) from
that small hard disk.

Maybe a picture makes it clear:


/ <br>| ±---------+ |
| | boot.ini | |
| | NTLDR | |
| | NTBOOTDD.SYS | |
| | minint.img | |
| ±--------------------------+ |
_________________________ /

The basic idea is to have the contents of the RAM disk that Gary
populates “at DOS run time” fixed in a file.

So when the machine boots from this CD, the CD becomes drive C: (because
it emulates a hard disk), the NT boot code in the boot sector of the
“hard disk CD’s” primary partition fires up NTLDR and NTLDR launches
NTBOOTDD.SYS… and BSODs :slight_smile:

No, obviously what NTBOOTDD.SYS needs to do first of all is to read
minint.img into memory, basically creating a RAM disk “on the fly” and
then just (?) continue like the original “Nebbett” NTBOOTDD.SYS, serving
read/write requests to the boot volume from the RAM disk.

So the big question is if within the limited NTLDR environment, there is
any possibility to open and read a file on the boot volume. NTLDR seems
to export functions BlGetFileInformation, BlLoadImage, BlOpen, BlRead,
BlSetFileInformation, BlWrite, BlClose etc. which sound promising but
are of course undocumented.

I also seem to remember that the NTLDR environment is “real mode BIOS”,
would it be possible to issue INT13 calls from NTBOOTDD.SYS to read from
the bootable CD? (INT13 should work because we have a hard disk
emulation)

Does anybody happen to have some documentation on the Bl* functions in
NTLDR?

More importantly, does what I’m describing sound even remotely possible
or do I just waste my time, am I missing something basic?

I would be most happy if some of the experts on this list could share
their thoughts on this. I must admit that I’m neither an SCSI nor a
driver expert in particular but do know people who would probably be
willing to take the challenge provided they can be convinced that it’s
not a dead end.

Thanks a lot!

Ralf.


================================================

Booting NT from Floppies
========================

When Microsoft knowledge base speaks of booting NT from floppies, it is
normally referring only to the first phase of booting - the loading of ntldr
(and perhaps ntbootdd.sys) and reading of boot.ini. Once these components
have been loaded from floppy, the rest of the files needed to boot and start
NT are loaded from a hard disk. This article describes how to boot NT from
floppies alone - it is not even necessary for a hard disk to be present in
the PC. The mini NT system which is started is able to log users on/off and
uses cmd.exe as the user’s shell.

The basic process which will be described is:

- Boot MSDOS and create a RAM disk
- Unzip a stripped down NT system on the RAM disk
- Reboot from the RAM disk

Using this technique it is possible to boot Windows NT 4.0 SP5 from four
1.44MB floppy disks in about 5 minutes. The four floppy disks do not
include utilities such as regedt32, chkdsk or winfile which might be needed
to repair a system, but these can be loaded from other floppies after the
boot is complete; alternatively if the NT installation on the hard disk of
the PC is not too badly damaged, it might be possible to access these
utilities from there.

The position of the RAM disk in memory is stored in three places:

- MSDOS config.sys (creates the RAM disk)
- boot.ini (/maxmem flag stops NT using RAM disk memory)
- ntbootdd.sys (the RAM disk device driver)

It is relatively easy to change its position (three edits and one build
would
be needed), but reserving the memory above 16MB for the RAM disk seems like
a
reasonable choice.

Since the RAM disk must be at least 12MB in size, the hardware requirements
for the PC to be bootable from floppies are a floppy drive and at least 28MB
of RAM (24MB might just be enough, if only 10-12MB of RAM were to be
reserved
for NT). The smallest configuration that I have tested is 16MB for NT and a
16MB RAM disk.

Creating the RAM disk
---------------------

The RAM disk can be created with the MSDOS ramdrive.sys. The following two
lines from config.sys reserve 16MB RAM for NT and create a 16MB RAM disk:

DEVICE=HIMEM.SYS /int15=15360
DEVICE=RAMDRIVE.SYS 16384 /e

Assuming that config.sys does not place any additional demands on extended
memory, the RAM disk created starts exactly at 0x1000000 (the 16MB
boundary). The MSDOS startup menu can be used to select larger RAM disk
sizes
(up to the 32MB limit of ramdrive.sys) if the PC has enough memory.

Content of the RAM disk
-----------------------

The files which need to be loaded into the RAM disks are listed below. Some
of the smaller files may be unnecessary (I did not test whether NT would run
without null.sys, for example, although I expect that it would). The list
includes atdisk.sys and atapi.sys so that any IDE/EIDE disks (or CDROM
drives) can be accessed after the boot. If necessary, some SCSI miniports
for
common SCSI disk devices could be added to the list.

Files used in approximate load order Reason for loading
------------------------------------ ------------------

\winnt\system32\ntoskrnl.exe Boot
\winnt\system32\hal.dll
\winnt\system32\config\system
\winnt\system32\l_intl.nls
\winnt\system32\c_1252.nls
\winnt\system32\c_850.nls
\winnt\system32\drivers\ntbootdd.sys Start = 0 (Boot) drivers
\winnt\system32\drivers\scsiport.sys
\winnt\system32\drivers\disk.sys
\winnt\system32\drivers\class2.sys
\winnt\system32\drivers\fastfat.sys

\winnt\system32\ntdll.dll

\winnt\system32\drivers\atapi.sys Start = 1 (System) drivers
\winnt\system32\drivers\atdisk.sys
\winnt\system32\drivers\floppy.sys
\winnt\system32\drivers\cdfs.sys
\winnt\system32\drivers\cdrom.sys
\winnt\system32\drivers\fs_rec.sys
\winnt\system32\drivers\i8042prt.sys
\winnt\system32\drivers\kbdclass.sys
\winnt\system32\drivers\ksecdd.sys
\winnt\system32\drivers\mouclass.sys
\winnt\system32\drivers\msfs.sys
\winnt\system32\drivers\npfs.sys
\winnt\system32\drivers\ntfs.sys
\winnt\system32\drivers\null.sys
\winnt\system32\drivers\vga.sys
\winnt\system32\drivers\videoprt.sys

\winnt\system32\smss.exe Started by ntoskrnl

\winnt\system32\advapi32.dll KnownDLLs
\winnt\system32\gdi32.dll
\winnt\system32\kernel32.dll
\winnt\system32\msvcrt.dll
\winnt\system32\rpcrt4.dll
\winnt\system32\user32.dll

\winnt\system32\config\sam
\winnt\system32\config\security
\winnt\system32\config\software

\winnt\system32\win32k.sys Kmode SubSystems

\winnt\system32\csrss.exe Required SubSystems
\winnt\system32\csrsrv.dll
\winnt\system32\basesrv.dll
\winnt\system32\winsrv.dll
\winnt\system32\unicode.nls
\winnt\system32\locale.nls
\winnt\system32\ctype.nls
\winnt\system32\sortkey.nls
\winnt\system32\sorttbls.nls

\winnt\system32\vga.dll
\winnt\system32\kbdus.dll

\winnt\system32\winlogon.exe Started by CSRSS
\winnt\system32\userenv.dll
\winnt\system32\shell32.dll
\winnt\system32\comctl32.dll
\winnt\system32\netapi32.dll
\winnt\system32\netrap.dll
\winnt\system32\samlib.dll
\winnt\system32\winmm.dll
\winnt\system32\msgina.dll
\winnt\system32\rpcltc1.dll
\winnt\system32\rpclts1.dll

\winnt\system32\services.exe Started by Winlogon
\winnt\system32\umpnpmgr.dll

\winnt\system32\lsass.exe Started by Winlogon
\winnt\system32\lsasrv.dll
\winnt\system32\samsrv.dll
\winnt\system32\msprivs.dll
\winnt\system32\netlogon.dll
\winnt\system32\msv1_0.dll
\winnt\system32\security.dll
\winnt\system32\wsock32.dll
\winnt\system32\ws2_32.dll
\winnt\system32\ws2help.dll

\winnt\system32\cmd.exe Started by Winlogon
\winnt\system32\mpr.dll (if Userinit = “cmd”)

The list includes four registry hives, some of which are often quite
large. Any source of these hives is acceptable and a good choice is the
hives
created during a new installation of NT (the hives are still quite small at
this point). The drawbacks of using large hives are that more floppies may
be needed to contain them and the corresponding additional delay when
copying them to the RAM disk.

Assuming that the files listed above are zipped into a file called nt.zip,
then the contents of the four floppies are:

Disk1 Disk2 Disk3 Disk4

(MSDOS boot sector) (NT boot
sector)
io.sys nt.zip nt.zip boot.ini
msdos.sys ntbootdd.sys
command.com ntdetect.com
config.sys ntldr
autoexec.bat reboot.com
himem.sys nt.zip
ramdrive.sys
unzip.exe
nt.zip

and boot.ini contains:

[boot loader]
default=scsi(0)disk(0)rdisk(0)partition(1)\winnt
[operating systems]
scsi(0)disk(0)rdisk(0)partition(1)\winnt=“Mini NT 4.0” /maxmem=16
/basevideo

Registry Settings
-----------------

There are a number of values in the system registry hive which need
modification:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit should
be
set to “cmd” so that a command window will be started as the user’s shell.

HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage\ACP and
HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage\OEMCP should either
be set to 1252 and 850 respectively, or the files c_1252.nls and c_850.nls
in
the zip file should be replaced by code page files which match the existing
registry values.

HKLM\SYSTEM\CurrentControlSet\Control\CrashControl\CrashDumpEnabled and
HKLM\SYSTEM\CurrentControlSet\Control\CrashControl\LogEvent should be
set to zero. This prevents the system from preparing for a crash dump. As a
side effect of making the RAM disk appear to the system as a hard disk,
“partition0” of the RAM disk appears to contain a FAT file system; ntoskrnl
expects this partition to contain a RAW file system and this mismatch leads
to a crash when preparing for a crash dump.

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory
Management\PagingFiles
should be set to “C:\winnt\system32\temppf.sys 2 8”. This will prevent
winlogon from filling the RAM disk with a temporary paging file.

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory
Management\SystemPages
should be set to 0x3000. This will ensure that there are enough system PTEs
to map a 32MB RAM disk.

HKLM\SYSTEM\CurrentControlSet\Services should be checked for “Start=0”
services. Only ntbootdd and disk should start at boot time; other services
which have “Start=0” should be modified to “Start=1”. The entry for ntbootdd
can be created manually if necessary, taking another SCSI miniport as
template (e.g. Aha154x).

Booting from the RAM Disk
-------------------------

After the RAM disk has been loaded, the next step is to reboot the PC from a
“normal” NT boot floppy (Disk4 in the table above) whose boot.ini selects
the
RAM disk as the boot disk. The only problem is that the normal Ctrl-Alt-Del
reboot zeros memory, erasing the contents of the RAM disk. Fortunately,
there
is a method of rebooting without zeroing memory - by executing the Intel x86
instruction “int 19h” to invoke the bootstrap loader service; quoting from
Ralf Brown’s “Interrupt List”:

“This interrupt reboots the system without clearing memory or restoring
interrupt vectors.”

A two byte .com file containing the values 0xCD, 0x19 does the trick (these
values being the hexadecimal code for “int 19h”); a suitable name for this
file is reboot.com.

Ntbootdd
--------

If boot.ini selects a boot device whose ARC name starts with “scsi”, then
there must be a file in the same directory as boot.ini with the name
“ntbootdd.sys”. Normally ntbootdd.sys is a renamed copy of the appropriate
SCSI miniport driver for the hard disks of the system, but when booting from
the RAM disk, ntbootdd.sys is built from ntbootdd.cpp (Listing 1).

ntbootdd.sys appears twice on the boot floppies: once on the “normal” NT
boot
floppy (where it is used by ntldr to load the initial system components) and
once in the zip file (from whence it is later loaded and used by ntoskrnl to
access the RAM disk). The same file is used in both places, but this is not
compulsory; there are some differences between the two environments into
which ntbootdd.sys is loaded and if necessary this could be compensated for
by alternative versions of the code.

Important environmental differences are that the ntldr implementation of
ScsiPortFreeDeviceBase() does nothing and the implementation of
ScsiPortGetDeviceBase() can map a maximum of 4MB and has problems mapping
non-paged aligned regions that straddle pages. The ntldr implementation of
ScsiPortGetDeviceBase() can be called from the HwScsiStartIo routine, but
the
ntoskrnl implementation cannot (because of IRQL considerations).
ntbootdd.sys detects which environment it is in (by examining the first
sector of the RAM disk) and adapts its behaviour accordingly.

The 4MB mapping limit places an upper bound on how much data ntbootdd.sys
can
load; excluding the system hive, about 1.3MB needs to be mapped so the
system
hive can be as large as 2.5MB (the system hive can be reduced to about 64kB
by deleting unnecessary keys and values).

Ntbootdd was debugged by using the checked version of ntldr; when using the
checked version, the ScsiPort routine ScsiDebugPrint() is available and the
level of output is controlled by the [debug] section in boot.ini. Setting
scsidebug=3 produces a great deal of output; scsidebug=2 is much more
manageable. Since the debug output is only visible on the screen and scrolls
very quickly, it is often helpful to follow a ScsiDebugPrint() with code
like:

for (int i = 0; i < 2000; i++) ScsiPortStallExecution(1000);

Since the RAM disk does not contain a partition table, the initial version
of
ntbootdd emulated a floppy device. This mostly worked, but attempts to
create
paging files on the RAM disk failed with the error STATUS_FLOPPY_VOLUME
(“The
paging file cannot be created on a floppy diskette”). The current version
emulates a hard disk and modifies the first sector of the RAM disk to
include
a partition table. Another change is needed to the first sector of the RAM
disk because the MDDOS ramdrive.sys does not format the BIOS parameter
blocks
in quite the same way as is expected of a FAT file system; it is necessary
to
explicitly set the “Large Sectors” field (offset 0x20) to zero, otherwise
the
RAM disk is not recognized as containing a FAT file system.

Drive Letters
-------------

The RAM disk is assigned the drive letter C:. Any other disks for which
drivers have been loaded are assigned drive letters, but these letters will
probably differ from the normal assignment for any particular PC. This is
because C: is already taken, there are no sticky drive letter assignments
and
drivers for some disks are not loaded or are loaded in a different order.

Keyboard Layout
---------------

Information about the keyboard layout is stored in the registry on a
per-user
basis. When no user is logged in or the logged in user’s hive is
unavailable,
the keyboard layout information is retrieved from HKEY_USERS.Default (which
is stored in the hive named “default”). Since neither the default hive nor
any user hives are included in the zip file, the system defaults the
keyboard
layout. Naturally, the default keyboard layout is a US keyboard layout. If
this is a problem, a suitable default hive could be included in the zip
file.

=============================<ntbootdd.cpp>=============================

extern “C” {
#include “miniport.h”
#include “scsi.h”
}
#include <memory.h>

#pragma pack(push, 1)

typedef struct PTABLE {
UCHAR Flag;
UCHAR Chs1[3];
UCHAR Type;
UCHAR Chs2[3];
ULONG Start;
ULONG Size;
} *PPTABLE;

typedef struct FAT {
UCHAR Jump[3];
UCHAR System[8];
USHORT BytesPerSector;
UCHAR SectorsPerCluster;
USHORT ReservedSectors;
UCHAR FatCopies;
USHORT RootEntries;
USHORT SmallSectors;
UCHAR MediaType;
USHORT SectorsPerFat;
USHORT SectorsPerTrack;
USHORT Heads;
ULONG HiddenSectors;
ULONG LargeSectors;
UCHAR Disk;
UCHAR Flags;
UCHAR Signature;
ULONG SerialNumber;
UCHAR Label[11];
UCHAR Format[8];
UCHAR Code[0x17A];
ULONG DiskSignature;
UCHAR Reserved;
UCHAR BootPartition;
PTABLE Table[4];
USHORT BootSignature;
} *PFAT;

#pragma pack(pop)

typedef PVOID PPVOID;

const ULONG PageSize = 0x1000;
const ULONG DiskBase = 0x1000000;

ULONG BytesPerBlock, Blocks;
PCHAR MapBase;
BOOLEAN Boot;

ULONG ChunkSize(ULONG Offset, ULONG Length, ULONG Position)
{
ULONG X = PageSize - ((Offset + Position) & (PageSize - 1));
ULONG Y = Length - Position;

return X < Y ? X : Y;
}

PVOID MapPage(PVOID DeviceExtension, ULONG Address)
{
ULONG X = (Address - DiskBase) / PageSize;

if (PPVOID(DeviceExtension)[X] == 0)

(PPVOID(DeviceExtension) + X) =

ScsiPortGetDeviceBase(DeviceExtension, Internal, 0,

ScsiPortConvertUlongToPhysicalAddress(Address & ~(PageSize - 1)),
PageSize, FALSE);

return PCHAR(PPVOID(DeviceExtension)) + (Address & (PageSize - 1));
}

PVOID MapAddress(PVOID DeviceExtension, ULONG Address, ULONG Size)
{
return ScsiPortGetDeviceBase(DeviceExtension, Internal, 0,

ScsiPortConvertUlongToPhysicalAddress(Address), Size, FALSE);
}

BOOLEAN StartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
{
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
Srb->ScsiStatus = SCSISTAT_GOOD;

if (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Lun == 0) {

switch (Srb->Cdb[0]) {

case SCSIOP_INQUIRY:
{
memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
PINQUIRYDATA Inq = PINQUIRYDATA(Srb->DataBuffer);
Inq->DeviceType = DIRECT_ACCESS_DEVICE;
Inq->DeviceTypeQualifier = DEVICE_CONNECTED;
memcpy(Inq->VendorId, "NEBBETT ", sizeof Inq->VendorId);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_MODE_SENSE:
{
memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
PMODE_PARM_READ_WRITE_DATA Mode =
PMODE_PARM_READ_WRITE_DATA(Srb->DataBuffer);
Mode->ParameterListHeader.ModeDataLength = sizeof Mode - 1;
Mode->ParameterListHeader.BlockDescriptorLength = sizeof
Mode->ParameterListBlock;
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_TEST_UNIT_READY:
case SCSIOP_MEDIUM_REMOVAL:
{
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_READ_CAPACITY:
{
ULONG X = BytesPerBlock;

REVERSE_BYTES(&PREAD_CAPACITY_DATA(Srb->DataBuffer)->BytesPerBlock, &X);
X = Blocks - 1;

REVERSE_BYTES(&PREAD_CAPACITY_DATA(Srb->DataBuffer)->LogicalBlockAddress,
&X);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_READ:
{
ULONG X;
REVERSE_BYTES(&X, &PCDB(Srb->Cdb)->CDB10.LogicalBlockByte0);

if (Boot) {
X = X * BytesPerBlock + DiskBase;
for (ULONG Z, Y = 0; Y < Srb->DataTransferLength; Y +=
Z) {
Z = ChunkSize(X, Srb->DataTransferLength, Y);
memcpy(PCHAR(Srb->DataBuffer) + Y,
MapPage(DeviceExtension, X + Y), Z);
}
}
else
memcpy(Srb->DataBuffer, MapBase + X * BytesPerBlock,
Srb->DataTransferLength);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_WRITE:
{
ULONG X;
REVERSE_BYTES(&X, &PCDB(Srb->Cdb)->CDB10.LogicalBlockByte0);

if (Boot) {
X = X * BytesPerBlock + DiskBase;
for (ULONG Z, Y = 0; Y < Srb->DataTransferLength; Y +=
Z) {
Z = ChunkSize(X, Srb->DataTransferLength, Y);
memcpy(MapPage(DeviceExtension, X + Y),
PCHAR(Srb->DataBuffer) + Y, Z);
}
}
else
memcpy(MapBase + X * BytesPerBlock, Srb->DataBuffer,
Srb->DataTransferLength);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

default:
{
ScsiDebugPrint(1, “StartIo Function Execute %x, Flags %lx,
Len %lx\n”,
int(Srb->Cdb[0]), Srb->SrbFlags,
Srb->DataTransferLength);
// for (int i = 0; i < 2000; i++)
ScsiPortStallExecution(1000);
}
break;
}
}

ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
ScsiPortNotification(NextRequest, DeviceExtension);

return TRUE;
}

ULONG FindAdapter(PVOID DeviceExtension, PVOID, PVOID, PCHAR,
PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN
Again)
{
PFAT Fat = PFAT(MapAddress(DeviceExtension, DiskBase, sizeof (FAT)));

Boot = Fat->LargeSectors != 0;

BytesPerBlock = Fat->BytesPerSector;
Blocks = Fat->SmallSectors;

Fat->LargeSectors = 0;
Fat->BootSignature = 0xAA55;
Fat->Table[0].Type = 4;
Fat->Table[0].Start = 0;
Fat->Table[0].Size = Blocks;
Fat->Table[1].Type = Fat->Table[2].Type = Fat->Table[3].Type = 0;

ScsiPortFreeDeviceBase(DeviceExtension, Fat);

if (!Boot) MapBase = PCHAR(MapAddress(DeviceExtension, DiskBase, Blocks
BytesPerBlock));

ConfigInfo->NumberOfBuses = 1;
ConfigInfo->MaximumNumberOfTargets = 1;

*Again = FALSE;

return SP_RETURN_FOUND;
}

BOOLEAN ResetBus(PVOID DeviceExtension, ULONG PathId)
{
ScsiPortCompleteRequest(DeviceExtension, UCHAR(PathId), SP_UNTAGGED,
SP_UNTAGGED,
SRB_STATUS_BUS_RESET);

return TRUE;
}

BOOLEAN Initialize(PVOID)
{
return TRUE;
}

extern “C”
ULONG DriverEntry(PVOID DriverObject, PVOID RegistryPath)
{
HW_INITIALIZATION_DATA Hid = {sizeof Hid};

Hid.AdapterInterfaceType = Isa;
Hid.DeviceExtensionSize = 0x2000 * sizeof (PVOID);
Hid.MapBuffers = TRUE;

Hid.HwFindAdapter = FindAdapter;
Hid.HwInitialize = Initialize;
Hid.HwResetBus = ResetBus;
Hid.HwStartIo = StartIo;

return ScsiPortInitialize(DriverObject, RegistryPath, &Hid, 0);
}


You are currently subscribed to ntdev as: xxxxx@compuware.com
To unsubscribe send a blank email to %%email.unsub%%

The contents of this e-mail are intended for the named addressee only. It
contains information that may be confidential. Unless you are the named
addressee or an authorized designee, you may not copy or use it, or disclose
it to anyone else. If you received it in error please notify us immediately
and then destroy it.</memory.h></ntbootdd.cpp>

Int 13h will work on El Torito emulated hard disk drives.

How about filtering int 13h and intercepting writes?

Jamey

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Ralf Buschmann
Sent: Monday, May 06, 2002 2:03 PM
To: NT Developers Interest List
Subject: [ntdev] NTBOOTDD.SYS or: booting NT/W2K/XP from CD (long)

Hi all,

the idea I’d like to discuss is based on Gary Nebbett’s article “Booting
NT from floppies” which I suggest you read before reading on, see
http://groups.google.com/groups?selm=01bd598b%244000c380%241eadf6a8%40ca
opi2
Also, Gary was kind enough to provide me with an updated version of the
article and the source code to his NTBOOTDD.SYS (basically ramboot.sys
is no longer needed). The updated article and the source code are
attached at the bottom of this message, please scroll down first and
read this too.

OK, the original approach is based on MS-DOS and does some tricky stuff
using DOS’ ramdrive.sys to create a RAM disk that stays intact across a
warm boot off of which NBOOTDD.SYS later “serves” the OS.

Well, my magic eight ball says that MS-DOS is not so good. So I was
thinking about how one could get rid of DOS and make the approach work
using NT technology only and have it work off of a bootable CD.

The following is a bit lengthy and I hope I can make it clear:

Let’s just assume I manage to create a much stripped down NT/W2K/XP on a
small, separate FAT partition, just enough to log somebody on and run a
custom shell and that this setup is reasonably small enough, say around
40-50 MB (I must admit that I never really tried even with NT4 what Gary
is describing, but I trust him enough).

Next I would create an 1:1 image of the partition this Mini-NT is
installed on. One would then need a small separate physical hard disk
(no larger than 640 MB), partition and format it to have a single,
active primary FAT partition, make sure it has the NT boot sector on it
and place a boot.ini (restricting NT’s memory to an amount that allows
to load the image of the mini NT partition into memory), NTLDR, a
customized version of Gary’s NTBOOTDD.SYS and the image of the Mini-NT
partition on that primary partition. Then I would create a bootable CD
emulating a hard disk (see
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q167685 ) from
that small hard disk.

Maybe a picture makes it clear:


/ <br>| ±---------+ |
| | boot.ini | |
| | NTLDR | |
| | NTBOOTDD.SYS | |
| | minint.img | |
| ±--------------------------+ |
_________________________ /

The basic idea is to have the contents of the RAM disk that Gary
populates “at DOS run time” fixed in a file.

So when the machine boots from this CD, the CD becomes drive C: (because
it emulates a hard disk), the NT boot code in the boot sector of the
“hard disk CD’s” primary partition fires up NTLDR and NTLDR launches
NTBOOTDD.SYS… and BSODs :slight_smile:

No, obviously what NTBOOTDD.SYS needs to do first of all is to read
minint.img into memory, basically creating a RAM disk “on the fly” and
then just (?) continue like the original “Nebbett” NTBOOTDD.SYS, serving
read/write requests to the boot volume from the RAM disk.

So the big question is if within the limited NTLDR environment, there is
any possibility to open and read a file on the boot volume. NTLDR seems
to export functions BlGetFileInformation, BlLoadImage, BlOpen, BlRead,
BlSetFileInformation, BlWrite, BlClose etc. which sound promising but
are of course undocumented.

I also seem to remember that the NTLDR environment is “real mode BIOS”,
would it be possible to issue INT13 calls from NTBOOTDD.SYS to read from
the bootable CD? (INT13 should work because we have a hard disk
emulation)

Does anybody happen to have some documentation on the Bl* functions in
NTLDR?

More importantly, does what I’m describing sound even remotely possible
or do I just waste my time, am I missing something basic?

I would be most happy if some of the experts on this list could share
their thoughts on this. I must admit that I’m neither an SCSI nor a
driver expert in particular but do know people who would probably be
willing to take the challenge provided they can be convinced that it’s
not a dead end.

Thanks a lot!

Ralf.


================================================

Booting NT from Floppies
========================

When Microsoft knowledge base speaks of booting NT from floppies, it is
normally referring only to the first phase of booting - the loading of
ntldr (and perhaps ntbootdd.sys) and reading of boot.ini. Once these
components have been loaded from floppy, the rest of the files needed to
boot and start NT are loaded from a hard disk. This article describes
how to boot NT from floppies alone - it is not even necessary for a hard
disk to be present in the PC. The mini NT system which is started is
able to log users on/off and uses cmd.exe as the user’s shell.

The basic process which will be described is:

- Boot MSDOS and create a RAM disk
- Unzip a stripped down NT system on the RAM disk
- Reboot from the RAM disk

Using this technique it is possible to boot Windows NT 4.0 SP5 from four
1.44MB floppy disks in about 5 minutes. The four floppy disks do not
include utilities such as regedt32, chkdsk or winfile which might be
needed to repair a system, but these can be loaded from other floppies
after the boot is complete; alternatively if the NT installation on the
hard disk of the PC is not too badly damaged, it might be possible to
access these utilities from there.

The position of the RAM disk in memory is stored in three places:

- MSDOS config.sys (creates the RAM disk)
- boot.ini (/maxmem flag stops NT using RAM disk memory)
- ntbootdd.sys (the RAM disk device driver)

It is relatively easy to change its position (three edits and one build
would be needed), but reserving the memory above 16MB for the RAM disk
seems like a reasonable choice.

Since the RAM disk must be at least 12MB in size, the hardware
requirements for the PC to be bootable from floppies are a floppy drive
and at least 28MB of RAM (24MB might just be enough, if only 10-12MB of
RAM were to be reserved for NT). The smallest configuration that I have
tested is 16MB for NT and a 16MB RAM disk.

Creating the RAM disk
---------------------

The RAM disk can be created with the MSDOS ramdrive.sys. The following
two lines from config.sys reserve 16MB RAM for NT and create a 16MB RAM
disk:

DEVICE=HIMEM.SYS /int15=15360
DEVICE=RAMDRIVE.SYS 16384 /e

Assuming that config.sys does not place any additional demands on
extended memory, the RAM disk created starts exactly at 0x1000000 (the
16MB boundary). The MSDOS startup menu can be used to select larger RAM
disk sizes (up to the 32MB limit of ramdrive.sys) if the PC has enough
memory.

Content of the RAM disk
-----------------------

The files which need to be loaded into the RAM disks are listed below.
Some of the smaller files may be unnecessary (I did not test whether NT
would run without null.sys, for example, although I expect that it
would). The list includes atdisk.sys and atapi.sys so that any IDE/EIDE
disks (or CDROM
drives) can be accessed after the boot. If necessary, some SCSI
miniports for common SCSI disk devices could be added to the list.

Files used in approximate load order Reason for loading
------------------------------------ ------------------

\winnt\system32\ntoskrnl.exe Boot
\winnt\system32\hal.dll
\winnt\system32\config\system
\winnt\system32\l_intl.nls
\winnt\system32\c_1252.nls
\winnt\system32\c_850.nls
\winnt\system32\drivers\ntbootdd.sys Start = 0 (Boot) drivers
\winnt\system32\drivers\scsiport.sys
\winnt\system32\drivers\disk.sys \winnt\system32\drivers\class2.sys
\winnt\system32\drivers\fastfat.sys

\winnt\system32\ntdll.dll

\winnt\system32\drivers\atapi.sys Start = 1 (System)
drivers
\winnt\system32\drivers\atdisk.sys
\winnt\system32\drivers\floppy.sys
\winnt\system32\drivers\cdfs.sys \winnt\system32\drivers\cdrom.sys
\winnt\system32\drivers\fs_rec.sys
\winnt\system32\drivers\i8042prt.sys
\winnt\system32\drivers\kbdclass.sys
\winnt\system32\drivers\ksecdd.sys
\winnt\system32\drivers\mouclass.sys
\winnt\system32\drivers\msfs.sys \winnt\system32\drivers\npfs.sys
\winnt\system32\drivers\ntfs.sys \winnt\system32\drivers\null.sys
\winnt\system32\drivers\vga.sys \winnt\system32\drivers\videoprt.sys

\winnt\system32\smss.exe Started by ntoskrnl

\winnt\system32\advapi32.dll KnownDLLs
\winnt\system32\gdi32.dll
\winnt\system32\kernel32.dll
\winnt\system32\msvcrt.dll
\winnt\system32\rpcrt4.dll
\winnt\system32\user32.dll

\winnt\system32\config\sam
\winnt\system32\config\security \winnt\system32\config\software

\winnt\system32\win32k.sys Kmode SubSystems

\winnt\system32\csrss.exe Required SubSystems
\winnt\system32\csrsrv.dll
\winnt\system32\basesrv.dll
\winnt\system32\winsrv.dll
\winnt\system32\unicode.nls
\winnt\system32\locale.nls
\winnt\system32\ctype.nls
\winnt\system32\sortkey.nls
\winnt\system32\sorttbls.nls

\winnt\system32\vga.dll
\winnt\system32\kbdus.dll

\winnt\system32\winlogon.exe Started by CSRSS
\winnt\system32\userenv.dll
\winnt\system32\shell32.dll
\winnt\system32\comctl32.dll
\winnt\system32\netapi32.dll
\winnt\system32\netrap.dll
\winnt\system32\samlib.dll
\winnt\system32\winmm.dll
\winnt\system32\msgina.dll
\winnt\system32\rpcltc1.dll
\winnt\system32\rpclts1.dll

\winnt\system32\services.exe Started by Winlogon
\winnt\system32\umpnpmgr.dll

\winnt\system32\lsass.exe Started by Winlogon
\winnt\system32\lsasrv.dll
\winnt\system32\samsrv.dll
\winnt\system32\msprivs.dll
\winnt\system32\netlogon.dll
\winnt\system32\msv1_0.dll
\winnt\system32\security.dll
\winnt\system32\wsock32.dll
\winnt\system32\ws2_32.dll
\winnt\system32\ws2help.dll

\winnt\system32\cmd.exe Started by Winlogon
\winnt\system32\mpr.dll (if Userinit = “cmd”)

The list includes four registry hives, some of which are often quite
large. Any source of these hives is acceptable and a good choice is the
hives created during a new installation of NT (the hives are still quite
small at this point). The drawbacks of using large hives are that more
floppies may be needed to contain them and the corresponding additional
delay when copying them to the RAM disk.

Assuming that the files listed above are zipped into a file called
nt.zip, then the contents of the four floppies are:

Disk1 Disk2 Disk3 Disk4

(MSDOS boot sector) (NT boot
sector)
io.sys nt.zip nt.zip boot.ini
msdos.sys
ntbootdd.sys
command.com
ntdetect.com
config.sys ntldr
autoexec.bat
reboot.com
himem.sys nt.zip
ramdrive.sys
unzip.exe
nt.zip

and boot.ini contains:

[boot loader]
default=scsi(0)disk(0)rdisk(0)partition(1)\winnt
[operating systems]
scsi(0)disk(0)rdisk(0)partition(1)\winnt=“Mini NT 4.0” /maxmem=16
/basevideo

Registry Settings
-----------------

There are a number of values in the system registry hive which need
modification:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit
should be set to “cmd” so that a command window will be started as the
user’s shell.

HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage\ACP and
HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage\OEMCP should either
be set to 1252 and 850 respectively, or the files c_1252.nls and
c_850.nls in the zip file should be replaced by code page files which
match the existing registry values.

HKLM\SYSTEM\CurrentControlSet\Control\CrashControl\CrashDumpEnabled and
HKLM\SYSTEM\CurrentControlSet\Control\CrashControl\LogEvent should be
set to zero. This prevents the system from preparing for a crash dump.
As a side effect of making the RAM disk appear to the system as a hard
disk, “partition0” of the RAM disk appears to contain a FAT file system;
ntoskrnl expects this partition to contain a RAW file system and this
mismatch leads to a crash when preparing for a crash dump.

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory
Management\PagingFiles should be set to “C:\winnt\system32\temppf.sys 2
8”. This will prevent winlogon from filling the RAM disk with a
temporary paging file.

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory
Management\SystemPages should be set to 0x3000. This will ensure that
there are enough system PTEs to map a 32MB RAM disk.

HKLM\SYSTEM\CurrentControlSet\Services should be checked for “Start=0”
services. Only ntbootdd and disk should start at boot time; other
services which have “Start=0” should be modified to “Start=1”. The entry
for ntbootdd can be created manually if necessary, taking another SCSI
miniport as template (e.g. Aha154x).

Booting from the RAM Disk
-------------------------

After the RAM disk has been loaded, the next step is to reboot the PC
from a “normal” NT boot floppy (Disk4 in the table above) whose boot.ini
selects the RAM disk as the boot disk. The only problem is that the
normal Ctrl-Alt-Del reboot zeros memory, erasing the contents of the RAM
disk. Fortunately, there is a method of rebooting without zeroing memory
- by executing the Intel x86 instruction “int 19h” to invoke the
bootstrap loader service; quoting from Ralf Brown’s “Interrupt List”:

“This interrupt reboots the system without clearing memory or
restoring
interrupt vectors.”

A two byte .com file containing the values 0xCD, 0x19 does the trick
(these values being the hexadecimal code for “int 19h”); a suitable name
for this file is reboot.com.

Ntbootdd
--------

If boot.ini selects a boot device whose ARC name starts with “scsi”,
then there must be a file in the same directory as boot.ini with the
name “ntbootdd.sys”. Normally ntbootdd.sys is a renamed copy of the
appropriate SCSI miniport driver for the hard disks of the system, but
when booting from the RAM disk, ntbootdd.sys is built from ntbootdd.cpp
(Listing 1).

ntbootdd.sys appears twice on the boot floppies: once on the “normal” NT
boot floppy (where it is used by ntldr to load the initial system
components) and once in the zip file (from whence it is later loaded and
used by ntoskrnl to access the RAM disk). The same file is used in both
places, but this is not compulsory; there are some differences between
the two environments into which ntbootdd.sys is loaded and if necessary
this could be compensated for by alternative versions of the code.

Important environmental differences are that the ntldr implementation of
ScsiPortFreeDeviceBase() does nothing and the implementation of
ScsiPortGetDeviceBase() can map a maximum of 4MB and has problems
mapping non-paged aligned regions that straddle pages. The ntldr
implementation of
ScsiPortGetDeviceBase() can be called from the HwScsiStartIo routine,
but the ntoskrnl implementation cannot (because of IRQL considerations).
ntbootdd.sys detects which environment it is in (by examining the first
sector of the RAM disk) and adapts its behaviour accordingly.

The 4MB mapping limit places an upper bound on how much data
ntbootdd.sys can load; excluding the system hive, about 1.3MB needs to
be mapped so the system hive can be as large as 2.5MB (the system hive
can be reduced to about 64kB by deleting unnecessary keys and values).

Ntbootdd was debugged by using the checked version of ntldr; when using
the checked version, the ScsiPort routine ScsiDebugPrint() is available
and the level of output is controlled by the [debug] section in
boot.ini. Setting scsidebug=3 produces a great deal of output;
scsidebug=2 is much more manageable. Since the debug output is only
visible on the screen and scrolls very quickly, it is often helpful to
follow a ScsiDebugPrint() with code
like:

for (int i = 0; i < 2000; i++) ScsiPortStallExecution(1000);

Since the RAM disk does not contain a partition table, the initial
version of ntbootdd emulated a floppy device. This mostly worked, but
attempts to create paging files on the RAM disk failed with the error
STATUS_FLOPPY_VOLUME (“The paging file cannot be created on a floppy
diskette”). The current version emulates a hard disk and modifies the
first sector of the RAM disk to include a partition table. Another
change is needed to the first sector of the RAM disk because the MDDOS
ramdrive.sys does not format the BIOS parameter blocks in quite the same
way as is expected of a FAT file system; it is necessary to explicitly
set the “Large Sectors” field (offset 0x20) to zero, otherwise the RAM
disk is not recognized as containing a FAT file system.

Drive Letters
-------------

The RAM disk is assigned the drive letter C:. Any other disks for which
drivers have been loaded are assigned drive letters, but these letters
will probably differ from the normal assignment for any particular PC.
This is because C: is already taken, there are no sticky drive letter
assignments and drivers for some disks are not loaded or are loaded in a
different order.

Keyboard Layout
---------------

Information about the keyboard layout is stored in the registry on a
per-user basis. When no user is logged in or the logged in user’s hive
is unavailable, the keyboard layout information is retrieved from
HKEY_USERS.Default (which is stored in the hive named “default”). Since
neither the default hive nor any user hives are included in the zip
file, the system defaults the keyboard layout. Naturally, the default
keyboard layout is a US keyboard layout. If this is a problem, a
suitable default hive could be included in the zip file.

=============================<ntbootdd.cpp>=============================

extern “C” {
#include “miniport.h”
#include “scsi.h”
}
#include <memory.h>

#pragma pack(push, 1)

typedef struct PTABLE {
UCHAR Flag;
UCHAR Chs1[3];
UCHAR Type;
UCHAR Chs2[3];
ULONG Start;
ULONG Size;
} *PPTABLE;

typedef struct FAT {
UCHAR Jump[3];
UCHAR System[8];
USHORT BytesPerSector;
UCHAR SectorsPerCluster;
USHORT ReservedSectors;
UCHAR FatCopies;
USHORT RootEntries;
USHORT SmallSectors;
UCHAR MediaType;
USHORT SectorsPerFat;
USHORT SectorsPerTrack;
USHORT Heads;
ULONG HiddenSectors;
ULONG LargeSectors;
UCHAR Disk;
UCHAR Flags;
UCHAR Signature;
ULONG SerialNumber;
UCHAR Label[11];
UCHAR Format[8];
UCHAR Code[0x17A];
ULONG DiskSignature;
UCHAR Reserved;
UCHAR BootPartition;
PTABLE Table[4];
USHORT BootSignature;
} *PFAT;

#pragma pack(pop)

typedef PVOID PPVOID;

const ULONG PageSize = 0x1000;
const ULONG DiskBase = 0x1000000;

ULONG BytesPerBlock, Blocks;
PCHAR MapBase;
BOOLEAN Boot;

ULONG ChunkSize(ULONG Offset, ULONG Length, ULONG Position)
{
ULONG X = PageSize - ((Offset + Position) & (PageSize - 1));
ULONG Y = Length - Position;

return X < Y ? X : Y;
}

PVOID MapPage(PVOID DeviceExtension, ULONG Address)
{
ULONG X = (Address - DiskBase) / PageSize;

if (PPVOID(DeviceExtension)[X] == 0)

(PPVOID(DeviceExtension) + X) =

ScsiPortGetDeviceBase(DeviceExtension, Internal, 0,

ScsiPortConvertUlongToPhysicalAddress(Address & ~(PageSize - 1)),
PageSize, FALSE);

return PCHAR(PPVOID(DeviceExtension)) + (Address & (PageSize -
1)); }

PVOID MapAddress(PVOID DeviceExtension, ULONG Address, ULONG Size) {
return ScsiPortGetDeviceBase(DeviceExtension, Internal, 0,

ScsiPortConvertUlongToPhysicalAddress(Address), Size, FALSE); }

BOOLEAN StartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb) {
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
Srb->ScsiStatus = SCSISTAT_GOOD;

if (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Lun == 0) {

switch (Srb->Cdb[0]) {

case SCSIOP_INQUIRY:
{
memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
PINQUIRYDATA Inq = PINQUIRYDATA(Srb->DataBuffer);
Inq->DeviceType = DIRECT_ACCESS_DEVICE;
Inq->DeviceTypeQualifier = DEVICE_CONNECTED;
memcpy(Inq->VendorId, "NEBBETT ", sizeof Inq->VendorId);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_MODE_SENSE:
{
memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
PMODE_PARM_READ_WRITE_DATA Mode =
PMODE_PARM_READ_WRITE_DATA(Srb->DataBuffer);
Mode->ParameterListHeader.ModeDataLength = sizeof *Mode
- 1;
Mode->ParameterListHeader.BlockDescriptorLength = sizeof
Mode->ParameterListBlock;
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_TEST_UNIT_READY:
case SCSIOP_MEDIUM_REMOVAL:
{
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_READ_CAPACITY:
{
ULONG X = BytesPerBlock;

REVERSE_BYTES(&PREAD_CAPACITY_DATA(Srb->DataBuffer)->BytesPerBlock, &X);
X = Blocks - 1;

REVERSE_BYTES(&PREAD_CAPACITY_DATA(Srb->DataBuffer)->LogicalBlockAddress
, &X);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_READ:
{
ULONG X;
REVERSE_BYTES(&X,
&PCDB(Srb->Cdb)->CDB10.LogicalBlockByte0);

if (Boot) {
X = X * BytesPerBlock + DiskBase;
for (ULONG Z, Y = 0; Y < Srb->DataTransferLength; Y
+= Z) {
Z = ChunkSize(X, Srb->DataTransferLength, Y);
memcpy(PCHAR(Srb->DataBuffer) + Y,
MapPage(DeviceExtension, X + Y), Z);
}
}
else
memcpy(Srb->DataBuffer, MapBase + X * BytesPerBlock,
Srb->DataTransferLength);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

case SCSIOP_WRITE:
{
ULONG X;
REVERSE_BYTES(&X,
&PCDB(Srb->Cdb)->CDB10.LogicalBlockByte0);

if (Boot) {
X = X * BytesPerBlock + DiskBase;
for (ULONG Z, Y = 0; Y < Srb->DataTransferLength; Y
+= Z) {
Z = ChunkSize(X, Srb->DataTransferLength, Y);
memcpy(MapPage(DeviceExtension, X + Y),
PCHAR(Srb->DataBuffer) + Y, Z);
}
}
else
memcpy(MapBase + X * BytesPerBlock, Srb->DataBuffer,
Srb->DataTransferLength);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
break;

default:
{
ScsiDebugPrint(1, “StartIo Function Execute %x, Flags
%lx, Len %lx\n”,
int(Srb->Cdb[0]), Srb->SrbFlags,
Srb->DataTransferLength);
// for (int i = 0; i < 2000; i++)
ScsiPortStallExecution(1000);
}
break;
}
}

ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
ScsiPortNotification(NextRequest, DeviceExtension);

return TRUE;
}

ULONG FindAdapter(PVOID DeviceExtension, PVOID, PVOID, PCHAR,
PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN
Again) {
PFAT Fat = PFAT(MapAddress(DeviceExtension, DiskBase, sizeof
(FAT)));

Boot = Fat->LargeSectors != 0;

BytesPerBlock = Fat->BytesPerSector;
Blocks = Fat->SmallSectors;

Fat->LargeSectors = 0;
Fat->BootSignature = 0xAA55;
Fat->Table[0].Type = 4;
Fat->Table[0].Start = 0;
Fat->Table[0].Size = Blocks;
Fat->Table[1].Type = Fat->Table[2].Type = Fat->Table[3].Type = 0;

ScsiPortFreeDeviceBase(DeviceExtension, Fat);

if (!Boot) MapBase = PCHAR(MapAddress(DeviceExtension, DiskBase,
Blocks * BytesPerBlock));

ConfigInfo->NumberOfBuses = 1;
ConfigInfo->MaximumNumberOfTargets = 1;

*Again = FALSE;

return SP_RETURN_FOUND;
}

BOOLEAN ResetBus(PVOID DeviceExtension, ULONG PathId)
{
ScsiPortCompleteRequest(DeviceExtension, UCHAR(PathId), SP_UNTAGGED,
SP_UNTAGGED,
SRB_STATUS_BUS_RESET);

return TRUE;
}

BOOLEAN Initialize(PVOID)
{
return TRUE;
}

extern “C”
ULONG DriverEntry(PVOID DriverObject, PVOID RegistryPath)
{
HW_INITIALIZATION_DATA Hid = {sizeof Hid};

Hid.AdapterInterfaceType = Isa;
Hid.DeviceExtensionSize = 0x2000 * sizeof (PVOID);
Hid.MapBuffers = TRUE;

Hid.HwFindAdapter = FindAdapter;
Hid.HwInitialize = Initialize;
Hid.HwResetBus = ResetBus;
Hid.HwStartIo = StartIo;

return ScsiPortInitialize(DriverObject, RegistryPath, &Hid, 0); }


You are currently subscribed to ntdev as: xxxxx@storagecraft.com To
unsubscribe send a blank email to %%email.unsub%%</memory.h></ntbootdd.cpp>

Alberto,

you wrote on Monday, May 06, 2002, 23:13:13:

MA> It would be great to be able to boot from a 256Mb or 512Mb
MA> CompactFlash, if nothing else, it fits in my wallet.

I have a few machines with mainboards/BIOSes that supposedly support
booting from an USB “thumb drive”. But I’ve never tried it.

Ralf.

Jamey,

you wrote on Monday, May 06, 2002, 23:29:04:

JK> Int 13h will work on El Torito emulated hard disk drives.

So how does one issue an INT13h from a driver like NTBOOTDD.SYS?

JK> How about filtering int 13h and intercepting writes?

Maybe, but in any event I first need to get the image into RAM.

Ralf.