btxldr.S revision 125780
143561Skato# 243561Skato# Copyright (c) 1998 Robert Nordier 343561Skato# All rights reserved. 443561Skato# 543561Skato# Redistribution and use in source and binary forms are freely 643561Skato# permitted provided that the above copyright notice and this 743561Skato# paragraph and the following disclaimer are duplicated in all 843561Skato# such forms. 943561Skato# 1043561Skato# This software is provided "AS IS" and without any express or 1143561Skato# implied warranties, including, without limitation, the implied 1243561Skato# warranties of merchantability and fitness for a particular 1343561Skato# purpose. 1443561Skato# 1543561Skato 1650477Speter# $FreeBSD: head/sys/boot/pc98/btx/btxldr/btxldr.S 125780 2004-02-13 15:39:59Z nyan $ 1743561Skato 1843561Skato# 1943561Skato# Prototype BTX loader program, written in a couple of hours. The 2043561Skato# real thing should probably be more flexible, and in C. 2143561Skato# 2243561Skato 2343561Skato# 2443561Skato# Memory locations. 2543561Skato# 2643561Skato .set MEM_STUB,0x600 # Real mode stub 2743561Skato .set MEM_ESP,0x1000 # New stack pointer 2843561Skato .set MEM_TBL,0x5000 # BTX page tables 2943561Skato .set MEM_ENTRY,0x9010 # BTX entry point 3058871Skato .set MEM_DATA,start+0x1000 # Data segment 3143561Skato# 3243561Skato# Segment selectors. 3343561Skato# 3443561Skato .set SEL_SCODE,0x8 # 4GB code 3543561Skato .set SEL_SDATA,0x10 # 4GB data 3643561Skato .set SEL_RCODE,0x18 # 64K code 3743561Skato .set SEL_RDATA,0x20 # 64K data 3843561Skato# 3943561Skato# Paging constants. 4043561Skato# 4143561Skato .set PAG_SIZ,0x1000 # Page size 4243561Skato .set PAG_ENT,0x4 # Page entry size 4343561Skato# 4443561Skato# Screen constants. 4543561Skato# 46125780Snyan#ifdef PC98 4743561Skato .set SCR_MAT,0xe1 # Mode/attribute 48125780Snyan#else 4943561Skato .set SCR_MAT,0x7 # Mode/attribute 50125780Snyan#endif 5143561Skato .set SCR_COL,0x50 # Columns per row 5243561Skato .set SCR_ROW,0x19 # Rows per screen 5343561Skato# 5443561Skato# BIOS Data Area locations. 5543561Skato# 56125780Snyan#ifdef PC98 5743561Skato .set BDA_MEM,0xa1501 # Free memory 5843561Skato .set BDA_POS,0xa153e # Cursor position 59125780Snyan#else 6043561Skato .set BDA_MEM,0x413 # Free memory 6143561Skato .set BDA_SCR,0x449 # Video mode 6243561Skato .set BDA_POS,0x450 # Cursor position 63125780Snyan#endif 6443561Skato# 6543561Skato# Required by aout gas inadequacy. 6643561Skato# 6743561Skato .set SIZ_STUB,0x1a # Size of stub 6843561Skato# 6958871Skato# We expect to be loaded by boot2 at the origin defined in ./Makefile. 7043561Skato# 7143561Skato .globl start 7243561Skato# 7343561Skato# BTX program loader for ELF clients. 7443561Skato# 7543561Skatostart: cld # String ops inc 76125780Snyan#ifdef PC98 7743561Skato cli 7843561Skatogdcwait.1: inb $0x60,%al 7943561Skato testb $0x04,%al 8043561Skato jz gdcwait.1 8143561Skato movb $0xe0,%al 8243561Skato outb %al,$0x62 8343561Skato nop 8443561Skatogdcwait.2: inb $0x60,%al 8543561Skato testb $0x01,%al 8643561Skato jz gdcwait.2 8743561Skato inb $0x62,%al 8843561Skato movb %al,%dl 8943561Skato inb $0x62,%al 9043561Skato movb %al,%dh 9143561Skato inb $0x62,%al 9243561Skato inb $0x62,%al 9343561Skato inb $0x62,%al 9443561Skato shlw $1,%dx 9543561Skato movl $BDA_POS,%ebx 9643561Skato movw %dx,(%ebx) 97125780Snyan#endif 9843561Skato movl $m_logo,%esi # Identify 9943561Skato call putstr # ourselves 10043561Skato movzwl BDA_MEM,%eax # Get base memory 101125780Snyan#ifdef PC98 10243561Skato andl $0x7,%eax 10343561Skato incl %eax 10443561Skato shll $0x11,%eax # in bytes 105125780Snyan#else 10643561Skato shll $0xa,%eax # in bytes 107125780Snyan#endif 10843561Skato movl %eax,%ebp # Base of user stack 109125780Snyan#ifdef BTXLDR_VERBOSE 11043561Skato movl $m_mem,%esi # Display 11158871Skato call hexout # amount of 11258871Skato call putstr # base memory 113125780Snyan#endif 11443561Skato lgdt gdtdesc # Load new GDT 11543561Skato# 11643561Skato# Relocate caller's arguments. 11743561Skato# 118125780Snyan#ifdef BTXLDR_VERBOSE 11943561Skato movl $m_esp,%esi # Display 12058871Skato movl %esp,%eax # caller 12158871Skato call hexout # stack 12258871Skato call putstr # pointer 12343561Skato movl $m_args,%esi # Format string 12443561Skato leal 0x4(%esp,1),%ebx # First argument 12543561Skato movl $0x6,%ecx # Count 12643561Skatostart.1: movl (%ebx),%eax # Get argument and 12743561Skato addl $0x4,%ebx # bump pointer 12858871Skato call hexout # Display it 12943561Skato loop start.1 # Till done 13058871Skato call putstr # End message 131125780Snyan#endif 13243561Skato movl $0x48,%ecx # Allocate space 13343561Skato subl %ecx,%ebp # for bootinfo 13458871Skato movl 0x18(%esp,1),%esi # Source: bootinfo 13558871Skato cmpl $0x0, %esi # If the bootinfo pointer 13658871Skato je start_null_bi # is null, don't copy it 13743561Skato movl %ebp,%edi # Destination 13843561Skato rep # Copy 13943561Skato movsb # it 14043561Skato movl %ebp,0x18(%esp,1) # Update pointer 141125780Snyan#ifdef BTXLDR_VERBOSE 14243561Skato movl $m_rel_bi,%esi # Display 14343561Skato movl %ebp,%eax # bootinfo 14458871Skato call hexout # relocation 14558871Skato call putstr # message 146125780Snyan#endif 14758871Skatostart_null_bi: movl $0x18,%ecx # Allocate space 14843561Skato subl %ecx,%ebp # for arguments 14943561Skato leal 0x4(%esp,1),%esi # Source 15043561Skato movl %ebp,%edi # Destination 15143561Skato rep # Copy 15243561Skato movsb # them 153125780Snyan#ifdef BTXLDR_VERBOSE 15443561Skato movl $m_rel_args,%esi # Display 15543561Skato movl %ebp,%eax # argument 15658871Skato call hexout # relocation 15758871Skato call putstr # message 158125780Snyan#endif 15943561Skato# 16043561Skato# Set up BTX kernel. 16143561Skato# 16243561Skato movl $MEM_ESP,%esp # Set up new stack 16343561Skato movl $MEM_DATA,%ebx # Data segment 16443561Skato movl $m_vers,%esi # Display BTX 16543561Skato call putstr # version message 16643561Skato movb 0x5(%ebx),%al # Get major version 16743561Skato addb $'0',%al # Display 16843561Skato call putchr # it 16943561Skato movb $'.',%al # And a 17043561Skato call putchr # dot 17143561Skato movb 0x6(%ebx),%al # Get minor 17243561Skato xorb %ah,%ah # version 17343561Skato movb $0xa,%dl # Divide 17443561Skato divb %dl,%al # by 10 17543561Skato addb $'0',%al # Display 17643561Skato call putchr # tens 17743561Skato movb %ah,%al # Get units 17843561Skato addb $'0',%al # Display 17943561Skato call putchr # units 18043561Skato call putstr # End message 18143561Skato movl %ebx,%esi # BTX image 18243561Skato movzwl 0x8(%ebx),%edi # Compute 18343561Skato orl $PAG_SIZ/PAG_ENT-1,%edi # the 18443561Skato incl %edi # BTX 18543561Skato shll $0x2,%edi # load 18643561Skato addl $MEM_TBL,%edi # address 18758871Skato pushl %edi # Save load address 18843561Skato movzwl 0xa(%ebx),%ecx # Image size 189125780Snyan#ifdef BTXLDR_VERBOSE 19058871Skato pushl %ecx # Save image size 191125780Snyan#endif 19243561Skato rep # Relocate 19343561Skato movsb # BTX 19443561Skato movl %esi,%ebx # Keep place 195125780Snyan#ifdef BTXLDR_VERBOSE 19643561Skato movl $m_rel_btx,%esi # Restore 19743561Skato popl %eax # parameters 19858871Skato call hexout # and 199125780Snyan#endif 20043561Skato popl %ebp # display 201125780Snyan#ifdef BTXLDR_VERBOSE 20243561Skato movl %ebp,%eax # the 20358871Skato call hexout # relocation 20458871Skato call putstr # message 205125780Snyan#endif 20643561Skato addl $PAG_SIZ,%ebp # Display 207125780Snyan#ifdef BTXLDR_VERBOSE 20843561Skato movl $m_base,%esi # the 20943561Skato movl %ebp,%eax # user 21058871Skato call hexout # base 21158871Skato call putstr # address 212125780Snyan#endif 21343561Skato# 21443561Skato# Set up ELF-format client program. 21543561Skato# 21643561Skato cmpl $0x464c457f,(%ebx) # ELF magic number? 21743561Skato je start.3 # Yes 21843561Skato movl $e_fmt,%esi # Display error 21943561Skato call putstr # message 22043561Skatostart.2: jmp start.2 # Hang 22158871Skatostart.3: 222125780Snyan#ifdef BTXLDR_VERBOSE 22358871Skato movl $m_elf,%esi # Display ELF 22458871Skato call putstr # message 22543561Skato movl $m_segs,%esi # Format string 226125780Snyan#endif 22743561Skato movl $0x2,%edi # Segment count 22843561Skato movl 0x1c(%ebx),%edx # Get e_phoff 22943561Skato addl %ebx,%edx # To pointer 23043561Skato movzwl 0x2c(%ebx),%ecx # Get e_phnum 23143561Skatostart.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD? 23243561Skato jne start.6 # No 233125780Snyan#ifdef BTXLDR_VERBOSE 23443561Skato movl 0x4(%edx),%eax # Display 23558871Skato call hexout # p_offset 23643561Skato movl 0x8(%edx),%eax # Display 23758871Skato call hexout # p_vaddr 23843561Skato movl 0x10(%edx),%eax # Display 23958871Skato call hexout # p_filesz 24043561Skato movl 0x14(%edx),%eax # Display 24158871Skato call hexout # p_memsz 24258871Skato call putstr # End message 243125780Snyan#endif 24443561Skato pushl %esi # Save 24543561Skato pushl %edi # working 24643561Skato pushl %ecx # registers 24743561Skato movl 0x4(%edx),%esi # Get p_offset 24843561Skato addl %ebx,%esi # as pointer 24943561Skato movl 0x8(%edx),%edi # Get p_vaddr 25043561Skato addl %ebp,%edi # as pointer 25143561Skato movl 0x10(%edx),%ecx # Get p_filesz 25243561Skato rep # Set up 25343561Skato movsb # segment 25443561Skato movl 0x14(%edx),%ecx # Any bytes 25543561Skato subl 0x10(%edx),%ecx # to zero? 25643561Skato jz start.5 # No 25743561Skato xorb %al,%al # Then 25843561Skato rep # zero 25943561Skato stosb # them 26043561Skatostart.5: popl %ecx # Restore 26143561Skato popl %edi # working 26243561Skato popl %esi # registers 26343561Skato decl %edi # Segments to do 26443561Skato je start.7 # If none 26543561Skatostart.6: addl $0x20,%edx # To next entry 26643561Skato loop start.4 # Till done 26758871Skatostart.7: 268125780Snyan#ifdef BTXLDR_VERBOSE 26958871Skato movl $m_done,%esi # Display done 27058871Skato call putstr # message 271125780Snyan#endif 27243561Skato movl $start.8,%esi # Real mode stub 27343561Skato movl $MEM_STUB,%edi # Destination 27461064Snyan movl $start.9-start.8,%ecx # Size 27543561Skato rep # Relocate 27643561Skato movsb # it 27743561Skato ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code 27861064Snyan .code16 27961064Snyanstart.8: xorw %ax,%ax # Data 28043561Skato movb $SEL_RDATA,%al # selector 28161064Snyan movw %ax,%ss # Reload SS 28261064Snyan movw %ax,%ds # Reset 28361064Snyan movw %ax,%es # other 28461064Snyan movw %ax,%fs # segment 28561064Snyan movw %ax,%gs # limits 28643561Skato movl %cr0,%eax # Switch to 28761064Snyan decw %ax # real 28843561Skato movl %eax,%cr0 # mode 28961064Snyan ljmp $0,$MEM_ENTRY # Jump to BTX entry point 29043561Skatostart.9: 29161064Snyan .code32 29243561Skato# 29343561Skato# Output message [ESI] followed by EAX in hex. 29443561Skato# 29543561Skatohexout: pushl %eax # Save 29643561Skato call putstr # Display message 29743561Skato popl %eax # Restore 29843561Skato pushl %esi # Save 29943561Skato pushl %edi # caller's 30043561Skato movl $buf,%edi # Buffer 30143561Skato pushl %edi # Save 30243561Skato call hex32 # To hex 30343561Skato xorb %al,%al # Terminate 30443561Skato stosb # string 30543561Skato popl %esi # Restore 30643561Skatohexout.1: lodsb # Get a char 30743561Skato cmpb $'0',%al # Leading zero? 30843561Skato je hexout.1 # Yes 30943561Skato testb %al,%al # End of string? 31043561Skato jne hexout.2 # No 31143561Skato decl %esi # Undo 31243561Skatohexout.2: decl %esi # Adjust for inc 31343561Skato call putstr # Display hex 31443561Skato popl %edi # Restore 31543561Skato popl %esi # caller's 31643561Skato ret # To caller 31743561Skato# 31843561Skato# Output zero-terminated string [ESI] to the console. 31943561Skato# 32043561Skatoputstr.0: call putchr # Output char 32143561Skatoputstr: lodsb # Load char 32243561Skato testb %al,%al # End of string? 32343561Skato jne putstr.0 # No 32443561Skato ret # To caller 32543561Skato# 32643561Skato# Output character AL to the console. 32743561Skato# 32843561Skatoputchr: pusha # Save 32943561Skato xorl %ecx,%ecx # Zero for loops 33043561Skato movb $SCR_MAT,%ah # Mode/attribute 33143561Skato movl $BDA_POS,%ebx # BDA pointer 33243561Skato movw (%ebx),%dx # Cursor position 333125780Snyan#ifdef PC98 33443561Skato movl $0xa0000,%edi # Regen buffer (color) 335125780Snyan#else 33643561Skato movl $0xb8000,%edi # Regen buffer (color) 33743561Skato cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode? 33843561Skato jne putchr.1 # No 33943561Skato xorw %di,%di # Regen buffer (mono) 340125780Snyan#endif 34143561Skatoputchr.1: cmpb $0xa,%al # New line? 34243561Skato je putchr.2 # Yes 343125780Snyan#ifdef PC98 34443561Skato movw %dx,%cx 34543561Skato movb %al,(%edi,%ecx,1) # Write char 34643561Skato addl $0x2000,%ecx 34743561Skato movb %ah,(%edi,%ecx,1) # Write attr 34843561Skato addw $0x2,%dx 34943561Skato jmp putchr.3 35043561Skatoputchr.2: movw %dx,%ax 35143561Skato movb $SCR_COL*2,%dl 35243561Skato div %dl 35343561Skato incb %al 35443561Skato mul %dl 35543561Skato movw %ax,%dx 35643561Skatoputchr.3: cmpw $SCR_COL*SCR_ROW*2,%dx 357125780Snyan#else 35843561Skato xchgl %eax,%ecx # Save char 35943561Skato movb $SCR_COL,%al # Columns per row 36043561Skato mulb %dh # * row position 36143561Skato addb %dl,%al # + column 36243561Skato adcb $0x0,%ah # position 36343561Skato shll %eax # * 2 36443561Skato xchgl %eax,%ecx # Swap char, offset 36543561Skato movw %ax,(%edi,%ecx,1) # Write attr:char 36643561Skato incl %edx # Bump cursor 36743561Skato cmpb $SCR_COL,%dl # Beyond row? 36843561Skato jb putchr.3 # No 36943561Skatoputchr.2: xorb %dl,%dl # Zero column 37043561Skato incb %dh # Bump row 37143561Skatoputchr.3: cmpb $SCR_ROW,%dh # Beyond screen? 372125780Snyan#endif 37343561Skato jb putchr.4 # No 37443561Skato leal 2*SCR_COL(%edi),%esi # New top line 37543561Skato movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move 37643561Skato rep # Scroll 37743561Skato movsl # screen 37843561Skato movb $' ',%al # Space 379125780Snyan#ifdef PC98 38043561Skato xorb %ah,%ah 381125780Snyan#endif 38243561Skato movb $SCR_COL,%cl # Columns to clear 38343561Skato rep # Clear 38443561Skato stosw # line 385125780Snyan#ifdef PC98 38643561Skato movw $(SCR_ROW-1)*SCR_COL*2,%dx 38743561Skatoputchr.4: movw %dx,(%ebx) # Update position 38843561Skato shrw $1,%dx 38943561Skatogdcwait.3: inb $0x60,%al 39043561Skato testb $0x04,%al 39143561Skato jz gdcwait.3 39243561Skato movb $0x49,%al 39343561Skato outb %al,$0x62 39443561Skato movb %dl,%al 39543561Skato outb %al,$0x60 39643561Skato movb %dh,%al 39743561Skato outb %al,$0x60 398125780Snyan#else 39943561Skato movb $SCR_ROW-1,%dh # Bottom line 40043561Skatoputchr.4: movw %dx,(%ebx) # Update position 401125780Snyan#endif 40243561Skato popa # Restore 40343561Skato ret # To caller 40443561Skato# 40543561Skato# Convert EAX, AX, or AL to hex, saving the result to [EDI]. 40643561Skato# 40743561Skatohex32: pushl %eax # Save 40843561Skato shrl $0x10,%eax # Do upper 40943561Skato call hex16 # 16 41043561Skato popl %eax # Restore 41143561Skatohex16: call hex16.1 # Do upper 8 41243561Skatohex16.1: xchgb %ah,%al # Save/restore 41343561Skatohex8: pushl %eax # Save 41443561Skato shrb $0x4,%al # Do upper 41543561Skato call hex8.1 # 4 41643561Skato popl %eax # Restore 41743561Skatohex8.1: andb $0xf,%al # Get lower 4 41843561Skato cmpb $0xa,%al # Convert 41943561Skato sbbb $0x69,%al # to hex 42043561Skato das # digit 42143561Skato orb $0x20,%al # To lower case 42243561Skato stosb # Save char 42343561Skato ret # (Recursive) 42443561Skato 42543561Skato .data 42643561Skato .p2align 4 42743561Skato# 42843561Skato# Global descriptor table. 42943561Skato# 43043561Skatogdt: .word 0x0,0x0,0x0,0x0 # Null entry 43143561Skato .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE 43243561Skato .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 43343561Skato .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE 43443561Skato .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 43543561Skatogdt.1: 43643561Skatogdtdesc: .word gdt.1-gdt-1 # Limit 43743561Skato .long gdt # Base 43843561Skato# 43943561Skato# Messages. 44043561Skato# 44152148Sbrianm_logo: .asciz " \nBTX loader 1.00 " 44243561Skatom_vers: .asciz "BTX version is \0\n" 44343561Skatoe_fmt: .asciz "Error: Client format not supported\n" 444125780Snyan#ifdef BTXLDR_VERBOSE 44543561Skatom_mem: .asciz "Starting in protected mode (base mem=\0)\n" 44643561Skatom_esp: .asciz "Arguments passed (esp=\0):\n" 44743561Skatom_args: .asciz"<howto=" 44843561Skato .asciz" bootdev=" 44943561Skato .asciz" junk=" 45043561Skato .asciz" " 45143561Skato .asciz" " 45243561Skato .asciz" bootinfo=\0>\n" 45343561Skatom_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n" 45443561Skatom_rel_args: .asciz "Relocated arguments (size=18) to \0\n" 45543561Skatom_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n" 45643561Skatom_base: .asciz "Client base address is \0\n" 45743561Skatom_elf: .asciz "Client format is ELF\n" 45843561Skatom_segs: .asciz "text segment: offset=" 45943561Skato .asciz " vaddr=" 46043561Skato .asciz " filesz=" 46143561Skato .asciz " memsz=\0\n" 46243561Skato .asciz "data segment: offset=" 46343561Skato .asciz " vaddr=" 46443561Skato .asciz " filesz=" 46543561Skato .asciz " memsz=\0\n" 46643561Skatom_done: .asciz "Loading complete\n" 467125780Snyan#endif 46843561Skato# 46943561Skato# Uninitialized data area. 47043561Skato# 47143561Skatobuf: # Scratch buffer 472