x86: BIOS -> boot0 -> boot1 -> BTX -> boot2 ->
boot0
) loaded from absolute disk sector to 0x7c00boot0
stageMaster Boot Record (MBR)
Note:
sys/boot/i386/boo0/Makefile
or stand/i386/boo0/boot0.S
, the special LDFLAG to strip out any file formating (-oformat,binary)Function: Scan the partition table and let the user choose which partition to boot from.
boot1
stagesys/boot/i386/boot2/boot1.S
or stand/i386/boot2/boot1.S
Note:
boot1
is 512 bytes; boot2
is much larger.boot1
and boot2
(which contains Boot Extender, BTX, and boot2 client
) are both included in a single file /boot/boot
on disk (cat boot1 boot2 > boot
)boot2 client
execute in user mode.Function: load the next boot stage: a server called BTX
, a client called boot2
.
start
-> main
boot
file, contains boot1, boot2, and BTX) to 0x8c00; BTX loaded to 0x9000; (execution at main.5
),cite: https://www.freebsd.org/doc/en_US.ISO8859-1/books/arch-handbook/btx-server.html
sys/boot/i386/btx/btx.S
Function:
boot2 client
and kernel mode BTX server
;passing control to the client boot2
/* stand/i386/btx/btx/btx.S
*/
start: # Start of code
/*
* BTX header.
*/
btx_hdr: .byte 0xeb # Machine ID
.byte 0xe # Header size
.ascii "BTX" # Magic
.byte 0x1 # Major version
.byte 0x2 # Minor version
.byte BTX_FLAGS # Flags
.word PAG_CNT-MEM_ORG>>0xc # Paging control
.word break-start # Text size
.long 0x0 # Entry address
The last field of the header is entry point to the client boot2
. This field is patched at link time.
Next is the BTX entry point:
/* stand/i386/btx/btx/btx.S
*/
/*
* Initialization routine.
*/
init: cli # Disable interrupts
xor %ax,%ax # Zero/segment
mov %ax,%ss # Set up
mov $0x1800,%sp # stack
mov %ax,%es # Address
mov %ax,%ds # data
pushl $0x2 # Clear
popfl # flags
It
Next is the memory initialization code:
/* stand/i386/btx/btx/btx.S
*/
/*
* Initialize memory.
*/
mov $0x5e00,%di # Memory to initialize
mov $(0x9000-0x5e00)/2,%cx # Words to zero
rep # Zero-fill
stosw # memory
It clears memory range 0x5e00 - 0x8fff
.
Then the real-mode IVT is updated:
/* stand/i386/btx/btx/btx.S
*/
/*
* Update real mode IDT for reflecting hardware interrupts.
*/
mov $intr20,%bx # Address first handler
mov $0x10,%cx # Number of handlers
mov $0x20*4,%di # First real mode IDT entry
init.0: mov %bx,(%di) # Store IP
inc %di # Address next
inc %di # entry
stosw # Store CS
add $4,%bx # Next handler
loop init.0 # Next IRQ
Next creating the IDT:
/* stand/i386/btx/btx/btx.S
*/
/*
* Create IDT.
*/
mov $0x5e00,%di # IDT's address
mov $idtctl,%si # Control string
init.1: lodsb # Get entry
cbw # count
xchg %ax,%cx # as word
jcxz init.4 # If done
lodsb # Get segment
xchg %ax,%dx # P:DPL:type
lodsw # Get control
xchg %ax,%bx # set
lodsw # Get handler offset
mov $SEL_SCODE,%dh # Segment selector
init.2: shr %bx # Handle this int?
jnc init.3 # No
mov %ax,(%di) # Set handler offset
mov %dh,0x2(%di) # and selector
mov %dl,0x5(%di) # Set P:DPL:type
add $0x4,%ax # Next handler
init.3: lea 0x8(%di),%di # Next entry
loop init.2 # Till set done
jmp init.1 # Continue
Each entry is 8 bytes long. contains
Interrupt numbers:
Note:
boot2 client
. Thus user mode client can use services provided by BTX.Next is to initialize TSS:
/* stand/i386/btx/btx/btx.S
*/
/*
* Initialize TSS.
*/
init.4:
movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0
movb $SEL_SDATA,TSS_SS0(%di) # Set SS0
movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base
A hardcode value is given to stack pointer and stack segment for privilege level 0 in the TSS.
A value is also given to the I/O Map base address field of the TSS.
Next is the allow the processor to switch to protected mode:
/* stand/i386/btx/btx/btx.S
*/
/*
* Bring up the system.
*/
mov $0x2820,%bx # Set protected mode
callw setpic # IRQ offsets
lidt idtdesc # Set IDT
lgdt gdtdesc # Set GDT
mov %cr0,%eax # Switch to protected
inc %ax # mode
mov %eax,%cr0 #
ljmp $SEL_SCODE,$init.8 # To 32-bit code
.code32
init.8: xorl %ecx,%ecx # Zero
movb $SEL_SDATA,%cl # To 32-bit
movw %cx,%ss # stack
Reference 1
sys/mips/mips/locore.S
CHERI specific
kernel_sealcap
;userspace_cap
;user_sealcap
;swap_restore_cap
more at cheribsd booting
GLOBAL(btext)
ASM_ENTRY(_start)
VECTOR(_locore, unknown)
...
/*
* Initialize stack and call machine startup.
*/
PTR_LA sp, _C_LABEL(pcpu_space)
PTR_ADDU sp, (PAGE_SIZE * 2) - CALLFRAME_SIZ
REG_S zero, CALLFRAME_RA(sp) # Zero out old ra for debugger
REG_S zero, CALLFRAME_SP(sp) # Zero out old fp for debugger
PTR_LA gp, _C_LABEL(_gp)
/* Call the platform-specific startup code. */
PTR_LA t9, _C_LABEL(platform_start)
jalr t9
nop
PTR_LA sp, _C_LABEL(thread0_st)
PTR_L a0, TD_PCB(sp)
REG_LI t0, ~7
and a0, a0, t0
PTR_SUBU sp, a0, CALLFRAME_SIZ
PTR_LA t9, _C_LABEL(mi_startup)
jalr t9 # mi_startup(frame)
sw zero, (CALLFRAME_SIZ - 8)(sp) # Zero out old fp for debugger
PANIC("Startup failed!")
stack pointer: pcpu_space + (page size * 2) - callframe_size
If you could revise
the fundmental principles of
computer system design
to improve security...
... what would you change?