1128710Sru/* 2128710Sru * Copyright (c) 1998 Robert Nordier 3128710Sru * All rights reserved. 4128710Sru * 5128710Sru * Redistribution and use in source and binary forms are freely 6128710Sru * permitted provided that the above copyright notice and this 7128710Sru * paragraph and the following disclaimer are duplicated in all 8128710Sru * such forms. 9128710Sru * 10128710Sru * This software is provided "AS IS" and without any express or 11128710Sru * implied warranties, including, without limitation, the implied 12128710Sru * warranties of merchantability and fitness for a particular 13128710Sru * purpose. 14128710Sru * 15128710Sru * $FreeBSD$ 16128710Sru */ 1743561Skato 18243448Snyan#include <bootargs.h> 19243448Snyan 20128710Sru/* 21128710Sru * Prototype BTX loader program, written in a couple of hours. The 22128710Sru * real thing should probably be more flexible, and in C. 23128710Sru */ 2443561Skato 25128710Sru/* 26128710Sru * Memory locations. 27128710Sru */ 2843561Skato .set MEM_STUB,0x600 # Real mode stub 2943561Skato .set MEM_ESP,0x1000 # New stack pointer 3043561Skato .set MEM_TBL,0x5000 # BTX page tables 3143561Skato .set MEM_ENTRY,0x9010 # BTX entry point 3258871Skato .set MEM_DATA,start+0x1000 # Data segment 33128710Sru/* 34128710Sru * Segment selectors. 35128710Sru */ 3643561Skato .set SEL_SCODE,0x8 # 4GB code 3743561Skato .set SEL_SDATA,0x10 # 4GB data 3843561Skato .set SEL_RCODE,0x18 # 64K code 3943561Skato .set SEL_RDATA,0x20 # 64K data 40128710Sru/* 41128710Sru * Paging constants. 42128710Sru */ 4343561Skato .set PAG_SIZ,0x1000 # Page size 4443561Skato .set PAG_ENT,0x4 # Page entry size 45128710Sru/* 46128710Sru * Screen constants. 47128710Sru */ 4843561Skato .set SCR_MAT,0xe1 # Mode/attribute 4943561Skato .set SCR_COL,0x50 # Columns per row 5043561Skato .set SCR_ROW,0x19 # Rows per screen 51128710Sru/* 52128710Sru * BIOS Data Area locations. 53128710Sru */ 5443561Skato .set BDA_MEM,0xa1501 # Free memory 5543561Skato .set BDA_POS,0xa153e # Cursor position 56128710Sru/* 57128710Sru * Required by aout gas inadequacy. 58128710Sru */ 5943561Skato .set SIZ_STUB,0x1a # Size of stub 60128710Sru/* 61128710Sru * We expect to be loaded by boot2 at the origin defined in ./Makefile. 62128710Sru */ 6343561Skato .globl start 64128710Sru/* 65128710Sru * BTX program loader for ELF clients. 66128710Sru */ 6743561Skatostart: cld # String ops inc 6843561Skato cli 6943561Skatogdcwait.1: inb $0x60,%al 7043561Skato testb $0x04,%al 7143561Skato jz gdcwait.1 7243561Skato movb $0xe0,%al 7343561Skato outb %al,$0x62 7443561Skato nop 7543561Skatogdcwait.2: inb $0x60,%al 7643561Skato testb $0x01,%al 7743561Skato jz gdcwait.2 7843561Skato inb $0x62,%al 7943561Skato movb %al,%dl 8043561Skato inb $0x62,%al 8143561Skato movb %al,%dh 8243561Skato inb $0x62,%al 8343561Skato inb $0x62,%al 8443561Skato inb $0x62,%al 8543561Skato shlw $1,%dx 8643561Skato movl $BDA_POS,%ebx 8743561Skato movw %dx,(%ebx) 8843561Skato movl $m_logo,%esi # Identify 8943561Skato call putstr # ourselves 9043561Skato movzwl BDA_MEM,%eax # Get base memory 9143561Skato andl $0x7,%eax 9243561Skato incl %eax 9343561Skato shll $0x11,%eax # in bytes 9443561Skato movl %eax,%ebp # Base of user stack 95125780Snyan#ifdef BTXLDR_VERBOSE 9643561Skato movl $m_mem,%esi # Display 9758871Skato call hexout # amount of 9858871Skato call putstr # base memory 99125780Snyan#endif 10043561Skato lgdt gdtdesc # Load new GDT 101128710Sru/* 102128710Sru * Relocate caller's arguments. 103128710Sru */ 104125780Snyan#ifdef BTXLDR_VERBOSE 10543561Skato movl $m_esp,%esi # Display 10658871Skato movl %esp,%eax # caller 10758871Skato call hexout # stack 10858871Skato call putstr # pointer 10943561Skato movl $m_args,%esi # Format string 110237763Savg leal 0x4(%esp),%ebx # First argument 11143561Skato movl $0x6,%ecx # Count 11243561Skatostart.1: movl (%ebx),%eax # Get argument and 11343561Skato addl $0x4,%ebx # bump pointer 11458871Skato call hexout # Display it 11543561Skato loop start.1 # Till done 11658871Skato call putstr # End message 117125780Snyan#endif 118237763Savg movl BA_BOOTINFO+4(%esp),%esi # Source: bootinfo 11958871Skato cmpl $0x0, %esi # If the bootinfo pointer 12058871Skato je start_null_bi # is null, don't copy it 121237763Savg movl BI_SIZE(%esi),%ecx # Allocate space 122237763Savg subl %ecx,%ebp # for bootinfo 12343561Skato movl %ebp,%edi # Destination 12443561Skato rep # Copy 12543561Skato movsb # it 126237763Savg movl %ebp,BA_BOOTINFO+4(%esp) # Update pointer 127237763Savg movl %edi,%ebp # Restore base pointer 128125780Snyan#ifdef BTXLDR_VERBOSE 12943561Skato movl $m_rel_bi,%esi # Display 13043561Skato movl %ebp,%eax # bootinfo 13158871Skato call hexout # relocation 13258871Skato call putstr # message 133125780Snyan#endif 134237763Savgstart_null_bi: movl $BOOTARGS_SIZE,%ecx # Fixed size of arguments 135237763Savg testl $KARGS_FLAGS_EXTARG, BA_BOOTFLAGS+4(%esp) # Check for extra data 136237763Savg jz start_fixed # Skip if the flag is not set 137237763Savg addl BOOTARGS_SIZE+4(%esp),%ecx # Add size of variable args 138237763Savgstart_fixed: subl $ARGOFF,%ebp # Place args at fixed offset 139237763Savg leal 0x4(%esp),%esi # Source 14043561Skato movl %ebp,%edi # Destination 14143561Skato rep # Copy 14243561Skato movsb # them 143125780Snyan#ifdef BTXLDR_VERBOSE 14443561Skato movl $m_rel_args,%esi # Display 14543561Skato movl %ebp,%eax # argument 14658871Skato call hexout # relocation 14758871Skato call putstr # message 148125780Snyan#endif 149128710Sru/* 150128710Sru * Set up BTX kernel. 151128710Sru */ 15243561Skato movl $MEM_ESP,%esp # Set up new stack 15343561Skato movl $MEM_DATA,%ebx # Data segment 15443561Skato movl $m_vers,%esi # Display BTX 15543561Skato call putstr # version message 15643561Skato movb 0x5(%ebx),%al # Get major version 15743561Skato addb $'0',%al # Display 15843561Skato call putchr # it 15943561Skato movb $'.',%al # And a 16043561Skato call putchr # dot 16143561Skato movb 0x6(%ebx),%al # Get minor 16243561Skato xorb %ah,%ah # version 16343561Skato movb $0xa,%dl # Divide 16443561Skato divb %dl,%al # by 10 16543561Skato addb $'0',%al # Display 16643561Skato call putchr # tens 16743561Skato movb %ah,%al # Get units 16843561Skato addb $'0',%al # Display 16943561Skato call putchr # units 17043561Skato call putstr # End message 17143561Skato movl %ebx,%esi # BTX image 17243561Skato movzwl 0x8(%ebx),%edi # Compute 17343561Skato orl $PAG_SIZ/PAG_ENT-1,%edi # the 17443561Skato incl %edi # BTX 17543561Skato shll $0x2,%edi # load 17643561Skato addl $MEM_TBL,%edi # address 17758871Skato pushl %edi # Save load address 17843561Skato movzwl 0xa(%ebx),%ecx # Image size 179125780Snyan#ifdef BTXLDR_VERBOSE 18058871Skato pushl %ecx # Save image size 181125780Snyan#endif 18243561Skato rep # Relocate 18343561Skato movsb # BTX 18443561Skato movl %esi,%ebx # Keep place 185125780Snyan#ifdef BTXLDR_VERBOSE 18643561Skato movl $m_rel_btx,%esi # Restore 18743561Skato popl %eax # parameters 18858871Skato call hexout # and 189125780Snyan#endif 19043561Skato popl %ebp # display 191125780Snyan#ifdef BTXLDR_VERBOSE 19243561Skato movl %ebp,%eax # the 19358871Skato call hexout # relocation 19458871Skato call putstr # message 195125780Snyan#endif 19643561Skato addl $PAG_SIZ,%ebp # Display 197125780Snyan#ifdef BTXLDR_VERBOSE 19843561Skato movl $m_base,%esi # the 19943561Skato movl %ebp,%eax # user 20058871Skato call hexout # base 20158871Skato call putstr # address 202125780Snyan#endif 203128710Sru/* 204128710Sru * Set up ELF-format client program. 205128710Sru */ 20643561Skato cmpl $0x464c457f,(%ebx) # ELF magic number? 20743561Skato je start.3 # Yes 20843561Skato movl $e_fmt,%esi # Display error 20943561Skato call putstr # message 21043561Skatostart.2: jmp start.2 # Hang 21158871Skatostart.3: 212125780Snyan#ifdef BTXLDR_VERBOSE 21358871Skato movl $m_elf,%esi # Display ELF 21458871Skato call putstr # message 21543561Skato movl $m_segs,%esi # Format string 216125780Snyan#endif 21743561Skato movl $0x2,%edi # Segment count 21843561Skato movl 0x1c(%ebx),%edx # Get e_phoff 21943561Skato addl %ebx,%edx # To pointer 22043561Skato movzwl 0x2c(%ebx),%ecx # Get e_phnum 22143561Skatostart.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD? 22243561Skato jne start.6 # No 223125780Snyan#ifdef BTXLDR_VERBOSE 22443561Skato movl 0x4(%edx),%eax # Display 22558871Skato call hexout # p_offset 22643561Skato movl 0x8(%edx),%eax # Display 22758871Skato call hexout # p_vaddr 22843561Skato movl 0x10(%edx),%eax # Display 22958871Skato call hexout # p_filesz 23043561Skato movl 0x14(%edx),%eax # Display 23158871Skato call hexout # p_memsz 23258871Skato call putstr # End message 233125780Snyan#endif 23443561Skato pushl %esi # Save 23543561Skato pushl %edi # working 23643561Skato pushl %ecx # registers 23743561Skato movl 0x4(%edx),%esi # Get p_offset 23843561Skato addl %ebx,%esi # as pointer 23943561Skato movl 0x8(%edx),%edi # Get p_vaddr 24043561Skato addl %ebp,%edi # as pointer 24143561Skato movl 0x10(%edx),%ecx # Get p_filesz 24243561Skato rep # Set up 24343561Skato movsb # segment 24443561Skato movl 0x14(%edx),%ecx # Any bytes 24543561Skato subl 0x10(%edx),%ecx # to zero? 24643561Skato jz start.5 # No 24743561Skato xorb %al,%al # Then 24843561Skato rep # zero 24943561Skato stosb # them 25043561Skatostart.5: popl %ecx # Restore 25143561Skato popl %edi # working 25243561Skato popl %esi # registers 25343561Skato decl %edi # Segments to do 25443561Skato je start.7 # If none 25543561Skatostart.6: addl $0x20,%edx # To next entry 25643561Skato loop start.4 # Till done 25758871Skatostart.7: 258125780Snyan#ifdef BTXLDR_VERBOSE 25958871Skato movl $m_done,%esi # Display done 26058871Skato call putstr # message 261125780Snyan#endif 26243561Skato movl $start.8,%esi # Real mode stub 26343561Skato movl $MEM_STUB,%edi # Destination 26461064Snyan movl $start.9-start.8,%ecx # Size 26543561Skato rep # Relocate 26643561Skato movsb # it 26743561Skato ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code 26861064Snyan .code16 26961064Snyanstart.8: xorw %ax,%ax # Data 27043561Skato movb $SEL_RDATA,%al # selector 27161064Snyan movw %ax,%ss # Reload SS 27261064Snyan movw %ax,%ds # Reset 27361064Snyan movw %ax,%es # other 27461064Snyan movw %ax,%fs # segment 27561064Snyan movw %ax,%gs # limits 27643561Skato movl %cr0,%eax # Switch to 27761064Snyan decw %ax # real 27843561Skato movl %eax,%cr0 # mode 27961064Snyan ljmp $0,$MEM_ENTRY # Jump to BTX entry point 28043561Skatostart.9: 28161064Snyan .code32 282128710Sru/* 283128710Sru * Output message [ESI] followed by EAX in hex. 284128710Sru */ 28543561Skatohexout: pushl %eax # Save 28643561Skato call putstr # Display message 28743561Skato popl %eax # Restore 28843561Skato pushl %esi # Save 28943561Skato pushl %edi # caller's 29043561Skato movl $buf,%edi # Buffer 29143561Skato pushl %edi # Save 29243561Skato call hex32 # To hex 29343561Skato xorb %al,%al # Terminate 29443561Skato stosb # string 29543561Skato popl %esi # Restore 29643561Skatohexout.1: lodsb # Get a char 29743561Skato cmpb $'0',%al # Leading zero? 29843561Skato je hexout.1 # Yes 29943561Skato testb %al,%al # End of string? 30043561Skato jne hexout.2 # No 30143561Skato decl %esi # Undo 30243561Skatohexout.2: decl %esi # Adjust for inc 30343561Skato call putstr # Display hex 30443561Skato popl %edi # Restore 30543561Skato popl %esi # caller's 30643561Skato ret # To caller 307128710Sru/* 308128710Sru * Output zero-terminated string [ESI] to the console. 309128710Sru */ 31043561Skatoputstr.0: call putchr # Output char 31143561Skatoputstr: lodsb # Load char 31243561Skato testb %al,%al # End of string? 31343561Skato jne putstr.0 # No 31443561Skato ret # To caller 315128710Sru/* 316128710Sru * Output character AL to the console. 317128710Sru */ 31843561Skatoputchr: pusha # Save 31943561Skato xorl %ecx,%ecx # Zero for loops 32043561Skato movb $SCR_MAT,%ah # Mode/attribute 32143561Skato movl $BDA_POS,%ebx # BDA pointer 32243561Skato movw (%ebx),%dx # Cursor position 32343561Skato movl $0xa0000,%edi # Regen buffer (color) 32443561Skatoputchr.1: cmpb $0xa,%al # New line? 32543561Skato je putchr.2 # Yes 32643561Skato movw %dx,%cx 32743561Skato movb %al,(%edi,%ecx,1) # Write char 32843561Skato addl $0x2000,%ecx 32943561Skato movb %ah,(%edi,%ecx,1) # Write attr 33043561Skato addw $0x2,%dx 33143561Skato jmp putchr.3 33243561Skatoputchr.2: movw %dx,%ax 33343561Skato movb $SCR_COL*2,%dl 33443561Skato div %dl 33543561Skato incb %al 33643561Skato mul %dl 33743561Skato movw %ax,%dx 33843561Skatoputchr.3: cmpw $SCR_COL*SCR_ROW*2,%dx 33943561Skato jb putchr.4 # No 34043561Skato leal 2*SCR_COL(%edi),%esi # New top line 34143561Skato movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move 34243561Skato rep # Scroll 34343561Skato movsl # screen 34443561Skato movb $' ',%al # Space 34543561Skato xorb %ah,%ah 34643561Skato movb $SCR_COL,%cl # Columns to clear 34743561Skato rep # Clear 34843561Skato stosw # line 34943561Skato movw $(SCR_ROW-1)*SCR_COL*2,%dx 35043561Skatoputchr.4: movw %dx,(%ebx) # Update position 35143561Skato shrw $1,%dx 35243561Skatogdcwait.3: inb $0x60,%al 35343561Skato testb $0x04,%al 35443561Skato jz gdcwait.3 35543561Skato movb $0x49,%al 35643561Skato outb %al,$0x62 35743561Skato movb %dl,%al 35843561Skato outb %al,$0x60 35943561Skato movb %dh,%al 36043561Skato outb %al,$0x60 36143561Skato popa # Restore 36243561Skato ret # To caller 363128710Sru/* 364128710Sru * Convert EAX, AX, or AL to hex, saving the result to [EDI]. 365128710Sru */ 36643561Skatohex32: pushl %eax # Save 36743561Skato shrl $0x10,%eax # Do upper 36843561Skato call hex16 # 16 36943561Skato popl %eax # Restore 37043561Skatohex16: call hex16.1 # Do upper 8 37143561Skatohex16.1: xchgb %ah,%al # Save/restore 37243561Skatohex8: pushl %eax # Save 37343561Skato shrb $0x4,%al # Do upper 37443561Skato call hex8.1 # 4 37543561Skato popl %eax # Restore 37643561Skatohex8.1: andb $0xf,%al # Get lower 4 37743561Skato cmpb $0xa,%al # Convert 37843561Skato sbbb $0x69,%al # to hex 37943561Skato das # digit 38043561Skato orb $0x20,%al # To lower case 38143561Skato stosb # Save char 38243561Skato ret # (Recursive) 38343561Skato 38443561Skato .data 38543561Skato .p2align 4 386128710Sru/* 387128710Sru * Global descriptor table. 388128710Sru */ 38943561Skatogdt: .word 0x0,0x0,0x0,0x0 # Null entry 39043561Skato .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE 39143561Skato .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 39243561Skato .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE 39343561Skato .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 39443561Skatogdt.1: 39543561Skatogdtdesc: .word gdt.1-gdt-1 # Limit 39643561Skato .long gdt # Base 397128710Sru/* 398128710Sru * Messages. 399128710Sru */ 40052148Sbrianm_logo: .asciz " \nBTX loader 1.00 " 40143561Skatom_vers: .asciz "BTX version is \0\n" 40243561Skatoe_fmt: .asciz "Error: Client format not supported\n" 403125780Snyan#ifdef BTXLDR_VERBOSE 40443561Skatom_mem: .asciz "Starting in protected mode (base mem=\0)\n" 40543561Skatom_esp: .asciz "Arguments passed (esp=\0):\n" 40643561Skatom_args: .asciz"<howto=" 40743561Skato .asciz" bootdev=" 40843561Skato .asciz" junk=" 40943561Skato .asciz" " 41043561Skato .asciz" " 41143561Skato .asciz" bootinfo=\0>\n" 41243561Skatom_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n" 41343561Skatom_rel_args: .asciz "Relocated arguments (size=18) to \0\n" 41443561Skatom_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n" 41543561Skatom_base: .asciz "Client base address is \0\n" 41643561Skatom_elf: .asciz "Client format is ELF\n" 41743561Skatom_segs: .asciz "text segment: offset=" 41843561Skato .asciz " vaddr=" 41943561Skato .asciz " filesz=" 42043561Skato .asciz " memsz=\0\n" 42143561Skato .asciz "data segment: offset=" 42243561Skato .asciz " vaddr=" 42343561Skato .asciz " filesz=" 42443561Skato .asciz " memsz=\0\n" 42543561Skatom_done: .asciz "Loading complete\n" 426125780Snyan#endif 427128710Sru/* 428128710Sru * Uninitialized data area. 429128710Sru */ 43043561Skatobuf: # Scratch buffer 431