As we all know that in real mode we can use the BIOS Interrupts function to do a lot of tasks. You can have in depth understanding of the different addressing ways of disk from this chapter: https://thejat.in/learn/disk-addressing
BIOS Disk Services (INT 13h)
BIOS provides a set of disk services through interrupt 13h, which are commonly used for accessing disk drives in real mode. Here are some key functions:
1️⃣ CHS Addressing (INT 13h)
CHS (Cylinder-Head-Sector) is an older method for addressing data on a hard drive. It divides the hard drive into a three-dimensional space, much like a grid, allowing data to be accessed by specifying three coordinates: the cylinder number, the head number, and the sector number.
- Cylinder: Represents a track through all the platters. Each platter has several tracks, and a stack of tracks across platters forms a cylinder.
- Think of it as a stack of concentric tracks on all platters. The number of cylinders is the total number of tracks on a single platter.
- The cylinder number is 0-based.
- Head: Refers to the read/write head of the disk. Each platter has two surfaces, each with a read/write head. The head number specifies which surface to use.
- Specifies which platter (or disk surface) the data is on. Each side of a platter has its own read/write head.
- The head number is 0-based.
- Sector: A subdivision of a track. Each track is divided into several sectors, usually 512 bytes each. The sector number is 1-based.
- The sector number is 1-based.
For example, a location could be specified as (Cylinder 1023, Head 15, Sector 63), which would mean:
- The 1023rd track (cylinder),
- The 15th head (surface),
- The 63rd sector on that track.
1.1 Reading Sectors (Function 02h):
- Function: 02h
- Description: Read sectors from the disk.
- Registers:
AH
: 02h (Function code for read)AL
: Number of sectors to readCH
: Cylinder numberCL
: Sector number (bits 0-5), high bits of cylinder number (bits 6-7)DH
: Head numberDL
: Drive number (80h for the first hard drive)ES:BX
: Register pair is used to specify the address of the buffer.
Example code to read sectors:
mov ax, 0x07C0 ; Set up segment
mov es, ax
mov bx, 0x0200 ; Offset of the buffer
; Set up the buffer to read sectors
; 0x7C00:0x0200 (0x7E00 physical address)
mov ah, 0x02 ; BIOS function: Read sectors
mov al, 1 ; Number of sectors to read
mov ch, 0 ; Cylinder number (starts form 0)
mov cl, 1 ; Sector number
mov dh, 0 ; Head number
mov dl, 0x80 ; Drive number (first hard drive)
int 0x13 ; Call BIOS disk interrupt
jc error ; Jump to error handler if carry flag is set
1.2 Writing Sectors (Function 03h):
- Function: 03h
- Description: Write sectors to the disk.
- Registers:
AH
: 03h (Function code for write)AL
: Number of sectors to writeCH
: Cylinder numberCL
: Sector number (bits 0-5), high bits of cylinder number (bits 6-7)DH
: Head numberDL
: Drive number (80h for the first hard drive)ES:BX
: Register pair is used to specify the address of the buffer.
Example code to write sectors:
mov ax, 0x07C0 ; Set up segment
mov ds, ax ; Data segment
mov es, ax ; Extra segment
; Set up the buffer at 0x7C00:0x0200 (0x7E00 physical address)
mov bx, 0x0200 ; Offset for the buffer
; Fill the buffer with data to be written (example data)
mov di, bx
mov byte [es:di], 'H'
mov byte [es:di + 1], 'e'
mov byte [es:di + 2], 'l'
mov byte [es:di + 3], 'l'
mov byte [es:di + 4], 'o'
; Write one sector to Cylinder 0, Head 0, Sector 1
mov ah, 0x03 ; BIOS function: Write sectors
mov al, 1 ; Number of sectors to write
mov ch, 0 ; Cylinder number
mov cl, 1 ; Sector number
mov dh, 0 ; Head number
mov dl, 0x80 ; Drive number (first hard drive)
int 0x13 ; Call BIOS disk interrupt
jc error ; Jump to error handler if carry flag is set
🤷♂️ Limitations of CHS Addressing in Real Mode
- Capacity Limitations:
- Maximum Addressable Size: CHS addressing has limitations in terms of the maximum disk size it can address. Typically, it can address up to 1024 cylinders, 256 heads, and 63 sectors per track, which limits the total capacity to around 8.4 GB.
- Complexity:
- Address Translation: The need to translate logical addresses to physical CHS addresses adds complexity to the disk access process.
- Obsolescence:
- Most modern hardware ignores CHS altogether and uses LBA for accessing disk sectors.
2️⃣ Transition to LBA (INT 13h)
With the advent of larger hard drives and the need for more efficient addressing, the Logical Block Addressing (LBA) scheme was introduced. In modern systems, even when operating in real mode, extensions to BIOS interrupts (such as the Enhanced Disk Drive (EDD) BIOS functions) allow for the use of LBA.
EDD (INT 13h Extensions): Extended functions for INT 13h support LBA, enabling access to larger disks and simplifying the addressing process.
- Function 42h: Extended Read using LBA
- Function 43h: Extended Write using LBA
INT 13h Extensions Uses the DAP:
DAP stands for Disk Address Packet. It is a data structure used in the context of BIOS disk services to specify parameters for disk operations, such as reading or writing sectors on a disk drive. It provides the necessary information for the BIOS to perform the read operation.
Structure of DAP:
The DAP is of 8 bytes long.
A typical DAP structure consists of the following fields:
- Size (1 byte): Size of the DAP (usually 16 or 24 bytes).
- Mostly 16 bytes which is
0x10
.
- Mostly 16 bytes which is
- Reserved (1 byte): Reserved, must be zero
- Number of Blocks (2 bytes): Number of blocks (sectors) to read.
- Buffer Address (4 bytes): Segment pointer to the buffer to store the read data (or a flat 32-bit address in newer implementations)
- The first two bytes is of segment.
- The new two bytes is of offset.
- Starting LBA (8 bytes): 64-bit LBA address of the first block(sector) to read.
- The LBA (Logical Block Addressing) scheme treats the entire disk as a linear array of sectors, starting from sector 0 up to the last sector on the disk. Each sector has a unique LBA number.
- When you're reading sectors from the disk using LBA, each LBA corresponds to a specific sector on the disk, starting from the very first sector of the disk (LBA 0).
Offset | Size | Description |
---|---|---|
0x00 | 1 byte | Size of the DAP (must be 0x10 for 16 bytes) |
0x01 | 1 byte | Reserved (must be 0) |
0x02 | 2 bytes | Number of sectors to read |
0x04 | 4 bytes | Address of the buffer (linear address) |
0x08 | 8 bytes | Starting LBA (64-bit value) |
dap: ; Define the DAP structure
db 0x10 ; Packet size (16 bytes)
db 0 ; Reserved (should be 0)
dw 1 ; Number of sectors to read
dw 0 ; Offset of buffer (lower 16 bits)
dw 0 ; Segment of buffer
dq 0 ; Reserved (upper 32 bits)
OR
; This is used for the extended read function (int 0x13)
DiskPackage: db 0x10
db 0
.SectorsToRead dw 0
.Offset dw 0
.Segment dw 0
.Sector dq 0
Understanding LBA and Sectors:
- LBA 0: The very first sector of the disk.
- LBA 1: The second sector of the disk.
- LBA 2: The third sector of the disk.
- ...
- LBA n: The (n+1)th sector of the disk.
References of LBA: https://en.wikipedia.org/wiki/Logical_block_addressing
How It Works :-
- Prepare the DAP: Set up a Disk Address Packet with the necessary details:
- Specify the number of sectors to read.
- Provide the memory address where the data should be stored.
- Set the starting LBA of the read operation.
- Set Registers: Load the registers with the appropriate values:
- AH = 0x42 (function number)
- DL = drive number
- DS= segment pointer to the DAP
- Interrupt Call: Execute the interrupt
int 0x13
. - Check Status: After the call, check the carry flag (CF) and the AH register to determine if the operation succeeded or failed.
- CF clear: Operation succeeded.
- CF set: Operation failed, with an error code in AH.
Example of Using LBA in Real Mode:
Using the extended BIOS functions, you can read from and write to disks using LBA addresses:
2.1 Read Sectors Using LBA Extended Read Sectors (Function 0x42):
Function 0x42 is part of the Extended Disk Access (EDA) functions introduced with the Enhanced Disk Drive (EDD) BIOS specification. It allows reading of sectors using LBA, which supports larger disks and more efficient disk access.
Overview of INT 13h, AH=0x42:
- Purpose: Read sectors from a disk using LBA.
- Input Registers:
- DL: Drive number (e.g., 0x80 for the first hard drive).
- DS:SI: Pointer to the Disk Address Packet (DAP).
- Output Registers:
- CF (Carry Flag): If set, an error occurred.
- AH: Error code if CF is set.
Step-by-Step Guide:
- Prepare the Disk Address Packet (DAP):
- The DAP is a structure that holds information about the read operation, such as the number of sectors to read, the memory buffer to store the data, and the starting LBA (Logical Block Address).
- Set Up Registers:
- Load the function number (0x42) into
AH
. - Load the drive number into
DL
(e.g., 0x80 for the first hard drive). - Load the segment pointer to the DAP into
DS:SI
.
- Load the function number (0x42) into
- Call the Interrupt:
- Execute
int 13h
.
- Execute
- Check for Errors:
- After the call, check the carry flag (CF) to see if an error occurred. If CF is set, the error code will be in
AH
.
- After the call, check the carry flag (CF) to see if an error occurred. If CF is set, the error code will be in
; Set up segment registers
xor ax, ax
mov ds, ax
mov es, ax
; Set up the Disk Address Packet (DAP)
mov si, disk_address_packet
mov byte [si], 0x10 ; Size of the DAP (16 bytes)
mov byte [si+1], 0x00 ; Reserved, must be 0
mov word [si+2], 2 ; Number of sectors to read (1 KB = 2 sectors)
mov dword [si+4], 0x0000b000 ; Buffer address (0xb000)
mov dword [si+8], 59 ; Starting LBA (low 32 bits)
mov dword [si+12], 0 ; Starting LBA (high 32 bits)
; Extended Read Function
mov ah, 0x42 ; BIOS function: Extended read
mov dl, 0x80 ; Drive number (first hard drive)
int 0x13 ; Call BIOS disk interrupt
jc error ; Jump to error handler if carry flag is set
disk_address_packet: ; Data address packet
db 0x10 ; Packet size (16 bytes)
db 0 ; Reserved
dw 1 ; Number of blocks
dw 0 ; Offset of buffer
dw 0 ; Segment of buffer
dq 0 ; LBA address (64-bit)
;; OR
disk_address_packet:
times 16 db 0 ; Disk Address Packet (DAP) space
🐱👓 Explanation :-
1 Initialization:
- Segment registers (
DS
,ES
) are cleared to 0.
2 Setting Up the Disk Address Packet (DAP):
- The
disk_address_packet
is set up starting atdisk_address_packet
label. - The DAP size is set to 16 bytes (
0x10
). - The reserved byte is set to 0.
- The number of sectors to read is set to 2 (
1 KB = 2 sectors
). - The buffer address is set to 0xb000 (where the kernel will be loaded).
- The starting LBA is set to 59.
3 Calling INT 13h, AH=0x42:
AH
is set to0x42
to indicate the extended read function.DL
is set to0x80
, indicating the first hard drive.SI
points to the DAP.- The BIOS interrupt
int 0x13
is called to perform the read operation. - If the read fails (carry flag is set), the loader halts.
2 Writing Sectors Using LBA:
mov ah, 0x43 ; BIOS function: Extended write
mov dl, 0x80 ; Drive number (first hard drive)
mov si, dap ; Data address packet pointer
int 0x13 ; Call BIOS disk interrupt
jc error ; Jump to error handler if carry flag is set
dap: ; Data address packet
db 0x10 ; Packet size (16 bytes)
db 0 ; Reserved
dw 1 ; Number of blocks
dw 0 ; Offset of buffer
dw 0 ; Segment of buffer
dq 0 ; LBA address (64-bit)