Skip to content

Instantly share code, notes, and snippets.

@olsner
Created October 31, 2010 22:16
Show Gist options
  • Select an option

  • Save olsner/657234 to your computer and use it in GitHub Desktop.

Select an option

Save olsner/657234 to your computer and use it in GitHub Desktop.

Revisions

  1. olsner revised this gist Nov 2, 2010. 1 changed file with 140 additions and 29 deletions.
    169 changes: 140 additions & 29 deletions start.asm
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,7 @@
    ; vim:ts=8:sts=8:sw=8:filetype=nasm:
    ; This is the real bootstrap of the kernel, and
    ; it is this part that is loaded by the boot sector (boot.asm)

    org 0
    bits 16

    @@ -19,52 +23,159 @@ bits 16
    RX_ACCESS equ 10011010b
    RW_ACCESS equ 10010010b

    jmp start
    code_seg equ 8
    data_seg equ 16

    align 4
    init_gdt:
    define_descriptor 0,0,0,0,0,0
    define_descriptor 0xffff,0,0,RX_ACCESS,0xcf,0
    define_descriptor 0xffff,0,0,RW_ACCESS,0xcf,0
    gdt_end:
    start:
    mov ax,cs
    mov ds,ax

    code_seg equ 8
    data_seg equ 16
    mov ax,0x0e00+'A'
    mov bl,0x0f
    int 10h

    gdtr:
    dw gdt_end-init_gdt-1 ; Limit
    dd init_gdt+0x8000 ; Offset
    cli
    mov al,0xff
    out 0xa1, al
    mov al,0xfb
    out 0x21, al
    mov ax,0x0e00+'B'
    mov bl,0x0f
    int 10h

    align 4
    idtr:
    dw 0
    dd 0
    start:
    [...]
    ; Protect Enable -> 1
    mov eax,cr0
    or eax,1
    mov cr0,eax
    lidt [ds:idtr]
    lgdt [ds:gdtr]
    lidt [idtr]
    lgdt [gdtr]

    ; Reset cs by far-jumping to the other side
    jmp code_seg:dword other_side+0x8000
    jmp code_seg:dword start32+0x8000
    bits 32
    other_side:
    start32:
    mov ax,data_seg
    mov ds,ax
    mov es,ax
    mov fs,ax
    mov gs,ax
    mov ss,ax

    start32:
    mov ebx,0xb8000
    mov [ds:0xb8000], byte 0x43
    inc ebx
    mov [ds:0xb8001], byte 0x0f
    hlt
    mov ebx, 0xb8000
    mov edi, ebx

    xor eax,eax
    mov ecx,2*80*25/4 ; 125 << 3
    rep stosd

    mov word [ebx],0x0f00+'P'

    ; magic flag time:
    ; All entries have the same lower 4 bits (all set to 1 here):
    ; - present (bit 0)
    ; - Read-only/Writable (bit 1), 1 = Writable
    ; - User/Supervisor bit (bit 2), 1 = Accessible from user mode
    ; - Page-level writethrough (bit 3)
    ; For the final one, we set a couple more flags:
    ; - Global (bit 8), along with PGE, the page will remain in TLB after
    ; changing the page tables, we promise that the page has the same
    ; mapping in all tables.
    ; - Page Size (bit 7), this is the final page entry rather than a link
    ; to another table. In our case, this makes this a 2MB page since the
    ; bit is set already in the third level.

    ; Write PML4 (one entry, pointing to one PDP)
    mov edi, 0xa000 ; base address, where we put the PML4's
    mov eax, 0xb00f ; 0xb000 is where the PDP starts, 0xf is magic
    stosd

    xor eax,eax
    mov ecx, 0x03ff ; number of zero double-words in PML4
    rep stosd

    ; Write PDP (one entry, pointing to one PD)
    mov eax, 0xc00f ; 0xc000 is the start of the PD
    stosd

    xor eax,eax
    mov ecx, 0x03ff ; number of zero double-words in PDP
    rep stosd

    ; Write PD (one entry mapped, address 0, plus flags)
    mov eax, 0x018f ; magic constant (see above)
    stosd
    xor eax,eax
    mov ecx, 0x03ff
    rep stosd

    ; Start mode-switching
    mov eax, 10100000b ; PAE and PGE
    mov cr4, eax

    mov edx, 0xa000 ; address of PML4
    mov cr3, edx

    mov ecx, 0xc0000080 ; EFER MSR
    rdmsr
    or eax, 0x100 ; Set LME
    wrmsr

    mov eax,cr0
    or eax,0x80000000 ; Enable paging
    mov cr0,eax

    ; Set code segment to L=1,D=0
    xor eax,eax
    mov edi,gdt_start+0x8000+8
    mov ecx,4
    rep stosd

    mov word [gdt_start+8+5+0x8000], 0x2098
    mov byte [gdt_start+16+5+0x8000], 0x90

    jmp code_seg:dword start64+0x8000

    bits 64
    start64:
    mov ax,data_seg
    mov ds,ax

    mov edi,0xb8004
    ; Just do something silly that should fail if we weren't in long mode
    shl rdi,32
    test edi,edi
    jnz not_long
    shr rdi,32
    ; Then proceed to write a message
    mov esi,message+0x8000
    mov ecx,2
    rep movsq

    mov rax,8 ; Random

    jmp $

    not_long:
    ud2

    message:
    dq 0x0747074e074f074c, 0x07450744074f074d
    gdt_start:
    define_descriptor 0,0,0,0,0,0
    define_descriptor 0xffff,0,0,RX_ACCESS,0xcf,0
    define_descriptor 0xffff,0,0,RW_ACCESS,0xcf,0
    gdt_end:

    align 4
    gdtr:
    dw gdt_end-gdt_start-1 ; Limit
    dd gdt_start+0x8000 ; Offset

    idtr:
    dw 0
    dd 0

    times 4096-($-$$) db 0
  2. olsner revised this gist Oct 31, 2010. 1 changed file with 0 additions and 9 deletions.
    9 changes: 0 additions & 9 deletions start.asm
    Original file line number Diff line number Diff line change
    @@ -1,15 +1,6 @@
    org 0
    bits 16

    struc Descriptor
    seg_limit: resw 1
    addr_00_15: resw 1
    addr_16_23: resb 1
    access: resb 1
    granularity: resb 1
    addr_24_31: resb 1
    endstruc

    %macro define_descriptor 6 ; 0-6 0,0,0,0,0,0
    dw %1 ;seg_limit
    dw %2 ;addr_00_15
  3. olsner renamed this gist Oct 31, 2010. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  4. olsner created this gist Oct 31, 2010.
    79 changes: 79 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,79 @@
    org 0
    bits 16

    struc Descriptor
    seg_limit: resw 1
    addr_00_15: resw 1
    addr_16_23: resb 1
    access: resb 1
    granularity: resb 1
    addr_24_31: resb 1
    endstruc

    %macro define_descriptor 6 ; 0-6 0,0,0,0,0,0
    dw %1 ;seg_limit
    dw %2 ;addr_00_15
    db %3 ;addr_16_23
    db %4 ;flags
    db %5 ;access
    db %6 ;addr_24_31
    %endmacro

    ; Bit Field
    ; 7 Present = 1
    ; 6..5 Ring == 0
    ; 4 Descriptor type == 1
    ; 3..0 Type = cs: 1010, ds: 0010

    RX_ACCESS equ 10011010b
    RW_ACCESS equ 10010010b

    jmp start

    align 4
    init_gdt:
    define_descriptor 0,0,0,0,0,0
    define_descriptor 0xffff,0,0,RX_ACCESS,0xcf,0
    define_descriptor 0xffff,0,0,RW_ACCESS,0xcf,0
    gdt_end:

    code_seg equ 8
    data_seg equ 16

    gdtr:
    dw gdt_end-init_gdt-1 ; Limit
    dd init_gdt+0x8000 ; Offset

    align 4
    idtr:
    dw 0
    dd 0
    start:
    [...]
    ; Protect Enable -> 1
    mov eax,cr0
    or eax,1
    mov cr0,eax

    lidt [ds:idtr]
    lgdt [ds:gdtr]

    ; Reset cs by far-jumping to the other side
    jmp code_seg:dword other_side+0x8000

    bits 32
    other_side:
    mov ax,data_seg
    mov ds,ax
    mov es,ax
    mov fs,ax
    mov gs,ax
    mov ss,ax

    start32:
    mov ebx,0xb8000
    mov [ds:0xb8000], byte 0x43
    inc ebx
    mov [ds:0xb8001], byte 0x0f

    hlt