Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions build/usb-boot-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
dd if=/dev/zero of=usbdisk.img bs=1M count=512
echo 'start=2048, type=c' | sfdisk usbdisk.img
LOOP=$(sudo losetup -f --show -P usbdisk.img)
sudo mkfs.vfat -F 32 ${LOOP}p1
sudo losetup -d $LOOP


qemu-system-x86_64 -machine q35,accel=kvm -m 2G \
-boot d \
-cdrom ZealOS-PublicDomain-BIOS-2026-07-24-03_43_40.iso \
-device qemu-xhci,id=xhci \
-drive if=none,id=ub,format=raw,file=usbdisk.img \
-device usb-storage,bus=xhci.0,drive=ub


CopyTree("::/", "V:/"); # copies the whole CD to the stick — wait for it, takes a bit
Dir("V:/"); # should now list Boot, Kernel, System, Compiler, Home, etc.
BootHDIns('V'); # recompiles kernel on V: (few min), writes FAT32 boot record
BootMHDIns('V'); # MBR chain-loader

# At the BootHDIns config prompt, enter V for boot drive, ENTER through the rest.

qemu-system-x86_64 -machine q35,accel=kvm -m 2G \
-device qemu-xhci,id=xhci \
-drive if=none,id=ub,format=raw,file=usbdisk.img \
-device usb-storage,bus=xhci.0,drive=ub \
-device usb-kbd,bus=xhci.0 -device usb-mouse,bus=xhci.0
43 changes: 38 additions & 5 deletions src/Kernel/BlkDev/DiskAddDev.ZC
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,29 @@ U0 BlkDevLockFwdingSet(CBlkDev *bd)
}
}

public Bool BlkDevRawBlksRead(CBlkDev *bd, U8 *buf, I64 blk, I64 count)
{//Whole-device read, bypassing partition bounds. Dispatches on BlkDev type.
//Used by $LK,"BlkDevAdd",A="MN:BlkDevAdd"$() partition scans and boot-loader installers.
if (bd->type == BDT_USB)
{
if (fp_usb_msd_blks_read)
return (*fp_usb_msd_blks_read)(bd, buf, blk, count);
return FALSE;
}
return AHCIAtaBlksRead(bd, buf, blk, count);
}

public Bool BlkDevRawBlksWrite(CBlkDev *bd, U8 *buf, I64 blk, I64 count)
{//Whole-device write, bypassing partition bounds. Dispatches on BlkDev type.
if (bd->type == BDT_USB)
{
if (fp_usb_msd_blks_write)
return (*fp_usb_msd_blks_write)(bd, buf, blk, count);
return FALSE;
}
return AHCIAtaBlksWrite(bd, buf, blk, count);
}

I64 BlkDevAdd(CBlkDev *bd, I64 prt_num=I64_MIN, Bool whole_drive, Bool make_free)
{//It will mount just one partition of prt_num>=0.
//When repartitioing whole drive, whole_drive=TRUE.
Expand Down Expand Up @@ -68,6 +91,7 @@ I64 BlkDevAdd(CBlkDev *bd, I64 prt_num=I64_MIN, Bool whole_drive, Bool make_free
break;

case BDT_ATA:
case BDT_USB:
drive->drive_signature = DRIVE_SIGNATURE_VAL; //Temporarily validate
if (!BlkDevInit(bd))
drive->drive_signature = 0; //Revoke validation
Expand All @@ -83,14 +107,14 @@ I64 BlkDevAdd(CBlkDev *bd, I64 prt_num=I64_MIN, Bool whole_drive, Bool make_free
drive->size = bd->max_blk + 1 - bd->drv_offset;
//The following read is a test read.
//if it hangs, the drive is not supported.
AHCIAtaBlksRead(bd, &mbr, 0, 1);
BlkDevRawBlksRead(bd, &mbr, 0, 1);
break;
}
offset = 0;
ext_base = INVALID_CLUS;
while (prt_num < 0 || num <= prt_num)
{
AHCIAtaBlksRead(bd, &mbr, offset, 1);
BlkDevRawBlksRead(bd, &mbr, offset, 1);
if (mbr.signature != 0xAA55)
break;
j = -1;
Expand Down Expand Up @@ -121,7 +145,7 @@ I64 BlkDevAdd(CBlkDev *bd, I64 prt_num=I64_MIN, Bool whole_drive, Bool make_free
case MBR_PT_FAT32d:
case MBR_PT_FAT32e:
case MBR_PT_FAT32f:
AHCIAtaBlksRead(bd, &br, drive->drv_offset, 1);
BlkDevRawBlksRead(bd, &br, drive->drv_offset, 1);

drive->drive_signature = DRIVE_SIGNATURE_VAL;
drive->prt_num = num;
Expand Down Expand Up @@ -238,21 +262,30 @@ U0 BlkDevsInitAll()
"\nAHCIInit;\n";
AHCIInit;

if (!blkdev.ahci_hba)
"\nUsbBootInit;\n";
i = UsbBootInit;

if (!blkdev.ahci_hba && !i)
{
"\nZealOS requires AHCI.\n\n"
"\nZealOS requires AHCI or a USB boot drive.\n\n"
"If in IDE compatibility mode, switch to SATA mode.\n"
"If running in a VM, ensure disks are organized under a SATA controller.\n\n"
"Rebooting in 10 seconds...\n";
Sleep(10*1000);
Reboot;
}

//Config mount code may reference missing hardware (e.g. DVD-configured kernel
//booted from a USB stick); failures fall through to UsbBootDriveFallback().
#exe {
StreamPrint("try {");
if (kernel_config->opts[CONFIG_MOUNT_AHCI_AUTO])
StreamPrint("MountAHCIAuto;");
StreamPrint("#exe {Option(OPTf_WARN_PAREN, OFF);}");
StreamDoc(kernel_config->add_dev);
StreamPrint("#exe {Option(OPTf_WARN_PAREN, ON);}");
StreamPrint("} catch { Fs->catch_except = TRUE; \"Boot mount code failed.\\n\"; }");
};

UsbBootDriveFallback;
}
14 changes: 14 additions & 0 deletions src/Kernel/BlkDev/DiskBlk.ZC
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ Bool BlkRead(CDrive *drive, U8 *buf, I64 blk, I64 count)
case BDT_ATAPI:
res = AHCIAtapiRBlks(drive, buf, blk, count);
break;

case BDT_USB:
if (fp_usb_msd_blks_read)
res = (*fp_usb_msd_blks_read)(bd, buf, blk, count);
else
res = FALSE;
break;
}
bd->last_time = tS;
if (bd->flags & BDF_READ_CACHE)
Expand Down Expand Up @@ -117,6 +124,13 @@ Bool BlkWrite(CDrive *drive, U8 *buf, I64 blk, I64 count)
case BDT_ATAPI:
res = AHCIAtaWBlks(drive, buf, blk, count);
break;

case BDT_USB:
if (fp_usb_msd_blks_write)
res = (*fp_usb_msd_blks_write)(bd, buf, blk, count);
else
res = FALSE;
break;
}
bd->last_time = tS;
if (bd->flags & BDF_READ_CACHE)
Expand Down
7 changes: 7 additions & 0 deletions src/Kernel/BlkDev/DiskBlkDev.ZC
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ Bool BlkDevInit(CBlkDev *bd)
if (res = AHCIAtaInit(bd))
drive->size = bd->max_blk + 1;
break;

case BDT_USB:
//USB mass storage driver fills in max_blk before BlkDevAdd().
bd->max_reads = 64;
bd->max_writes = 64;
res = TRUE;
break;
}
if (res && bd->flags & BDF_READ_CACHE)
DiskCacheInvalidate(drive);
Expand Down
6 changes: 4 additions & 2 deletions src/Kernel/BlkDev/DiskDrive.ZC
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,10 @@ I64 Letter2BlkDevType(U8 drv_let)
return BDT_ISO_FILE_READ;
if ('Q' <= drv_let <= 'S')
return BDT_ISO_FILE_WRITE;
if ('T' <= drv_let <= 'Z')
if ('T' <= drv_let <= 'U')
return BDT_ATAPI;
if ('V' <= drv_let <= 'Z')
return BDT_USB;

return BDT_NULL;
}
Expand Down Expand Up @@ -347,7 +349,7 @@ U8 *DriveModelNum(U8 drv_let=0)
return res;
}

U8 blkdev_text_attr[BDT_TYPES_NUM] = {BLACK, LTCYAN, WHITE, LTGREEN, LTRED, LTBLUE};
U8 blkdev_text_attr[BDT_TYPES_NUM] = {BLACK, LTCYAN, WHITE, LTGREEN, LTRED, LTBLUE, LTPURPLE};
U8 drv_text_attr[3] = {BLACK, BLUE, RED};

U8 DriveTextAttrGet(U8 drv_let=0)
Expand Down
5 changes: 3 additions & 2 deletions src/Kernel/BlkDev/DiskFormat.ZC
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ Bool DriveTypeSet(U8 drv_let, I64 type=FSt_REDSEA)
switch (bd->type)
{
case BDT_ATA:
case BDT_USB:
offset = 0;
ext_base = INVALID_CLUS;
while (TRUE)
{
AHCIAtaBlksRead(bd, &mbr, offset, 1);
BlkDevRawBlksRead(bd, &mbr, offset, 1);
j =- 1;
for (i = 0; i < 4; i++)
{
Expand Down Expand Up @@ -45,7 +46,7 @@ Bool DriveTypeSet(U8 drv_let, I64 type=FSt_REDSEA)
throw('Drive');
}
mbr.p[i].active = 0x80;
AHCIAtaBlksWrite(bd, &mbr, offset, 1);
BlkDevRawBlksWrite(bd, &mbr, offset, 1);
return TRUE;
}
drv_num++;
Expand Down
3 changes: 2 additions & 1 deletion src/Kernel/KDefine.ZC
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ U0 SysDefinesLoad()
"ATA\0"
"FILE_READ\0"
"FILE_WRITE\0"
"ATAPI\0");
"ATAPI\0"
"USB\0");

DefineListLoad("ST_DRIVE_TYPES",
"NULL\0"
Expand Down
2 changes: 2 additions & 0 deletions src/Kernel/KExterns.ZC
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import Bool Ed(U8 *link_st=NULL, I64 edf_dof_flags=0);

extern U0 SysErr(U8 *format, ...);
extern U0 SysLog(U8 *format, ...);
extern I64 UsbBootInit();
extern U0 UsbBootDriveFallback();

extern I64 MemBIOSTotal();

Expand Down
3 changes: 3 additions & 0 deletions src/Kernel/KGlobals.ZC
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ CMouseHardStateGlobals mouse_hard, mouse_hard_last;
CScreenCastGlobals screencast;
CTextGlobals text;

Bool (*fp_usb_msd_blks_read )(CBlkDev *bd, U8 *buf, I64 blk, I64 count); //Set by USB mass storage driver.
Bool (*fp_usb_msd_blks_write)(CBlkDev *bd, U8 *buf, I64 blk, I64 count);

U8 *(*fp_getstr2)(I64 flags=0);
U0 (*fp_update_ctrls)(CTask *task);
CDoc *(*fp_doc_put)(CTask *task=NULL);
Expand Down
2 changes: 2 additions & 0 deletions src/Kernel/KMain.ZC
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ U0 KMain()
Spawn(&MouseHardDriverInstall);
"Spawn(&MouseRawWatcher,, \"MouseRawWatcher\");\n";
Spawn(&MouseRawWatcher,, "MouseRawWatcher");
"Spawn(&UsbTaskMain,, \"USB\");\n";
Spawn(&UsbTaskMain,, "USB");

"Load(\"Compiler\");\n";
Cd("/Compiler");
Expand Down
1 change: 1 addition & 0 deletions src/Kernel/Kernel.PRJ
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "MultiProc"
#include "EdLite"
#include "BlkDev/MakeBlkDev"
#include "Usb/MakeKUsb"
#include "FunSeg"
#include "SMBIOS"
#include "KMain"
Expand Down
3 changes: 2 additions & 1 deletion src/Kernel/KernelA.HH
Original file line number Diff line number Diff line change
Expand Up @@ -3319,7 +3319,8 @@ public class CDirEntry
#define BDT_ISO_FILE_READ 3
#define BDT_ISO_FILE_WRITE 4
#define BDT_ATAPI 5
#define BDT_TYPES_NUM 6
#define BDT_USB 6
#define BDT_TYPES_NUM 7

#define BDf_REMOVABLE 0
#define BDf_INITIALIZED 1
Expand Down
2 changes: 2 additions & 0 deletions src/Kernel/KernelC.HH
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ public extern CBlkDev *BlkDevCheck(CBlkDev *bd, Bool except=TRUE);
public extern U0 BlkDevDel( CBlkDev *bd);
public extern Bool BlkDevLock( CBlkDev *bd);
public extern CBlkDev *BlkDevNextFreeSlot(U8 first_drive_let, I64 type);
public extern Bool (*fp_usb_msd_blks_read )(CBlkDev *bd, U8 *buf, I64 blk, I64 count);
public extern Bool (*fp_usb_msd_blks_write)(CBlkDev *bd, U8 *buf, I64 blk, I64 count);
public extern Bool BlkDevUnlock(CBlkDev *bd, Bool reset=FALSE);
public extern U0 BlkDevsRelease();
public extern U0 BlkDevRep();
Expand Down
Loading
Loading