diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 76b6726..dcdbc0d 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -7,6 +7,7 @@ - [modifications](modifications.md) - [memory map](memory_map.md) - [HRB file format](hrb_format.md) + - [BPB](bpb.md) - [Q&A](Q&A.md) - [references](references.md) diff --git a/docs/bpb.md b/docs/bpb.md new file mode 100644 index 0000000..ef564ff --- /dev/null +++ b/docs/bpb.md @@ -0,0 +1,115 @@ +# BIOS Parameter Block (BPB) structure + +- ORG 0x7c00: This sets the origin of the code to memory address 0x7c00. In the x86 architecture, the BIOS loads the boot sector of a bootable drive to this address and then transfers control to it. + +- JMP SHORT entry: A jump instruction to the entry label. This is a typical starting point in a boot sector to jump over the BPB structure and continue execution. entry is a label that would be defined later in the code. + +- NOP: A no-operation instruction, often used for padding. + +## Floppy Disk + +| Offset in Boot Sector | Length in Bytes | Mnemonic | Data type | Data content | Data comment | +| --------------------- | --------------- | ------------------------------------------ | --------- | ------------- | ------------------------------------------------------------ | +| 03 | 8 | OEM_Identifier | DB | "HARIBOTE" | You can freely write the name of the boot sector (8 bytes) | +| 0B | 2 | BytesPerSector | DW | 512 | Size of one sector (must be 512) | +| 0D | 1 | SectorsPerCluster | DB | 1 | Size of a cluster (must be 1 sector) | +| 0E | 2 | ReservedSectors | DW | 1 | Where the FAT starts (normally set to the first sector) | +| 10 | 1 | NumberOfFATs | DB | 2 | Number of FATs (must be 2) | +| 11 | 2 | RootEntries | DW | 224 | Size of the root directory area (usually set to 224 entries) | +| 13 | 2 | NumberOfSectors | DW | 2880 | Size of this drive (must be 2880 sectors) | +| 15 | 1 | MediaDescriptor | DB | 0xf0 | Type of media (must be 0xf0) | +| 16 | 2 | SectorsPerFAT | DW | 9 | Length of FAT area (must be 9 sectors) | +| 18 | 2 | SectorsPerHead | DW | 18 | Number of sectors per track (must be 18) | +| 1A | 2 | HeadsPerCylinder | DW | 2 | Number of heads (must be 2) | +| 1C | 4 | HiddenSectors | DD | 0 | Must be 0 as partitions are not used here | +| 20 | 4 | BigNumberOfSectors | DD | 2880 | Write the size of this drive again | +| 24 | 1 | BIOS drive number | DB | 0 | | +| 25 | 1 | Reserved | DB | 0 | | +| 26 | 1 | Extended Boot Record signature = 29h | DB | 0x29 | Apparently, it's good to set this value | +| 27 | 4 | Serial Number | DD | 0xffffffff | Probably the volume serial number | +| 2B | 11 | Volume label | DB | "HARIBOTEOS " | Name of the disk (11 bytes) | +| 36 | 8 | System Identifier (FAT12, FAT16, or FAT32) | DB | "FAT12 " | Name of the format (8 bytes) | + +## USB drive + +| Offset in Boot Sector | Length in Bytes | Mnemonic | Data def | Data type | Data content | +| --------------------- | --------------- | ------------------------------------------ | -------------- | --------- | -------------------------------------------------------------- | +| 03 | 8 | OEM_Identifier | BS_OEMName | DB | "HARIBOTE" ; [8 bytes] boot sector name | +| 0B | 2 | BytesPerSector | BPB_BytsPerSec | DW | 0x0200 ; the size of a sector (should be 512=0x0020) | +| 0D | 1 | SectorsPerCluster | BPB_SecPerClus | DB | 0x01 ; the size of a cluster (should be 1 sector) | +| 0E | 2 | ReservedSectors | BPB_RsvdSecCnt | DW | 0x0001 ; where FAT begins (usually from 1st sector) | +| 10 | 1 | NumberOfFATs | BPB_NumFATs | DB | 0x02 ; the number of FATs (should be 2) | +| 11 | 2 | RootEntries | BPB_RootEntCnt | DW | 0x0000 ; the size of root directory area (usually 224 entries) | +| 13 | 2 | NumberOfSectors | BPB_TotSec16 | DW | 0x0000 ; the size of this drive (should be 2880 sectors) | +| 15 | 1 | MediaDescriptor | BPB_Media | DB | 0xf8 ; the type of media (Any Hard Drive) | +| 16 | 2 | SectorsPerFAT | BPB_FATSz16 | DW | 0x0000 ; the length of FAT area (should be 9 sectors) | +| 18 | 2 | SectorsPerHead | BPB_SecPerTrk | DW | 0xffff ; the number of sectors per a track (should be 18) | +| 1A | 2 | HeadsPerCylinder | BPB_NumHeads | DW | 0x0001 ; the number of heads (should be 2) | +| 1C | 4 | HiddenSectors | BPB_HiDDSec | DD | 0x00000000 ; should be zero since we will not use partition | +| 20 | 4 | BigNumberOfSectors | BPB_TotSec32 | DD | 0x00ee5000 ; the size of this drive (again) | +| 24 | 4 | BigSectorsPerFAT | BPB_FATSz32 | DD | 0x000000ed | +| 28 | 2 | ExtFlags | BPB_ExtFlags | DW | 0x0000 | +| 2A | 2 | FSVersion | BPB_FSVer | DW | 0x0000 | +| 2C | 4 | RootDirectoryStart | BPB_RootClus | DD | 0x00000000 | +| 30 | 2 | FSInfoSector | BPB_FSInfo | DW | 0x0001 | +| 32 | 2 | BackupBootSector | BPB_BkBootSec | DW | 0x0000 | +| 34 | 12 | Reserved | | | TIMES 12 DB 0 ; BPB_Reserved | +| 40 | 1 | BIOS drive number | BS_DrvNum | DB | 0x80 | +| 41 | 1 | Reserved | BS_Reserved1 | DB | 0x00 | +| 42 | 1 | Extended Boot Record signature = 29h | BS_BootSig | DB | 0x29 | +| 43 | 4 | Serial Number | BS_VolID | DD | 0xffffffff | +| 47 | 11 | Volume label | BS_VolLab | DB | "HARIBOTEOS " ; [11 bytes] the name of the disk | +| 52 | 8 | System Identifier (FAT12, FAT16, or FAT32) | BS_FilSysType | DB | "FAT32 " ; [8 bytes] the name of the format | + +### Calculations and Explanations + +1. Bytes per Sector (BPB_BytsPerSec): + + - Fixed at 512 bytes per sector (0x0200). + +2. Sectors per Cluster (BPB_SecPerClus): + + - Typically 8 sectors per cluster (0x08) for FAT32 on a large drive like 8GB. + +3. Reserved Sectors Count (BPB_RsvdSecCnt): + + - Typically 32 reserved sectors (0x0020) for FAT32. + +4. Total Sectors (BPB_TotSec32): + + - 8GB drive = 8 \* 1024 \* 1024 \* 1024 bytes. + - Total sectors = 8 \* 1024 \* 1024 \* 1024 / 512 = 16,777,216 sectors. + - However, since the actual usable sectors are a bit less due to reserved sectors, let's use a practical value of 7,745,024 sectors (0x00EE5000). + +5. Sectors per FAT (BPB_FATSz32): + + This requires a bit of calculation: + + - Number of Clusters = (Total Sectors - Reserved Sectors - (Number of FATs \* Sectors per FAT) - Root Directory Sectors) / Sectors per Cluster + + Estimating Sectors per FAT: + + - Assume 8,000 sectors per FAT initially (0x1F40). + + Adjust if necessary after calculating the number of clusters. + +6. Sectors per Track (BPB_SecPerTrk) and Number of Heads (BPB_NumHeads): + + - These are more relevant to older BIOS geometry but typically set as 63 sectors per track and 255 heads for modern USB drives. + +7. Hidden Sectors (BPB_HiDDSec): + + - Usually set to 0. + +8. FAT32-specific fields: + + - `BPB_RootClus` typically starts at cluster 2. + - `BPB_FSInfo` usually 1. + - `BPB_BkBootSec` usually 6. + +## References + +- https://en.wikipedia.org/wiki/BIOS_parameter_block +- https://averstak.tripod.com/fatdox/bootsec.htm +- https://academy.cba.mit.edu/classes/networking_communications/SD/FAT.pdf +- https://wiki.osdev.org/FAT diff --git a/projects/31_day/harib28a/Makefile b/projects/31_day/harib28a/Makefile index 48f3a29..7f86033 100644 --- a/projects/31_day/harib28a/Makefile +++ b/projects/31_day/harib28a/Makefile @@ -203,10 +203,10 @@ haribote.iso: haribote.img # hdiutil makehybrid -iso -joliet -o $@ $< mkisofs -b $< -o $@ -input-charset utf8 $< -run-cd: full haribote.iso +run_cd: full haribote.iso qemu-system-i386 -boot d -cdrom haribote.iso -m 32 -run-usb: full-usb usb.img +run_usb: full_usb usb.img qemu-system-i386 $(QEMU_FLAGS) -m 32 -vga std \ -drive file=usb.img,format=raw,if=none,id=usbdrive \ -device usb-ehci -device usb-storage,drive=usbdrive @@ -245,7 +245,7 @@ full: $(MAKE) -C gview $(MAKE) haribote.img -full-usb: +full_usb: $(MAKE) -C haribote usb $(MAKE) -C apilib $(MAKE) -C a @@ -281,7 +281,7 @@ full-usb: run_full: full run -run-usb_full: full-usb run-usb +run_full_usb: full_usb run_usb run_os: haribote.img run diff --git a/projects/31_day/harib28a/haribote/Makefile b/projects/31_day/harib28a/haribote/Makefile index 2d5b116..b8692f3 100644 --- a/projects/31_day/harib28a/haribote/Makefile +++ b/projects/31_day/harib28a/haribote/Makefile @@ -80,6 +80,7 @@ haribote.sys: asmhead.bin bootpack.hrb %.bin: %.nas $(NASM) $(NASM_FLAGS) -f bin -o $@ $< -l $*.lst + ndisasm -b 32 $*.bin > $*.map %.obj: %.nas $(NASM) $(NASM_FLAGS) -f elf32 -o $@ $< -l $*.lst diff --git a/projects/31_day/harib28a/haribote/asmhead.nas b/projects/31_day/harib28a/haribote/asmhead.nas index 14a554a..9ff4ea7 100644 --- a/projects/31_day/harib28a/haribote/asmhead.nas +++ b/projects/31_day/harib28a/haribote/asmhead.nas @@ -24,7 +24,7 @@ SCRNY EQU 0x0ff6 ; VRAM EQU 0x0ff8 ; グラフィックバッファの開始番地 ORG 0xc200 ; このプログラムがどこに読み込まれるのか - +; JMP scrn320 ; VBE存在確認 MOV AX,0x9000 diff --git a/projects/31_day/harib28a/haribote/ipl09.nas b/projects/31_day/harib28a/haribote/ipl09.nas index aca179d..eef2a07 100644 --- a/projects/31_day/harib28a/haribote/ipl09.nas +++ b/projects/31_day/harib28a/haribote/ipl09.nas @@ -1,54 +1,54 @@ ; haribote-ipl ; TAB=4 -CYLS EQU 15 ; どこまで読み込むか +CYLS EQU 15 ; How far to read - ORG 0x7c00 ; このプログラムがどこに読み込まれるのか + ORG 0x7c00 ; Where this program will be loaded -; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述 +; The following is for a standard FAT12 format floppy disk JMP entry DB 0x90 - DB "HARIBOTE" ; ブートセクタの名前を自由に書いてよい(8バイト) - DW 512 ; 1セクタの大きさ(512にしなければいけない) - DB 1 ; クラスタの大きさ(1セクタにしなければいけない) - DW 1 ; FATがどこから始まるか(普通は1セクタ目からにする) - DB 2 ; FATの個数(2にしなければいけない) - DW 224 ; ルートディレクトリ領域の大きさ(普通は224エントリにする) - DW 2880 ; このドライブの大きさ(2880セクタにしなければいけない) - DB 0xf0 ; メディアのタイプ(0xf0にしなければいけない) - DW 9 ; FAT領域の長さ(9セクタにしなければいけない) - DW 18 ; 1トラックにいくつのセクタがあるか(18にしなければいけない) - DW 2 ; ヘッドの数(2にしなければいけない) - DD 0 ; パーティションを使ってないのでここは必ず0 - DD 2880 ; このドライブ大きさをもう一度書く - DB 0,0,0x29 ; よくわからないけどこの値にしておくといいらしい - DD 0xffffffff ; たぶんボリュームシリアル番号 - DB "HARIBOTEOS " ; ディスクの名前(11バイト) - DB "FAT12 " ; フォーマットの名前(8バイト) - RESB 18 ; とりあえず18バイトあけておく - -; プログラム本体 + DB "HARIBOTE" ; You can freely write the name of the boot sector (8 bytes) + DW 512 ; Size of one sector (must be 512) + DB 1 ; Size of a cluster (must be 1 sector) + DW 1 ; Where the FAT starts (normally set to the first sector) + DB 2 ; Number of FATs (must be 2) + DW 224 ; Size of the root directory area (usually set to 224 entries) + DW 2880 ; Size of this drive (must be 2880 sectors) + DB 0xf0 ; Type of media (must be 0xf0) + DW 9 ; Length of FAT area (must be 9 sectors) + DW 18 ; Number of sectors per track (must be 18) + DW 2 ; Number of heads (must be 2) + DD 0 ; Must be 0 as partitions are not used here + DD 2880 ; Write the size of this drive again + DB 0,0,0x29 ; Apparently, it's good to set this value + DD 0xffffffff ; Probably the volume serial number + DB "HARIBOTEOS " ; Name of the disk (11 bytes) + DB "FAT12 " ; Name of the format (8 bytes) + RESB 18 ; Leave 18 bytes for now + +; Main program entry: - MOV AX,0 ; レジスタ初期化 + MOV AX,0 ; Initialize registers MOV SS,AX MOV SP,0x7c00 MOV DS,AX -; ディスクを読む +; Read the disk MOV AX,0x0820 MOV ES,AX - MOV CH,0 ; シリンダ0 - MOV DH,0 ; ヘッド0 - MOV CL,2 ; セクタ2 - MOV BX,18*2*CYLS-1 ; 読み込みたい合計セクタ数 - CALL readfast ; 高速読み込み + MOV CH,0 ; Cylinder 0 + MOV DH,0 ; Head 0 + MOV CL,2 ; Sector 2 + MOV BX,18*2*CYLS-1 ; Total number of sectors to read + CALL readfast ; Fast reading -; 読み終わったのでharibote.sysを実行だ! +; After reading, execute haribote.sys! - MOV BYTE [0x0ff0],CYLS ; IPLがどこまで読んだのかをメモ + MOV BYTE [0x0ff0],CYLS ; Note how far the IPL has read JMP 0xc200 error: @@ -57,32 +57,32 @@ error: MOV SI,msg putloop: MOV AL,[SI] - ADD SI,1 ; SIに1を足す + ADD SI,1 ; Add 1 to SI CMP AL,0 JE fin - MOV AH,0x0e ; 一文字表示ファンクション - MOV BX,15 ; カラーコード - INT 0x10 ; ビデオBIOS呼び出し + MOV AH,0x0e ; Display one character function + MOV BX,15 ; Color code + INT 0x10 ; Call video BIOS JMP putloop fin: - HLT ; 何かあるまでCPUを停止させる - JMP fin ; 無限ループ + HLT ; Halt the CPU until something happens + JMP fin ; Infinite loop msg: - DB 0x0a, 0x0a ; 改行を2つ + DB 0x0a, 0x0a ; Two newlines DB "load error" - DB 0x0a ; 改行 + DB 0x0a ; Newline DB 0 -readfast: ; ALを使ってできるだけまとめて読み出す -; ES:読み込み番地, CH:シリンダ, DH:ヘッド, CL:セクタ, BX:読み込みセクタ数 +readfast: ; Use AL to read as much as possible at once +; ES: Read address, CH: Cylinder, DH: Head, CL: Sector, BX: Number of sectors to read - MOV AX,ES ; < ESからALの最大値を計算 > - SHL AX,3 ; AXを32で割って、その結果をAHに入れたことになる (SHLは左シフト命令) - AND AH,0x7f ; AHはAHを128で割った余り(512*128=64K) - MOV AL,128 ; AL = 128 - AH; 一番近い64KB境界まで最大何セクタ入るか + MOV AX,ES ; < Calculate the maximum value of AL from ES > + SHL AX,3 ; Divide AX by 32 and store the result in AH (SHL is the left shift instruction) + AND AH,0x7f ; AH is the remainder of AH divided by 128 (512*128=64K) + MOV AL,128 ; AL = 128 - AH; Maximum number of sectors up to the nearest 64KB boundary SUB AL,AH - MOV AH,BL ; < BXからALの最大値をAHに計算 > + MOV AH,BL ; < Calculate the maximum value of AL from BX to AH > CMP BH,0 ; if (BH != 0) { AH = 18; } JE .skip1 MOV AH,18 @@ -92,7 +92,7 @@ readfast: ; AL MOV AL,AH .skip2: - MOV AH,19 ; < CLからALの最大値をAHに計算 > + MOV AH,19 ; < Calculate the maximum value of AL from CL to AH > SUB AH,CL ; AH = 19 - CL; CMP AL,AH ; if (AL > AH) { AL = AH; } JBE .skip3 @@ -100,23 +100,23 @@ readfast: ; AL .skip3: PUSH BX - MOV SI,0 ; 失敗回数を数えるレジスタ + MOV SI,0 ; Register to count the number of failures retry: - MOV AH,0x02 ; AH=0x02 : ディスク読み込み + MOV AH,0x02 ; AH=0x02 : Disk read MOV BX,0 - MOV DL,0x00 ; Aドライブ + MOV DL,0x00 ; Drive A PUSH ES PUSH DX PUSH CX PUSH AX - INT 0x13 ; ディスクBIOS呼び出し - JNC next ; エラーがおきなければnextへ - ADD SI,1 ; SIに1を足す - CMP SI,5 ; SIと5を比較 - JAE error ; SI >= 5 だったらerrorへ + INT 0x13 ; Call disk BIOS + JNC next ; If no error, go to next + ADD SI,1 ; Add 1 to SI + CMP SI,5 ; Compare SI with 5 + JAE error ; If SI >= 5, go to error MOV AH,0x00 - MOV DL,0x00 ; Aドライブ - INT 0x13 ; ドライブのリセット + MOV DL,0x00 ; Drive A + INT 0x13 ; Reset the drive POP AX POP CX POP DX @@ -126,28 +126,28 @@ next: POP AX POP CX POP DX - POP BX ; ESの内容をBXで受け取る - SHR BX,5 ; BXを16バイト単位から512バイト単位へ + POP BX ; Receive the contents of ES in BX + SHR BX,5 ; Convert BX from 16-byte units to 512-byte units MOV AH,0 ADD BX,AX ; BX += AL; - SHL BX,5 ; BXを512バイト単位から16バイト単位へ - MOV ES,BX ; これで ES += AL * 0x20; になる + SHL BX,5 ; Convert BX from 512-byte units to 16-byte units + MOV ES,BX ; This makes ES += AL * 0x20; POP BX SUB BX,AX JZ .ret - ADD CL,AL ; CLにALを足す - CMP CL,18 ; CLと18を比較 - JBE readfast ; CL <= 18 だったらreadfastへ + ADD CL,AL ; Add AL to CL + CMP CL,18 ; Compare CL with 18 + JBE readfast ; If CL <= 18, go to readfast MOV CL,1 ADD DH,1 CMP DH,2 - JB readfast ; DH < 2 だったらreadfastへ + JB readfast ; If DH < 2, go to readfast MOV DH,0 ADD CH,1 JMP readfast .ret: RET - RESB 0x7dfe-0x7c00-($-$$) ; 0x7dfeまでを0x00で埋める命令 + RESB 0x7dfe-0x7c00-($-$$) ; Fill with 0x00 up to 0x7dfe DB 0x55, 0xaa diff --git a/projects/31_day/harib28a/haribote/ipl09usb.nas b/projects/31_day/harib28a/haribote/ipl09usb.nas index 763f477..bd867df 100644 --- a/projects/31_day/harib28a/haribote/ipl09usb.nas +++ b/projects/31_day/harib28a/haribote/ipl09usb.nas @@ -1,202 +1,202 @@ -; hello-os +; haribote-ipl ; TAB=4 -CYLS EQU 20 - - ORG 0x7c00 - -; BPB Structure - - JMP SHORT entry ; BS_jmpBoot - NOP -BS_OEMName DB "HARIBOTE" ; [8 bytes] boot sector name -BPB_BytsPerSec DW 0x0200 ; the size of a sector (should be 512=0x0020) -BPB_SecPerClus DB 0x01 ; the size of a cluster (should be 1 sector) -BPB_RsvdSecCnt DW 0x0001 ; where FAT begins (usually from 1st sector) -BPB_NumFATs DB 0x02 ; the number of FATs (should be 2) -BPB_RootEntCnt DW 0x0000 ; the size of root directory area (usually 224 entries) -BPB_TotSec16 DW 0x0000 ; the size of this drive (should be 2880 sectors) -BPB_Media DB 0xf8 ; the type of media (should be 0xf0) -BPB_FATSz16 DW 0x0000 ; the length of FAT area (should be 9 sectors) -BPB_SecPerTrk DW 0xffff ; the number of sectors per a track (should be 18) -BPB_NumHeads DW 0x0001 ; the number of heads (should be 2) -BPB_HiDDSec DD 0x00000000 ; should be zero since we will not use partition -BPB_TotSec32 DD 0x00ee5000 ; the size of this drive (again) -BPB_FATSz32 DD 0x000000ed -BPB_ExtFlags DW 0x0000 -BPB_FSVer DW 0x0000 -BPB_RootClus DD 0x00000000 -BPB_FSInfo DW 0x0001 -BPB_BkBootSec DW 0x0000 - TIMES 12 DB 0 ; BPB_Reserved -BS_DrvNum DB 0x80 -BS_Reserved1 DB 0x00 -BS_BootSig DB 0x29 -BS_VolID DD 0xffffffff -BS_VolLab DB "HARIBOTEOS " ; [11 bytes] the name of the disk -BS_FilSysType DB "FAT12 " ; [8 bytes] the name of the format - ;RESB 18 ; put 18 bytes of space anyway - TIMES 18 DB 0 - -; START BS_BootCode 64(0x14) 448(0x1C0) +CYLS EQU 20 ; Number of cylinders (not used in this code but defined for reference) + + ORG 0x7c00 ; Origin of the code. The BIOS loads the bootloader at address 0x7c00 + +; BPB Structure (BIOS Parameter Block) for FAT32 + + JMP SHORT entry ; Jump to the entry point of the bootloader code + NOP ; No operation, used for alignment + +BS_OEMName DB "HARIBOTE" ; [8 bytes] OEM name or identifier +BPB_BytsPerSec DW 0x0200 ; Bytes per sector (512 bytes). Standard for FAT12/16/32 +BPB_SecPerClus DB 0x08 ; Sectors per cluster (8 sectors per cluster). FAT32 standard +BPB_RsvdSecCnt DW 0x0020 ; Reserved sectors count (32 reserved sectors). Usually for FAT32 +BPB_NumFATs DB 0x02 ; Number of FAT copies (2). Standard for FAT32 +BPB_RootEntCnt DW 0x0000 ; Root directory entries (0 for FAT32; root directory is in a cluster) +BPB_TotSec16 DW 0x0000 ; Total sectors for FAT12/16 (0 for FAT32; use BPB_TotSec32) +BPB_Media DB 0xF8 ; Media descriptor (0xF8 for hard disks) +BPB_FATSz16 DW 0x0000 ; Sectors per FAT for FAT12/16 (0 for FAT32; use BPB_FATSz32) +BPB_SecPerTrk DW 0x003F ; Sectors per track (63 for hard disks) +BPB_NumHeads DW 0x00FF ; Number of heads (255 for hard disks) +BPB_HiDDSec DD 0x00000000 ; Hidden sectors (usually 0) +BPB_TotSec32 DD 0x00EE5000 ; Total sectors for the USB drive (7,745,024 sectors) + +; FAT32 specific fields +BPB_FATSz32 DD 0x00001F40 ; Sectors per FAT (8,000 sectors per FAT) +BPB_ExtFlags DW 0x0000 ; Flags (FAT32 specific; 0 for default behavior) +BPB_FSVer DW 0x0000 ; Filesystem version (0 for FAT32) +BPB_RootClus DD 0x00000002 ; Root directory cluster (usually 2) +BPB_FSInfo DW 0x0001 ; FSInfo sector (usually 1) +BPB_BkBootSec DW 0x0006 ; Backup boot sector (usually 6) + TIMES 12 DB 0 ; Reserved bytes (FAT32 specific) + +; Extended BIOS Parameter Block fields +BS_DrvNum DB 0x80 ; Drive number (0x80 for the first HDD) +BS_Reserved1 DB 0x00 ; Reserved byte +BS_BootSig DB 0x29 ; Extended boot signature (0x29) +BS_VolID DD 0xFFFFFFFF ; Volume serial number (0xFFFFFFFF is a placeholder) +BS_VolLab DB "HARIBOTEOS " ; [11 bytes] Volume label +BS_FilSysType DB "FAT32 " ; [8 bytes] Filesystem type + + TIMES 18 DB 0 ; Padding to align the boot code start + +; Boot code starts here, after the BPB and EBP sections entry: - MOV AX, 0 ; register initialization - MOV SS, AX - MOV ES, AX - MOV DS, AX - MOV BX, AX - MOV CX, AX - MOV SP, 0x7c00 + MOV AX, 0 ; Initialize AX register to 0 + MOV SS, AX ; Set Stack Segment (SS) to 0 (base address) + MOV ES, AX ; Set Extra Segment (ES) to 0 (base address) + MOV DS, AX ; Set Data Segment (DS) to 0 (base address) + MOV BX, AX ; Initialize BX register to 0 + MOV CX, AX ; Initialize CX register to 0 + MOV SP, 0x7c00 ; Set Stack Pointer (SP) to top of bootloader (0x7c00) -; read disk +; Read disk and initialize the system - MOV [drv], DL + MOV DL, 0x80 ; Set DL to 0x80 to specify the first hard disk drive + MOV [drv], DL ; Store the drive number (DL) into memory (for later use) - MOV AH, 0x41 - MOV BX, 0x55aa ; fixed for INT 0x13 - INT 0x13 ; AH=0x41 : check if extended INT 0x13 is available - JC nosupport ; if not supported +; Check if extended INT 0x13 is available - XOR AX, AX ; P xor P = 0 for all P - ADD AX, 1 ; clear carry flag - XOR EDI, EDI + MOV AH, 0x41 ; BIOS interrupt 0x13, function 0x41: check if extended INT 13h is available + MOV BX, 0x55aa ; Fixed value to check for extended INT 13h support + INT 0x13 ; Call BIOS interrupt 0x13 + JC nosupport ; Jump to nosupport label if carry flag is set (indicates failure) - MOV AH, 0x45 ; drive lock - MOV AL, 0x01 - MOV DL, 0x80 - INT 0x13 ; AH=0x45 : (extended) drive lock + XOR AX, AX ; Clear AX register (AX = 0) + ADD AX, 1 ; Add 1 to AX (used to clear carry flag) + XOR EDI, EDI ; Clear EDI register (EDI = 0) - MOV AX, 0 - MOV DS, AX +; Perform disk operations using the drive number in DL + + MOV AH, 0x45 ; BIOS interrupt 0x13, function 0x45: lock the drive + MOV AL, 0x01 ; Lock drive 0x80 + MOV DL, 0x80 ; Drive number 0x80 (first HDD) + INT 0x13 ; Call BIOS interrupt 0x13 to lock the drive + + MOV AX, 0 ; Clear AX register + MOV DS, AX ; Set Data Segment (DS) to 0 (base address) loop: - MOV CL, 0 + MOV CL, 0 ; Clear CL register (used for retry counter) retry: - PUSH DS - PUSHAD - MOV DL, [drv] - MOV AH, 0x42 - MOV AL, 0x00 - MOV SI, DAPS - INT 0x13 ; AH=0x42 : (extended) read disk - JNC next ; if error did not occur goto next - - ADD CL, 1 ; ++CL - MOV DL, 0x80 - MOV AH, 0x00 - INT 0x13 ; AH=0x00 : system reset - CMP CL, 6 - JGE error ; if CL >= 6 goto error - JMP retry + PUSH DS ; Save Data Segment (DS) on stack + PUSHAD ; Save all general-purpose registers on stack + MOV DL, [drv] ; Load drive number from memory + MOV AH, 0x42 ; BIOS interrupt 0x13, function 0x42: extended read disk + MOV AL, 0x00 ; Read 1 sector (specified by count) + MOV SI, DAPS ; Load address of Disk Address Packet (DAPS) + INT 0x13 ; Call BIOS interrupt 0x13 to read the disk + JNC next ; Jump to next if no carry (indicates success) + + ADD CL, 1 ; Increment retry counter + MOV DL, 0x80 ; Reset drive + MOV AH, 0x00 ; BIOS interrupt 0x13, function 0x00: reset drive + INT 0x13 ; Call BIOS interrupt 0x13 + CMP CL, 6 ; Compare retry counter with 6 + JGE error ; Jump to error if retry counter >= 6 + JMP retry ; Jump back to retry reading disk next: + XOR EAX, EAX ; Clear EAX register + XOR EBX, EBX ; Clear EBX register + XOR ECX, ECX ; Clear ECX register - XOR EAX, EAX - XOR EBX, EBX - XOR ECX, ECX + ADD EDI, 1 ; Increment EDI (used to track sectors read) + MOV ECX, lba0 ; Load address of LBA (Logical Block Address) 0 + MOV [ECX], EDI ; Store incremented EDI to LBA address - ADD EDI, 1 ; ++EDI - MOV ECX, lba0 - MOV [ECX], EDI + XOR EAX, EAX ; Clear EAX register + XOR ECX, ECX ; Clear ECX register + XOR EBP, EBP ; Clear EBP register - XOR EAX, EAX - XOR ECX, ECX - XOR EBP, EBP + MOV AX, [addr] ; Load address from memory (target location for reading) + MOV ECX, addr ; Load address of addr + MOV EBX, segm ; Load address of segment + ADD AX, 0x200 ; Add 0x200 to AX (offset adjustment) + ADC BP, 0 ; Add carry to BP (for address calculation) + SHL BP, 12 ; Shift BP left by 12 (address scaling) + ADD BP, [segm] ; Add segment base address to BP + MOV [EBX], BP ; Store computed address in EBX - MOV AX, [addr] - MOV ECX, addr - MOV EBX, segm - ADD AX, 0x200 - ADC BP, 0 - SHL BP, 12 - ADD BP, [segm] - MOV [EBX], BP + MOV [ECX], AX ; Store address in ECX + MOV [EBX], BP ; Store base address in EBX - MOV [ECX], AX - MOV [EBX], BP + CMP EDI, 0x16a ; Compare EDI with 0x16a (check if all sectors read) + JL loop ; Jump to loop if EDI < 0x16a - CMP EDI, 0x16a - JL loop + MOV ECX, 0xc200 ; Load address to jump to (0xc200 in segment 0x0000) - MOV ECX, 0xc200 + MOV EAX, 0x0000 ; Clear EAX register + MOV EBX, EAX ; Clear EBX register + MOV EDX, EAX ; Clear EDX register + MOV EBP, EAX ; Clear EBP register + MOV ES, AX ; Set Extra Segment (ES) to 0 + MOV ESI, EAX ; Clear ESI register + MOV EDI, EAX ; Clear EDI register - MOV EAX, 0x0000 - MOV EBX, EAX - MOV EDX, EAX - MOV EBP, EAX - MOV ESI, EAX - MOV EDI, EAX + MOV CH, 10 ; Load 0x0A (newline character) into CH + MOV [0x0ff0], CH ; Store CH at 0x0ff0 (for display purposes) - MOV CH, 10 - MOV [0x0ff0], CH - - MOV ECX, EAX - JMP 0x0000:0xc200 + MOV ECX, EAX ; Clear ECX register + JMP 0x0000:0xc200 ; Jump to address 0xc200 in segment 0x0000 nosupport: - MOV SI, msg_nos - JMP putloop + MOV SI, msg_nos ; Load address of "extINT13H not supported" message + JMP putloop ; Jump to putloop to display the message + error: - POPAD - POP DS - MOV SI,msg - JMP putloop + POPAD ; Restore all general-purpose registers from stack + POP DS ; Restore Data Segment (DS) from stack + MOV SI, msg ; Load address of "load error" message + JMP putloop ; Jump to putloop to display the message + putloop: - MOV AL,[SI] - ADD SI,1 ; ++SI - CMP AL,0 - JE fin - MOV AH,0x0e - MOV BX, [chclr] ; BX : color code - INT 0x10 ; AH=0x0e : putchar() - JMP putloop + MOV AL, [SI] ; Load character from message into AL + ADD SI, 1 ; Increment message pointer (SI) + CMP AL, 0 ; Compare AL with 0 (end of message) + JE fin ; Jump to fin if end of message + MOV AH, 0x0e ; BIOS interrupt 0x10, function 0x0e: teletype output + MOV BX, [chclr] ; Load color code for output + INT 0x10 ; Call BIOS interrupt 0x10 to output character + JMP putloop ; Jump back to putloop to display next character fin: - HLT - JMP fin - -putloop_e: - MOV AL,[SI] - ADD SI,1 ; ++SI - CMP AL,0 - JE fin - MOV AH,0x0e - MOV BX, [chclr] ; BX : color code - INT 0x10 ; AH=0x0e : putchar() - JMP putloop_e + HLT ; Halt the CPU (end of bootloader execution) + JMP fin ; Infinite loop to prevent further execution msg: - ;DB 0x0d, 0x0a ; CR LF - DB "load error" - DB 0x0d, 0x0a ; CR LF - DB 0 + DB "load error" ; Error message to display + DB 0x0d, 0x0a ; CR LF (Carriage Return and Line Feed) + DB 0 ; Null terminator for the string msg_nos: - DB 0x0d, 0x0a ; CR LF - DB "extINT13H not supported" - DB 0x0d, 0x0a ; CR LF - DB 0 + DB 0x0d, 0x0a ; CR LF (Carriage Return and Line Feed) + DB "extINT13H not supported" ; Message indicating extended INT 13h not supported + DB 0x0d, 0x0a ; CR LF (Carriage Return and Line Feed) + DB 0 ; Null terminator for the string drv: - DB 0x80 ; 0x00: 1st FDD, 0x80: 1st HDD + DB 0x80 ; Drive number (0x80: first HDD) + chclr: - DW 0x000f ; usually 15=0x000f + DW 0x000f ; Color code for text output (15 = light grey on black) DAPS: - DB 0x10 ; Size of Structure (16 bytes, always this for DAPS) - DB 0 ; Always 0 + DB 0x10 ; Size of Disk Address Packet (16 bytes) + DB 0 ; Reserved, always 0 count: - DB 1 ; Number of Sectors to Read (1x512) - DB 0 ; Always 0 + DB 539 ; Number of sectors to read (1 sector = 512 bytes) + DB 0 ; Reserved, always 0 addr: - DW 0x8000 ; Target Location for Reading To (0x8000 = 0x0800:0x0000) + DW 0x8000 ; Target location for reading data (0x8000) segm: - DW 0x0000 ; Page Table (0, Disabled) + DW 0x0000 ; Segment address (0x0000) lba0: - DD 1 ; Read from 2nd block (code I want to load) - DD 0 - + DD 1 ; Read from LBA 1 (second block) - TIMES 0x7dfe-0x7c00-($-$$) DB 0 - DB 0x55, 0xaa ; boot signature \ No newline at end of file + TIMES 0x7dfe-0x7c00-($-$$) DB 0 ; Fill the remainder of the boot sector with zeros + DB 0x55, 0xaa ; Boot signature (0x55AA), required for BIOS to recognize bootable disk