251 lines
8.5 KiB
Markdown
251 lines
8.5 KiB
Markdown
# **Bootloader Documentation**
|
|
|
|
## **1. Calling Conventions**
|
|
|
|
### __cdecl16near Calling Convention
|
|
|
|
- **Purpose**: For calling near (within the same segment) functions in 16-bit code.
|
|
- **Stack Management**: Caller cleans up the stack after the function call.
|
|
- **Parameter Passing**: Parameters are pushed onto the stack from right to left.
|
|
- **Return Address**: A near return address (16-bit) is pushed onto the stack.
|
|
- **Return Value**: Placed in the AX register.
|
|
|
|
Example:
|
|
|
|
```assembly
|
|
; Caller
|
|
push param2
|
|
push param1
|
|
call near_func
|
|
add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each)
|
|
|
|
; Callee (near_func)
|
|
near_func:
|
|
push bp
|
|
mov bp, sp
|
|
; Function body
|
|
mov sp, bp
|
|
pop bp
|
|
ret
|
|
```
|
|
|
|
### __cdecl16far Calling Convention
|
|
|
|
- **Purpose**: For calling far (across different segments) functions in 16-bit code.
|
|
- **Stack Management**: Caller cleans up the stack after the function call.
|
|
- **Parameter Passing**: Parameters are pushed onto the stack from right to left.
|
|
- **Return Address**: A far return address (32-bit, consisting of a segment and an offset) is pushed onto the stack.
|
|
- **Return Value**: Placed in the AX register.
|
|
|
|
Example:
|
|
|
|
```assembly
|
|
; Caller
|
|
push param2
|
|
push param1
|
|
call far_func
|
|
add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each)
|
|
|
|
; Callee (far_func)
|
|
far_func:
|
|
push bp
|
|
mov bp, sp
|
|
; Function body
|
|
mov sp, bp
|
|
pop bp
|
|
retf ; Far return
|
|
```
|
|
|
|
### **Key Differences**
|
|
|
|
- **Return Address**: `__cdecl16near` uses a 16-bit return address; `__cdecl16far` uses a 32-bit return address (segment:offset).
|
|
- **Function Scope**: `__cdecl16near` is for functions within the same segment; `__cdecl16far` is for functions that may be in different segments.
|
|
- **Return Instruction**: `__cdecl16near` uses `ret`; `__cdecl16far` uses `retf` (far return).
|
|
|
|
### **Register Usage**
|
|
|
|
#### Caller-Saved (Volatile) Registers
|
|
|
|
- **AX**: Accumulator, often used for return values.
|
|
- **CX**: Counter register.
|
|
- **DX**: Data register, used for I/O operations.
|
|
- **SI/DI**: String operation indexes.
|
|
|
|
#### Callee-Saved (Non-Volatile) Registers
|
|
|
|
- **BP**: Base pointer, used for stack frame management.
|
|
- **SP**: Stack pointer.
|
|
- **BX**: Base register.
|
|
|
|
Example:
|
|
|
|
```assembly
|
|
; Caller
|
|
push param2
|
|
push param1
|
|
call near_func
|
|
add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each)
|
|
|
|
; Callee (near_func)
|
|
near_func:
|
|
push bp
|
|
mov bp, sp
|
|
; Save callee-saved registers if used
|
|
push bx
|
|
push si
|
|
push di
|
|
; Function body
|
|
; Use AX, CX, DX freely
|
|
; Restore callee-saved registers
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
mov sp, bp
|
|
pop bp
|
|
ret
|
|
```
|
|
|
|
## **2. E820 Memory Map Usage**
|
|
|
|
### **Address Range Descriptor Structure**
|
|
|
|
| Offset | Name | Description |
|
|
|--------|---------------|---------------------------------------|
|
|
| 0 | BaseAddrLow | Low 32 bits of base address |
|
|
| 4 | BaseAddrHigh | High 32 bits of base address |
|
|
| 8 | LengthLow | Low 32 bits of length in bytes |
|
|
| 12 | LengthHigh | High 32 bits of length in bytes |
|
|
| 16 | Type | Address type of this range |
|
|
|
|
### **E820 Function Call**
|
|
|
|
#### Input
|
|
|
|
- **EAX**: Function code `E820h`.
|
|
- **EBX**: Continuation value for physical memory retrieval (0 for the first call).
|
|
- **ES:DI**: Buffer pointer to an Address Range Descriptor structure.
|
|
- **ECX**: Buffer size (minimum size 20 bytes).
|
|
- **EDX**: Signature ('SMAP').
|
|
|
|
#### Output
|
|
|
|
- **CF**: Carry flag (indicates success/failure).
|
|
- **EAX**: Signature ('SMAP').
|
|
- **ECX**: Buffer size (number of bytes returned).
|
|
- **EBX**: Continuation value for subsequent E820 calls.
|
|
|
|
### **Address Type Values**
|
|
|
|
| Value | Pneumonic | Description |
|
|
|-------|----------------------|-----------------------------------------------------------|
|
|
| 1 | AddressRangeMemory | Available RAM usable by the operating system. |
|
|
| 2 | AddressRangeReserved | Reserved by the system, unusable by the operating system. |
|
|
|
|
## **3. Example Calculations**
|
|
|
|
### **Partition Offset**
|
|
|
|
- Partition 1 offset = LBA 0x800 = 0x100000
|
|
- `bsSectorSize = 512`
|
|
|
|
### **First FAT Sector**
|
|
|
|
- `first_fat_sector = bsResSector = 32 => (32*512) = 0x4000`
|
|
- `first_fat_sector = 0x100000 + 0x4000 = 0x104000`
|
|
|
|
### **Total FAT Sectors**
|
|
|
|
- `total_fat_sectors = fat_sectors * number_of_FATs = 2001 * 2 = 4002`
|
|
- `total_fat_size = total_fat_sectors * bsSectorSize = 0x1F4400`
|
|
|
|
### **First Data Sector**
|
|
|
|
- `first_data_sector = FatStartSector + FatAreaSize = 0x104000 + 0x1F4400 = 0x2F8400`
|
|
|
|
### **FAT Table Look Up**
|
|
|
|
```c
|
|
if the cluster we got from the table entry was cluster 354
|
|
fat_sector = 354 / 128 = 2
|
|
fat_entry = 354 mod 128 = 98
|
|
|
|
so we load the 3rd (indexed from 0) fat table sector and read the 98th entry
|
|
|
|
```
|
|
|
|
Example:
|
|
|
|
```c
|
|
|
|
fat_table_offset = (first_fat_sector + 2) * 512
|
|
fat_table = *(fat_table_offset)
|
|
disk_read(fat_table[98])
|
|
```
|
|
|
|
## **4. Global Descriptor Table (GDT)**
|
|
|
|
### **Segment Attributes**
|
|
|
|
- **Pr**: Present bit (must be 1 for valid selectors).
|
|
- **Privl**: Privilege level (0 = kernel, 3 = user).
|
|
- **S**: Descriptor type (set for code/data segments, cleared for system segments).
|
|
- **Ex**: Executable bit (set if segment contains code).
|
|
- **DC**: Direction/Conforming bit (for data or code segments).
|
|
- **RW**: Readable/Writable (depends on segment type).
|
|
|
|
### **Granularity (Gr)**
|
|
|
|
- **Gr**: Granularity bit (0 = byte granularity, 1 = 4 KiB blocks).
|
|
- **Sz**: Size bit (0 = 16-bit mode, 1 = 32-bit mode).
|
|
|
|
### **GDT Entry Construction**
|
|
|
|
Each GDT entry is 8 bytes:
|
|
|
|
- First DWORD: Limit (0:15), Base (0:15)
|
|
- Second DWORD: Base (16:31), Attributes (8:12)
|
|
|
|
## **5. Memory Layout Example**
|
|
|
|
### **Low Memory/Upper Memory map (<= 1MiB)**
|
|
|
|
| Start | End | Size | Type | Description |
|
|
|-------------|-------------|-----------------|----------------------|--------------------------------|
|
|
| 0x00000000 | 0x000003FF | 1 KiB | RAM reclaimable~1~ | Real Mode IVT |
|
|
| 0x00000400 | 0x000004FF | 256 bytes | RAM reclaimable~1~ | BDA |
|
|
| 0x00000500 | 0x00007BFF | 29 KiB + 767b | RAM - free | Conventional memory |
|
|
| 0x00007C00 | 0x00007DFF | 512 bytes | RAM reclaimable~2~ | OS BootSector |
|
|
| 0x00007E00 | 0x0007FFFF | 480.5 KiB | RAM - free | Conventional memory |
|
|
| 0x00080000 | 0x0009FFFF | 128 KiB | RAM (unusable)~1~ | EBDA (Extended BIOS Data Area) |
|
|
| 0x000A0000 | 0x000FFFFF | 384 KiB | Upper RAM (unusable) | Video memory, ROM Area |
|
|
|
|
1. Reclaimable in the event that you *never* need the BIOS again & once the CPU is in protected mode.
|
|
2. Reclaimable after you are done with with the MBR/VBR stages.
|
|
|
|
### **Extended Memory (> 1 MiB)**
|
|
|
|
This is only an example, you should always check the memory map.
|
|
|
|
| Start | End | Size | Description |
|
|
|-------------|-------------|-----------------|---------------------------------------|
|
|
| 0x00100000 | 0x00EFFFFF | 14 MiB | RAM(?) - free for use |
|
|
| 0x00F00000 | 0x00FFFFFF | 1 MiB | Possible memory-mapped hardware (ISA) |
|
|
| 0x01000000 | ? | ? | More extended memory |
|
|
| 0xC0000000 | 0xFFFFFFFF | 1 GiB | Memory mapped PCI devices, BIOS, etc. |
|
|
| 0x0000000100000000 | ? | ? | RAM(?) - usable in PAE/64-bit mode |
|
|
|
|
|
|
## **6. Stage2 Memory Layout **
|
|
|
|
Overall, Tiny (64 KiB page) Code/Data, Flat 4GiB mapping in gs/fs after unreal switch
|
|
|
|
| Start | End | Size (Bytes) | Type | Description |
|
|
|-------------|-------------|--------------|--------------------|----------------------------|
|
|
| 0x00000000 | 0x000003FF | 0x400 | RAM - (BIOS) | Real Mode IVT |
|
|
| 0x00000400 | 0x000004FF | 0x100 | RAM - (BIOS) | BDA |
|
|
| 0x00000500 | 0x000042FF | 0x3E00 | RAM - .text/.data | Code and constants/strings |
|
|
| 0x00004300 | 0x000044FF | 0x100 | RAM - .sign | EOF marker/signature |
|
|
| 0x00004500 | 0x000074FF | 0x3000 | RAM - bss | Runtime data/stack |
|
|
| 0x00007500 | 0x00007FFF | 0xB00 | RAM - reserved | Reserved |
|
|
| 0x00008000 | 0x0000DFFF | 0x6000 | RAM - heap | Conventional memory |
|
|
| 0x0000F000 | 0x0000FFFF | 0x1000 | RAM - reserved | Reserved | |