1*479ab7f0SSascha Wildner/* 2*479ab7f0SSascha Wildner * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved. 3*479ab7f0SSascha Wildner * 4*479ab7f0SSascha Wildner * This code is derived from software contributed to The DragonFly Project 5*479ab7f0SSascha Wildner * by Matthew Dillon <dillon@backplane.com> 6*479ab7f0SSascha Wildner * 7*479ab7f0SSascha Wildner * Redistribution and use in source and binary forms, with or without 8*479ab7f0SSascha Wildner * modification, are permitted provided that the following conditions 9*479ab7f0SSascha Wildner * are met: 10*479ab7f0SSascha Wildner * 11*479ab7f0SSascha Wildner * 1. Redistributions of source code must retain the above copyright 12*479ab7f0SSascha Wildner * notice, this list of conditions and the following disclaimer. 13*479ab7f0SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 14*479ab7f0SSascha Wildner * notice, this list of conditions and the following disclaimer in 15*479ab7f0SSascha Wildner * the documentation and/or other materials provided with the 16*479ab7f0SSascha Wildner * distribution. 17*479ab7f0SSascha Wildner * 3. Neither the name of The DragonFly Project nor the names of its 18*479ab7f0SSascha Wildner * contributors may be used to endorse or promote products derived 19*479ab7f0SSascha Wildner * from this software without specific, prior written permission. 20*479ab7f0SSascha Wildner * 21*479ab7f0SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*479ab7f0SSascha Wildner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*479ab7f0SSascha Wildner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24*479ab7f0SSascha Wildner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25*479ab7f0SSascha Wildner * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26*479ab7f0SSascha Wildner * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27*479ab7f0SSascha Wildner * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28*479ab7f0SSascha Wildner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29*479ab7f0SSascha Wildner * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30*479ab7f0SSascha Wildner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31*479ab7f0SSascha Wildner * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*479ab7f0SSascha Wildner * SUCH DAMAGE. 33*479ab7f0SSascha Wildner * 34*479ab7f0SSascha Wildner * Copyright (c) 1998 Robert Nordier 35*479ab7f0SSascha Wildner * All rights reserved. 36*479ab7f0SSascha Wildner * 37*479ab7f0SSascha Wildner * Redistribution and use in source and binary forms are freely 38*479ab7f0SSascha Wildner * permitted provided that the above copyright notice and this 39*479ab7f0SSascha Wildner * paragraph and the following disclaimer are duplicated in all 40*479ab7f0SSascha Wildner * such forms. 41*479ab7f0SSascha Wildner * 42*479ab7f0SSascha Wildner * This software is provided "AS IS" and without any express or 43*479ab7f0SSascha Wildner * implied warranties, including, without limitation, the implied 44*479ab7f0SSascha Wildner * warranties of merchantability and fitness for a particular 45*479ab7f0SSascha Wildner * purpose. 46*479ab7f0SSascha Wildner * 47*479ab7f0SSascha Wildner * $FreeBSD: src/sys/boot/i386/btx/btxldr/Makefile,v 1.17 2004/04/27 19:45:16 ru Exp $ 48*479ab7f0SSascha Wildner * $DragonFly: src/sys/boot/pc32/btx/btxldr/btxldr.S,v 1.3 2004/07/19 23:30:34 dillon Exp $ 49*479ab7f0SSascha Wildner */ 50*479ab7f0SSascha Wildner 51*479ab7f0SSascha Wildner/* 52*479ab7f0SSascha Wildner * Prototype BTX loader program, written in a couple of hours. The 53*479ab7f0SSascha Wildner * real thing should probably be more flexible, and in C. 54*479ab7f0SSascha Wildner */ 55*479ab7f0SSascha Wildner 56*479ab7f0SSascha Wildner#include "../../bootasm.h" 57*479ab7f0SSascha Wildner/* 58*479ab7f0SSascha Wildner * Memory locations. 59*479ab7f0SSascha Wildner */ 60*479ab7f0SSascha Wildner .set MEM_DATA,start+0x1000 # Data segment 61*479ab7f0SSascha Wildner/* 62*479ab7f0SSascha Wildner * Segment selectors. 63*479ab7f0SSascha Wildner */ 64*479ab7f0SSascha Wildner .set SEL_SCODE,0x8 # 4GB code 65*479ab7f0SSascha Wildner .set SEL_SDATA,0x10 # 4GB data 66*479ab7f0SSascha Wildner .set SEL_RCODE,0x18 # 64K code 67*479ab7f0SSascha Wildner .set SEL_RDATA,0x20 # 64K data 68*479ab7f0SSascha Wildner/* 69*479ab7f0SSascha Wildner * Paging constants. 70*479ab7f0SSascha Wildner */ 71*479ab7f0SSascha Wildner .set PAG_SIZ,0x1000 # Page size 72*479ab7f0SSascha Wildner .set PAG_ENT,0x4 # Page entry size 73*479ab7f0SSascha Wildner/* 74*479ab7f0SSascha Wildner * Screen constants. 75*479ab7f0SSascha Wildner */ 76*479ab7f0SSascha Wildner .set SCR_MAT,0x7 # Mode/attribute 77*479ab7f0SSascha Wildner .set SCR_COL,0x50 # Columns per row 78*479ab7f0SSascha Wildner .set SCR_ROW,0x19 # Rows per screen 79*479ab7f0SSascha Wildner/* 80*479ab7f0SSascha Wildner * Required by aout gas inadequacy. 81*479ab7f0SSascha Wildner */ 82*479ab7f0SSascha Wildner .set SIZ_STUB,0x1a # Size of stub 83*479ab7f0SSascha Wildner/* 84*479ab7f0SSascha Wildner * We expect to be loaded by boot2 at the origin defined in ./Makefile. 85*479ab7f0SSascha Wildner * This is typically 0x200000. 86*479ab7f0SSascha Wildner * 87*479ab7f0SSascha Wildner * I *THINK* (not sure) that execution begins with us in 'virtual mode', 88*479ab7f0SSascha Wildner * meaning everything is offset by MEM_BTX_USR. We will load a gdt to 89*479ab7f0SSascha Wildner * set the base offsets back to 0. 90*479ab7f0SSascha Wildner */ 91*479ab7f0SSascha Wildner .globl start 92*479ab7f0SSascha Wildner/* 93*479ab7f0SSascha Wildner * BTX program loader for ELF clients. 94*479ab7f0SSascha Wildner */ 95*479ab7f0SSascha Wildnerstart: cld # String ops inc 96*479ab7f0SSascha Wildner movl $m_logo,%esi # Identify 97*479ab7f0SSascha Wildner call putstr # ourselves 98*479ab7f0SSascha Wildner#if !defined(MEM_BTX_USR_STK) 99*479ab7f0SSascha Wildner movzwl BDA_MEM,%eax # Get base memory 100*479ab7f0SSascha Wildner decl %eax 101*479ab7f0SSascha Wildner shll $0xa,%eax # Convert to bytes 102*479ab7f0SSascha Wildner#else 103*479ab7f0SSascha Wildner movl $MEM_BTX_USR_STK,%eax 104*479ab7f0SSascha Wildner#endif 105*479ab7f0SSascha Wildner movl %eax,%ebp # Base of user stack 106*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 107*479ab7f0SSascha Wildner movl $m_mem,%esi # Display 108*479ab7f0SSascha Wildner call hexout # amount of 109*479ab7f0SSascha Wildner call putstr # base memory 110*479ab7f0SSascha Wildner#endif 111*479ab7f0SSascha Wildner 112*479ab7f0SSascha Wildner /* 113*479ab7f0SSascha Wildner * Load a new GDT. XXX what does this do to running code 114*479ab7f0SSascha Wildner * segments? What if an interrupt occurs? What if the 115*479ab7f0SSascha Wildner * segment registers are reloaded? 116*479ab7f0SSascha Wildner */ 117*479ab7f0SSascha Wildner lgdt gdtdesc 118*479ab7f0SSascha Wildner 119*479ab7f0SSascha Wildner /* 120*479ab7f0SSascha Wildner * Relocate caller's arguments. 121*479ab7f0SSascha Wildner */ 122*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 123*479ab7f0SSascha Wildner movl $m_esp,%esi # Display 124*479ab7f0SSascha Wildner movl %esp,%eax # caller 125*479ab7f0SSascha Wildner call hexout # stack 126*479ab7f0SSascha Wildner call putstr # pointer 127*479ab7f0SSascha Wildner movl $m_args,%esi # Format string 128*479ab7f0SSascha Wildner leal 0x4(%esp,1),%ebx # First argument 129*479ab7f0SSascha Wildner movl $0x6,%ecx # Count 130*479ab7f0SSascha Wildnerstart.1: movl (%ebx),%eax # Get argument and 131*479ab7f0SSascha Wildner addl $0x4,%ebx # bump pointer 132*479ab7f0SSascha Wildner call hexout # Display it 133*479ab7f0SSascha Wildner loop start.1 # Till done 134*479ab7f0SSascha Wildner call putstr # End message 135*479ab7f0SSascha Wildner#endif 136*479ab7f0SSascha Wildner /* 137*479ab7f0SSascha Wildner * Arguments: (entry, boothowto, bootdev, 0, 0, 0, bootinfo) 138*479ab7f0SSascha Wildner * 0x00, 0x04, 0x08, 0x18 139*479ab7f0SSascha Wildner * 140*479ab7f0SSascha Wildner * sizeof(bootinfo) == 0x48 (BOOTINFO_SIZE) 141*479ab7f0SSascha Wildner * sizeof arguments == 0x18 (MEM_ARG_SIZE) 142*479ab7f0SSascha Wildner * total arguments == 0x60 bytes (USR_ARGOFFSET) 143*479ab7f0SSascha Wildner */ 144*479ab7f0SSascha Wildner 145*479ab7f0SSascha Wildner movl $BOOTINFO_SIZE,%ecx # Allocate space 146*479ab7f0SSascha Wildner subl %ecx,%ebp # for bootinfo 147*479ab7f0SSascha Wildner movl 0x18(%esp,1),%esi # Source: bootinfo 148*479ab7f0SSascha Wildner cmpl $0x0, %esi # If the bootinfo pointer 149*479ab7f0SSascha Wildner je start_null_bi # is null, do not copy it 150*479ab7f0SSascha Wildner movl %ebp,%edi # Destination 151*479ab7f0SSascha Wildner rep # Copy 152*479ab7f0SSascha Wildner movsb # it 153*479ab7f0SSascha Wildner movl %ebp,0x18(%esp,1) # Update pointer 154*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 155*479ab7f0SSascha Wildner movl $m_rel_bi,%esi # Display 156*479ab7f0SSascha Wildner movl %ebp,%eax # bootinfo 157*479ab7f0SSascha Wildner call hexout # relocation 158*479ab7f0SSascha Wildner call putstr # message 159*479ab7f0SSascha Wildner#endif 160*479ab7f0SSascha Wildnerstart_null_bi: movl $0x18,%ecx # Allocate space 161*479ab7f0SSascha Wildner subl %ecx,%ebp # for arguments 162*479ab7f0SSascha Wildner leal 0x4(%esp,1),%esi # Source 163*479ab7f0SSascha Wildner movl %ebp,%edi # Destination 164*479ab7f0SSascha Wildner rep # Copy 165*479ab7f0SSascha Wildner movsb # them 166*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 167*479ab7f0SSascha Wildner movl $m_rel_args,%esi # Display 168*479ab7f0SSascha Wildner movl %ebp,%eax # argument 169*479ab7f0SSascha Wildner call hexout # relocation 170*479ab7f0SSascha Wildner call putstr # message 171*479ab7f0SSascha Wildner#endif 172*479ab7f0SSascha Wildner/* 173*479ab7f0SSascha Wildner * Set up BTX kernel. 174*479ab7f0SSascha Wildner */ 175*479ab7f0SSascha Wildner movl $MEM_BTX_ESP,%esp # Set up new stack 176*479ab7f0SSascha Wildner movl $MEM_DATA,%ebx # Data segment 177*479ab7f0SSascha Wildner movl $m_vers,%esi # Display BTX 178*479ab7f0SSascha Wildner call putstr # version message 179*479ab7f0SSascha Wildner movb 0x5(%ebx),%al # Get major version 180*479ab7f0SSascha Wildner addb $'0',%al # Display 181*479ab7f0SSascha Wildner call putchr # it 182*479ab7f0SSascha Wildner movb $'.',%al # And a 183*479ab7f0SSascha Wildner call putchr # dot 184*479ab7f0SSascha Wildner movb 0x6(%ebx),%al # Get minor 185*479ab7f0SSascha Wildner xorb %ah,%ah # version 186*479ab7f0SSascha Wildner movb $0xa,%dl # Divide 187*479ab7f0SSascha Wildner divb %dl,%al # by 10 188*479ab7f0SSascha Wildner addb $'0',%al # Display 189*479ab7f0SSascha Wildner call putchr # tens 190*479ab7f0SSascha Wildner movb %ah,%al # Get units 191*479ab7f0SSascha Wildner addb $'0',%al # Display 192*479ab7f0SSascha Wildner call putchr # units 193*479ab7f0SSascha Wildner call putstr # End message 194*479ab7f0SSascha Wildner 195*479ab7f0SSascha Wildner # Relocate the BTX image from wherever it was loaded (%ebx), 196*479ab7f0SSascha Wildner # which is typically offset 0x1000 in the load data, to 197*479ab7f0SSascha Wildner # MEM_BTX_ORG (typically 0x9000). 198*479ab7f0SSascha Wildner # 199*479ab7f0SSascha Wildner # MEM_BTX_TBL + ((mappages | 0x3ff) + 1) * 4 200*479ab7f0SSascha Wildner # mappages is typically 0x0ffn so we get 0x1000*4 = 0x4000 201*479ab7f0SSascha Wildner # MEM_BTX_TBL is traditionally mapped at 0x5000 so the 202*479ab7f0SSascha Wildner # whole calculation translated to MEM_BTX_ORG (0x9000). 203*479ab7f0SSascha Wildner#if 0 204*479ab7f0SSascha Wildner /* XXX what is all of this junk? */ 205*479ab7f0SSascha Wildner movzwl 0x8(%ebx),%edi # Compute the BTX load address 206*479ab7f0SSascha Wildner orl $PAG_SIZ/PAG_ENT-1,%edi # (by skipping the page table) 207*479ab7f0SSascha Wildner incl %edi 208*479ab7f0SSascha Wildner shll $0x2,%edi 209*479ab7f0SSascha Wildner addl $MEM_BTX_TBL,%edi 210*479ab7f0SSascha Wildner#else 211*479ab7f0SSascha Wildner movl $MEM_BTX_ORG,%edi 212*479ab7f0SSascha Wildner#endif 213*479ab7f0SSascha Wildner movl %ebx,%esi # %esi = BTX image source 214*479ab7f0SSascha Wildner pushl %edi # Save load address 215*479ab7f0SSascha Wildner movzwl 0xa(%ebx),%ecx # Image size (bytes) 216*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 217*479ab7f0SSascha Wildner pushl %ecx # Save image size 218*479ab7f0SSascha Wildner#endif 219*479ab7f0SSascha Wildner rep # Relocate BTX 220*479ab7f0SSascha Wildner movsb 221*479ab7f0SSascha Wildner movl %esi,%ebx # Keep place 222*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 223*479ab7f0SSascha Wildner movl $m_rel_btx,%esi # Restore 224*479ab7f0SSascha Wildner popl %eax # parameters 225*479ab7f0SSascha Wildner call hexout # and 226*479ab7f0SSascha Wildner#endif 227*479ab7f0SSascha Wildner popl %ebp # display 228*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 229*479ab7f0SSascha Wildner movl %ebp,%eax # the 230*479ab7f0SSascha Wildner call hexout # relocation 231*479ab7f0SSascha Wildner call putstr # message 232*479ab7f0SSascha Wildner#endif 233*479ab7f0SSascha Wildner /* 234*479ab7f0SSascha Wildner * ADJUST EBP FOR USER BASE ADDRESS 235*479ab7f0SSascha Wildner * 236*479ab7f0SSascha Wildner * XXX why not just move MEM_BTX_USR into %ebp ? 237*479ab7f0SSascha Wildner */ 238*479ab7f0SSascha Wildner addl $MEM_BTX_USR-MEM_BTX_ORG,%ebp 239*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 240*479ab7f0SSascha Wildner movl $m_base,%esi # the 241*479ab7f0SSascha Wildner movl %ebp,%eax # user 242*479ab7f0SSascha Wildner call hexout # base 243*479ab7f0SSascha Wildner call putstr # address 244*479ab7f0SSascha Wildner#endif 245*479ab7f0SSascha Wildner/* 246*479ab7f0SSascha Wildner * Set up ELF-format client program. 247*479ab7f0SSascha Wildner */ 248*479ab7f0SSascha Wildner cmpl $0x464c457f,(%ebx) # ELF magic number? 249*479ab7f0SSascha Wildner je start.3 # Yes 250*479ab7f0SSascha Wildner movl $e_fmt,%esi # Display error 251*479ab7f0SSascha Wildner call putstr # message 252*479ab7f0SSascha Wildnerstart.2: jmp start.2 # Hang 253*479ab7f0SSascha Wildnerstart.3: 254*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 255*479ab7f0SSascha Wildner movl $m_elf,%esi # Display ELF 256*479ab7f0SSascha Wildner call putstr # message 257*479ab7f0SSascha Wildner movl $m_segs,%esi # Format string 258*479ab7f0SSascha Wildner#endif 259*479ab7f0SSascha Wildner movl $0x2,%edi # Segment count 260*479ab7f0SSascha Wildner movl 0x1c(%ebx),%edx # Get e_phoff 261*479ab7f0SSascha Wildner addl %ebx,%edx # To pointer 262*479ab7f0SSascha Wildner movzwl 0x2c(%ebx),%ecx # Get e_phnum 263*479ab7f0SSascha Wildnerstart.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD? 264*479ab7f0SSascha Wildner jne start.6 # No 265*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 266*479ab7f0SSascha Wildner movl 0x4(%edx),%eax # Display 267*479ab7f0SSascha Wildner call hexout # p_offset 268*479ab7f0SSascha Wildner movl 0x8(%edx),%eax # Display 269*479ab7f0SSascha Wildner call hexout # p_vaddr 270*479ab7f0SSascha Wildner movl 0x10(%edx),%eax # Display 271*479ab7f0SSascha Wildner call hexout # p_filesz 272*479ab7f0SSascha Wildner movl 0x14(%edx),%eax # Display 273*479ab7f0SSascha Wildner call hexout # p_memsz 274*479ab7f0SSascha Wildner call putstr # End message 275*479ab7f0SSascha Wildner#endif 276*479ab7f0SSascha Wildner pushl %esi # Save 277*479ab7f0SSascha Wildner pushl %edi # working 278*479ab7f0SSascha Wildner pushl %ecx # registers 279*479ab7f0SSascha Wildner movl 0x4(%edx),%esi # Get p_offset 280*479ab7f0SSascha Wildner addl %ebx,%esi # as pointer 281*479ab7f0SSascha Wildner movl 0x8(%edx),%edi # Get p_vaddr 282*479ab7f0SSascha Wildner addl %ebp,%edi # as pointer 283*479ab7f0SSascha Wildner movl 0x10(%edx),%ecx # Get p_filesz 284*479ab7f0SSascha Wildner rep # Set up 285*479ab7f0SSascha Wildner movsb # segment 286*479ab7f0SSascha Wildner movl 0x14(%edx),%ecx # Any bytes 287*479ab7f0SSascha Wildner subl 0x10(%edx),%ecx # to zero? 288*479ab7f0SSascha Wildner jz start.5 # No 289*479ab7f0SSascha Wildner xorb %al,%al # Then 290*479ab7f0SSascha Wildner rep # zero 291*479ab7f0SSascha Wildner stosb # them 292*479ab7f0SSascha Wildnerstart.5: popl %ecx # Restore 293*479ab7f0SSascha Wildner popl %edi # working 294*479ab7f0SSascha Wildner popl %esi # registers 295*479ab7f0SSascha Wildner decl %edi # Segments to do 296*479ab7f0SSascha Wildner je start.7 # If none 297*479ab7f0SSascha Wildnerstart.6: addl $0x20,%edx # To next entry 298*479ab7f0SSascha Wildner loop start.4 # Till done 299*479ab7f0SSascha Wildnerstart.7: 300*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 301*479ab7f0SSascha Wildner movl $m_done,%esi # Display done 302*479ab7f0SSascha Wildner call putstr # message 303*479ab7f0SSascha Wildner#endif 304*479ab7f0SSascha Wildner movl $start.8,%esi # Real mode stub 305*479ab7f0SSascha Wildner movl $BOOT0_ORIGIN,%edi # Destination 306*479ab7f0SSascha Wildner movl $start.9-start.8,%ecx # Size 307*479ab7f0SSascha Wildner rep # Relocate 308*479ab7f0SSascha Wildner movsb # it 309*479ab7f0SSascha Wildner ljmp $SEL_RCODE,$BOOT0_ORIGIN # To 16-bit code 310*479ab7f0SSascha Wildner .code16 311*479ab7f0SSascha Wildnerstart.8: xorw %ax,%ax # Data 312*479ab7f0SSascha Wildner movb $SEL_RDATA,%al # selector 313*479ab7f0SSascha Wildner movw %ax,%ss # Reload SS 314*479ab7f0SSascha Wildner movw %ax,%ds # Reset 315*479ab7f0SSascha Wildner movw %ax,%es # other 316*479ab7f0SSascha Wildner movw %ax,%fs # segment 317*479ab7f0SSascha Wildner movw %ax,%gs # limits 318*479ab7f0SSascha Wildner movl %cr0,%eax # Switch to 319*479ab7f0SSascha Wildner decw %ax # real 320*479ab7f0SSascha Wildner movl %eax,%cr0 # mode 321*479ab7f0SSascha Wildner ljmp $0,$MEM_BTX_ENTRY # Jump to BTX entry point 322*479ab7f0SSascha Wildnerstart.9: 323*479ab7f0SSascha Wildner .code32 324*479ab7f0SSascha Wildner/* 325*479ab7f0SSascha Wildner * Output message [ESI] followed by EAX in hex. 326*479ab7f0SSascha Wildner */ 327*479ab7f0SSascha Wildnerhexout: pushl %eax # Save 328*479ab7f0SSascha Wildner call putstr # Display message 329*479ab7f0SSascha Wildner popl %eax # Restore 330*479ab7f0SSascha Wildner pushl %esi # Save 331*479ab7f0SSascha Wildner pushl %edi # callers 332*479ab7f0SSascha Wildner movl $buf,%edi # Buffer 333*479ab7f0SSascha Wildner pushl %edi # Save 334*479ab7f0SSascha Wildner call hex32 # To hex 335*479ab7f0SSascha Wildner xorb %al,%al # Terminate 336*479ab7f0SSascha Wildner stosb # string 337*479ab7f0SSascha Wildner popl %esi # Restore 338*479ab7f0SSascha Wildnerhexout.1: lodsb # Get a char 339*479ab7f0SSascha Wildner cmpb $'0',%al # Leading zero? 340*479ab7f0SSascha Wildner je hexout.1 # Yes 341*479ab7f0SSascha Wildner testb %al,%al # End of string? 342*479ab7f0SSascha Wildner jne hexout.2 # No 343*479ab7f0SSascha Wildner decl %esi # Undo 344*479ab7f0SSascha Wildnerhexout.2: decl %esi # Adjust for inc 345*479ab7f0SSascha Wildner call putstr # Display hex 346*479ab7f0SSascha Wildner popl %edi # Restore 347*479ab7f0SSascha Wildner popl %esi # callers 348*479ab7f0SSascha Wildner ret # To caller 349*479ab7f0SSascha Wildner/* 350*479ab7f0SSascha Wildner * Output zero-terminated string [ESI] to the console. 351*479ab7f0SSascha Wildner */ 352*479ab7f0SSascha Wildnerputstr.0: call putchr # Output char 353*479ab7f0SSascha Wildnerputstr: lodsb # Load char 354*479ab7f0SSascha Wildner testb %al,%al # End of string? 355*479ab7f0SSascha Wildner jne putstr.0 # No 356*479ab7f0SSascha Wildner ret # To caller 357*479ab7f0SSascha Wildner/* 358*479ab7f0SSascha Wildner * Output character AL to the console. 359*479ab7f0SSascha Wildner */ 360*479ab7f0SSascha Wildnerputchr: pusha # Save 361*479ab7f0SSascha Wildner xorl %ecx,%ecx # Zero for loops 362*479ab7f0SSascha Wildner movb $SCR_MAT,%ah # Mode/attribute 363*479ab7f0SSascha Wildner movl $BDA_POS,%ebx # BDA pointer 364*479ab7f0SSascha Wildner movw (%ebx),%dx # Cursor position 365*479ab7f0SSascha Wildner movl $0xb8000,%edi # Regen buffer (color) 366*479ab7f0SSascha Wildner cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode? 367*479ab7f0SSascha Wildner jne putchr.1 # No 368*479ab7f0SSascha Wildner xorw %di,%di # Regen buffer (mono) 369*479ab7f0SSascha Wildnerputchr.1: cmpb $0xa,%al # New line? 370*479ab7f0SSascha Wildner je putchr.2 # Yes 371*479ab7f0SSascha Wildner xchgl %eax,%ecx # Save char 372*479ab7f0SSascha Wildner movb $SCR_COL,%al # Columns per row 373*479ab7f0SSascha Wildner mulb %dh # * row position 374*479ab7f0SSascha Wildner addb %dl,%al # + column 375*479ab7f0SSascha Wildner adcb $0x0,%ah # position 376*479ab7f0SSascha Wildner shll %eax # * 2 377*479ab7f0SSascha Wildner xchgl %eax,%ecx # Swap char, offset 378*479ab7f0SSascha Wildner movw %ax,(%edi,%ecx,1) # Write attr:char 379*479ab7f0SSascha Wildner incl %edx # Bump cursor 380*479ab7f0SSascha Wildner cmpb $SCR_COL,%dl # Beyond row? 381*479ab7f0SSascha Wildner jb putchr.3 # No 382*479ab7f0SSascha Wildnerputchr.2: xorb %dl,%dl # Zero column 383*479ab7f0SSascha Wildner incb %dh # Bump row 384*479ab7f0SSascha Wildnerputchr.3: cmpb $SCR_ROW,%dh # Beyond screen? 385*479ab7f0SSascha Wildner jb putchr.4 # No 386*479ab7f0SSascha Wildner leal 2*SCR_COL(%edi),%esi # New top line 387*479ab7f0SSascha Wildner movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move 388*479ab7f0SSascha Wildner rep # Scroll 389*479ab7f0SSascha Wildner movsl # screen 390*479ab7f0SSascha Wildner movb $' ',%al # Space 391*479ab7f0SSascha Wildner movb $SCR_COL,%cl # Columns to clear 392*479ab7f0SSascha Wildner rep # Clear 393*479ab7f0SSascha Wildner stosw # line 394*479ab7f0SSascha Wildner movb $SCR_ROW-1,%dh # Bottom line 395*479ab7f0SSascha Wildnerputchr.4: movw %dx,(%ebx) # Update position 396*479ab7f0SSascha Wildner popa # Restore 397*479ab7f0SSascha Wildner ret # To caller 398*479ab7f0SSascha Wildner/* 399*479ab7f0SSascha Wildner * Convert EAX, AX, or AL to hex, saving the result to [EDI]. 400*479ab7f0SSascha Wildner */ 401*479ab7f0SSascha Wildnerhex32: pushl %eax # Save 402*479ab7f0SSascha Wildner shrl $0x10,%eax # Do upper 403*479ab7f0SSascha Wildner call hex16 # 16 404*479ab7f0SSascha Wildner popl %eax # Restore 405*479ab7f0SSascha Wildnerhex16: call hex16.1 # Do upper 8 406*479ab7f0SSascha Wildnerhex16.1: xchgb %ah,%al # Save/restore 407*479ab7f0SSascha Wildnerhex8: pushl %eax # Save 408*479ab7f0SSascha Wildner shrb $0x4,%al # Do upper 409*479ab7f0SSascha Wildner call hex8.1 # 4 410*479ab7f0SSascha Wildner popl %eax # Restore 411*479ab7f0SSascha Wildnerhex8.1: andb $0xf,%al # Get lower 4 412*479ab7f0SSascha Wildner cmpb $0xa,%al # Convert 413*479ab7f0SSascha Wildner sbbb $0x69,%al # to hex 414*479ab7f0SSascha Wildner das # digit 415*479ab7f0SSascha Wildner orb $0x20,%al # To lower case 416*479ab7f0SSascha Wildner stosb # Save char 417*479ab7f0SSascha Wildner ret # (Recursive) 418*479ab7f0SSascha Wildner 419*479ab7f0SSascha Wildner .data 420*479ab7f0SSascha Wildner .p2align 4 421*479ab7f0SSascha Wildner/* 422*479ab7f0SSascha Wildner * Global descriptor table. 423*479ab7f0SSascha Wildner */ 424*479ab7f0SSascha Wildnergdt: .word 0x0,0x0,0x0,0x0 # Null entry 425*479ab7f0SSascha Wildner .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE 426*479ab7f0SSascha Wildner .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 427*479ab7f0SSascha Wildner .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE 428*479ab7f0SSascha Wildner .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 429*479ab7f0SSascha Wildnergdt.1: 430*479ab7f0SSascha Wildnergdtdesc: .word gdt.1-gdt-1 # Limit 431*479ab7f0SSascha Wildner .long gdt # Base 432*479ab7f0SSascha Wildner/* 433*479ab7f0SSascha Wildner * Messages. 434*479ab7f0SSascha Wildner */ 435*479ab7f0SSascha Wildnerm_logo: .asciz " \nBTX loader 1.00 " 436*479ab7f0SSascha Wildnerm_vers: .asciz "BTX version is \0\n" 437*479ab7f0SSascha Wildnere_fmt: .asciz "Error: Client format not supported\n" 438*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE 439*479ab7f0SSascha Wildnerm_mem: .asciz "Starting in protected mode (base mem=\0)\n" 440*479ab7f0SSascha Wildnerm_esp: .asciz "Arguments passed (esp=\0):\n" 441*479ab7f0SSascha Wildnerm_args: .asciz"<howto=" 442*479ab7f0SSascha Wildner .asciz" bootdev=" 443*479ab7f0SSascha Wildner .asciz" junk=" 444*479ab7f0SSascha Wildner .asciz" " 445*479ab7f0SSascha Wildner .asciz" " 446*479ab7f0SSascha Wildner .asciz" bootinfo=\0>\n" 447*479ab7f0SSascha Wildnerm_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n" 448*479ab7f0SSascha Wildnerm_rel_args: .asciz "Relocated arguments (size=18) to \0\n" 449*479ab7f0SSascha Wildnerm_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n" 450*479ab7f0SSascha Wildnerm_base: .asciz "Client base address is \0\n" 451*479ab7f0SSascha Wildnerm_elf: .asciz "Client format is ELF\n" 452*479ab7f0SSascha Wildnerm_segs: .asciz "text segment: offset=" 453*479ab7f0SSascha Wildner .asciz " vaddr=" 454*479ab7f0SSascha Wildner .asciz " filesz=" 455*479ab7f0SSascha Wildner .asciz " memsz=\0\n" 456*479ab7f0SSascha Wildner .asciz "data segment: offset=" 457*479ab7f0SSascha Wildner .asciz " vaddr=" 458*479ab7f0SSascha Wildner .asciz " filesz=" 459*479ab7f0SSascha Wildner .asciz " memsz=\0\n" 460*479ab7f0SSascha Wildnerm_done: .asciz "Loading complete\n" 461*479ab7f0SSascha Wildner#endif 462*479ab7f0SSascha Wildner/* 463*479ab7f0SSascha Wildner * Uninitialized data area. 464*479ab7f0SSascha Wildner */ 465*479ab7f0SSascha Wildnerbuf: # Scratch buffer 466