An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
129 lines
3.3 KiB
ArmAsm
129 lines
3.3 KiB
ArmAsm
# Stage 2 — loaded by stage1 at 0x7E00, still in 16-bit real mode. Does the
|
|
# VBE mode setup, A20 line, and real->protected mode switch that used to
|
|
# live directly in the boot sector, then hands off to stage2main() (C) to
|
|
# draw a splash and load the actual kernel. Not sector-size-constrained —
|
|
# only bounded by STAGE2_SECTORS in bootasm.S / the Makefile.
|
|
#include "../include/asm.h"
|
|
#include "../include/memlayout.h"
|
|
#include "../include/mmu.h"
|
|
|
|
.code16
|
|
.global stage2start
|
|
stage2start:
|
|
# Segments are already zeroed by stage1; %sp is inherited too.
|
|
|
|
movw $bootmsg, %si
|
|
call print16
|
|
|
|
# VBE Setup. Mode info block goes at 0x30000, not 0x9000 — stage2 itself
|
|
# is loaded starting at 0x7E00 and, with the boot-menu/progress-bar code,
|
|
# is now big enough to reach 0x9000, so writing the VBE block there would
|
|
# clobber stage2's own tail end. 0x30000 is clear of stage2 (ends well
|
|
# under 0xA000), the multiboot kernel-search buffer (0x10000-0x14000),
|
|
# and the kernel's own load address (0x100000).
|
|
movw $0x3000, %ax
|
|
movw %ax, %es
|
|
xorw %di, %di # ES:DI = 3000:0000 = flat 0x30000
|
|
movw $0x0143, %cx
|
|
movw $0x4F01, %ax
|
|
int $0x10
|
|
|
|
cmpw $0x004F, %ax
|
|
jne e820
|
|
movw $0x4143, %bx
|
|
movw $0x4F02, %ax
|
|
int $0x10
|
|
|
|
# BIOS E820 memory map — the standard firmware interface every serious
|
|
# loader (GRUB, Linux's own boot stub, the BSDs) uses to learn the real
|
|
# RAM layout instead of guessing. Entry count goes to flat 0x30200,
|
|
# 24-byte entries start at 0x30208 (both inside the 0x3000 segment the
|
|
# VBE block already claimed; verbose flag sits at +0x100). Capped at 32
|
|
# entries so a pathological BIOS can't run us past the buffer.
|
|
e820:
|
|
movw $0x3000, %ax
|
|
movw %ax, %es
|
|
xorl %ebx, %ebx # continuation cookie, 0 = first call
|
|
movw $0x208, %di
|
|
xorl %ebp, %ebp # entry count
|
|
e820loop:
|
|
movl $0xE820, %eax
|
|
movl $0x534D4150, %edx # 'SMAP'
|
|
movl $24, %ecx
|
|
int $0x15
|
|
jc e820done # carry = end of map (or unsupported BIOS)
|
|
cmpl $0x534D4150, %eax
|
|
jne e820done
|
|
addw $24, %di
|
|
incl %ebp
|
|
cmpl $32, %ebp
|
|
jae e820done
|
|
testl %ebx, %ebx
|
|
jnz e820loop
|
|
e820done:
|
|
movl %ebp, %es:(0x200)
|
|
xorw %ax, %ax
|
|
movw %ax, %es
|
|
|
|
seta20.1:
|
|
inb $0x64, %al
|
|
testb $0x2, %al
|
|
jnz seta20.1
|
|
movb $0xd1, %al
|
|
outb %al, $0x64
|
|
seta20.2:
|
|
inb $0x64, %al
|
|
testb $0x2, %al
|
|
jnz seta20.2
|
|
movb $0xdf, %al
|
|
outb %al, $0x60
|
|
|
|
lgdt gdtdesc
|
|
movl %cr0, %eax
|
|
orl $CR0_PE, %eax
|
|
movl %eax, %cr0
|
|
|
|
ljmp $(SEG_KCODE<<3), $start32
|
|
|
|
# Print null-terminated string at DS:SI via BIOS teletype (real mode only).
|
|
# Clobbers AX, BX, SI.
|
|
print16:
|
|
.Lp16loop:
|
|
lodsb
|
|
testb %al, %al
|
|
jz .Lp16done
|
|
movb $0x0E, %ah
|
|
movw $0x0007, %bx
|
|
int $0x10
|
|
jmp .Lp16loop
|
|
.Lp16done:
|
|
ret
|
|
|
|
bootmsg:
|
|
.asciz "Schunix booting...\r\n"
|
|
|
|
.code32
|
|
start32:
|
|
movw $(SEG_KDATA<<3), %ax
|
|
movw %ax, %ds
|
|
movw %ax, %es
|
|
movw %ax, %ss
|
|
xorw %ax, %ax
|
|
movw %ax, %fs
|
|
movw %ax, %gs
|
|
|
|
movl $0x7c00, %esp
|
|
call stage2main
|
|
|
|
spin:
|
|
jmp spin
|
|
|
|
.p2align 2
|
|
gdt:
|
|
SEG_NULLASM
|
|
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)
|
|
SEG_ASM(STA_W, 0x0, 0xffffffff)
|
|
|
|
gdtdesc:
|
|
.word (gdtdesc - gdt - 1)
|
|
.long gdt
|