wok annotate ipxe/stuff/lkrnprefix.S @ rev 15368

Up ipxe (1.0.0-20130925)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Oct 14 13:38:36 2013 +0000 (2013-10-14)
parents
children 4ae7c7dde4e2
rev   line source
pascal@15368 1 /*
pascal@15368 2 Copyright (C) 2000, Entity Cyber, Inc.
pascal@15368 3
pascal@15368 4 Authors: Gary Byers (gb@thinguin.org)
pascal@15368 5 Marty Connor (mdc@thinguin.org)
pascal@15368 6
pascal@15368 7 This software may be used and distributed according to the terms
pascal@15368 8 of the GNU Public License (GPL), incorporated herein by reference.
pascal@15368 9
pascal@15368 10 Description:
pascal@15368 11
pascal@15368 12 This is just a little bit of code and data that can get prepended
pascal@15368 13 to a ROM image in order to allow bootloaders to load the result
pascal@15368 14 as if it were a Linux kernel image.
pascal@15368 15
pascal@15368 16 A real Linux kernel image consists of a one-sector boot loader
pascal@15368 17 (to load the image from a floppy disk), followed a few sectors
pascal@15368 18 of setup code, followed by the kernel code itself. There's
pascal@15368 19 a table in the first sector (starting at offset 497) that indicates
pascal@15368 20 how many sectors of setup code follow the first sector and which
pascal@15368 21 contains some other parameters that aren't interesting in this
pascal@15368 22 case.
pascal@15368 23
pascal@15368 24 When a bootloader loads the sectors that comprise a kernel image,
pascal@15368 25 it doesn't execute the code in the first sector (since that code
pascal@15368 26 would try to load the image from a floppy disk.) The code in the
pascal@15368 27 first sector below doesn't expect to get executed (and prints an
pascal@15368 28 error message if it ever -is- executed.)
pascal@15368 29
pascal@15368 30 We don't require much in the way of setup code. Historically, the
pascal@15368 31 Linux kernel required at least 4 sectors of setup code.
pascal@15368 32 Therefore, at least 4 sectors must be present even though we don't
pascal@15368 33 use them.
pascal@15368 34
pascal@15368 35 */
pascal@15368 36
pascal@15368 37 FILE_LICENCE ( GPL_ANY )
pascal@15368 38
pascal@15368 39 #define SETUPSECS 4 /* Minimal nr of setup-sectors */
pascal@15368 40 #define PREFIXSIZE ((SETUPSECS+1)*512)
pascal@15368 41 #define PREFIXPGH (PREFIXSIZE / 16 )
pascal@15368 42 #define BOOTSEG 0x07C0 /* original address of boot-sector */
pascal@15368 43 #define INITSEG 0x9000 /* we move boot here - out of the way */
pascal@15368 44 #define SETUPSEG 0x9020 /* setup starts here */
pascal@15368 45 #define SYSSEG 0x1000 /* system loaded at 0x10000 (65536). */
pascal@15368 46
pascal@15368 47 .text
pascal@15368 48 .code16
pascal@15368 49 .arch i386
pascal@15368 50 .org 0
pascal@15368 51 .section ".prefix", "ax", @progbits
pascal@15368 52 .globl _lkrn_start
pascal@15368 53 _lkrn_start:
pascal@15368 54
pascal@15368 55 bootsector:
pascal@15368 56 _start:
pascal@15368 57
pascal@15368 58 /* some extra features */
pascal@15368 59 #define EXE_SUPPORT real mode dos .exe file support
pascal@15368 60
pascal@15368 61 #define EXEADRS(x) (x+0xE0)
pascal@15368 62
pascal@15368 63 /* some contraints to reduce the size */
pascal@15368 64 //#define FLOPPY_1440K_ONLY 1.44M floppies support only
pascal@15368 65
pascal@15368 66 #ifdef EXE_SUPPORT
pascal@15368 67 /* Initial temporary stack size */
pascal@15368 68 #define EXE_STACK_SIZE 0x400
pascal@15368 69
pascal@15368 70 /* Temporary decompression area (avoid DOS high memory area) */
pascal@15368 71 #define EXE_DECOMPRESS_ADDRESS 0x110000
pascal@15368 72
pascal@15368 73 /* Fields within the Program Segment Prefix */
pascal@15368 74 #define PSP_CMDLINE_LEN 0x80
pascal@15368 75 #define PSP_CMDLINE_START 0x81
pascal@15368 76
pascal@15368 77 #define HEADER_SIZE 0x20
pascal@15368 78
pascal@15368 79 signature:
pascal@15368 80 decw %bp // Magic number: MZ
pascal@15368 81 popw %dx
pascal@15368 82 jmp start // Bytes on last page of file
pascal@15368 83 blocks:
pascal@15368 84 .word 0 // Pages in file
pascal@15368 85 .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
pascal@15368 86 .ascii "ADDW"
pascal@15368 87 .long blocks
pascal@15368 88 .long 512
pascal@15368 89 .long 0
pascal@15368 90 .previous
pascal@15368 91 .word 0 // Relocations
pascal@15368 92 .word ( HEADER_SIZE / 16 ) // Size of header in paragraphs
pascal@15368 93 .word ( EXE_STACK_SIZE / 16 ) // Minimum extra paragraphs needed
pascal@15368 94 .word ( EXE_STACK_SIZE / 16 ) // Maximum extra paragraphs needed
pascal@15368 95 init_ss:
pascal@15368 96 .word -( ( _exe_start - signature ) / 16 ) // Initial (relative) SS value
pascal@15368 97 .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
pascal@15368 98 .ascii "ADDW"
pascal@15368 99 .long init_ss
pascal@15368 100 .long 16
pascal@15368 101 .long 0
pascal@15368 102 .previous
pascal@15368 103 .word EXE_STACK_SIZE // Initial SP value
pascal@15368 104 .word 0 // Checksum
pascal@15368 105 .word _exe_start // Initial IP value
pascal@15368 106 /* Initial code segment (relative to start of executable) */
pascal@15368 107 //.word -( ( _exe_start - signature ) / 16 ) // Initial (relative) CS value
pascal@15368 108 .word -( HEADER_SIZE / 16 ) // Initial (relative) CS value
pascal@15368 109 // .word 0x001C // File address of relocation table
pascal@15368 110 // .word 0,0,0 // Overlay number
pascal@15368 111
pascal@15368 112 start:
pascal@15368 113 pushw %dx
pascal@15368 114 xorw %dx, %dx
pascal@15368 115 #endif
pascal@15368 116 cld # assume nothing
pascal@15368 117 stacktop = 0x9E00 # in 0x8000 .. 0xA000
pascal@15368 118 zeroed = 12 # zeroed registers
pascal@15368 119 movw $stacktop-12-zeroed, %di # stacktop is an arbitrary value >=
pascal@15368 120 # length of bootsect + length of
pascal@15368 121 # setup + room for stack;
pascal@15368 122 # 12 is disk parm size.
pascal@15368 123 pushw $INITSEG
pascal@15368 124 popw %ss # %ss contain INITSEG
pascal@15368 125 movw %di, %sp # put stack at INITSEG:stacktop-...
pascal@15368 126
pascal@15368 127 # Many BIOS's default disk parameter tables will not recognize
pascal@15368 128 # multi-sector reads beyond the maximum sector number specified
pascal@15368 129 # in the default diskette parameter tables - this may mean 7
pascal@15368 130 # sectors in some cases.
pascal@15368 131 #
pascal@15368 132 # Since single sector reads are slow and out of the question,
pascal@15368 133 # we must take care of this by creating new parameter tables
pascal@15368 134 # (for the first disk) in RAM. We can set the maximum sector
pascal@15368 135 # count to 36 - the most we will encounter on an ED 2.88.
pascal@15368 136 #
pascal@15368 137 # High doesn't hurt. Low does. Let's use the max: 63
pascal@15368 138
pascal@15368 139 pushw %ss
pascal@15368 140 popw %es # %es = %ss = INITSEG
pascal@15368 141 xorw %ax, %ax # %ax = 0
pascal@15368 142 movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
pascal@15368 143 rep # don't worry about cld
pascal@15368 144 stosw # already done above
pascal@15368 145 popw %bx # offset = 0
pascal@15368 146 popw %ds # %ds = 0
pascal@15368 147 popw %fs # %fs = 0
pascal@15368 148
pascal@15368 149 movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0)
pascal@15368 150 incw %ax
pascal@15368 151
pascal@15368 152 ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address
pascal@15368 153 pushw %es
pascal@15368 154 pushw %di
pascal@15368 155 movb $6, %cl # copy 12 bytes
pascal@15368 156 rep # don't worry about cld
pascal@15368 157 movsw # already done above
pascal@15368 158 pushw %ss
pascal@15368 159 popw %ds # now %ds = %es = %ss = INITSEG
pascal@15368 160 popl %fs:0x78(%bx) # update parameter table address
pascal@15368 161 movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
pascal@15368 162 cli
pascal@15368 163
pascal@15368 164 xchg %ax, %di # sector count
pascal@15368 165 popw %ax # limits = 0
pascal@15368 166 incw %cx # cylinder 0, sector 1, clear Z
pascal@15368 167 call read_first_sectors # read setup
pascal@15368 168
pascal@15368 169 # This routine loads the system at address LOADSEG, making sure
pascal@15368 170 # no 64kB boundaries are crossed. We try to load it as fast as
pascal@15368 171 # possible, loading whole tracks whenever we can.
pascal@15368 172
pascal@15368 173 popw %bx # clear %bx
pascal@15368 174 movw syssize, %di
pascal@15368 175 addw $(512/16)-1, %di
pascal@15368 176 shrw $9-4, %di
pascal@15368 177 movw $SYSSEG, %cx
pascal@15368 178 call read_sectorsCX
pascal@15368 179
pascal@15368 180 # This procedure turns off the floppy drive motor, so
pascal@15368 181 # that we enter the kernel in a known state, and
pascal@15368 182 # don't have to worry about it later.
pascal@15368 183
pascal@15368 184 kill_motor:
pascal@15368 185 xchgw %ax, %di # reset FDC (%di < 128)
pascal@15368 186 int $0x13
pascal@15368 187
pascal@15368 188 # After that (everything loaded), we jump to the setup-routine
pascal@15368 189 # loaded directly after the bootblock:
pascal@15368 190 # Segments are as follows: %ds = %ss = INITSEG
pascal@15368 191
pascal@15368 192 ljmp $SETUPSEG, $0
pascal@15368 193
pascal@15368 194 #ifdef EXE_SUPPORT
pascal@15368 195 dosexit:
pascal@15368 196 movw $0x4c00, %ax
pascal@15368 197 int $0x21
pascal@15368 198
pascal@15368 199 _exe_start:
pascal@15368 200 pushw $dosexit
pascal@15368 201 movw $EXEADRS(need386), %si
pascal@15368 202 pushfw // save flags
pascal@15368 203 // bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
pascal@15368 204 // flags 0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF
pascal@15368 205 movb $0x10, %ah // DF = IF = TF = 0
pascal@15368 206 pushw %ax
pascal@15368 207 popfw // < 286 : flags[12..15] are forced 1
pascal@15368 208 pushfw // = 286 : flags[12..15] are forced 0
pascal@15368 209 popw %cx // > 286 : only flags[15] is forced 0
pascal@15368 210 popfw // restore flags
pascal@15368 211 addb %ah, %ch // test F0 and 00 cases
pascal@15368 212 cmpb %ah, %ch
pascal@15368 213 jbe puts // C=8086/80186, Z=80286
pascal@15368 214 // smsww %ax
pascal@15368 215 // andb $1, %al
pascal@15368 216 // jne puts
pascal@15368 217
pascal@15368 218 /* Terminate command line with a NUL */
pascal@15368 219 movzbw PSP_CMDLINE_LEN, %si
pascal@15368 220 movb $0, PSP_CMDLINE_START(%si)
pascal@15368 221 cmpb $'?', PSP_CMDLINE_START-1(%si)
pascal@15368 222 je help
pascal@15368 223 pushw %si
pascal@15368 224
pascal@15368 225 /* Install iPXE. Use a fixed temporary decompression area to
pascal@15368 226 * avoid trashing the DOS high memory area.
pascal@15368 227 */
pascal@15368 228 call alloc_basemem
pascal@15368 229 movl $EXE_DECOMPRESS_ADDRESS, %edi
pascal@15368 230 stc
pascal@15368 231 sbbl %ebp, %ebp /* Allow arbitrary relocation */
pascal@15368 232 xorl %esi, %esi
pascal@15368 233 call install_prealloc
pascal@15368 234
pascal@15368 235 xorl %ebp, %ebp
pascal@15368 236 xorl %ecx, %ecx
pascal@15368 237
pascal@15368 238 /* Calculate command line physical address */
pascal@15368 239 xorl %edx, %edx
pascal@15368 240 movw %ds, %dx
pascal@15368 241 shll $4, %edx
pascal@15368 242 popw %si
pascal@15368 243 orw %si, %si
pascal@15368 244 jne gotarg
pascal@15368 245 movw $EXEADRS(default_config), %bp
pascal@15368 246 addl %edx, %ebp
pascal@15368 247 movw $0xA00-default_config, %cx
pascal@15368 248 gotarg:
pascal@15368 249 addl $PSP_CMDLINE_START, %edx
pascal@15368 250
pascal@15368 251 jmp start_ipxe
pascal@15368 252
pascal@15368 253 help:
pascal@15368 254 movw $EXEADRS(helpmsg), %si
pascal@15368 255 puts:
pascal@15368 256 lodsb
pascal@15368 257 orb %al, %al
pascal@15368 258 je exit
pascal@15368 259 call putc
pascal@15368 260 jmp puts
pascal@15368 261 #endif
pascal@15368 262
pascal@15368 263 putcdot:
pascal@15368 264 movb $0x2E, %al
pascal@15368 265 putc:
pascal@15368 266 movb $0xE, %ah
pascal@15368 267 movw $7, %bx
pascal@15368 268 int $0x10
pascal@15368 269 exit:
pascal@15368 270 ret
pascal@15368 271
pascal@15368 272
pascal@15368 273 # read_sectors reads %di sectors into %es:0 buffer.
pascal@15368 274 # %es:0 is updated to the next memory location.
pascal@15368 275 # First, sectors are read sector by sector until
pascal@15368 276 # sector per track count is known. Then they are
pascal@15368 277 # read track by track.
pascal@15368 278 # Assume no error on first track.
pascal@15368 279
pascal@15368 280 #ifdef FLOPPY_1440K_ONLY
pascal@15368 281 #define FLOPPY_HEADS 2 /* 2 heads */
pascal@15368 282 #define FLOPPY_SECTORS 18 /* 18 sectors */
pascal@15368 283 #else
pascal@15368 284 #define FLOPPY_HEADS 2 /* 2 heads minimum */
pascal@15368 285 #define FLOPPY_SECTORS 9 /* 9 sectors minimum */
pascal@15368 286 #endif
pascal@15368 287
pascal@15368 288 check_limits:
pascal@15368 289 #ifndef FLOPPY_1440K_ONLY
pascal@15368 290 popw %dx
pascal@15368 291 #ifdef FLOPPY_SECTORS
pascal@15368 292 cmpb $FLOPPY_SECTORS+1, %cl # minimum sector count
pascal@15368 293 jb check_head
pascal@15368 294 #endif
pascal@15368 295 cmpb %al, %cl # max sector known ?
pascal@15368 296 ja next_head # no -> store it
pascal@15368 297 check_head:
pascal@15368 298 #ifdef FLOPPY_HEADS
pascal@15368 299 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
pascal@15368 300 jb check_cylinder
pascal@15368 301 #endif
pascal@15368 302 cmpb %ah, %dh # max head known ?
pascal@15368 303 ja next_cylinder # no -> store it
pascal@15368 304 check_cylinder:
pascal@15368 305 #endif
pascal@15368 306 pushaw
pascal@15368 307 #ifndef FLOPPY_1440K_ONLY
pascal@15368 308 cbw # %ah = 0
pascal@15368 309 #endif
pascal@15368 310 int $0x13 # reset controler
pascal@15368 311 popaw
pascal@15368 312 movb $1, %al # sector by sector...
pascal@15368 313 read_sectorslp:
pascal@15368 314 pushw %dx # some bios break dx...
pascal@15368 315 #ifndef FLOPPY_1440K_ONLY
pascal@15368 316 pushw %ax # limits
pascal@15368 317 subb %cl, %al # sectors remaining in track
pascal@15368 318 ja tolastsect
pascal@15368 319 movb $1, %al # 1 sector mini
pascal@15368 320 tolastsect:
pascal@15368 321 #else
pascal@15368 322 mov $FLOPPY_SECTORS+1, %al
pascal@15368 323 subb %cl, %al # sectors remaining in track
pascal@15368 324 #endif
pascal@15368 325 cbw
pascal@15368 326 cmpw %di, %ax
pascal@15368 327 jb more1trk
pascal@15368 328 movw %di, %ax # sectors to read
pascal@15368 329 more1trk:
pascal@15368 330 pushw %ax # save context
pascal@15368 331 movb $2, %ah # cmd: read chs
pascal@15368 332 int $0x13
pascal@15368 333 #ifndef FLOPPY_1440K_ONLY
pascal@15368 334 popw %dx # save %ax
pascal@15368 335 popw %ax # limits
pascal@15368 336 #else
pascal@15368 337 popw %ax # restore context
pascal@15368 338 popw %dx
pascal@15368 339 #endif
pascal@15368 340 jc check_limits
pascal@15368 341 #ifndef FLOPPY_1440K_ONLY
pascal@15368 342 xchgw %ax, %bp
pascal@15368 343 addw %dx,%cx # next sector
pascal@15368 344 movw %cx, %gs
pascal@15368 345 movw %es, %cx
pascal@15368 346 pushw %dx
pascal@15368 347 shlw $5, %dx
pascal@15368 348 addw %dx, %cx
pascal@15368 349 popw %dx
pascal@15368 350 subw %dx,%di # update sector counter
pascal@15368 351 popw %dx
pascal@15368 352 read_sectorsCX:
pascal@15368 353 movw %cx, %es # next location
pascal@15368 354 jz putcdot
pascal@15368 355 #else
pascal@15368 356 addw %ax,%cx # next sector
pascal@15368 357 movw %cx, %gs
pascal@15368 358 movw %es, %cx
pascal@15368 359 pushw %ax
pascal@15368 360 shlw $5, %ax
pascal@15368 361 addw %ax, %cx
pascal@15368 362 popw %ax
pascal@15368 363 subw %ax,%di # update sector counter
pascal@15368 364 read_sectorsCX:
pascal@15368 365 movw %cx, %es # next location
pascal@15368 366 jz putcdot
pascal@15368 367 #endif
pascal@15368 368 read_sectors:
pascal@15368 369 movw %gs, %cx
pascal@15368 370 #ifndef FLOPPY_1440K_ONLY
pascal@15368 371 # al is last sector+1
pascal@15368 372 # ah is last cylinder+1
pascal@15368 373 xchgw %ax, %bp
pascal@15368 374 #endif
pascal@15368 375 #ifndef FLOPPY_1440K_ONLY
pascal@15368 376 cmpb %al,%cl # reach sector limit ?
pascal@15368 377 jne bdendlp
pascal@15368 378 next_head:
pascal@15368 379 movb %cl,%al
pascal@15368 380 #else
pascal@15368 381 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
pascal@15368 382 jne bdendlp
pascal@15368 383 #endif
pascal@15368 384 incb %dh # next head
pascal@15368 385 movb $1,%cl # first sector
pascal@15368 386 #ifndef FLOPPY_1440K_ONLY
pascal@15368 387 cmpb %ah, %dh # reach head limit ?
pascal@15368 388 jne bdendlp
pascal@15368 389 next_cylinder:
pascal@15368 390 movb %dh,%ah
pascal@15368 391 #else
pascal@15368 392 cmpb %cl,%dh # reach head limit ?
pascal@15368 393 je bdendlp
pascal@15368 394 #endif
pascal@15368 395 # NOTE : support 256 cylinders max
pascal@15368 396 incb %ch # next cylinder
pascal@15368 397 read_first_sectors:
pascal@15368 398 movb $0,%dh # first head
pascal@15368 399 bdendlp:
pascal@15368 400 jmp read_sectorslp
pascal@15368 401
pascal@15368 402 #ifdef EXE_SUPPORT
pascal@15368 403 need386:
pascal@15368 404 .ascii "No 386+."
pascal@15368 405 .byte 13,10
pascal@15368 406 .byte 0
pascal@15368 407 helpmsg:
pascal@15368 408 .ascii "No help available."
pascal@15368 409 .byte 13,10
pascal@15368 410 .byte 0
pascal@15368 411 #endif
pascal@15368 412
pascal@15368 413 /*
pascal@15368 414 The following header is documented in the Linux source code at
pascal@15368 415 Documentation/x86/boot.txt
pascal@15368 416 */
pascal@15368 417 .org 497
pascal@15368 418 setup_sects:
pascal@15368 419 .byte SETUPSECS
pascal@15368 420 root_flags:
pascal@15368 421 .word 0
pascal@15368 422 syssize:
pascal@15368 423 .long -PREFIXPGH
pascal@15368 424
pascal@15368 425 .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
pascal@15368 426 .ascii "ADDL"
pascal@15368 427 .long syssize
pascal@15368 428 .long 16
pascal@15368 429 .long 0
pascal@15368 430 .previous
pascal@15368 431
pascal@15368 432 ram_size:
pascal@15368 433 .word 0
pascal@15368 434 vid_mode:
pascal@15368 435 .word 0
pascal@15368 436 root_dev:
pascal@15368 437 .word 0
pascal@15368 438 boot_flag:
pascal@15368 439 .word 0xAA55
pascal@15368 440 jump:
pascal@15368 441 /* Manually specify a two-byte jmp instruction here rather
pascal@15368 442 * than leaving it up to the assembler. */
pascal@15368 443 .byte 0xeb
pascal@15368 444 .byte setup_code - header
pascal@15368 445 header:
pascal@15368 446 .byte 'H', 'd', 'r', 'S'
pascal@15368 447 version:
pascal@15368 448 .word 0x0207 /* 2.07 */
pascal@15368 449 realmode_swtch:
pascal@15368 450 .long 0
pascal@15368 451 start_sys:
pascal@15368 452 .word 0
pascal@15368 453 kernel_version:
pascal@15368 454 .word 0
pascal@15368 455 type_of_loader:
pascal@15368 456 .byte 0
pascal@15368 457 loadflags:
pascal@15368 458 .byte 0
pascal@15368 459 setup_move_size:
pascal@15368 460 .word 0
pascal@15368 461 code32_start:
pascal@15368 462 .long SYSSEG*16
pascal@15368 463 ramdisk_image:
pascal@15368 464 .long 0
pascal@15368 465 ramdisk_size:
pascal@15368 466 .long 0
pascal@15368 467 bootsect_kludge:
pascal@15368 468 .long 0
pascal@15368 469 heap_end_ptr:
pascal@15368 470 .word 0
pascal@15368 471 pad1:
pascal@15368 472 .word 0
pascal@15368 473 cmd_line_ptr:
pascal@15368 474 .long 0
pascal@15368 475 initrd_addr_max:
pascal@15368 476 /* We don't use an initrd but some bootloaders (e.g. SYSLINUX) have
pascal@15368 477 * been known to require this field. Set the value to 2 GB. This
pascal@15368 478 * value is also used by the Linux kernel. */
pascal@15368 479 .long 0x7fffffff
pascal@15368 480 kernel_alignment:
pascal@15368 481 .long 0
pascal@15368 482 relocatable_kernel:
pascal@15368 483 .byte 0
pascal@15368 484 pad2:
pascal@15368 485 .byte 0, 0, 0
pascal@15368 486 cmdline_size:
pascal@15368 487 .long 0x7ff
pascal@15368 488 hardware_subarch:
pascal@15368 489 .long 0
pascal@15368 490 hardware_subarch_data:
pascal@15368 491 .byte 0, 0, 0, 0, 0, 0, 0, 0
pascal@15368 492
pascal@15368 493 /*
pascal@15368 494 We don't need to do too much setup.
pascal@15368 495
pascal@15368 496 This code gets loaded at SETUPSEG:0. It wants to start
pascal@15368 497 executing the image that's loaded at SYSSEG:0 and
pascal@15368 498 whose entry point is SYSSEG:0.
pascal@15368 499 */
pascal@15368 500 setup_code:
pascal@15368 501 movl ramdisk_image, %eax
pascal@15368 502 orl %eax, %eax
pascal@15368 503 jnz setup_done
pascal@15368 504
pascal@15368 505 movw $default_config, %di
pascal@15368 506 movw $-1, %bx
pascal@15368 507
pascal@15368 508 movw $9, %cx
pascal@15368 509 1:
pascal@15368 510 pushw %ax
pascal@15368 511 loop 1b
pascal@15368 512 pushw $0x9310
pascal@15368 513 pushw %ax
pascal@15368 514 pushw %bx
pascal@15368 515 pushw %ax
pascal@15368 516 pushw $0x9300+(INITSEG>>12)
pascal@15368 517 pushw %di
pascal@15368 518 pushw %bx
pascal@15368 519 movb $8, %cl
pascal@15368 520 1:
pascal@15368 521 pushw %ax
pascal@15368 522 loop 1b
pascal@15368 523 1:
pascal@15368 524 incw %bx
pascal@15368 525 cmpb %al, (%bx,%di)
pascal@15368 526 jne 1b
pascal@15368 527 movw %bx, ramdisk_size
pascal@15368 528 movb $0x10, ramdisk_image+2
pascal@15368 529
pascal@15368 530 pushw %ss
pascal@15368 531 popw %es
pascal@15368 532 movw %sp, %si
pascal@15368 533 movb $0x87, %ah
pascal@15368 534 movw $(run_ipxe-default_config)/2+1, %cx
pascal@15368 535 int $0x15
pascal@15368 536
pascal@15368 537 setup_done:
pascal@15368 538 /* We expect to be contiguous in memory once loaded. The Linux image
pascal@15368 539 * boot process requires that setup code is loaded separately from
pascal@15368 540 * "non-real code". Since we don't need any information that's left
pascal@15368 541 * in the prefix, it doesn't matter: we just have to ensure that
pascal@15368 542 * %cs:0000 is where the start of the image *would* be.
pascal@15368 543 */
pascal@15368 544 ljmp $(SYSSEG-(PREFIXSIZE/16)), $run_ipxe
pascal@15368 545
pascal@15368 546 default_config:
pascal@15368 547
pascal@15368 548 .org PREFIXSIZE
pascal@15368 549 /*
pascal@15368 550 We're now at the beginning of the kernel proper.
pascal@15368 551 */
pascal@15368 552 run_ipxe:
pascal@15368 553 /* Set up stack just below 0x7c00 and clear direction flag */
pascal@15368 554 xorw %ax, %ax
pascal@15368 555 movw %ax, %ss
pascal@15368 556 movw $0x7c00, %sp
pascal@15368 557 cld
pascal@15368 558
pascal@15368 559 /* Retrieve command-line pointer */
pascal@15368 560 movl %ds:cmd_line_ptr, %edx
pascal@15368 561 testl %edx, %edx
pascal@15368 562 jz no_cmd_line
pascal@15368 563
pascal@15368 564 /* Set up %es:%di to point to command line */
pascal@15368 565 movl %edx, %edi
pascal@15368 566 andl $0xf, %edi
pascal@15368 567 rorl $4, %edx
pascal@15368 568 movw %dx, %es
pascal@15368 569
pascal@15368 570 /* Find length of command line */
pascal@15368 571 pushw %di
pascal@15368 572 movw $0xffff, %cx
pascal@15368 573 repnz scasb
pascal@15368 574 notw %cx
pascal@15368 575 popw %si
pascal@15368 576
pascal@15368 577 /* Make space for command line on stack */
pascal@15368 578 movw %sp, %di
pascal@15368 579 subw %cx, %di
pascal@15368 580 andw $~0xf, %di
pascal@15368 581 movw %di, %sp
pascal@15368 582
pascal@15368 583 /* Copy command line to stack */
pascal@15368 584 pushw %ds
pascal@15368 585 pushw %es
pascal@15368 586 popw %ds
pascal@15368 587 pushw %ss
pascal@15368 588 popw %es
pascal@15368 589 rep movsb
pascal@15368 590 popw %ds
pascal@15368 591
pascal@15368 592 /* Store new command-line pointer */
pascal@15368 593 movzwl %sp, %edx
pascal@15368 594 no_cmd_line:
pascal@15368 595
pascal@15368 596 /* Calculate maximum relocation address */
pascal@15368 597 movl ramdisk_image, %ebp
pascal@15368 598 testl %ebp, %ebp
pascal@15368 599 jnz 1f
pascal@15368 600 decl %ebp /* Allow arbitrary relocation if no initrd */
pascal@15368 601 1:
pascal@15368 602
pascal@15368 603 /* Install iPXE */
pascal@15368 604 call alloc_basemem
pascal@15368 605 xorl %esi, %esi
pascal@15368 606 xorl %edi, %edi
pascal@15368 607 call install_prealloc
pascal@15368 608
pascal@15368 609 /* Retrieve initrd pointer and size */
pascal@15368 610 movl ramdisk_image, %ebp
pascal@15368 611 movl ramdisk_size, %ecx
pascal@15368 612
pascal@15368 613 start_ipxe:
pascal@15368 614 /* Set up real-mode stack */
pascal@15368 615 movw %bx, %ss
pascal@15368 616 movw $_estack16, %sp
pascal@15368 617
pascal@15368 618 /* Jump to .text16 segment */
pascal@15368 619 pushw %ax
pascal@15368 620 pushw $1f
pascal@15368 621 lret
pascal@15368 622 .section ".text16", "awx", @progbits
pascal@15368 623 1:
pascal@15368 624 /* Set up %ds for access to .data16 */
pascal@15368 625 movw %bx, %ds
pascal@15368 626
pascal@15368 627 /* Store command-line pointer */
pascal@15368 628 movl %edx, cmdline_phys
pascal@15368 629
pascal@15368 630 /* Store initrd pointer and size */
pascal@15368 631 movl %ebp, initrd_phys
pascal@15368 632 movl %ecx, initrd_len
pascal@15368 633
pascal@15368 634 /* Run iPXE */
pascal@15368 635 pushl $main
pascal@15368 636 pushw %cs
pascal@15368 637 call prot_call
pascal@15368 638 popl %ecx /* discard */
pascal@15368 639
pascal@15368 640 /* Uninstall iPXE */
pascal@15368 641 call uninstall
pascal@15368 642
pascal@15368 643 /* Boot next device */
pascal@15368 644 int $0x18