From 933cccb88e7a52ef9bfcc176e7533ac31fbf33c2 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Mon, 14 Oct 2024 10:44:44 -0400 Subject: [PATCH] replace text documentation with markdown --- docs/Stevia Notes.md | 230 ++++++++++++++++++++++++++++ docs/calling_convention_cdecl16.txt | 104 ------------- docs/e820_usage.txt | 78 ---------- docs/examples.txt | 35 ----- docs/gdt.txt | 61 -------- include/early_mem.inc | 23 --- 6 files changed, 230 insertions(+), 301 deletions(-) create mode 100644 docs/Stevia Notes.md delete mode 100644 docs/calling_convention_cdecl16.txt delete mode 100644 docs/e820_usage.txt delete mode 100755 docs/examples.txt delete mode 100644 docs/gdt.txt diff --git a/docs/Stevia Notes.md b/docs/Stevia Notes.md new file mode 100644 index 0000000..14aa37e --- /dev/null +++ b/docs/Stevia Notes.md @@ -0,0 +1,230 @@ +# **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 (First MiB)** + +| Start | End | Size | Type | Description | +|-------------|-------------|-----------------|-----------------------|----------------------------------| +| 0x00000000 | 0x000003FF | 1 KiB | RAM (partially unusable) | Real Mode IVT (Interrupt Vector Table) | +| 0x00000400 | 0x000004FF | 256 bytes | RAM (partially unusable) | BDA (BIOS data area) | +| 0x00000500 | 0x00007BFF | almost 30 KiB | RAM - free for use | Conventional memory | +| 0x00007C00 | 0x00007DFF | 512 bytes | RAM (partially unusable) | OS BootSector | +| 0x00007E00 | 0x0007FFFF | 480.5 KiB | RAM - free for use | Conventional memory | +| 0x00080000 | 0x0009FFFF | 128 KiB | RAM (partially unusable) | EBDA (Extended BIOS Data Area) | +| 0x000A0000 | 0x000FFFFF | 384 KiB | various (unusable) | Video memory, ROM Area | + +### **Extended Memory (Above 1 MiB)** + +| 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 | diff --git a/docs/calling_convention_cdecl16.txt b/docs/calling_convention_cdecl16.txt deleted file mode 100644 index 24837b5..0000000 --- a/docs/calling_convention_cdecl16.txt +++ /dev/null @@ -1,104 +0,0 @@ -__cdecl16near Calling Convention -Purpose: Used for calling near (within the same segment) functions in 16-bit code. -Stack Management: The 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: The return value is typically placed in the AX register. - -e.g - -; 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: Used for calling far (across different segments) functions in 16-bit code. -Stack Management: The 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: The return value is typically placed in the AX register. - -e.g - -; 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, while __cdecl16far uses a 32-bit return address (segment:offset). -Function Scope: __cdecl16near is for functions within the same segment, whereas __cdecl16far is for functions that may be in different segments. -Return Instruction: __cdecl16near uses ret, while __cdecl16far uses retf (far return). - - -### REGISTERS ### - -Register Usage in __cdecl16near and __cdecl16far -Caller-Saved Registers (Volatile) -These registers must be saved by the caller if they wish to preserve their values across function calls: - -AX: Accumulator register, often used for return values. -CX: Counter register, commonly used in loops and string operations. -DX: Data register, used for I/O operations and arithmetic. -SI: Source index for string operations. -DI: Destination index for string operations. -Callee-Saved Registers (Non-Volatile) -These registers must be preserved by the callee. If the callee uses these registers, it must save their original values and restore them before returning: - -BP: Base pointer, used for stack frame management. -SP: Stack pointer, although typically managed by the calling convention itself. -BX: Base register, often used for addressing. -SI: Source index, if not used for string operations. -DI: Destination index, if not used for string operations. - -e.g - -; 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 - mov ax, [bp+4] ; Access first parameter - mov bx, [bp+6] ; Access second parameter - ; - ; your other code here - ; - ; Restore callee-saved registers - pop di - pop si - pop bx - mov sp, bp - pop bp - ret diff --git a/docs/e820_usage.txt b/docs/e820_usage.txt deleted file mode 100644 index 200bf83..0000000 --- a/docs/e820_usage.txt +++ /dev/null @@ -1,78 +0,0 @@ -; Address Range Descriptor Structure -; -; Offset in Bytes 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. -; Address Range Descriptor Structure -; -; Offset in Bytes 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. -; Input: -; -; EAX Function Code E820h -; EBX Continuation Contains the "continuation value" to get the -; next run of physical memory. This is the -; value returned by a previous call to this -; routine. If this is the first call, EBX -; must contain zero. -; ES:DI Buffer Pointer Pointer to an Address Range Descriptor -; structure which the BIOS is to fill in. -; ECX Buffer Size The length in bytes of the structure passed -; to the BIOS. The BIOS will fill in at most -; ECX bytes of the structure or however much -; of the structure the BIOS implements. The -; minimum size which must be supported by both -; the BIOS and the caller is 20 bytes. Future -; implementations may extend this structure. -; EDX Signature 'SMAP' - Used by the BIOS to verify the -; caller is requesting the system map -; information to be returned in ES:DI. -; -; Output: -; -; CF Carry Flag Non-Carry - indicates no error -; EAX Signature 'SMAP' - Signature to verify correct BIOS -; revision. -; ES:DI Buffer Pointer Returned Address Range Descriptor pointer. -; Same value as on input. -; ECX Buffer Size Number of bytes returned by the BIOS in the -; address range descriptor. The minimum size -; structure returned by the BIOS is 20 bytes. -; EBX Continuation Contains the continuation value to get the -; next address descriptor. The actual -; significance of the continuation value is up -; to the discretion of the BIOS. The caller -; must pass the continuation value unchanged -; as input to the next iteration of the E820 -; call in order to get the next Address Range -; Descriptor. A return value of zero means that -; this is the last descriptor -; -; Address Range Descriptor Structure -; -; Offset in Bytes 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. -; -; The BaseAddrLow and BaseAddrHigh together are the 64 bit BaseAddress of this range. -; The BaseAddress is the physical address of the start of the range being specified. -; -; The LengthLow and LengthHigh together are the 64 bit Length of this range. -; The Length is the physical contiguous length in bytes of a range being specified. -; -; The Type field describes the usage of the described address range as defined in the table below. - -; Value Pneumonic Description -; 1 AddressRangeMemory This run is available RAM usable by the operating system. -; 2 AddressRangeReserved This run of addresses is in use or reserved by the system, and must not be used by the operating system. -; Other Undefined Undefined - Reserved for future use. \ No newline at end of file diff --git a/docs/examples.txt b/docs/examples.txt deleted file mode 100755 index 21f9ceb..0000000 --- a/docs/examples.txt +++ /dev/null @@ -1,35 +0,0 @@ -Partition 1 offset = LBA 0x800 - = 0x100000 -bsSectorSize = 512 - -first_fat_sector = bsResSector - = 32 => (32*512) = 0x4000 - = 0x100000 + 0x4000 - = 0x104000 - -total_fat_sectors = fat_sectors * number_of_FATs - = 2001 * 2 - = 4002 - -total_fat_size = total_fat_sectors * bsSectorSize - = 0x1F4400 - -first_data_sector = FatStartSector + FatAreaSize - = 0x104000 + 0x1F4400 - = 0x2F8400 - -FAT table look up - - 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 - for the cluster chain. - - // bad fake code below - fat_table_offset = (first_fat_sector + 2) * 512 - fat_table = *(fat_table_offset) - disk_read(fat_table[98]) diff --git a/docs/gdt.txt b/docs/gdt.txt deleted file mode 100644 index d3da195..0000000 --- a/docs/gdt.txt +++ /dev/null @@ -1,61 +0,0 @@ -GDT documentation below: - - Pr: Present bit. This must be 1 for all valid selectors. - - Privl: Privilege, 2 bits. Contains the ring level, - 0 = highest (kernel), 3 = lowest (user applications). - - S: Descriptor type. This bit should be set for code or data segments - and should be cleared for system segments (eg. a Task State Segment) - - Ex: Executable bit. If 1 code in this segment can be executed - ie. a code selector. If 0 it is a data selector. - - DC: Direction bit/Conforming bit. - Direction bit for data selectors: Tells the direction. - 0 the segment grows up. 1 the segment grows down, ie. the offset has to be greater than the limit. - - Conforming bit for code selectors: - If 1 code in this segment can be executed from an equal or lower privilege level. - For example, code in ring 3 can far-jump to conforming code in a ring 2 segment. - The privl-bits represent the highest privilege level that is allowed to execute the segment. - For example, code in ring 0 cannot far-jump to a conforming code segment with privl==0x2 - while code in ring 2 and 3 can. Note that the privilege level remains the same - ie. a far-jump form ring 3 to a privl==2-segment remains in ring 3 after the jump. - - If 0 code in this segment can only be executed from the ring set in privl. - - RW: Readable bit/Writable bit. - Readable bit for code selectors: Whether read access for this segment is allowed. Write access is never allowed for code segments. - Writable bit for data selectors: Whether write access for this segment is allowed. Read access is always allowed for data segments. - - Ac: Accessed bit. Just set to 0. The CPU sets this to 1 when the segment is accessed. - - Gr: Granularity bit. If 0 the limit is in 1 B blocks (byte granularity), if 1 the limit is in 4 KiB blocks (page granularity). - - Sz: Size bit. If 0 the selector defines 16 bit protected mode. If 1 it defines 32 bit protected mode. - You can have both 16 bit and 32 bit selectors at once. - - AvL: Availible to software bit, the CPU does not use this field and software can read/write to it - - D/B bit: The default operand-size bit is found in code-segment and data-segment descriptors but not in system-segment descriptors. Setting - this bit to 1 indicates a 32-bit default operand size, and clearing it indicates a 16-bit default size. - - E bit: Expand down bit: Setting this bit to 1 identifies the data segment as expand-down. - In expand-down segments, the segment limit defines the lower segment boundary while the base is the upper boundary - - A GDT entry is 8 bytes and is constructed as follows: - First DWORD - 0-15 Limit 0:15 First 16 bits in the segment limiter - 16-31 Base 0:15 First 16 bits in the base address - - 2nd DWORD - - 0:7 Base 16:23 Bits 16-23 in the base address - 8:12 S/Type Segment type and attributes, S = bit 12, Type = 8:11, Type is either [1, DC, RW, Ac] or [0, E, RW, Ac] - 13:14 Privl 0 = Highest privilege (OS), 3 = Lowest privilege (User applications) - 15 Pr Set to 1 if segment is present - 16:19 Limit 16:19 Bits 16-19 in the segment limiter - 20:22 Attributes Different attributes, depending on the segment type - 23 Gr Used together with the limiter, to determine the size of the segment - 24:31 Base 24:31 The last 24-31 bits in the base address \ No newline at end of file diff --git a/include/early_mem.inc b/include/early_mem.inc index bce18d9..a705b2f 100755 --- a/include/early_mem.inc +++ b/include/early_mem.inc @@ -20,29 +20,6 @@ %ifndef __INC_EARLY_MEM - -; ## Generic Low mem map (from osdev wiki) ## -; start end size type description -; Low Memory (the first MiB) -; 0x00000000 0x000003FF 1 KiB RAM - partially unusable Real Mode IVT (Interrupt Vector Table) -; 0x00000400 0x000004FF 256 bytes RAM - partially unusable BDA (BIOS data area) -; 0x00000500 0x00007BFF almost 30 KiB RAM - free for use Conventional memory -; 0x00007C00 0x00007DFF 512 bytes RAM - partially unusable OS BootSector -; 0x00007E00 0x0007FFFF 480.5 KiB RAM - free for use Conventional memory -; 0x00080000 0x0009FFFF 128 KiB RAM - partially unusable EBDA (Extended BIOS Data Area) -; 0x000A0000 0x000FFFFF 384 KiB various (unusable) Video memory, ROM Area - -; ## A rough overview of high mem ## -; Idealy this needs to be probed with the E820 functions -; # Start # End # size # description -; -; 0x00100000 0x00EFFFFF 0x00E00000 (14 MiB) RAM -- free for use (if it exists) Extended memory -; 0x00F00000 0x00FFFFFF 0x00100000 (1 MiB) Possible memory mapped hardware ISA Memory Hole 15-16MB -; 0x01000000 ???????? ??? (whatever exists) RAM -- free for use More Extended memory -; 0xC0000000 (sometimes) 0xFFFFFFFF 0x40000000 (1 GiB) Memory mapped PCI devices, PnP NVRAM?, IO APIC/s, local APIC/s, BIOS, ... -; 0x0000000100000000 ??? ??? (whatever exists) RAM -- free for use (PAE/64bit)/More Extended memory -; ???????????????? ??? ??? Potentially usable for memory mapped PCI devices in modern hardware (but typically not, due to backward compatibility) - ;PhysicalAddress = Segment * 16 + Offset %define SEG_TO_LINEAR(s,o) ((s << 4) + o)