wok diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipxe/stuff/lkrnprefix.S Mon Oct 14 13:38:36 2013 +0000 1.3 @@ -0,0 +1,644 @@ 1.4 +/* 1.5 + Copyright (C) 2000, Entity Cyber, Inc. 1.6 + 1.7 + Authors: Gary Byers (gb@thinguin.org) 1.8 + Marty Connor (mdc@thinguin.org) 1.9 + 1.10 + This software may be used and distributed according to the terms 1.11 + of the GNU Public License (GPL), incorporated herein by reference. 1.12 + 1.13 + Description: 1.14 + 1.15 + This is just a little bit of code and data that can get prepended 1.16 + to a ROM image in order to allow bootloaders to load the result 1.17 + as if it were a Linux kernel image. 1.18 + 1.19 + A real Linux kernel image consists of a one-sector boot loader 1.20 + (to load the image from a floppy disk), followed a few sectors 1.21 + of setup code, followed by the kernel code itself. There's 1.22 + a table in the first sector (starting at offset 497) that indicates 1.23 + how many sectors of setup code follow the first sector and which 1.24 + contains some other parameters that aren't interesting in this 1.25 + case. 1.26 + 1.27 + When a bootloader loads the sectors that comprise a kernel image, 1.28 + it doesn't execute the code in the first sector (since that code 1.29 + would try to load the image from a floppy disk.) The code in the 1.30 + first sector below doesn't expect to get executed (and prints an 1.31 + error message if it ever -is- executed.) 1.32 + 1.33 + We don't require much in the way of setup code. Historically, the 1.34 + Linux kernel required at least 4 sectors of setup code. 1.35 + Therefore, at least 4 sectors must be present even though we don't 1.36 + use them. 1.37 + 1.38 +*/ 1.39 + 1.40 +FILE_LICENCE ( GPL_ANY ) 1.41 + 1.42 +#define SETUPSECS 4 /* Minimal nr of setup-sectors */ 1.43 +#define PREFIXSIZE ((SETUPSECS+1)*512) 1.44 +#define PREFIXPGH (PREFIXSIZE / 16 ) 1.45 +#define BOOTSEG 0x07C0 /* original address of boot-sector */ 1.46 +#define INITSEG 0x9000 /* we move boot here - out of the way */ 1.47 +#define SETUPSEG 0x9020 /* setup starts here */ 1.48 +#define SYSSEG 0x1000 /* system loaded at 0x10000 (65536). */ 1.49 + 1.50 + .text 1.51 + .code16 1.52 + .arch i386 1.53 + .org 0 1.54 + .section ".prefix", "ax", @progbits 1.55 + .globl _lkrn_start 1.56 +_lkrn_start: 1.57 + 1.58 +bootsector: 1.59 +_start: 1.60 + 1.61 +/* some extra features */ 1.62 +#define EXE_SUPPORT real mode dos .exe file support 1.63 + 1.64 +#define EXEADRS(x) (x+0xE0) 1.65 + 1.66 +/* some contraints to reduce the size */ 1.67 +//#define FLOPPY_1440K_ONLY 1.44M floppies support only 1.68 + 1.69 +#ifdef EXE_SUPPORT 1.70 +/* Initial temporary stack size */ 1.71 +#define EXE_STACK_SIZE 0x400 1.72 + 1.73 +/* Temporary decompression area (avoid DOS high memory area) */ 1.74 +#define EXE_DECOMPRESS_ADDRESS 0x110000 1.75 + 1.76 +/* Fields within the Program Segment Prefix */ 1.77 +#define PSP_CMDLINE_LEN 0x80 1.78 +#define PSP_CMDLINE_START 0x81 1.79 + 1.80 +#define HEADER_SIZE 0x20 1.81 + 1.82 +signature: 1.83 + decw %bp // Magic number: MZ 1.84 + popw %dx 1.85 + jmp start // Bytes on last page of file 1.86 +blocks: 1.87 + .word 0 // Pages in file 1.88 + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ 1.89 + .ascii "ADDW" 1.90 + .long blocks 1.91 + .long 512 1.92 + .long 0 1.93 + .previous 1.94 + .word 0 // Relocations 1.95 + .word ( HEADER_SIZE / 16 ) // Size of header in paragraphs 1.96 + .word ( EXE_STACK_SIZE / 16 ) // Minimum extra paragraphs needed 1.97 + .word ( EXE_STACK_SIZE / 16 ) // Maximum extra paragraphs needed 1.98 +init_ss: 1.99 + .word -( ( _exe_start - signature ) / 16 ) // Initial (relative) SS value 1.100 + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ 1.101 + .ascii "ADDW" 1.102 + .long init_ss 1.103 + .long 16 1.104 + .long 0 1.105 + .previous 1.106 + .word EXE_STACK_SIZE // Initial SP value 1.107 + .word 0 // Checksum 1.108 + .word _exe_start // Initial IP value 1.109 + /* Initial code segment (relative to start of executable) */ 1.110 + //.word -( ( _exe_start - signature ) / 16 ) // Initial (relative) CS value 1.111 + .word -( HEADER_SIZE / 16 ) // Initial (relative) CS value 1.112 +// .word 0x001C // File address of relocation table 1.113 +// .word 0,0,0 // Overlay number 1.114 + 1.115 +start: 1.116 + pushw %dx 1.117 + xorw %dx, %dx 1.118 +#endif 1.119 + cld # assume nothing 1.120 +stacktop = 0x9E00 # in 0x8000 .. 0xA000 1.121 +zeroed = 12 # zeroed registers 1.122 + movw $stacktop-12-zeroed, %di # stacktop is an arbitrary value >= 1.123 + # length of bootsect + length of 1.124 + # setup + room for stack; 1.125 + # 12 is disk parm size. 1.126 + pushw $INITSEG 1.127 + popw %ss # %ss contain INITSEG 1.128 + movw %di, %sp # put stack at INITSEG:stacktop-... 1.129 + 1.130 +# Many BIOS's default disk parameter tables will not recognize 1.131 +# multi-sector reads beyond the maximum sector number specified 1.132 +# in the default diskette parameter tables - this may mean 7 1.133 +# sectors in some cases. 1.134 +# 1.135 +# Since single sector reads are slow and out of the question, 1.136 +# we must take care of this by creating new parameter tables 1.137 +# (for the first disk) in RAM. We can set the maximum sector 1.138 +# count to 36 - the most we will encounter on an ED 2.88. 1.139 +# 1.140 +# High doesn't hurt. Low does. Let's use the max: 63 1.141 + 1.142 + pushw %ss 1.143 + popw %es # %es = %ss = INITSEG 1.144 + xorw %ax, %ax # %ax = 0 1.145 + movw $zeroed/2, %cx # clear gdt + offset, %ds, limits 1.146 + rep # don't worry about cld 1.147 + stosw # already done above 1.148 + popw %bx # offset = 0 1.149 + popw %ds # %ds = 0 1.150 + popw %fs # %fs = 0 1.151 + 1.152 + movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0) 1.153 + incw %ax 1.154 + 1.155 + ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address 1.156 + pushw %es 1.157 + pushw %di 1.158 + movb $6, %cl # copy 12 bytes 1.159 + rep # don't worry about cld 1.160 + movsw # already done above 1.161 + pushw %ss 1.162 + popw %ds # now %ds = %es = %ss = INITSEG 1.163 + popl %fs:0x78(%bx) # update parameter table address 1.164 + movb $63, 0x4-12(%di) # patch sector count, %di = stacktop 1.165 + cli 1.166 + 1.167 + xchg %ax, %di # sector count 1.168 + popw %ax # limits = 0 1.169 + incw %cx # cylinder 0, sector 1, clear Z 1.170 + call read_first_sectors # read setup 1.171 + 1.172 +# This routine loads the system at address LOADSEG, making sure 1.173 +# no 64kB boundaries are crossed. We try to load it as fast as 1.174 +# possible, loading whole tracks whenever we can. 1.175 + 1.176 + popw %bx # clear %bx 1.177 + movw syssize, %di 1.178 + addw $(512/16)-1, %di 1.179 + shrw $9-4, %di 1.180 + movw $SYSSEG, %cx 1.181 + call read_sectorsCX 1.182 + 1.183 +# This procedure turns off the floppy drive motor, so 1.184 +# that we enter the kernel in a known state, and 1.185 +# don't have to worry about it later. 1.186 + 1.187 +kill_motor: 1.188 + xchgw %ax, %di # reset FDC (%di < 128) 1.189 + int $0x13 1.190 + 1.191 +# After that (everything loaded), we jump to the setup-routine 1.192 +# loaded directly after the bootblock: 1.193 +# Segments are as follows: %ds = %ss = INITSEG 1.194 + 1.195 + ljmp $SETUPSEG, $0 1.196 + 1.197 +#ifdef EXE_SUPPORT 1.198 +dosexit: 1.199 + movw $0x4c00, %ax 1.200 + int $0x21 1.201 + 1.202 +_exe_start: 1.203 + pushw $dosexit 1.204 + movw $EXEADRS(need386), %si 1.205 + pushfw // save flags 1.206 + // bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1.207 + // flags 0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF 1.208 + movb $0x10, %ah // DF = IF = TF = 0 1.209 + pushw %ax 1.210 + popfw // < 286 : flags[12..15] are forced 1 1.211 + pushfw // = 286 : flags[12..15] are forced 0 1.212 + popw %cx // > 286 : only flags[15] is forced 0 1.213 + popfw // restore flags 1.214 + addb %ah, %ch // test F0 and 00 cases 1.215 + cmpb %ah, %ch 1.216 + jbe puts // C=8086/80186, Z=80286 1.217 +// smsww %ax 1.218 +// andb $1, %al 1.219 +// jne puts 1.220 + 1.221 + /* Terminate command line with a NUL */ 1.222 + movzbw PSP_CMDLINE_LEN, %si 1.223 + movb $0, PSP_CMDLINE_START(%si) 1.224 + cmpb $'?', PSP_CMDLINE_START-1(%si) 1.225 + je help 1.226 + pushw %si 1.227 + 1.228 + /* Install iPXE. Use a fixed temporary decompression area to 1.229 + * avoid trashing the DOS high memory area. 1.230 + */ 1.231 + call alloc_basemem 1.232 + movl $EXE_DECOMPRESS_ADDRESS, %edi 1.233 + stc 1.234 + sbbl %ebp, %ebp /* Allow arbitrary relocation */ 1.235 + xorl %esi, %esi 1.236 + call install_prealloc 1.237 + 1.238 + xorl %ebp, %ebp 1.239 + xorl %ecx, %ecx 1.240 + 1.241 + /* Calculate command line physical address */ 1.242 + xorl %edx, %edx 1.243 + movw %ds, %dx 1.244 + shll $4, %edx 1.245 + popw %si 1.246 + orw %si, %si 1.247 + jne gotarg 1.248 + movw $EXEADRS(default_config), %bp 1.249 + addl %edx, %ebp 1.250 + movw $0xA00-default_config, %cx 1.251 +gotarg: 1.252 + addl $PSP_CMDLINE_START, %edx 1.253 + 1.254 + jmp start_ipxe 1.255 + 1.256 +help: 1.257 + movw $EXEADRS(helpmsg), %si 1.258 +puts: 1.259 + lodsb 1.260 + orb %al, %al 1.261 + je exit 1.262 + call putc 1.263 + jmp puts 1.264 +#endif 1.265 + 1.266 +putcdot: 1.267 + movb $0x2E, %al 1.268 +putc: 1.269 + movb $0xE, %ah 1.270 + movw $7, %bx 1.271 + int $0x10 1.272 +exit: 1.273 + ret 1.274 + 1.275 + 1.276 +# read_sectors reads %di sectors into %es:0 buffer. 1.277 +# %es:0 is updated to the next memory location. 1.278 +# First, sectors are read sector by sector until 1.279 +# sector per track count is known. Then they are 1.280 +# read track by track. 1.281 +# Assume no error on first track. 1.282 + 1.283 +#ifdef FLOPPY_1440K_ONLY 1.284 +#define FLOPPY_HEADS 2 /* 2 heads */ 1.285 +#define FLOPPY_SECTORS 18 /* 18 sectors */ 1.286 +#else 1.287 +#define FLOPPY_HEADS 2 /* 2 heads minimum */ 1.288 +#define FLOPPY_SECTORS 9 /* 9 sectors minimum */ 1.289 +#endif 1.290 + 1.291 +check_limits: 1.292 +#ifndef FLOPPY_1440K_ONLY 1.293 + popw %dx 1.294 +#ifdef FLOPPY_SECTORS 1.295 + cmpb $FLOPPY_SECTORS+1, %cl # minimum sector count 1.296 + jb check_head 1.297 +#endif 1.298 + cmpb %al, %cl # max sector known ? 1.299 + ja next_head # no -> store it 1.300 +check_head: 1.301 +#ifdef FLOPPY_HEADS 1.302 + cmpb $FLOPPY_HEADS, %dh # 2 heads minimum 1.303 + jb check_cylinder 1.304 +#endif 1.305 + cmpb %ah, %dh # max head known ? 1.306 + ja next_cylinder # no -> store it 1.307 +check_cylinder: 1.308 +#endif 1.309 + pushaw 1.310 +#ifndef FLOPPY_1440K_ONLY 1.311 + cbw # %ah = 0 1.312 +#endif 1.313 + int $0x13 # reset controler 1.314 + popaw 1.315 + movb $1, %al # sector by sector... 1.316 +read_sectorslp: 1.317 + pushw %dx # some bios break dx... 1.318 +#ifndef FLOPPY_1440K_ONLY 1.319 + pushw %ax # limits 1.320 + subb %cl, %al # sectors remaining in track 1.321 + ja tolastsect 1.322 + movb $1, %al # 1 sector mini 1.323 +tolastsect: 1.324 +#else 1.325 + mov $FLOPPY_SECTORS+1, %al 1.326 + subb %cl, %al # sectors remaining in track 1.327 +#endif 1.328 + cbw 1.329 + cmpw %di, %ax 1.330 + jb more1trk 1.331 + movw %di, %ax # sectors to read 1.332 +more1trk: 1.333 + pushw %ax # save context 1.334 + movb $2, %ah # cmd: read chs 1.335 + int $0x13 1.336 +#ifndef FLOPPY_1440K_ONLY 1.337 + popw %dx # save %ax 1.338 + popw %ax # limits 1.339 +#else 1.340 + popw %ax # restore context 1.341 + popw %dx 1.342 +#endif 1.343 + jc check_limits 1.344 +#ifndef FLOPPY_1440K_ONLY 1.345 + xchgw %ax, %bp 1.346 + addw %dx,%cx # next sector 1.347 + movw %cx, %gs 1.348 + movw %es, %cx 1.349 + pushw %dx 1.350 + shlw $5, %dx 1.351 + addw %dx, %cx 1.352 + popw %dx 1.353 + subw %dx,%di # update sector counter 1.354 + popw %dx 1.355 +read_sectorsCX: 1.356 + movw %cx, %es # next location 1.357 + jz putcdot 1.358 +#else 1.359 + addw %ax,%cx # next sector 1.360 + movw %cx, %gs 1.361 + movw %es, %cx 1.362 + pushw %ax 1.363 + shlw $5, %ax 1.364 + addw %ax, %cx 1.365 + popw %ax 1.366 + subw %ax,%di # update sector counter 1.367 +read_sectorsCX: 1.368 + movw %cx, %es # next location 1.369 + jz putcdot 1.370 +#endif 1.371 +read_sectors: 1.372 + movw %gs, %cx 1.373 +#ifndef FLOPPY_1440K_ONLY 1.374 +# al is last sector+1 1.375 +# ah is last cylinder+1 1.376 + xchgw %ax, %bp 1.377 +#endif 1.378 +#ifndef FLOPPY_1440K_ONLY 1.379 + cmpb %al,%cl # reach sector limit ? 1.380 + jne bdendlp 1.381 +next_head: 1.382 + movb %cl,%al 1.383 +#else 1.384 + cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ? 1.385 + jne bdendlp 1.386 +#endif 1.387 + incb %dh # next head 1.388 + movb $1,%cl # first sector 1.389 +#ifndef FLOPPY_1440K_ONLY 1.390 + cmpb %ah, %dh # reach head limit ? 1.391 + jne bdendlp 1.392 +next_cylinder: 1.393 + movb %dh,%ah 1.394 +#else 1.395 + cmpb %cl,%dh # reach head limit ? 1.396 + je bdendlp 1.397 +#endif 1.398 +# NOTE : support 256 cylinders max 1.399 + incb %ch # next cylinder 1.400 +read_first_sectors: 1.401 + movb $0,%dh # first head 1.402 +bdendlp: 1.403 + jmp read_sectorslp 1.404 + 1.405 +#ifdef EXE_SUPPORT 1.406 +need386: 1.407 + .ascii "No 386+." 1.408 + .byte 13,10 1.409 + .byte 0 1.410 +helpmsg: 1.411 + .ascii "No help available." 1.412 + .byte 13,10 1.413 + .byte 0 1.414 +#endif 1.415 + 1.416 +/* 1.417 + The following header is documented in the Linux source code at 1.418 + Documentation/x86/boot.txt 1.419 +*/ 1.420 + .org 497 1.421 +setup_sects: 1.422 + .byte SETUPSECS 1.423 +root_flags: 1.424 + .word 0 1.425 +syssize: 1.426 + .long -PREFIXPGH 1.427 + 1.428 + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ 1.429 + .ascii "ADDL" 1.430 + .long syssize 1.431 + .long 16 1.432 + .long 0 1.433 + .previous 1.434 + 1.435 +ram_size: 1.436 + .word 0 1.437 +vid_mode: 1.438 + .word 0 1.439 +root_dev: 1.440 + .word 0 1.441 +boot_flag: 1.442 + .word 0xAA55 1.443 +jump: 1.444 + /* Manually specify a two-byte jmp instruction here rather 1.445 + * than leaving it up to the assembler. */ 1.446 + .byte 0xeb 1.447 + .byte setup_code - header 1.448 +header: 1.449 + .byte 'H', 'd', 'r', 'S' 1.450 +version: 1.451 + .word 0x0207 /* 2.07 */ 1.452 +realmode_swtch: 1.453 + .long 0 1.454 +start_sys: 1.455 + .word 0 1.456 +kernel_version: 1.457 + .word 0 1.458 +type_of_loader: 1.459 + .byte 0 1.460 +loadflags: 1.461 + .byte 0 1.462 +setup_move_size: 1.463 + .word 0 1.464 +code32_start: 1.465 + .long SYSSEG*16 1.466 +ramdisk_image: 1.467 + .long 0 1.468 +ramdisk_size: 1.469 + .long 0 1.470 +bootsect_kludge: 1.471 + .long 0 1.472 +heap_end_ptr: 1.473 + .word 0 1.474 +pad1: 1.475 + .word 0 1.476 +cmd_line_ptr: 1.477 + .long 0 1.478 +initrd_addr_max: 1.479 + /* We don't use an initrd but some bootloaders (e.g. SYSLINUX) have 1.480 + * been known to require this field. Set the value to 2 GB. This 1.481 + * value is also used by the Linux kernel. */ 1.482 + .long 0x7fffffff 1.483 +kernel_alignment: 1.484 + .long 0 1.485 +relocatable_kernel: 1.486 + .byte 0 1.487 +pad2: 1.488 + .byte 0, 0, 0 1.489 +cmdline_size: 1.490 + .long 0x7ff 1.491 +hardware_subarch: 1.492 + .long 0 1.493 +hardware_subarch_data: 1.494 + .byte 0, 0, 0, 0, 0, 0, 0, 0 1.495 + 1.496 +/* 1.497 + We don't need to do too much setup. 1.498 + 1.499 + This code gets loaded at SETUPSEG:0. It wants to start 1.500 + executing the image that's loaded at SYSSEG:0 and 1.501 + whose entry point is SYSSEG:0. 1.502 +*/ 1.503 +setup_code: 1.504 + movl ramdisk_image, %eax 1.505 + orl %eax, %eax 1.506 + jnz setup_done 1.507 + 1.508 + movw $default_config, %di 1.509 + movw $-1, %bx 1.510 + 1.511 + movw $9, %cx 1.512 +1: 1.513 + pushw %ax 1.514 + loop 1b 1.515 + pushw $0x9310 1.516 + pushw %ax 1.517 + pushw %bx 1.518 + pushw %ax 1.519 + pushw $0x9300+(INITSEG>>12) 1.520 + pushw %di 1.521 + pushw %bx 1.522 + movb $8, %cl 1.523 +1: 1.524 + pushw %ax 1.525 + loop 1b 1.526 +1: 1.527 + incw %bx 1.528 + cmpb %al, (%bx,%di) 1.529 + jne 1b 1.530 + movw %bx, ramdisk_size 1.531 + movb $0x10, ramdisk_image+2 1.532 + 1.533 + pushw %ss 1.534 + popw %es 1.535 + movw %sp, %si 1.536 + movb $0x87, %ah 1.537 + movw $(run_ipxe-default_config)/2+1, %cx 1.538 + int $0x15 1.539 + 1.540 +setup_done: 1.541 + /* We expect to be contiguous in memory once loaded. The Linux image 1.542 + * boot process requires that setup code is loaded separately from 1.543 + * "non-real code". Since we don't need any information that's left 1.544 + * in the prefix, it doesn't matter: we just have to ensure that 1.545 + * %cs:0000 is where the start of the image *would* be. 1.546 + */ 1.547 + ljmp $(SYSSEG-(PREFIXSIZE/16)), $run_ipxe 1.548 + 1.549 +default_config: 1.550 + 1.551 + .org PREFIXSIZE 1.552 +/* 1.553 + We're now at the beginning of the kernel proper. 1.554 + */ 1.555 +run_ipxe: 1.556 + /* Set up stack just below 0x7c00 and clear direction flag */ 1.557 + xorw %ax, %ax 1.558 + movw %ax, %ss 1.559 + movw $0x7c00, %sp 1.560 + cld 1.561 + 1.562 + /* Retrieve command-line pointer */ 1.563 + movl %ds:cmd_line_ptr, %edx 1.564 + testl %edx, %edx 1.565 + jz no_cmd_line 1.566 + 1.567 + /* Set up %es:%di to point to command line */ 1.568 + movl %edx, %edi 1.569 + andl $0xf, %edi 1.570 + rorl $4, %edx 1.571 + movw %dx, %es 1.572 + 1.573 + /* Find length of command line */ 1.574 + pushw %di 1.575 + movw $0xffff, %cx 1.576 + repnz scasb 1.577 + notw %cx 1.578 + popw %si 1.579 + 1.580 + /* Make space for command line on stack */ 1.581 + movw %sp, %di 1.582 + subw %cx, %di 1.583 + andw $~0xf, %di 1.584 + movw %di, %sp 1.585 + 1.586 + /* Copy command line to stack */ 1.587 + pushw %ds 1.588 + pushw %es 1.589 + popw %ds 1.590 + pushw %ss 1.591 + popw %es 1.592 + rep movsb 1.593 + popw %ds 1.594 + 1.595 + /* Store new command-line pointer */ 1.596 + movzwl %sp, %edx 1.597 +no_cmd_line: 1.598 + 1.599 + /* Calculate maximum relocation address */ 1.600 + movl ramdisk_image, %ebp 1.601 + testl %ebp, %ebp 1.602 + jnz 1f 1.603 + decl %ebp /* Allow arbitrary relocation if no initrd */ 1.604 +1: 1.605 + 1.606 + /* Install iPXE */ 1.607 + call alloc_basemem 1.608 + xorl %esi, %esi 1.609 + xorl %edi, %edi 1.610 + call install_prealloc 1.611 + 1.612 + /* Retrieve initrd pointer and size */ 1.613 + movl ramdisk_image, %ebp 1.614 + movl ramdisk_size, %ecx 1.615 + 1.616 +start_ipxe: 1.617 + /* Set up real-mode stack */ 1.618 + movw %bx, %ss 1.619 + movw $_estack16, %sp 1.620 + 1.621 + /* Jump to .text16 segment */ 1.622 + pushw %ax 1.623 + pushw $1f 1.624 + lret 1.625 + .section ".text16", "awx", @progbits 1.626 +1: 1.627 + /* Set up %ds for access to .data16 */ 1.628 + movw %bx, %ds 1.629 + 1.630 + /* Store command-line pointer */ 1.631 + movl %edx, cmdline_phys 1.632 + 1.633 + /* Store initrd pointer and size */ 1.634 + movl %ebp, initrd_phys 1.635 + movl %ecx, initrd_len 1.636 + 1.637 + /* Run iPXE */ 1.638 + pushl $main 1.639 + pushw %cs 1.640 + call prot_call 1.641 + popl %ecx /* discard */ 1.642 + 1.643 + /* Uninstall iPXE */ 1.644 + call uninstall 1.645 + 1.646 + /* Boot next device */ 1.647 + int $0x18