- movb $0x88,%ah
- int $0x15
- jc panic # Carry flag set on error
-2: 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 starting at physical address LOADER_KERN_BASE by
-#### frobbing the IDE controller directly.
-
- movl $1, %ebx
- movl $LOADER_KERN_BASE, %edi
-read_sector:
-
- ### Poll status register while controller busy.
- movl $0x1f7, %edx
-1: inb %dx, %al
- testb $0x80, %al
- jnz 1b
-
- ### Read a single sector.
- movl $0x1f2, %edx
- movb $1, %al
- outb %al, %dx
-
- ### Sector number to write in low 28 bits.
- ### LBA mode, device 0 in top 4 bits.
- movl %ebx, %eax
- andl $0x0fffffff, %eax
- orl $0xe0000000, %eax
-
- ### Dump %eax to ports 0x1f3...0x1f6.
- movl $4, %ecx
-2: incw %dx
- outb %al, %dx
- shrl $8, %eax
- loop 2b
-
- ### READ command to command register.
- incw %dx
- movb $0x20, %al
- outb %al, %dx
-
- ### Poll status register while controller busy.
-1: inb %dx, %al
- testb $0x80, %al
- jnz 1b
-
- ### Poll status register until data ready.
-1: inb %dx, %al
- testb $0x08, %al
- jz 1b
-
- ### Transfer sector.
- movl $512 / 4, %ecx
- movl $0x1f0, %edx
- rep insl
-
- ### Next sector.
- incl %ebx
- cmpl $KERNEL_LOAD_PAGES*8 + 1, %ebx
- jnz read_sector
-
-##### Create temporary page directory and page table, set page
-##### directory pointer, and turn on paging.
-##### FIXME? We could use a single 4 MB page instead of 1024 4 kB pages.
-
- # Create page directory at 64 kB.
- movl $0x10000, %edi
- movl %edi, %cr3
-
- # Fill page directory with zeroes.
- subl %eax, %eax
- movl $0x400, %ecx
- rep stosl
-
- # Set PDEs for 0 and LOADER_PHYS_BASE to point to the
- # page table.
- movl $0x11000 | PG_U | PG_W | PG_P, %eax
- movl %eax, 0x10000
- movl %eax, 0x10000 | (LOADER_PHYS_BASE >> 20)
-
- # Initialize page table.
- movl $PG_U | PG_W | PG_P, %eax
- movl $0x400, %ecx
-1: stosl
- addl $0x1000, %eax
+ 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