/*1* Copyright (c) 1998 Robert Nordier2* All rights reserved.3*4* Redistribution and use in source and binary forms are freely5* permitted provided that the above copyright notice and this6* paragraph and the following disclaimer are duplicated in all7* such forms.8*9* This software is provided "AS IS" and without any express or10* implied warranties, including, without limitation, the implied11* warranties of merchantability and fitness for a particular12* purpose.13*/1415#include <bootargs.h>1617#define RBX_MUTE 0x10 /* -m */18#define OPT_SET(opt) (1 << (opt))1920/*21* Prototype BTX loader program, written in a couple of hours. The22* real thing should probably be more flexible, and in C.23*/2425/*26* Memory locations.27*/28.set MEM_STUB,0x600 # Real mode stub29.set MEM_ESP,0x1000 # New stack pointer30.set MEM_TBL,0x5000 # BTX page tables31.set MEM_ENTRY,0x9010 # BTX entry point32.set MEM_DATA,start+0x1000 # Data segment33/*34* Segment selectors.35*/36.set SEL_SCODE,0x8 # 4GB code37.set SEL_SDATA,0x10 # 4GB data38.set SEL_RCODE,0x18 # 64K code39.set SEL_RDATA,0x20 # 64K data40/*41* Paging constants.42*/43.set PAG_SIZ,0x1000 # Page size44.set PAG_ENT,0x4 # Page entry size45/*46* Screen constants.47*/48.set SCR_MAT,0x7 # Mode/attribute49.set SCR_COL,0x50 # Columns per row50.set SCR_ROW,0x19 # Rows per screen51/*52* BIOS Data Area locations.53*/54.set BDA_MEM,0x413 # Free memory55.set BDA_SCR,0x449 # Video mode56.set BDA_POS,0x450 # Cursor position57/*58* Required by aout gas inadequacy.59*/60.set SIZ_STUB,0x1a # Size of stub61/*62* We expect to be loaded by boot2 at the origin defined in ./Makefile.63*/64.globl start65/*66* BTX program loader for ELF clients.67*/68start: cld # String ops inc69testl $OPT_SET(RBX_MUTE), 4(%esp) # Check first argument70setnz muted # for RBX_MUTE, set flag71movl $m_logo,%esi # Identify72call putstr # ourselves73movzwl BDA_MEM,%eax # Get base memory74shll $0xa,%eax # in bytes75movl %eax,%ebp # Base of user stack76#ifdef BTXLDR_VERBOSE77movl $m_mem,%esi # Display78call hexout # amount of79call putstr # base memory80#endif81lgdt gdtdesc # Load new GDT82/*83* Relocate caller's arguments.84*/85#ifdef BTXLDR_VERBOSE86movl $m_esp,%esi # Display87movl %esp,%eax # caller88call hexout # stack89call putstr # pointer90movl $m_args,%esi # Format string91leal 0x4(%esp),%ebx # First argument92movl $0x6,%ecx # Count93start.1: movl (%ebx),%eax # Get argument and94addl $0x4,%ebx # bump pointer95call hexout # Display it96loop start.1 # Till done97call putstr # End message98#endif99movl BA_BOOTINFO+4(%esp),%esi # Source: bootinfo100cmpl $0x0, %esi # If the bootinfo pointer101je start_null_bi # is null, don't copy it102movl BI_SIZE(%esi),%ecx # Allocate space103subl %ecx,%ebp # for bootinfo104movl %ebp,%edi # Destination105rep # Copy106movsb # it107movl %ebp,BA_BOOTINFO+4(%esp) # Update pointer108movl %edi,%ebp # Restore base pointer109#ifdef BTXLDR_VERBOSE110movl $m_rel_bi,%esi # Display111movl %ebp,%eax # bootinfo112call hexout # relocation113call putstr # message114#endif115start_null_bi: movl $BOOTARGS_SIZE,%ecx # Fixed size of arguments116testl $KARGS_FLAGS_EXTARG, BA_BOOTFLAGS+4(%esp) # Check for extra data117jz start_fixed # Skip if the flag is not set118addl BOOTARGS_SIZE+4(%esp),%ecx # Add size of variable args119start_fixed: subl $ARGOFF,%ebp # Place args at fixed offset120leal 0x4(%esp),%esi # Source121movl %ebp,%edi # Destination122rep # Copy123movsb # them124#ifdef BTXLDR_VERBOSE125movl $m_rel_args,%esi # Display126movl %ebp,%eax # argument127call hexout # relocation128call putstr # message129#endif130/*131* Set up BTX kernel.132*/133movl $MEM_ESP,%esp # Set up new stack134movl $MEM_DATA,%ebx # Data segment135movl $m_vers,%esi # Display BTX136call putstr # version message137movb 0x5(%ebx),%al # Get major version138addb $'0',%al # Display139call putchr # it140movb $'.',%al # And a141call putchr # dot142movb 0x6(%ebx),%al # Get minor143xorb %ah,%ah # version144movb $0xa,%dl # Divide145divb %dl,%al # by 10146addb $'0',%al # Display147call putchr # tens148movb %ah,%al # Get units149addb $'0',%al # Display150call putchr # units151call putstr # End message152movl %ebx,%esi # BTX image153movzwl 0x8(%ebx),%edi # Compute154orl $PAG_SIZ/PAG_ENT-1,%edi # the155incl %edi # BTX156shll $0x2,%edi # load157addl $MEM_TBL,%edi # address158pushl %edi # Save load address159movzwl 0xa(%ebx),%ecx # Image size160#ifdef BTXLDR_VERBOSE161pushl %ecx # Save image size162#endif163rep # Relocate164movsb # BTX165movl %esi,%ebx # Keep place166#ifdef BTXLDR_VERBOSE167movl $m_rel_btx,%esi # Restore168popl %eax # parameters169call hexout # and170#endif171popl %ebp # display172#ifdef BTXLDR_VERBOSE173movl %ebp,%eax # the174call hexout # relocation175call putstr # message176#endif177addl $PAG_SIZ,%ebp # Display178#ifdef BTXLDR_VERBOSE179movl $m_base,%esi # the180movl %ebp,%eax # user181call hexout # base182call putstr # address183#endif184/*185* Set up ELF-format client program.186*/187cmpl $0x464c457f,(%ebx) # ELF magic number?188je start.3 # Yes189movl $e_fmt,%esi # Display error190call putstr # message191start.2: jmp start.2 # Hang192start.3:193#ifdef BTXLDR_VERBOSE194movl $m_elf,%esi # Display ELF195call putstr # message196movl $m_segs,%esi # Format string197#endif198movl 0x1c(%ebx),%edx # Get e_phoff199addl %ebx,%edx # To pointer200movzwl 0x2c(%ebx),%ecx # Get e_phnum201start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD?202jne start.6 # No203#ifdef BTXLDR_VERBOSE204movl 0x4(%edx),%eax # Display205call hexout # p_offset206movl 0x8(%edx),%eax # Display207call hexout # p_vaddr208movl 0x10(%edx),%eax # Display209call hexout # p_filesz210movl 0x14(%edx),%eax # Display211call hexout # p_memsz212call putstr # End message213#endif214pushl %esi # Save215pushl %ecx # working registers216movl 0x4(%edx),%esi # Get p_offset217addl %ebx,%esi # as pointer218movl 0x8(%edx),%edi # Get p_vaddr219addl %ebp,%edi # as pointer220movl 0x10(%edx),%ecx # Get p_filesz221rep # Set up222movsb # segment223movl 0x14(%edx),%ecx # Any bytes224subl 0x10(%edx),%ecx # to zero?225jz start.5 # No226xorb %al,%al # Then227rep # zero228stosb # them229start.5: popl %ecx # Restore230popl %esi # registers231start.6: addl $0x20,%edx # To next entry232loop start.4 # Till done233#ifdef BTXLDR_VERBOSE234movl $m_done,%esi # Display done235call putstr # message236#endif237movl $start.8,%esi # Real mode stub238movl $MEM_STUB,%edi # Destination239movl $start.9-start.8,%ecx # Size240rep # Relocate241movsb # it242ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code243.code16244start.8: xorw %ax,%ax # Data245movb $SEL_RDATA,%al # selector246movw %ax,%ss # Reload SS247movw %ax,%ds # Reset248movw %ax,%es # other249movw %ax,%fs # segment250movw %ax,%gs # limits251movl %cr0,%eax # Switch to252decw %ax # real253movl %eax,%cr0 # mode254ljmp $0,$MEM_ENTRY # Jump to BTX entry point255start.9:256.code32257/*258* Output message [ESI] followed by EAX in hex.259*/260hexout: pushl %eax # Save261call putstr # Display message262popl %eax # Restore263pushl %esi # Save264pushl %edi # caller's265movl $buf,%edi # Buffer266pushl %edi # Save267call hex32 # To hex268xorb %al,%al # Terminate269stosb # string270popl %esi # Restore271hexout.1: lodsb # Get a char272cmpb $'0',%al # Leading zero?273je hexout.1 # Yes274testb %al,%al # End of string?275jne hexout.2 # No276decl %esi # Undo277hexout.2: decl %esi # Adjust for inc278call putstr # Display hex279popl %edi # Restore280popl %esi # caller's281ret # To caller282/*283* Output zero-terminated string [ESI] to the console.284*/285putstr.0: call putchr # Output char286putstr: lodsb # Load char287testb %al,%al # End of string?288jne putstr.0 # No289ret # To caller290/*291* Output character AL to the console.292*/293putchr: testb $1,muted # Check muted294jnz putchr.5 # do a nop295pusha # Save296xorl %ecx,%ecx # Zero for loops297movb $SCR_MAT,%ah # Mode/attribute298movl $BDA_POS,%ebx # BDA pointer299movw (%ebx),%dx # Cursor position300movl $0xb8000,%edi # Regen buffer (color)301cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode?302jne putchr.1 # No303xorw %di,%di # Regen buffer (mono)304putchr.1: cmpb $0xa,%al # New line?305je putchr.2 # Yes306xchgl %eax,%ecx # Save char307movb $SCR_COL,%al # Columns per row308mulb %dh # * row position309addb %dl,%al # + column310adcb $0x0,%ah # position311shll %eax # * 2312xchgl %eax,%ecx # Swap char, offset313movw %ax,(%edi,%ecx,1) # Write attr:char314incl %edx # Bump cursor315cmpb $SCR_COL,%dl # Beyond row?316jb putchr.3 # No317putchr.2: xorb %dl,%dl # Zero column318incb %dh # Bump row319putchr.3: cmpb $SCR_ROW,%dh # Beyond screen?320jb putchr.4 # No321leal 2*SCR_COL(%edi),%esi # New top line322movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move323rep # Scroll324movsl # screen325movb $' ',%al # Space326movb $SCR_COL,%cl # Columns to clear327rep # Clear328stosw # line329movb $SCR_ROW-1,%dh # Bottom line330putchr.4: movw %dx,(%ebx) # Update position331popa # Restore332putchr.5: ret # To caller333/*334* Convert EAX, AX, or AL to hex, saving the result to [EDI].335*/336hex32: pushl %eax # Save337shrl $0x10,%eax # Do upper338call hex16 # 16339popl %eax # Restore340hex16: call hex16.1 # Do upper 8341hex16.1: xchgb %ah,%al # Save/restore342hex8: pushl %eax # Save343shrb $0x4,%al # Do upper344call hex8.1 # 4345popl %eax # Restore346hex8.1: andb $0xf,%al # Get lower 4347cmpb $0xa,%al # Convert348sbbb $0x69,%al # to hex349das # digit350orb $0x20,%al # To lower case351stosb # Save char352ret # (Recursive)353354.data355.p2align 4356/*357* Global descriptor table.358*/359gdt: .word 0x0,0x0,0x0,0x0 # Null entry360.word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE361.word 0xffff,0x0,0x9200,0xcf # SEL_SDATA362.word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE363.word 0xffff,0x0,0x9200,0x0 # SEL_RDATA364gdt.1:365gdtdesc: .word gdt.1-gdt-1 # Limit366.long gdt # Base367/*368* Messages.369*/370m_logo: .asciz " \nBTX loader 1.00 "371m_vers: .asciz "BTX version is \0\n"372e_fmt: .asciz "Error: Client format not supported\n"373#ifdef BTXLDR_VERBOSE374m_mem: .asciz "Starting in protected mode (base mem=\0)\n"375m_esp: .asciz "Arguments passed (esp=\0):\n"376m_args: .asciz "<howto="377.asciz " bootdev="378.asciz " junk="379.asciz " "380.asciz " "381.asciz " bootinfo=\0>\n"382m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n"383m_rel_args: .asciz "Relocated arguments (size=18) to \0\n"384m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n"385m_base: .asciz "Client base address is \0\n"386m_elf: .asciz "Client format is ELF\n"387m_segs: .asciz "text segment: offset="388.asciz " vaddr="389.asciz " filesz="390.asciz " memsz=\0\n"391.asciz "data segment: offset="392.asciz " vaddr="393.asciz " filesz="394.asciz " memsz=\0\n"395m_done: .asciz "Loading complete\n"396#endif397398/*399* Flags400*/401muted: .byte 0x0402403/*404* Uninitialized data area.405*/406buf: # Scratch buffer407408409