Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; Second stage bootloader
- [BITS 16]
- [ORG 0x7E00]
- ; in first_stage.asm ensure this appears just before far hmp
- ; to this location.
- ; mov dl, [bootDrive] ; Drive number
- KERNEL_OFFSET_HIGH equ 0xFFFF_FFFF_8000_0000
- KERNEL_OFFSET_LOW equ 0x8400
- start:
- ; Set up segments
- xor ax, ax
- mov ds, ax
- mov es, ax
- mov ss, ax
- mov sp, 0x7C00 ; Set stack just below the bootloader
- ; Print initial success message
- mov si, stage2Msg
- call print_string_16
- ; Load the rest of Stage 2 and the kernel
- call load_kernel
- ; Enable A20 line
- call enable_A20
- ; Load GDT and switch to protected mode
- call enable_protected_mode
- load_kernel:
- ; Load the rest of Stage 2 and the kernel from disk
- mov ah, 0x02 ; BIOS read sector function
- mov al, 60 ; Number of sectors to read (adjust as needed)
- mov ch, 0 ; Cylinder number
- mov cl, 5 ; Start from sector 5
- mov dh, 0 ; Head number
- mov bx, KERNEL_OFFSET_LOW
- ; Load starting at KERNEL_OFFSET_LOW
- int 0x13 ; BIOS interrupt to read disk
- jc disk_error ; Jump if error
- ret
- enable_A20:
- in al, 0x92
- or al, 2
- out 0x92, al
- ret
- enable_protected_mode:
- cli ; Disable interrupts
- lgdt [gdt_descriptor]
- ; Enable protected mode
- mov eax, cr0
- or eax, 1 ; Set PE (Protection Enable) bit
- mov cr0, eax
- ; Far jump to flush prefetch and enter protected mode
- jmp 0x08:protected_mode_entry
- [BITS 32]
- protected_mode_entry:
- ; Set up 32-bit data segments
- mov ax, 0x10 ; Data segment selector
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- ; Set up stack for protected mode
- mov esp, 0x90000
- ; Print protected mode message
- mov esi, protected_mode_msg
- call print_string_pm
- ; Set up paging for long mode
- call setup_paging
- ; Load 64-bit GDT
- lgdt [gdt64_descriptor]
- ; Enable long mode
- call enable_long_mode
- ; Jump to long mode entry
- jmp 0x08:long_mode_entry
- setup_paging:
- ; Identity map first 2MB
- mov edi, 0x1000 ; Page directory base address
- xor eax, eax ; Clear EAX (for zero-fill)
- mov ecx, (5*4096)/4 ; Number of 4KB entries
- rep stosd ; Zero the page directory and tables
- ; Identity map first 2MiB
- ; Map 0x0000000000000000-0x00000000001fffff to physical 0x00000000-0x001fffff
- mov dword [0x1000], 0x00002003 ; PML4[0] = 0x2000 | PRESENT | READWRITE
- mov dword [0x2000], 0x00003003 ; PDP[0] = 0x3000 | PRESENT | READWRITE
- mov dword [0x3000], 0x00000083 ; PD[0] = 0x0000 | PRESENT | READWRITE | 2MIB_PAGE
- ; Map 0xFFFFFFFF80000000-0xffffffff801fffff to physical 0x00000000-0x001fffff
- mov dword [0x1000+8*((KERNEL_OFFSET_HIGH>>39) & 0x1ff)], 0x00004003
- ; PML4[511] = 0x4000 | PRESENT | READWRITE
- mov dword [0x4000+8*((KERNEL_OFFSET_HIGH>>30) & 0x1ff)], 0x00005003
- ; PDP[510] = 0x5000 | PRESENT | READWRITE
- mov dword [0x5000+8*((KERNEL_OFFSET_HIGH>>21) & 0x1ff)], 0x00000083
- ; PD[0] = 0x0000 | PRESENT | READWRITE | 2MIB_PAGE
- mov edi, 0x1000
- mov cr3, edi ; Load the page directory base into CR3 (set PDBR)
- ret
- enable_long_mode:
- ; Enable long mode in IA32_EFER MSR
- mov ecx, 0xC0000080
- rdmsr
- or eax, 1 << 8 ; Set Long Mode Enable (LME) bit
- wrmsr
- mov eax, 10100000b ; Enable PAE and PGE bits and everything else off.
- mov cr4, eax
- ; Enable paging and long mode by setting the PG and PE bits in CR0
- mov eax, cr0
- or eax, 1 << 31 ; Enable paging (PG bit)
- mov cr0, eax
- ret
- [BITS 64]
- long_mode_entry:
- ; Set up segment registers for long mode
- mov ax, 0x10 ; Data segment selector
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- ; Set up stack in higher half
- mov rsp, 0x90000 + KERNEL_OFFSET_HIGH
- ; Print long mode message
- mov rsi, long_mode_msg
- call print_string_lm
- ; Jump to kernel entry point (higher-half address)
- mov rax, KERNEL_OFFSET_HIGH+KERNEL_OFFSET_LOW
- ; Kernel address in higher-half memory
- jmp rax
- [BITS 16]
- print_string_16:
- lodsb
- or al, al
- jz .done
- mov ah, 0x0E ; BIOS teletype function
- int 0x10
- jmp print_string_16
- .done:
- ret
- [BITS 32]
- print_string_pm:
- push eax
- push ebx
- mov ebx, 0xB8000 ; VGA video memory address
- .loop:
- lodsb
- or al, al
- jz .done
- mov ah, 0x0F ; Text attribute for character
- mov [ebx], ax ; Write character to VGA memory
- add ebx, 2 ; Move to next character
- jmp .loop
- .done:
- pop ebx
- pop eax
- ret
- [BITS 64]
- print_string_lm:
- push rax
- push rbx
- mov rbx, 0xB8000 ; VGA video memory address
- .loop:
- lodsb
- or al, al
- jz .done
- mov ah, 0x0F ; Text attribute for character
- mov [rbx], ax ; Write character to VGA memory
- add rbx, 2 ; Move to next character
- jmp .loop
- .done:
- pop rbx
- pop rax
- ret
- disk_error:
- ; Display error and halt
- mov si, diskErrorMsg
- call print_string_16
- cli
- hlt
- ; Data
- stage3Msg db 'Entered Stage 2', 13, 10, 0
- stage2Msg db 'Entered Stage 2', 13, 10, 0
- protected_mode_msg db 'Entered Protected Mode', 0
- long_mode_msg db 'Entered Long Mode', 0
- diskErrorMsg db 'Disk Error in Stage 2!', 13, 10, 0
- ; GDT for Protected Mode
- gdt_start:
- dq 0x0000000000000000 ; Null descriptor
- dq 0x00CF9A000000FFFF ; 32-bit code descriptor
- dq 0x00CF92000000FFFF ; 32-bit data descriptor
- gdt_end:
- gdt_descriptor:
- dw gdt_end - gdt_start - 1
- dd gdt_start
- ; GDT for Long Mode
- gdt64_start:
- dq 0x0000000000000000 ; Null descriptor
- dq 0x00AF9A000000FFFF ; 64-bit code descriptor
- dq 0x00AF92000000FFFF ; 64-bit data descriptor
- gdt64_end:
- gdt64_descriptor:
- dw gdt64_end - gdt64_start - 1
- dq gdt64_start
- times 512*3 - ($ - $$) db 0 ; Pad to 3 sectors
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement