- movb $0x88,%ah
- int $0x15
- jc panic # Carry flag set on error
- addl $1024,%eax # Total kB
- shrl $2,%eax # Total 4 kB pages
- movl %eax, ram_pages
-
-#### switch from real to protected mode
-#### The segments in GDT allow all of physical memory to be accessed.
-#### Furthermore, the segments have base addresses of 0, so that the
-#### segment translation is a NOP, ie. virtual addresses are identical to
-#### their physical addresses. With this setup, it appears to this code
-#### that it is running directly on physical memory.
-
- cli # Mandatory since we dont set up an IDT
- lgdt gdtdesc # load GDT -- mandatory in protected mode
- movl %cr0, %eax # turn on protected mode
- orl $CR0_PE, %eax #
- movl %eax, %cr0 #
- ### CPU magic: jump to relocation, flush prefetch queue, and reload %cs
- ### Has the effect of just jmp to the next instruction, but simultaneous
- ### loads CS with $PROT_MODE_CSEG.
- ljmp $SEL_KCSEG, $protcseg
-
-#### We are in protected mode in a 32-bit segment (hence the .code32)
-protcseg:
- .code32
- movw $SEL_KDSEG, %ax # set up data segment registers
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %fs
- movw %ax, %gs
- movw %ax, %ss
-
-#### Load kernel at 1 MB by frobbing the IDE controller directly.
-
- movl $1, %ebx
- movl $0x100000, %edi
-read_sector:
- movl $0x1f7, %edx
-1: inb %dx, %al
- testb $0x80, %al
- jnz 1b
+ mov si, 446
+1: mov al, [es:si+4]
+ cmp al, 0x20
+ jz found_boot_partition
+ cmp al, 0x05
+ jz found_extended_partition
+ cmp al, 0x0f
+ jz found_extended_partition
+ cmp al, 0x85
+ jz found_extended_partition
+ cmp al, 0xc5
+ jz found_extended_partition
+next_parttbl_entry:
+ add si, 16
+ cmp si, 510
+ jb 1b
+
+no_boot_partition:
+ clc
+ ret
+no_such_drive:
+ stc
+ ret
+
+found_extended_partition:
+ # DL = drive number.
+ # ES:SI -> partition table entry for extended partition.
+ # Recursively examine it.
+ pusha
+ mov ebx, es:[si+8]
+ mov ax, es
+ add ax, 0x20
+ mov es, ax
+ call scan_partitions
+ popa
+ jmp next_parttbl_entry
+
+found_boot_partition:
+ mov ebx, [es:si+8] # EBX = first sector
+ mov cx, [es:si+12] # CX = number of sectors
+ mov ax, 0x1000 # ES:0000 -> load address
+ mov es, ax
+1: call read_sector
+ add ax, 0x20
+ mov es, ax
+ loop 1b
+
+ ljmp 0x1000, 0
+
+ # ebx: sector number
+ # dl: drive number
+ # es:0000: destination buffer
+ # returns error flag in CF
+read_sector:
+ pusha
+ or dl, dl # Floppy drives: DL >= 0
+ jns read_floppy_sector
+
+read_harddrv_sector:
+ sub eax, eax
+ push eax # LBA sector number [32:63]
+ push ebx # LBA sector number [0:31]
+ push es
+ push 0
+ push 1 # Transfer one sector
+ push 16 # Packet size
+ mov ah, 0x42 # Extended read
+ mov si, sp # DS:SI -> packet
+ int 0x13 # Error code in CF
+ lahf
+ add sp, 16
+ sahf
+read_sector_done:
+ popa
+ ret # Error code in CF
+
+read_floppy_sector:
+ #define HEADS 2
+ #define SECTORS 36
+
+ # In: BX = LBA sector number, DL = drive.
+ # Out: BL = drive, DX = cylinder, AL = head, AH = sector.
+ sub ax, ax
+ xchg dx, bx # DX = LBA sector number, BL = drive
+ mov cx, HEADS * SECTORS
+ div cx # AX = cyl, DX = hd + (sec-1) * SECTORS
+ xchg ax, dx # DX = cyl, AX = hd + (sec-1) * SECTORS
+ mov cl, SECTORS
+ div cl # AL = head, AH = sector - 1
+ inc ah
+
+ # Read sector.
+ mov ch, dl # CH = cylinder
+ mov cl, ah # CL = sector
+ mov dh, al # DH = head
+ mov dl, bl # DL = drive
+ mov ax, 0x0201 # AH = function, AL = sectors to read
+ sub bx, bx # ES:BX -> buffer
+ mov di, 3 # Number of tries left.