Skip to content

Commit

Permalink
Updated docs and 31_day
Browse files Browse the repository at this point in the history
  • Loading branch information
insightintoself committed Jul 19, 2024
1 parent 3df1b7e commit 2a118af
Show file tree
Hide file tree
Showing 7 changed files with 347 additions and 230 deletions.
1 change: 1 addition & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
115 changes: 115 additions & 0 deletions docs/bpb.md
Original file line number Diff line number Diff line change
@@ -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
8 changes: 4 additions & 4 deletions projects/31_day/harib28a/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions projects/31_day/harib28a/haribote/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion projects/31_day/harib28a/haribote/asmhead.nas
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ SCRNY EQU 0x0ff6 ;
VRAM EQU 0x0ff8 ; グラフィックバッファの開始番地

ORG 0xc200 ; このプログラムがどこに読み込まれるのか

; JMP scrn320
; VBE存在確認

MOV AX,0x9000
Expand Down
134 changes: 67 additions & 67 deletions projects/31_day/harib28a/haribote/ipl09.nas
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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
Expand All @@ -92,31 +92,31 @@ 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
MOV AL,AH
.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
Expand All @@ -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
Loading

0 comments on commit 2a118af

Please sign in to comment.