btxldr.S revision 39988
1132451Sroberto# 2132451Sroberto# Copyright (c) 1998 Robert Nordier 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms are freely 6# permitted provided that the above copyright notice and this 7# paragraph and the following disclaimer are duplicated in all 8# such forms. 9# 10# This software is provided "AS IS" and without any express or 11# implied warranties, including, without limitation, the implied 12# warranties of merchantability and fitness for a particular 13# purpose. 14# 15 16# $Id: btxldr.s,v 1.2 1998/10/06 06:13:36 msmith Exp $ 17 18# 19# Prototype BTX loader program, written in a couple of hours. The 20# real thing should probably be more flexible, and in C. 21# 22 23# 24# Memory locations. 25# 26 .set MEM_STUB,0x600 # Real mode stub 27 .set MEM_ESP,0x1000 # New stack pointer 28 .set MEM_TBL,0x5000 # BTX page tables 29 .set MEM_ENTRY,0x9010 # BTX entry point 30 .set MEM_DATA,0x101000 # Data segment 31# 32# Segment selectors. 33# 34 .set SEL_SCODE,0x8 # 4GB code 35 .set SEL_SDATA,0x10 # 4GB data 36 .set SEL_RCODE,0x18 # 64K code 37 .set SEL_RDATA,0x20 # 64K data 38# 39# Paging constants. 40# 41 .set PAG_SIZ,0x1000 # Page size 42 .set PAG_ENT,0x4 # Page entry size 43# 44# Screen constants. 45# 46 .set SCR_MAT,0x7 # Mode/attribute 47 .set SCR_COL,0x50 # Columns per row 48 .set SCR_ROW,0x19 # Rows per screen 49# 50# BIOS Data Area locations. 51# 52 .set BDA_MEM,0x413 # Free memory 53 .set BDA_SCR,0x449 # Video mode 54 .set BDA_POS,0x450 # Cursor position 55# 56# Required by aout gas inadequacy. 57# 58 .set SIZ_STUB,0x1a # Size of stub 59# 60# We expect to be loaded by boot2 at 0x100000. 61# 62 .globl start 63# 64# BTX program loader for ELF clients. 65# 66start: cld # String ops inc 67 movl $m_logo,%esi # Identify 68 call putstr # ourselves 69 movzwl BDA_MEM,%eax # Get base memory 70 shll $0xa,%eax # in bytes 71 movl %eax,%ebp # Base of user stack 72 movl $m_mem,%esi # Display 73 call hexout # amount of 74 call putstr # base memory 75 lgdt gdtdesc # Load new GDT 76# 77# Relocate caller's arguments. 78# 79 movl $m_esp,%esi # Display 80 movl %esp,%eax # caller's 81 call hexout # stack 82 call putstr # pointer 83 movl $m_args,%esi # Format string 84 leal 0x4(%esp,1),%ebx # First argument 85 movl $0x6,%ecx # Count 86start.1: movl (%ebx),%eax # Get argument and 87 addl $0x4,%ebx # bump pointer 88 call hexout # Display it 89 loop start.1 # Till done 90 call putstr # End message 91 movl $0x48,%ecx # Allocate space 92 subl %ecx,%ebp # for bootinfo 93 movl 0x18(%esp,1),%esi # Source 94 movl %ebp,%edi # Destination 95 rep # Copy 96 movsb # it 97 movl %ebp,0x18(%esp,1) # Update pointer 98 movl $m_rel_bi,%esi # Display 99 movl %ebp,%eax # bootinfo 100 call hexout # relocation 101 call putstr # message 102 movl $0x18,%ecx # Allocate space 103 subl %ecx,%ebp # for arguments 104 leal 0x4(%esp,1),%esi # Source 105 movl %ebp,%edi # Destination 106 rep # Copy 107 movsb # them 108 movl $m_rel_args,%esi # Display 109 movl %ebp,%eax # argument 110 call hexout # relocation 111 call putstr # message 112# 113# Set up BTX kernel. 114# 115 movl $MEM_ESP,%esp # Set up new stack 116 movl $MEM_DATA,%ebx # Data segment 117 movl $m_vers,%esi # Display BTX 118 call putstr # version message 119 movb 0x5(%ebx),%al # Get major version 120 addb $'0',%al # Display 121 call putchr # it 122 movb $'.',%al # And a 123 call putchr # dot 124 movb 0x6(%ebx),%al # Get minor 125 xorb %ah,%ah # version 126 movb $0xa,%dl # Divide 127 divb %dl,%al # by 10 128 addb $'0',%al # Display 129 call putchr # tens 130 movb %ah,%al # Get units 131 addb $'0',%al # Display 132 call putchr # units 133 call putstr # End message 134 movl %ebx,%esi # BTX image 135 movzwl 0x8(%ebx),%edi # Compute 136 orl $PAG_SIZ/PAG_ENT-1,%edi # the 137 incl %edi # BTX 138 shll $0x2,%edi # load 139 addl $MEM_TBL,%edi # address 140 pushl %edi # Save 141 movzwl 0xa(%ebx),%ecx # Image size 142 pushl %ecx # Save 143 rep # Relocate 144 movsb # BTX 145 movl %esi,%ebx # Keep place 146 movl $m_rel_btx,%esi # Restore 147 popl %eax # parameters 148 call hexout # and 149 popl %ebp # display 150 movl %ebp,%eax # the 151 call hexout # relocation 152 call putstr # message 153 addl $PAG_SIZ,%ebp # Display 154 movl $m_base,%esi # the 155 movl %ebp,%eax # user 156 call hexout # base 157 call putstr # address 158# 159# Set up ELF-format client program. 160# 161 cmpl $0x464c457f,(%ebx) # ELF magic number? 162 je start.3 # Yes 163 movl $e_fmt,%esi # Display error 164 call putstr # message 165start.2: jmp start.2 # Hang 166start.3: movl $m_elf,%esi # Display ELF 167 call putstr # message 168 movl $m_segs,%esi # Format string 169 movl $0x2,%edi # Segment count 170 movl 0x1c(%ebx),%edx # Get e_phoff 171 addl %ebx,%edx # To pointer 172 movzwl 0x2c(%ebx),%ecx # Get e_phnum 173start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD? 174 jne start.6 # No 175 movl 0x4(%edx),%eax # Display 176 call hexout # p_offset 177 movl 0x8(%edx),%eax # Display 178 call hexout # p_vaddr 179 movl 0x10(%edx),%eax # Display 180 call hexout # p_filesz 181 movl 0x14(%edx),%eax # Display 182 call hexout # p_memsz 183 call putstr # End message 184 pushl %esi # Save 185 pushl %edi # working 186 pushl %ecx # registers 187 movl 0x4(%edx),%esi # Get p_offset 188 addl %ebx,%esi # as pointer 189 movl 0x8(%edx),%edi # Get p_vaddr 190 addl %ebp,%edi # as pointer 191 movl 0x10(%edx),%ecx # Get p_filesz 192 rep # Set up 193 movsb # segment 194 movl 0x14(%edx),%ecx # Any bytes 195 subl 0x10(%edx),%ecx # to zero? 196 jz start.5 # No 197 xorb %al,%al # Then 198 rep # zero 199 stosb # them 200start.5: popl %ecx # Restore 201 popl %edi # working 202 popl %esi # registers 203 decl %edi # Segments to do 204 je start.7 # If none 205start.6: addl $0x20,%edx # To next entry 206 loop start.4 # Till done 207start.7: movl $m_done,%esi # Display done 208 call putstr # message 209 movl $start.8,%esi # Real mode stub 210 movl $MEM_STUB,%edi # Destination 211 movl $SIZ_STUB,%ecx # Size 212 rep # Relocate 213 movsb # it 214 ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code 215start.8: xorl %eax,%eax # Data 216 movb $SEL_RDATA,%al # selector 217 movl %eax,%ss # Reload SS 218 movl %eax,%ds # Reset 219 movl %eax,%es # other 220 movl %eax,%fs # segment 221 movl %eax,%gs # limits 222 movl %cr0,%eax # Switch to 223 decl %eax # real 224 movl %eax,%cr0 # mode 225 .byte 0xea # Jump to 226 .word MEM_ENTRY # BTX entry 227 .word 0x0 # point 228start.9: 229# 230# Output message [ESI] followed by EAX in hex. 231# 232hexout: pushl %eax # Save 233 call putstr # Display message 234 popl %eax # Restore 235 pushl %esi # Save 236 pushl %edi # caller's 237 movl $buf,%edi # Buffer 238 pushl %edi # Save 239 call hex32 # To hex 240 xorb %al,%al # Terminate 241 stosb # string 242 popl %esi # Restore 243hexout.1: lodsb # Get a char 244 cmpb $'0',%al # Leading zero? 245 je hexout.1 # Yes 246 testb %al,%al # End of string? 247 jne hexout.2 # No 248 decl %esi # Undo 249hexout.2: decl %esi # Adjust for inc 250 call putstr # Display hex 251 popl %edi # Restore 252 popl %esi # caller's 253 ret # To caller 254# 255# Output zero-terminated string [ESI] to the console. 256# 257putstr.0: call putchr # Output char 258putstr: lodsb # Load char 259 testb %al,%al # End of string? 260 jne putstr.0 # No 261 ret # To caller 262# 263# Output character AL to the console. 264# 265putchr: pusha # Save 266 xorl %ecx,%ecx # Zero for loops 267 movb $SCR_MAT,%ah # Mode/attribute 268 movl $BDA_POS,%ebx # BDA pointer 269 movw (%ebx),%dx # Cursor position 270 movl $0xb8000,%edi # Regen buffer (color) 271 cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode? 272 jne putchr.1 # No 273 xorw %di,%di # Regen buffer (mono) 274putchr.1: cmpb $0xa,%al # New line? 275 je putchr.2 # Yes 276 xchgl %eax,%ecx # Save char 277 movb $SCR_COL,%al # Columns per row 278 mulb %dh # * row position 279 addb %dl,%al # + column 280 adcb $0x0,%ah # position 281 shll %eax # * 2 282 xchgl %eax,%ecx # Swap char, offset 283 movw %ax,(%edi,%ecx,1) # Write attr:char 284 incl %edx # Bump cursor 285 cmpb $SCR_COL,%dl # Beyond row? 286 jb putchr.3 # No 287putchr.2: xorb %dl,%dl # Zero column 288 incb %dh # Bump row 289putchr.3: cmpb $SCR_ROW,%dh # Beyond screen? 290 jb putchr.4 # No 291 leal 2*SCR_COL(%edi),%esi # New top line 292 movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move 293 rep # Scroll 294 movsl # screen 295 movb $' ',%al # Space 296 movb $SCR_COL,%cl # Columns to clear 297 rep # Clear 298 stosw # line 299 movb $SCR_ROW-1,%dh # Bottom line 300putchr.4: movw %dx,(%ebx) # Update position 301 popa # Restore 302 ret # To caller 303# 304# Convert EAX, AX, or AL to hex, saving the result to [EDI]. 305# 306hex32: pushl %eax # Save 307 shrl $0x10,%eax # Do upper 308 call hex16 # 16 309 popl %eax # Restore 310hex16: call hex16.1 # Do upper 8 311hex16.1: xchgb %ah,%al # Save/restore 312hex8: pushl %eax # Save 313 shrb $0x4,%al # Do upper 314 call hex8.1 # 4 315 popl %eax # Restore 316hex8.1: andb $0xf,%al # Get lower 4 317 cmpb $0xa,%al # Convert 318 sbbb $0x69,%al # to hex 319 das # digit 320 orb $0x20,%al # To lower case 321 stosb # Save char 322 ret # (Recursive) 323 324 .data 325 .p2align 4 326# 327# Global descriptor table. 328# 329gdt: .word 0x0,0x0,0x0,0x0 # Null entry 330 .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE 331 .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 332 .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE 333 .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 334gdt.1: 335gdtdesc: .word gdt.1-gdt-1 # Limit 336 .long gdt # Base 337# 338# Messages. 339# 340m_logo: .asciz "\nBTX loader 0.01\n" 341m_mem: .asciz "Starting in protected mode (base mem=\0)\n" 342m_esp: .asciz "Arguments passed (esp=\0):\n" 343m_args: .asciz"<howto=" 344 .asciz" bootdev=" 345 .asciz" junk=" 346 .asciz" " 347 .asciz" " 348 .asciz" bootinfo=\0>\n" 349m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n" 350m_rel_args: .asciz "Relocated arguments (size=18) to \0\n" 351m_vers: .asciz "BTX version is \0\n" 352m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n" 353m_base: .asciz "Client base address is \0\n" 354e_fmt: .asciz "Error: Client format not supported\n" 355m_elf: .asciz "Client format is ELF\n" 356m_segs: .asciz "text segment: offset=" 357 .asciz " vaddr=" 358 .asciz " filesz=" 359 .asciz " memsz=\0\n" 360 .asciz "data segment: offset=" 361 .asciz " vaddr=" 362 .asciz " filesz=" 363 .asciz " memsz=\0\n" 364m_done: .asciz "Loading complete\n" 365# 366# Uninitialized data area. 367# 368buf: # Scratch buffer 369