cdboot.S revision 58713
156693Sjhb# 256693Sjhb# Copyright (c) 2000 John Baldwin 356693Sjhb# All rights reserved. 456693Sjhb# 556693Sjhb# Redistribution and use in source and binary forms are freely 656693Sjhb# permitted provided that the above copyright notice and this 756693Sjhb# paragraph and the following disclaimer are duplicated in all 856693Sjhb# such forms. 956693Sjhb# 1056693Sjhb# This software is provided "AS IS" and without any express or 1156693Sjhb# implied warranties, including, without limitation, the implied 1256693Sjhb# warranties of merchantability and fitness for a particular 1356693Sjhb# purpose. 1456693Sjhb# 1556693Sjhb 1656693Sjhb# $FreeBSD: head/sys/boot/i386/cdboot/cdboot.s 58713 2000-03-28 01:19:53Z jhb $ 1756693Sjhb 1856693Sjhb# 1956693Sjhb# This simple program is a preloader for the normal boot3 loader. It is simply 2056693Sjhb# prepended to the beginning of a fully built and btxld'd loader. It then 2156693Sjhb# copies the loader to the address boot2 normally loads it, emulates the 2256693Sjhb# boot[12] environment (protected mode, a bootinfo struct, etc.), and then jumps 2356693Sjhb# to the start of btxldr to start the boot process. This method allows a stock 2456693Sjhb# /boot/loader to be used w/o having to fully rewrite boot[12] to handle the 2556693Sjhb# cd9660 file system. 2656693Sjhb# 2756693Sjhb 2856693Sjhb# 2956693Sjhb# Memory locations. 3056693Sjhb# 3158713Sjhb .set MEM_PAGE_SIZE,0x1000 # memory page size, 4k 3256693Sjhb .set MEM_ARG,0x900 # Arguments at start 3356693Sjhb .set MEM_ARG_BTX,0xa100 # Where we move them to so the 3456693Sjhb # BTX client can see them 3556693Sjhb .set MEM_ARG_SIZE,0x18 # Size of the arguments 3656693Sjhb .set MEM_BTX_ADDRESS,0x9000 # where BTX lives 3756693Sjhb .set MEM_BTX_ENTRY,0x9010 # where BTX starts to execute 3858713Sjhb .set MEM_BTX_OFFSET,MEM_PAGE_SIZE # offset of BTX in the loader 3956693Sjhb .set MEM_BTX_CLIENT,0xa000 # where BTX clients live 4056693Sjhb# 4158713Sjhb# a.out header fields 4258713Sjhb# 4358713Sjhb .set AOUT_TEXT,0x04 # text segment size 4458713Sjhb .set AOUT_DATA,0x08 # data segment size 4558713Sjhb .set AOUT_BSS,0x0c # zero'd BSS size 4658713Sjhb .set AOUT_SYMBOLS,0x10 # symbol table 4758713Sjhb .set AOUT_ENTRY,0x14 # entry point 4858713Sjhb .set AOUT_HEADER,MEM_PAGE_SIZE # size of the a.out header 4958713Sjhb# 5056693Sjhb# Flags for kargs->bootflags 5156693Sjhb# 5256693Sjhb .set KARGS_FLAGS_CD,0x1 # flag to indicate booting from 5356693Sjhb # CD loader 5456693Sjhb# 5556693Sjhb# Segment selectors. 5656693Sjhb# 5756693Sjhb .set SEL_SDATA,0x8 # Supervisor data 5856693Sjhb .set SEL_RDATA,0x10 # Real mode data 5956693Sjhb .set SEL_SCODE,0x18 # PM-32 code 6056693Sjhb .set SEL_SCODE16,0x20 # PM-16 code 6156693Sjhb# 6256693Sjhb# BTX constants 6356693Sjhb# 6456693Sjhb .set INT_SYS,0x30 # BTX syscall interrupt 6556693Sjhb# 6658713Sjhb# We expect to be loaded by the BIOS at 0x7c00 (standard boot loader entry 6758713Sjhb# point) 6856693Sjhb# 6956693Sjhb .code16 7056693Sjhb .globl start 7156693Sjhb .org 0x0, 0x0 7256693Sjhb# 7356693Sjhb# BTX program loader for CD booting 7456693Sjhb# 7558713Sjhbstart: cld # string ops inc 7656693Sjhb xorw %ax, %ax # zero %ax 7756693Sjhb movw %ax, %ss # setup the 7858713Sjhb movw $start, %sp # stack 7956693Sjhb pushw %dx # save the BIOS boot device in 8056693Sjhb # %dl for later 8158713Sjhb movw %ax, %ds # setup the 8258713Sjhb movw %ax, %es # data segments 8358713Sjhb movw $welcome_msg, %si # %ds:(%si) -> welcome message 8456693Sjhb call putstr # display the welcome message 8556693Sjhb# 8656693Sjhb# Setup the arguments that the loader is expecting from boot[12] 8756693Sjhb# 8858713Sjhb movw $bootinfo_msg, %si # %ds:(%si) -> boot args message 8956693Sjhb call putstr # display the message 9058713Sjhb movl $MEM_ARG, %ebx # %ds:(%ebx) -> boot args 9156693Sjhb movw %bx, %di # %es:(%di) -> boot args 9256693Sjhb xorl %eax, %eax # zero %eax 9356693Sjhb movw $(MEM_ARG_SIZE/4), %cx # Size of arguments in 32-bit 9456693Sjhb # dwords 9556693Sjhb rep # Clear the arguments 9656693Sjhb stosl # to zero 9756693Sjhb popw %dx # restore BIOS boot device 9858713Sjhb movb %dl, 0x4(%ebx) # set kargs->bootdev 9958713Sjhb orb $KARGS_FLAGS_CD, 0x8(%ebx) # kargs->bootflags |= 10058713Sjhb # KARGS_FLAGS_CD 10156693Sjhb# 10256693Sjhb# Turn on the A20 address line 10356693Sjhb# 10456693Sjhb call seta20 # Turn A20 on 10556693Sjhb# 10656693Sjhb# Relocate the loader and BTX using a very lazy protected mode 10756693Sjhb# 10856693Sjhb movw $relocate_msg, %si # Display the 10956693Sjhb call putstr # relocation message 11058713Sjhb movl end+AOUT_ENTRY, %edi # %edi is the destination 11158713Sjhb movl $(end+AOUT_HEADER), %esi # %esi is 11258713Sjhb # the start of the text 11358713Sjhb # segment 11458713Sjhb movl end+AOUT_TEXT, %ecx # %ecx = length of the text 11558713Sjhb # segment 11656693Sjhb lgdt gdtdesc # setup our own gdt 11756693Sjhb cli # turn off interrupts 11856693Sjhb movl %cr0, %eax # Turn on 11958713Sjhb orb $0x1, %al # protected 12056693Sjhb movl %eax, %cr0 # mode 12156693Sjhb .byte 0xea # long jump to 12258713Sjhb .word pm_start # clear the instruction 12358713Sjhb .word SEL_SCODE # pre-fetch queue 12456693Sjhb .code32 12556693Sjhbpm_start: movw $SEL_SDATA, %ax # Initialize 12656693Sjhb movw %ax, %ds # %ds and 12756693Sjhb movw %ax, %es # %es to a flat selector 12858713Sjhb rep # Relocate the 12958713Sjhb movsb # text segment 13058713Sjhb addl $(MEM_PAGE_SIZE - 1), %edi # pad %edi out to a new page 13158713Sjhb andl $~(MEM_PAGE_SIZE - 1), %edi # for the data segment 13258713Sjhb movl end+AOUT_DATA, %ecx # size of the data segment 13358713Sjhb rep # Relocate the 13458713Sjhb movsb # data segment 13558713Sjhb movl end+AOUT_BSS, %ecx # size of the bss 13658713Sjhb xorl %eax, %eax # zero %eax 13758713Sjhb addb $3, %cl # round %ecx up to 13858713Sjhb shrl $2, %ecx # a multiple of 4 13958713Sjhb rep # zero the 14058713Sjhb stosl # bss 14158713Sjhb movl end+AOUT_ENTRY, %esi # %esi -> relocated loader 14258713Sjhb addl $MEM_BTX_OFFSET, %esi # %esi -> BTX in the loader 14356693Sjhb movl $MEM_BTX_ADDRESS, %edi # %edi -> where BTX needs to go 14456693Sjhb movzwl 0xa(%esi), %ecx # %ecx -> length of BTX 14556693Sjhb rep # Relocate 14656693Sjhb movsb # BTX 14758713Sjhb ljmp $SEL_SCODE16,$pm_16 # Jump to 16-bit PM 14856693Sjhb .code16 14956693Sjhbpm_16: movw $SEL_RDATA, %ax # Initialize 15056693Sjhb movw %ax, %ds # %ds and 15156693Sjhb movw %ax, %es # %es to a real mode selector 15256693Sjhb movl %cr0, %eax # Turn off 15358713Sjhb andb $~0x1, %al # protected 15456693Sjhb movl %eax, %cr0 # mode 15556693Sjhb .byte 0xea # Long jump to 15656693Sjhb .word pm_end # clear the instruction 15758713Sjhb .word 0x0 # pre-fetch 15856693Sjhbpm_end: sti # Turn interrupts back on now 15956693Sjhb# 16056693Sjhb# Copy the BTX client to MEM_BTX_CLIENT 16156693Sjhb# 16258713Sjhb xorw %ax, %ax # zero %ax and set 16358713Sjhb movw %ax, %ds # %ds and %es 16458713Sjhb movw %ax, %es # to segment 0 16556693Sjhb movw $MEM_BTX_CLIENT, %di # Prepare to relocate 16656693Sjhb movw $btx_client, %si # the simple btx client 16756693Sjhb movw $(btx_client_end-btx_client), %cx # length of btx client 16856693Sjhb rep # Relocate the 16956693Sjhb movsb # simple BTX client 17056693Sjhb# 17156693Sjhb# Copy the boot[12] args to where the BTX client can see them 17256693Sjhb# 17356693Sjhb movw $MEM_ARG, %si # where the args are at now 17456693Sjhb movw $MEM_ARG_BTX, %di # where the args are moving to 17556693Sjhb movw $(MEM_ARG_SIZE/4), %cx # size of the arguments in longs 17656693Sjhb rep # Relocate 17756693Sjhb movsl # the words 17856693Sjhb# 17958713Sjhb# Save the entry point so the client can get to it later on 18058713Sjhb# 18158713Sjhb movl end+AOUT_ENTRY, %eax # load the entry point 18258713Sjhb stosl # add it to the end of the 18358713Sjhb # arguments 18458713Sjhb# 18556693Sjhb# Now we just start up BTX and let it do the rest 18656693Sjhb# 18758713Sjhb movw $jump_message, %si # Display the 18856693Sjhb call putstr # jump message 18956693Sjhb .byte 0xea # Jump to 19056693Sjhb .word MEM_BTX_ENTRY # BTX entry 19156693Sjhb .word 0x0 # point 19256693Sjhb 19356693Sjhb# 19456693Sjhb# Display a null-terminated string 19556693Sjhb# 19656693Sjhbputstr: lodsb # load %al from %ds:(%si) 19756693Sjhb testb %al,%al # stop at null 19856693Sjhb jnz putc # if the char != null, output it 19956693Sjhb ret # return when null is hit 20056693Sjhbputc: movw $0x7,%bx # attribute for output 20156693Sjhb movb $0xe,%ah # BIOS: put_char 20256693Sjhb int $0x10 # call BIOS, print char in %al 20356693Sjhb jmp putstr # keep looping 20456693Sjhb 20556693Sjhb# 20656693Sjhb# Enable A20 20756693Sjhb# 20856693Sjhbseta20: cli # Disable interrupts 20956693Sjhbseta20.1: inb $0x64,%al # Get status 21056693Sjhb testb $0x2,%al # Busy? 21156693Sjhb jnz seta20.1 # Yes 21256693Sjhb movb $0xd1,%al # Command: Write 21356693Sjhb outb %al,$0x64 # output port 21456693Sjhbseta20.2: inb $0x64,%al # Get status 21556693Sjhb testb $0x2,%al # Busy? 21656693Sjhb jnz seta20.2 # Yes 21756693Sjhb movb $0xdf,%al # Enable 21856693Sjhb outb %al,$0x60 # A20 21956693Sjhb sti # Enable interrupts 22056693Sjhb ret # To caller 22156693Sjhb 22256693Sjhb# 22358713Sjhb# BTX client to start btxldr 22456693Sjhb# 22556693Sjhb .code32 22656693Sjhbbtx_client: movl $(MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE-4), %esi 22756693Sjhb # %ds:(%esi) -> end 22856693Sjhb # of boot[12] args 22956693Sjhb movl $(MEM_ARG_SIZE/4), %ecx # Number of words to push 23056693Sjhb std # Go backwards 23156693Sjhbpush_arg: lodsl # Read argument 23256693Sjhb pushl %eax # Push it onto the stack 23356693Sjhb loop push_arg # Push all of the arguments 23456693Sjhb cld # In case anyone depends on this 23558713Sjhb pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE # Entry point of 23658713Sjhb # the loader 23756693Sjhb pushl %eax # Emulate a near call 23856693Sjhb movl $0x1, %eax # 'exec' system call 23956693Sjhb int $INT_SYS # BTX system call 24056693Sjhbbtx_client_end: 24156693Sjhb .code16 24256693Sjhb 24356693Sjhb .p2align 4 24456693Sjhb# 24556693Sjhb# Global descriptor table. 24656693Sjhb# 24756693Sjhbgdt: .word 0x0,0x0,0x0,0x0 # Null entry 24856693Sjhb .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 24956693Sjhb .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 25056693Sjhb .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE (32-bit) 25156693Sjhb .word 0xffff,0x0,0x9a00,0x8f # SEL_SCODE16 (16-bit) 25256693Sjhbgdt.1: 25356693Sjhb# 25456693Sjhb# Pseudo-descriptors. 25556693Sjhb# 25656693Sjhbgdtdesc: .word gdt.1-gdt-1 # Limit 25758713Sjhb .long gdt # Base 25856693Sjhb 25956693Sjhbwelcome_msg: .asciz "CD Loader 1.00\r\n\n" 26056693Sjhbbootinfo_msg: .asciz "Building the boot loader arguments\r\n" 26156693Sjhbrelocate_msg: .asciz "Relocating the loader and the BTX\r\n" 26256693Sjhbjump_message: .asciz "Starting the BTX loader\r\n" 26356693Sjhb 26456693Sjhbend: 265