148 lines
2.9 KiB
NASM
148 lines
2.9 KiB
NASM
ORG 0x7c00
|
|
BITS 16
|
|
|
|
CODE_SEG equ gdt_code - gdt_start
|
|
DATA_SEG equ gdt_data - gdt_start
|
|
|
|
jmp short start
|
|
nop
|
|
|
|
;FAT16 HEADER
|
|
OEMIdentifier db 'AOMUAOMU' ; Must be 8 bytes
|
|
BytesPerSector dw 0x200 ; 512 bytes per sector
|
|
SectorsPerCluster db 0x80 ;
|
|
ReservedSectors dw 0xC8 ; 200 reserved sectors for kernel
|
|
FATCopies db 0x02 ;
|
|
RootDirEntries dw 0x40 ;
|
|
NumSectors dw 0x00 ; Unused
|
|
MediaType db 0xF8 ; ?
|
|
SectorsPerFat dw 0x100 ; ?
|
|
SectorsPerTrack dw 0x20
|
|
NumberOfHeads dw 0x40
|
|
HiddenSectors dd 0x00
|
|
SectorsBig dd 0x773594 ; ??
|
|
|
|
; Extended BPB (Dos 4.0)
|
|
DriveNumber db 0x80
|
|
WinNTBit db 0x00
|
|
Signature db 0x29
|
|
VolumeID dd 0xd105
|
|
VolumeIDString db 'AOMUAOMUBOO' ; Must be 11 bytes
|
|
SystemIDString db 'FAT16 ' ; Must be 8 bytes
|
|
|
|
start:
|
|
jmp 0:step2 ; Set code segment
|
|
|
|
step2:
|
|
cli ; Clear Interrupts
|
|
mov ax, 0x00
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov ss, ax
|
|
mov sp, 0x7c00
|
|
sti ; Enable Interrupts
|
|
|
|
.load_protected:
|
|
cli
|
|
lgdt[gdt_descriptor]
|
|
mov eax, cr0
|
|
or eax, 0x1
|
|
mov cr0, eax
|
|
jmp CODE_SEG:load32
|
|
|
|
;GDT
|
|
gdt_start:
|
|
gdt_null:
|
|
dd 0x0
|
|
dd 0x0
|
|
|
|
; offset 0x8
|
|
gdt_code: ; CS should point here
|
|
dw 0xffff ; Segment limit 0:15
|
|
dw 0 ; Base 0:15
|
|
db 0 ; Base 16:23
|
|
db 0x9a ; Access byte
|
|
db 11001111b; high 4 bit & low 4 bit flags
|
|
db 0 ; Base 24:31
|
|
|
|
gdt_data: ; DS, SS, ES, FS, GS
|
|
dw 0xffff ; Segment limit 0:15
|
|
dw 0 ; Base 0:15
|
|
db 0 ; Base 16:23
|
|
db 0x92 ; Access byte
|
|
db 11001111b ; high 4 bit & low 4 bit flags
|
|
db 0 ; Base 24:31
|
|
|
|
gdt_end:
|
|
|
|
gdt_descriptor:
|
|
dw gdt_end - gdt_start - 1
|
|
dd gdt_start
|
|
|
|
[BITS 32]
|
|
load32:
|
|
mov eax, 1 ; start sector
|
|
mov ecx, 100 ; number of sectors to read
|
|
mov edi, 0x0100000 ; destination address
|
|
call ata_lba_read
|
|
jmp CODE_SEG:0x0100000
|
|
|
|
ata_lba_read:
|
|
mov ebx, eax ; backup eax for later
|
|
|
|
; send the highest 8 bits to the disk controller
|
|
shr eax, 24
|
|
or eax, 0xE0 ; select master drive
|
|
mov dx, 0x1F6
|
|
out dx, al
|
|
|
|
; send total sectors to read
|
|
mov eax, ecx
|
|
mov dx, 0x1F2
|
|
out dx, al
|
|
|
|
; send another 8 bits of the lba
|
|
mov eax, ebx
|
|
mov dx, 0x1F3
|
|
out dx, al
|
|
|
|
; send another 8 bits of the lba
|
|
mov dx, 0x1F4
|
|
mov eax, ebx ; restore the backup lba, just in case
|
|
shr eax, 8
|
|
out dx, al
|
|
|
|
; send upper 16 bits of lba
|
|
mov dx, 0x1F5
|
|
mov eax, ebx
|
|
shr eax, 16
|
|
out dx, al
|
|
|
|
mov dx, 0x1F7
|
|
mov al, 0x20
|
|
out dx, al
|
|
|
|
; Read all sectors into memory
|
|
.next_sector:
|
|
push ecx
|
|
|
|
; checking if we need to read
|
|
.try_again:
|
|
mov dx, 0x1F7
|
|
in al, dx
|
|
test al, 8
|
|
jz .try_again
|
|
|
|
; read 256 words at a time
|
|
mov ecx, 256
|
|
mov dx, 0x1F0
|
|
rep insw
|
|
pop ecx
|
|
loop .next_sector
|
|
|
|
ret
|
|
|
|
times 510- ($ - $$) db 0 ; pad with zeros to 510 bytes (+boot signature)
|
|
dw 0xAA55
|
|
|