os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

pxe.asm (13797B)


      1 	bits 16
      2 
      3 _start:
      4 	mov bp, sp
      5 
      6 	call .1
      7 .1:
      8 	pop di
      9 
     10 	mov cs:[di + pxenv_ptr - .1], bx
     11 	mov cs:[di + pxenv_ptr - .1 + 2], es
     12 
     13 	mov eax, ss:[bp + 4]
     14 	mov cs:[di + pxe_ptr - .1], eax
     15 
     16 	push booting_msg
     17 	call puts
     18 	pop ax
     19 
     20 	call enable_a20
     21 	test ax, ax
     22 	jnz .no_a20
     23 
     24 	call detect_mem
     25 	test ax, ax
     26 	jnz .no_mem
     27 
     28 	call enter_unreal
     29 	test ax, ax
     30 	jnz .no_unreal
     31 
     32 	call check_unreal
     33 	test ax, ax
     34 	jnz .no_unreal
     35 
     36 	call find_pxe
     37 	test ax, ax
     38 	jnz .no_pxe
     39 
     40 	push dot
     41 	call puts
     42 	pop ax
     43 
     44 	call download
     45 	test ax, ax
     46 	jnz .no_download
     47 
     48 	push dot
     49 	call puts
     50 	pop ax
     51 
     52 	call parse_mb
     53 	test ax, ax
     54 	jnz .no_mb
     55 
     56 	call boot
     57 
     58 	push fail_errmsg
     59 	call puts
     60 	pop ax
     61 	jmp hang
     62 .no_a20:
     63 	push a20_errmsg
     64 	call puts
     65 	pop ax
     66 	jmp hang
     67 .no_mem:
     68 	push mem_errmsg
     69 	call puts
     70 	pop ax
     71 	jmp hang
     72 .no_unreal:
     73 	push unreal_errmsg
     74 	call puts
     75 	pop ax
     76 	jmp hang
     77 .no_pxe:
     78 	push pxe_errmsg
     79 	call puts
     80 	pop ax
     81 	jmp hang
     82 .no_download:
     83 	push download_errmsg
     84 	call puts
     85 	pop ax
     86 	jmp hang
     87 .no_mb:
     88 	push mb_errmsg
     89 	call puts
     90 	pop ax
     91 	jmp hang
     92 
     93 dot:
     94 	db `.`, 0
     95 booting_msg:
     96 	db `Booting.`, 0
     97 fail_errmsg:
     98 	db `\r\nBoot failed!`, 0
     99 a20_errmsg:
    100 	db `\r\nFailed to enable A20!`, 0
    101 mem_errmsg:
    102 	db `\r\nFailed to detect memory!`, 0
    103 unreal_errmsg:
    104 	db `\r\nFailed to enter unreal mode!`, 0
    105 pxe_errmsg:
    106 	db `\r\nNo pxe!`, 0
    107 download_errmsg:
    108 	db `\r\nFailed to download!`, 0
    109 mb_errmsg:
    110 	db `\r\nFailed to find a.out multiboot header!`, 0
    111 
    112 hang:
    113 	cli
    114 	hlt
    115 	jmp hang
    116 
    117 enable_a20:
    118 	pusha
    119 	; Check if we need to do anything
    120 	call test_a20
    121 	test ax, ax
    122 	jz .a20_ok
    123 	; BIOS - Query A20 Gate Support
    124 	mov ax, 0x2403
    125 	clc
    126 	int 0x15
    127 	jc .a20_bios
    128 	test ah, ah
    129 	jnz .a20_bios
    130 	test bx, 2
    131 	jz .a20_bios
    132 .a20_fast:
    133 	; Fast A20
    134 	in al, 0x92
    135 	or al, 2
    136 	out 0x92, al
    137 	; Check if that worked
    138 	call test_a20
    139 	test ax, ax
    140 	jz .a20_ok
    141 .a20_bios:
    142 	; BIOS - Enable A20 Gate
    143 	mov ax, 0x2401
    144 	clc
    145 	int 0x15
    146 	jc .a20_slow
    147 	test ah, ah
    148 	jnz .a20_slow
    149 	; Double check the bios
    150 	call test_a20
    151 	test ax, ax
    152 	jz .a20_ok
    153 .a20_slow:
    154 	; Give up
    155 	popa
    156 	mov ax, 1
    157 	ret
    158 .a20_ok:
    159 	popa
    160 	mov ax, 0
    161 	ret
    162 
    163 	; Result ax=0 if A20 is enabled
    164 test_a20:
    165 	push es
    166 	push ds
    167 	push si
    168 	push di
    169 	; ds:[di] es:[si] are aliases if A20=0
    170 	mov ax, 0
    171 	mov ds, ax
    172 	mov di, 0x0500
    173 	mov ax, -1
    174 	mov es, ax
    175 	mov si, 0x1500
    176 	; Write different values to ds:[di] to es:[si]
    177 	mov ax, 0
    178 	mov ds:[di], ax
    179 	mov ax, -1
    180 	mov es:[si], ax
    181 	; Compare the values
    182 	mov ax, ds:[di]
    183 	xor ax, es:[si]
    184 	not ax
    185 	pop di
    186 	pop si
    187 	pop ds
    188 	pop es
    189 	ret
    190 
    191 detect_mem:
    192 	pusha
    193 	push ds
    194 	push es
    195 	call .1
    196 .1:
    197 	pop bp
    198 	sub bp, .1
    199 	push cs
    200 	pop es
    201 	; BIOS  - Get memory size
    202 	clc
    203 	int 0x12
    204 	jc .no_mem
    205 	push ax
    206 	xor eax, eax
    207 	pop ax
    208 	shl eax, 10
    209 	mov es:[bp + low_mem_size], eax
    210 	; BIOS - Get high memory size
    211 	mov ah, 0x88
    212 	clc
    213 	int 0x15
    214 	jc .no_mem
    215 	push ax
    216 	xor eax, eax
    217 	pop ax
    218 	shl eax, 10
    219 	mov es:[bp + high_mem_size], eax
    220 	; Zero kernel size
    221 	mov dword es:[bp + kernel_size], 0
    222 	mov di, bp
    223 	add di, mmap + 4
    224 	mov ebx, 0
    225 	mov word es:[bp + mmap_size], 0
    226 .loop:
    227 	; BIOS - Get system memory map
    228 	mov edx, 0x534D4150
    229 	mov eax, 0xe820
    230 	mov ecx, 20
    231 	clc
    232 	int 0x15
    233 	jc .no_mem
    234 	mov edx, 0x534d4150
    235 	cmp eax, edx
    236 	jnz .no_mem
    237 	cmp ecx, 20
    238 	jnz .no_mem
    239 	mov es:[di - 4], ecx
    240 	add word es:[bp + mmap_size], 24
    241 	cmp word es:[bp + mmap_size], (mmap_end - mmap)
    242 	jz .no_mem
    243 	add di, 24
    244 	test ebx, ebx
    245 	jnz .loop
    246 	pop es
    247 	pop ds
    248 	popa
    249 	mov ax, 0
    250 	ret
    251 .no_mem:
    252 	pop es
    253 	pop ds
    254 	popa
    255 	mov ax, 1
    256 	ret
    257 
    258 enter_unreal:
    259 	pop ax
    260 	push cs
    261 	push ax
    262 	pusha
    263 	push ds
    264 	push es
    265 	push fs
    266 	push gs
    267 	pushf
    268 	cli
    269 	call .1
    270 .1:
    271 	xor ebx, ebx
    272 	pop bx
    273 	; Load the gdt
    274 	sub sp, 6
    275 	mov bp, sp
    276 	mov word ss:[bp], 39
    277 	xor eax, eax
    278 	mov ax, cs
    279 	shl eax, 4
    280 	add eax, ebx
    281 	add eax, (gdt - .1)
    282 	mov ss:[bp + 2], eax
    283 	lgdt ss:[bp]
    284 	add sp, 6
    285 
    286 	mov bx, sp
    287 	mov dx, ss
    288 
    289 	xor ebp, ebp
    290 	mov bp, sp
    291 	xor eax, eax
    292 	mov ax, ss
    293 	shl eax, 4
    294 	add ebp, eax
    295 
    296 	mov ecx, cr0
    297 	or ecx, 1
    298 	mov cr0, ecx
    299 
    300 	push 24
    301 	call .retf
    302 
    303 	mov ax, 32
    304 	mov ds, ax
    305 	mov es, ax
    306 	mov fs, ax
    307 	mov gs, ax
    308 	mov ss, ax
    309 	mov esp, ebp
    310 
    311 	mov ecx, cr0
    312 	and ecx, -2
    313 	mov cr0, ecx
    314 
    315 	mov ss, dx
    316 	mov sp, bx
    317 
    318 	popf
    319 	pop gs
    320 	pop fs
    321 	pop es
    322 	pop ds
    323 	popa
    324 	mov ax, 0
    325 .retf:
    326 	retf
    327 
    328 gdt:
    329 	; 0 = null
    330 	dq 0x0000000000000000
    331 	; 8 = 32 code
    332 	dq 0x00cf9b000000ffff
    333 	; 16 = 32 data
    334 	dq 0x00cf93000000ffff
    335 	; 24 = 16 code
    336 	dq 0x008f9b000000ffff
    337 	; 32 = 16 data
    338 	dq 0x008f93000000ffff
    339 
    340 check_unreal:
    341 	push ds
    342 	push es
    343 
    344 	mov ax, 0
    345 	mov ds, ax
    346 	mov ax, -1
    347 	mov es, ax
    348 
    349 	mov word ds:[0x500], 0
    350 	mov eax, 0x100500
    351 	mov word ds:[eax], 44
    352 	mov ax, ds:[0x500]
    353 	cmp ax, 0
    354 	jnz .fail
    355 
    356 	mov ax, es:[0x510]
    357 	cmp ax, 44
    358 	jnz .fail
    359 
    360 	mov ax, 0
    361 	pop es
    362 	pop ds
    363 	ret
    364 .fail:
    365 	mov ax, 1
    366 	pop es
    367 	pop ds
    368 	ret
    369 
    370 getframe:
    371 	call .1
    372 .1:
    373 	pop di
    374 	add di, (frame - .1)
    375 	push cs
    376 	pop ds
    377 	push cs
    378 	pop es
    379 	ret
    380 
    381 download:
    382 	push ds
    383 	push es
    384 	pusha
    385 	pushf
    386 
    387 	call getframe
    388 
    389 	mov word [di], 0		; status
    390 	mov word [di + 2], 2		; PXENV_PACKET_TYPE_DHCP_ACK
    391 	mov word [di + 4], 0		; buffer size
    392 	mov word [di + 6], 0		; buffer base
    393 	mov word [di + 8], 0		; buffer segment
    394 	mov word [di + 10], 0		; buffer limit
    395 	push ds
    396 	push di
    397 	mov bx, 0x71
    398 	push bx				; PXENV_GET_CACHED_INFO = 0x71
    399 	call far word [di + (pxe_entry - frame)]
    400 	add sp, 6
    401 	test ax, ax
    402 	jnz .fail
    403 
    404 	call getframe
    405 
    406 	mov si, di
    407 	add si, (filename - frame)
    408 	add di, 10
    409 	mov cx, 128
    410 	rep movsb
    411 
    412 	call getframe
    413 
    414 	mov word [di], 0		; status
    415 	mov byte [di + 2], 192		; server ip
    416 	mov byte [di + 3], 168
    417 	mov byte [di + 4], 30
    418 	mov byte [di + 5], 1
    419 	mov dword [di + 6], 0		; gateway ip
    420 	mov word [di + 138], 69		; port
    421 	mov word [di + 140], 512	; packet size
    422 	push ds
    423 	push di
    424 	mov bx, 0x20
    425 	push bx				; PXENV_TFTP_OPEN = 0x0020
    426 	call far [di + (pxe_entry - frame)]
    427 	add sp, 6
    428 	test ax, ax
    429 	jnz .fail
    430 
    431 	call getframe
    432 	mov eax, 0x100000
    433 	mov cs:[di + (download_ptr - frame)], eax
    434 
    435 .loop:
    436 
    437 	call getframe
    438 
    439 	mov ax, di
    440 	add ax, (page - frame)
    441 	mov word [di], 0		; status
    442 	mov word [di + 2], 0		; packet number
    443 	mov word [di + 4], 0		; buffer size
    444 	mov word [di + 6], ax		; buffer
    445 	mov word [di + 8], ds
    446 	push ds
    447 	push di
    448 	mov bx, 0x22
    449 	push bx				; PXENV_TFTP_READ = 0x0022
    450 	call far [di + (pxe_entry - frame)]
    451 	add sp, 6
    452 	test ax, ax
    453 	jnz .fail
    454 
    455 	call getframe
    456 
    457 	; Push the kernel pointer
    458 	xor ecx, ecx
    459 	mov cx, cs:[di + 4]
    460 	mov ebx, cs:[di + (kernel_size - frame)]
    461 	mov eax, ebx
    462 	add eax, ecx
    463 	mov cs:[di + (kernel_size - frame)], eax
    464 	add ebx, cs:[di + (download_ptr - frame)]
    465 
    466 	cmp cs:[di + (high_mem_size - frame)], eax
    467 	jb .fail
    468 
    469 	xor esi, esi
    470 	mov si, di
    471 	add si, (page - frame)
    472 
    473 	mov ax, 0
    474 	mov es, ax
    475 	mov edi, ebx
    476 
    477 	cld
    478 	rep a32 movsb
    479 
    480 	call getframe
    481 
    482 	; Keep reading blocks until we get a small one
    483 	cmp word cs:[di + 4], 512
    484 	jz .loop
    485 
    486 	call getframe
    487 
    488 	mov word cs:[di], 0		; status
    489 	push ds
    490 	push di
    491 	mov bx, 0x21
    492 	push bx				; PXENV_TFTP_CLOSE = 0x0021
    493 	call far [di + (pxe_entry - frame)]
    494 	add sp, 6
    495 	test ax, ax
    496 	jnz .fail
    497 
    498 	popf
    499 	popa
    500 	pop es
    501 	pop ds
    502 	mov ax, 0
    503 	ret
    504 .fail:
    505 	popf
    506 	popa
    507 	pop es
    508 	pop ds
    509 	mov ax, 1
    510 	ret
    511 
    512 find_pxe:
    513 	pusha
    514 	push ds
    515 	push es
    516 
    517 	mov ax, cs
    518 	mov es, ax
    519 
    520 	call .1
    521 .1:
    522 	pop bx
    523 
    524 	mov ax, es:[bx + (pxenv_ptr - .1 + 2)]
    525 	mov ds, ax
    526 	mov si, es:[bx + (pxenv_ptr - .1)]
    527 
    528 	; PXENV+
    529 	cmp word [si], 0x5850
    530 	jnz .fail
    531 	cmp word [si + 2], 0x4e45
    532 	jnz .fail
    533 	cmp word [si + 4], 0x2b56
    534 	jnz .fail
    535 	cmp word [si + 6], 0x0201
    536 	jb .fail
    537 	cmp byte [si + 8], 44
    538 	jb .fail
    539 	mov ch, 0
    540 	mov cl, [si + 8]
    541 	call bsum
    542 	test ax, ax
    543 	jnz .fail
    544 
    545 	mov ax, [si + 40]
    546 	mov es:[bx + (pxe_ptr - .1)], ax
    547 	mov ax, [si + 42]
    548 	mov es:[bx + (pxe_ptr - .1 + 2)], ax
    549 	mov ds, ax
    550 	mov si, es:[bx + (pxe_ptr - .1)]
    551 
    552 	; !PXE
    553 	cmp word [si], 0x5021
    554 	jnz .fail
    555 	cmp word [si + 2], 0x4558
    556 	jnz .fail
    557 	cmp byte [si + 4], 20
    558 	jb .fail
    559 	mov ch, 0
    560 	mov cl, [si + 4]
    561 	call bsum
    562 	test ax, ax
    563 	jnz .fail
    564 
    565 	; Save pxe entry point
    566 	mov ax, [si + 16]
    567 	mov es:[bx + pxe_entry - .1], ax
    568 	mov ax, [si + 18]
    569 	mov es:[bx + pxe_entry - .1 + 2], ax
    570 
    571 	pop es
    572 	pop ds
    573 	popa
    574 	mov ax, 0
    575 	ret
    576 .fail:
    577 	pop es
    578 	pop ds
    579 	popa
    580 	mov ax, 1
    581 	ret
    582 
    583 bsum:
    584 	push si
    585 	push cx
    586 	xor ax, ax
    587 	test cx, cx
    588 	jz .out
    589 .loop:
    590 	add al, ds:[si]
    591 	inc si
    592 	dec cx
    593 	jnz .loop
    594 .out:
    595 	pop cx
    596 	pop si
    597 	ret
    598 
    599 bzero32:
    600 	push edi
    601 	push ecx
    602 	test ecx, ecx
    603 	jz .out
    604 .loop:
    605 	mov byte ds:[edi], 0
    606 	inc edi
    607 	dec ecx
    608 	jz .out
    609 	jmp .loop
    610 .out:
    611 	pop ecx
    612 	pop edi
    613 	ret
    614 
    615 bcopy32:
    616 	push edi
    617 	push esi
    618 	push ecx
    619 	test ecx, ecx
    620 	jz .out
    621 	cmp edi, esi
    622 	je .out
    623 	jb .loop_forward
    624 	add esi, ecx
    625 	add edi, ecx
    626 .loop_backward:
    627 	dec edi
    628 	dec esi
    629 	mov al, ds:[esi]
    630 	mov ds:[edi], al
    631 	dec ecx
    632 	jz .out
    633 	jmp .loop_backward
    634 .loop_forward:
    635 	mov al, ds:[esi]
    636 	mov ds:[edi], al
    637 	inc esi
    638 	inc edi
    639 	dec ecx
    640 	jz .out
    641 	jmp .loop_forward
    642 .out:
    643 	pop ecx
    644 	pop esi
    645 	pop edi
    646 	ret
    647 
    648 parse_mb:
    649 	pusha
    650 	push ds
    651 	push es
    652 	pushf
    653 	cld
    654 	mov ax, 0
    655 	mov ds, ax
    656 	mov es, ax
    657 	call .1
    658 .1:
    659 	xor ebx, ebx
    660 	pop bx
    661 	; Bound the search to the first 8k (2k dwords)
    662 	mov ecx, 2048
    663 
    664 	sub ecx, 7
    665 	jbe .fail
    666 	; Find the multiboot header
    667 	mov edi, cs:[bx + (download_ptr - .1)]
    668 .loop:
    669 	mov eax, ds:[edi]
    670 	cmp eax, 0x1badb002
    671 	jnz .next
    672 	add eax, ds:[edi + 4]
    673 	add eax, ds:[edi + 8]
    674 	jz .found
    675 .next:
    676 	add edi, 4
    677 	dec ecx
    678 	jz .fail
    679 	jmp .loop
    680 .found:
    681 	test dword ds:[edi + 4], 0x10000
    682 	jz .fail
    683 
    684 	mov cs:[bx + (mb_ptr - .1)], edi
    685 
    686 	mov eax, ds:[edi + 12]
    687 	mov cs:[bx + (mb_header_addr - .1)], eax
    688 
    689 	mov eax, ds:[edi + 16]
    690 	mov cs:[bx + (mb_load_addr - .1)], eax
    691 
    692 	mov eax, ds:[edi + 20]
    693 	test eax, eax
    694 	jnz .endok
    695 	mov eax, cs:[bx + (mb_load_addr - .1)]
    696 	add eax, cs:[bx + (kernel_size - .1)]
    697 .endok:
    698 	mov cs:[bx + (mb_load_end_addr - .1)], eax
    699 
    700 	mov eax, ds:[edi + 24]
    701 	test eax, eax
    702 	jnz .bssok
    703 	mov eax, cs:[bx + (mb_load_end_addr - .1)]
    704 .bssok:
    705 	mov cs:[bx + (mb_bss_end_addr - .1)], eax
    706 
    707 	mov eax, ds:[edi + 28]
    708 	mov cs:[bx + (mb_entry_addr - .1)], eax
    709 
    710 	; sanity checks
    711 
    712 	; 0x100000 <= load_addr
    713 	cmp dword cs:[bx + (mb_load_addr - .1)], 0x100000
    714 	jb .fail
    715 
    716 	; load_addr <= header_addr
    717 	mov eax, cs:[bx + (mb_load_addr - .1)]
    718 	cmp eax, cs:[bx + (mb_header_addr - .1)]
    719 	ja .fail
    720 
    721 	; header_addr <= load_end_addr
    722 	mov eax, cs:[bx + (mb_header_addr - .1)]
    723 	cmp eax, cs:[bx + (mb_load_end_addr - .1)]
    724 	ja .fail
    725 
    726 	; load_addr <= entry_addr
    727 	mov eax, cs:[bx + (mb_load_addr - .1)]
    728 	cmp eax, cs:[bx + (mb_entry_addr - .1)]
    729 	ja .fail
    730 
    731 	; entry_addr <= load_end_addr
    732 	mov eax, cs:[bx + (mb_entry_addr - .1)]
    733 	cmp eax, cs:[bx + (mb_load_end_addr - .1)]
    734 	ja .fail
    735 
    736 	; load_end_addr <= bss_end_addr
    737 	mov eax, cs:[bx + (mb_load_end_addr - .1)]
    738 	cmp eax, cs:[bx + (mb_bss_end_addr - .1)]
    739 	ja .fail
    740 
    741 	; load_end_addr - load_addr <= kernel_size
    742 	mov ecx, cs:[bx + (mb_load_end_addr - .1)]
    743 	sub ecx, cs:[bx + (mb_load_addr - .1)]
    744 	cmp ecx, cs:[bx + (kernel_size - .1)]
    745 	ja .fail
    746 
    747 	; bss_end_addr - load_addr <= high_mem_size
    748 	mov ecx, cs:[bx + (mb_bss_end_addr - .1)]
    749 	sub ecx, cs:[bx + (mb_load_addr - .1)]
    750 	cmp ecx, cs:[bx + (high_mem_size - .1)]
    751 	ja .fail
    752 
    753 	; header_addr - load_addr <= mb_ptr - download_ptr
    754 	mov eax, cs:[bx + (mb_header_addr - .1)]
    755 	sub eax, cs:[bx + (mb_load_addr - .1)]
    756 	mov ecx, cs:[bx + (mb_ptr - .1)]
    757 	sub ecx, cs:[bx + (download_ptr - .1)]
    758 	cmp eax, ecx
    759 	ja .fail
    760 
    761 	; copy to load_addr
    762 	; from mb_ptr - header_addr + load_addr
    763 	mov edi, cs:[bx + (mb_load_addr - .1)]
    764 	mov esi, cs:[bx + (mb_ptr - .1)]
    765 	sub esi, cs:[bx + (mb_header_addr - .1)]
    766 	add esi, edi
    767 	mov ecx, cs:[bx + (mb_load_end_addr - .1)]
    768 	sub ecx, edi
    769 	call bcopy32
    770 
    771 	; zero bss
    772 	mov edi, cs:[bx + (mb_load_end_addr - .1)]
    773 	mov ecx, cs:[bx + (mb_bss_end_addr - .1)]
    774 	sub ecx, edi
    775 	call bzero32
    776 
    777 	; Align to dword
    778 	xor edi, edi
    779 	mov di, cs
    780 	shl edi, 4
    781 	add edi, ebx
    782 	add edi, (frame - .1 + 3)
    783 	and edi, -4
    784 
    785 	mov cs:[bx + (mb_info_ptr - .1)], edi
    786 
    787 	; Write multiboot info
    788 	mov dword ds:[edi], ((1 << 0) + (1 << 6))
    789 
    790 	; Save mem_lower
    791 	mov eax, cs:[bx + low_mem_size - .1]
    792 	shr eax, 10
    793 	mov dword ds:[edi + 4], eax
    794 
    795 	; Save mem_upper
    796 	mov eax, cs:[bx + high_mem_size - .1]
    797 	shr eax, 10
    798 	mov dword ds:[edi + 8], eax
    799 
    800 	; Save mmap_len
    801 	xor eax, eax
    802 	mov ax, cs:[bx + mmap_size - .1]
    803 	mov dword ds:[edi + 44], eax
    804 
    805 	; Save mmap_addr
    806 	xor eax, eax
    807 	mov ax, cs
    808 	shl eax, 4
    809 	add eax, ebx
    810 	add eax, (mmap - .1)
    811 	mov dword ds:[edi + 48], eax
    812 
    813 	popf
    814 	pop es
    815 	pop ds
    816 	popa
    817 	mov ax, 0
    818 	ret
    819 .fail:
    820 	popf
    821 	pop es
    822 	pop ds
    823 	popa
    824 	mov ax, 1
    825 	ret
    826 
    827 boot:
    828 	mov ax, 0
    829 	mov ds, ax
    830 	mov es, ax
    831 	call .1
    832 .1:
    833 	xor ebx, ebx
    834 	pop bx
    835 
    836 	mov esi, cs:[bx + mb_info_ptr - .1]
    837 	mov edi, cs:[bx + mb_entry_addr - .1]
    838 
    839 	cli
    840 
    841 	; Load the gdt
    842 	sub sp, 6
    843 	mov bp, sp
    844 	mov word ss:[bp], 39
    845 	xor eax, eax
    846 	mov ax, cs
    847 	shl eax, 4
    848 	add eax, ebx
    849 	add eax, (gdt - .1)
    850 	mov ss:[bp + 2], eax
    851 	lgdt ss:[bp]
    852 	add sp, 6
    853 
    854 	mov ecx, cr0
    855 	or ecx, 1
    856 	mov cr0, ecx
    857 
    858 
    859 	xor ebp, ebp
    860 	mov bp, sp
    861 	xor eax, eax
    862 	mov ax, ss
    863 	shl eax, 4
    864 	add ebp, eax
    865 
    866 	push 8
    867 	call .retf
    868 
    869 	bits 32
    870 
    871 .3:
    872 
    873 	mov ax, 16
    874 	mov ds, ax
    875 	mov es, ax
    876 	mov fs, ax
    877 	mov gs, ax
    878 	mov ss, ax
    879 	mov esp, ebp
    880 
    881 	mov eax, 0x2badb002
    882 	mov ebx, esi
    883 	jmp edi
    884 
    885 	bits 16
    886 
    887 .retf:
    888 	retf
    889 
    890 puts:
    891 	push bp
    892 	mov bp, sp
    893 	pusha
    894 	push ds
    895 	push es
    896 	push fs
    897 	push gs
    898 	pushf
    899 	call .1
    900 .1:
    901 	pop ax
    902 	sub ax, .1
    903 	mov si, ss:[bp + 4]
    904 	add si, ax
    905 	cld
    906 .loop:
    907 	mov ah, 0x0e
    908 	mov al, cs:[si]
    909 	test al, al
    910 	jz .out
    911 	mov bx, 0x0001
    912 	int 0x10
    913 	inc si
    914 	jmp .loop
    915 .out:
    916 	popf
    917 	pop gs
    918 	pop fs
    919 	pop es
    920 	pop ds
    921 	popa
    922 	pop bp
    923 	ret
    924 
    925 puth:
    926 	push bp
    927 	mov bp, sp
    928 	pusha
    929 	push ds
    930 	push es
    931 	push fs
    932 	push gs
    933 	pushf
    934 	mov cx, 32
    935 .loop:
    936 	sub cx, 4
    937 	mov eax, [bp + 4]
    938 	shr eax, cl
    939 	and eax, 15
    940 	cmp eax, 10
    941 	jb .a
    942 	add eax, 'a' - '0' - 10
    943 .a:
    944 	add eax, 0x0e00 + '0'
    945 	mov bx, 0x0001
    946 	int 0x10
    947 	test cx, cx
    948 	jnz .loop
    949 .out:
    950 	popf
    951 	pop gs
    952 	pop fs
    953 	pop es
    954 	pop ds
    955 	popa
    956 	pop bp
    957 	ret
    958 
    959 low_mem_size:
    960 	dd 0
    961 high_mem_size:
    962 	dd 0
    963 kernel_size:
    964 	dd 0
    965 mmap_size:
    966 	dw 0
    967 pxenv_ptr:
    968 	dd 0
    969 pxe_ptr:
    970 	dd 0
    971 pxe_entry:
    972 	dd 0
    973 download_ptr:
    974 	dd 0
    975 mb_ptr:
    976 	dd 0
    977 mb_header_addr:
    978 	dd 0
    979 mb_load_addr:
    980 	dd 0
    981 mb_load_end_addr:
    982 	dd 0
    983 mb_bss_end_addr:
    984 	dd 0
    985 mb_entry_addr:
    986 	dd 0
    987 mb_info_ptr:
    988 	dd 0
    989 	align 16, db 0
    990 filename:
    991 	db `/kernel`, 0
    992 	times 128 - ($ - filename) db 0
    993 frame equ $
    994 	;times 256 db 0
    995 page equ frame + 256
    996 	;times 512 db 0
    997 mmap equ page + 512
    998 	;times (8192 + 8192) db 0
    999 mmap_end equ mmap + (8192 + 8192)