1 ; -*- fundamental -*- (asm-mode sucks) 2 ; **************************************************************************** 3 ; 4 ; pxelinux.asm 5 ; 6 ; A program to boot Linux kernels off a TFTP server using the Intel PXE 7 ; network booting API. It is based on the SYSLINUX boot loader for 8 ; MS-DOS floppies. 9 ; 10 ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 11 ; Copyright 2009 Intel Corporation; author: H. Peter Anvin 12 ; 13 ; This program is free software; you can redistribute it and/or modify 14 ; it under the terms of the GNU General Public License as published by 15 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 16 ; Boston MA 02111-1307, USA; either version 2 of the License, or 17 ; (at your option) any later version; incorporated herein by reference. 18 ; 19 ; **************************************************************************** 20 21 %define IS_PXELINUX 1 22 %include "head.inc" 1 <1> ; -*- fundamental -*- (asm-mode sucks) 2 <1> ; ----------------------------------------------------------------------- 3 <1> ; 4 <1> ; Copyright 2006-2008 H. Peter Anvin - All Rights Reserved 5 <1> ; 6 <1> ; This program is free software; you can redistribute it and/or modify 7 <1> ; it under the terms of the GNU General Public License as published by 8 <1> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <1> ; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <1> ; (at your option) any later version; incorporated herein by reference. 11 <1> ; 12 <1> ; ----------------------------------------------------------------------- 13 <1> 14 <1> ; 15 <1> ; head.inc 16 <1> ; 17 <1> ; Common header includes 18 <1> ; 19 <1> 20 <1> %ifndef _HEAD_INC 21 <1> %define _HEAD_INC 22 <1> 23 <1> %if __NASM_MAJOR__ < 2 || (__NASM_MAJOR__ == 2 && __NASM_MINOR__ < 3) 24 <1> %error "NASM 2.03 or later required to compile correctly" 25 <1> %elif __NASM_VERSION_ID__ == 0x020b0600 26 <1> %fatal "NASM 2.11.06 is known to miscompile Syslinux" 27 <1> %endif 28 <1> 29 <1> %include "macros.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <2> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 <2> ;; 6 <2> ;; This program is free software; you can redistribute it and/or modify 7 <2> ;; it under the terms of the GNU General Public License as published by 8 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <2> ;; (at your option) any later version; incorporated herein by reference. 11 <2> ;; 12 <2> ;; ----------------------------------------------------------------------- 13 <2> 14 <2> ;; 15 <2> ;; macros.inc 16 <2> ;; 17 <2> ;; Convenient macros 18 <2> ;; 19 <2> 20 <2> %ifndef _MACROS_INC 21 <2> %define _MACROS_INC 22 <2> 23 <2> ; 24 <2> ; Identify the module we're compiling; the "correct" should be defined 25 <2> ; in the module itself to 1 26 <2> ; 27 <2> %ifdef IS_SYSLINUX 28 <2> %define MY_NAME 'SYSLINUX' 29 <2> %else 30 <2> %define IS_SYSLINUX 0 31 <2> %endif 32 <2> %ifdef IS_PXELINUX 33 <2> %define MY_NAME 'PXELINUX' 34 <2> %if IS_LPXELINUX > 0 35 <2> %define MY_TYPE 'lwIP' 36 <2> %else 37 <2> %define MY_TYPE 'PXE' 38 <2> %endif 39 <2> %else 40 <2> %define IS_PXELINUX 0 41 <2> %endif 42 <2> %ifdef IS_ISOLINUX 43 <2> %define MY_NAME 'ISOLINUX' 44 <2> %else 45 <2> %define IS_ISOLINUX 0 46 <2> %endif 47 <2> %ifdef IS_EXTLINUX 48 <2> %define MY_NAME 'EXTLINUX' 49 <2> %else 50 <2> %define IS_EXTLINUX 0 51 <2> %endif 52 <2> 53 <2> ; 54 <2> ; Macros similar to res[bwd], but which works in the code segment (after 55 <2> ; section .text16) or the data segment (section .data16) 56 <2> ; 57 <2> %macro zb 1.nolist 58 <2> times %1 db 0 59 <2> %endmacro 60 <2> 61 <2> %macro zw 1.nolist 62 <2> times %1 dw 0 63 <2> %endmacro 64 <2> 65 <2> %macro zd 1.nolist 66 <2> times %1 dd 0 67 <2> %endmacro 68 <2> 69 <2> ; 70 <2> ; Align with zero bytes in a progbits segment 71 <2> ; 72 <2> %macro alignz 1.nolist 73 <2> times (((%1) - (($-$$) % (%1))) % (%1)) db 0 74 <2> %endmacro 75 <2> 76 <2> ; 77 <2> ; Macro to emit an unsigned decimal number as a string 78 <2> ; 79 <2> %macro asciidec 1.nolist 80 <2> %ifndef DEPEND ; Not safe for "depend" 81 <2> %push asciidec 82 <2> %assign %$v %1 83 <2> %if %$v == 0 84 <2> db '0' 85 <2> %else 86 <2> %assign %$dcount 0 87 <2> %assign %$n %$v 88 <2> %assign %$d 1 89 <2> %rep 20 90 <2> %if %$n != 0 91 <2> %assign %$dcount %$dcount + 1 92 <2> %assign %$n %$n / 10 93 <2> %assign %$d %$d * 10 94 <2> %endif 95 <2> %endrep 96 <2> %rep %$dcount 97 <2> %assign %$d %$d / 10 98 <2> db ((%$v / %$d) % 10) + '0' 99 <2> %endrep 100 <2> %endif 101 <2> %pop 102 <2> %endif 103 <2> %endmacro 104 <2> 105 <2> ; 106 <2> ; Macros for network byte order of constants 107 <2> ; 108 <2> %define htons(x) ( ( ((x) & 0FFh) << 8 ) + ( ((x) & 0FF00h) >> 8 ) ) 109 <2> %define ntohs(x) htons(x) 110 <2> %define htonl(x) ( ( ((x) & 0FFh) << 24) + ( ((x) & 0FF00h) << 8 ) + ( ((x) & 0FF0000h) >> 8 ) + ( ((x) & 0FF000000h) >> 24) ) 111 <2> %define ntohl(x) htonl(x) 112 <2> 113 <2> ; 114 <2> ; ASCII 115 <2> ; 116 <2> CR equ 13 ; Carriage Return 117 <2> LF equ 10 ; Line Feed 118 <2> FF equ 12 ; Form Feed 119 <2> BS equ 8 ; Backspace 120 <2> 121 <2> %endif ; _MACROS_INC 30 <1> %include "config.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 2002-2009 H. Peter Anvin - All Rights Reserved 4 <2> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 <2> ;; 6 <2> ;; This program is free software; you can redistribute it and/or modify 7 <2> ;; it under the terms of the GNU General Public License as published by 8 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <2> ;; (at your option) any later version; incorporated herein by reference. 11 <2> ;; 12 <2> ;; ----------------------------------------------------------------------- 13 <2> 14 <2> ;; 15 <2> ;; config.inc 16 <2> ;; 17 <2> ;; Common configuration options. Some of these are imposed by the kernel. 18 <2> ;; 19 <2> 20 <2> %ifndef _CONFIG_INC 21 <2> %define _CONFIG_INC 22 <2> 23 <2> max_cmd_len equ 2047 ; Must be &3; 2047 is the kernel limit 24 <2> HIGHMEM_MAX equ 037FFFFFFh ; DEFAULT highest address for an initrd 25 <2> DEFAULT_BAUD equ 9600 ; Default baud rate for serial port 26 <2> BAUD_DIVISOR equ 115200 ; Serial port parameter 27 <2> MAX_FKEYS equ 12 ; Number of F-key help files 28 <2> 29 <2> ; 30 <2> ; log2(Max filename size Including final null) 31 <2> ; 32 <2> FILENAME_MAX_LG2 equ 8 33 <2> FILENAME_MAX equ (1 << FILENAME_MAX_LG2) ; Max mangled filename size 34 <2> 35 <2> ; 36 <2> ; Version number definitinons 37 <2> ; 38 <2> %include "../version.gen" 1 <3> %define VERSION 6.04 2 <3> %define VERSION_STR "6.04" 3 <3> %define VERSION_MAJOR 6 4 <3> %define VERSION_MINOR 4 5 <3> %define YEAR 2015 6 <3> %define YEAR_STR "2015" 39 <2> 40 <2> %endif ; _CONFIG_INC 31 <1> %include "layout.inc" 1 <2> ; ----------------------------------------------------------------------- 2 <2> ; 3 <2> ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <2> ; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin 5 <2> ; 6 <2> ; This program is free software; you can redistribute it and/or modify 7 <2> ; it under the terms of the GNU General Public License as published by 8 <2> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ; Bostom MA 02111-1307, USA; either version 2 of the License, or 10 <2> ; (at your option) any later version; incorporated herein by reference. 11 <2> ; 12 <2> ; ----------------------------------------------------------------------- 13 <2> 14 <2> ; 15 <2> ; layout.inc 16 <2> ; 17 <2> ; Memory layout of segments 18 <2> ; 19 <2> 20 <2> ; Default to 16-bit code 21 <2> bits 16 22 <2> 23 <2> ; Memory below 0800h is reserved for the BIOS and the MBR. 24 <2> BSS_START equ 0800h 25 <2> 26 <2> ; Text starts at the load address of 07C00h. 27 <2> TEXT_START equ 7C00h 28 <2> 29 <2> ; 30 <2> ; 16-bit stack layout 31 <2> ; 32 <2> ; PXELINUX: There are apparently some AMI BIOSes in the field which 33 <2> ; put their BEV stack somewhere below 7C00h (and therefore don't 34 <2> ; handle localboot properly), so avoid that immediate memory region. 35 <2> ; The range that is known to be bad is approximately 75E8..7C00; the 36 <2> ; lower bound is tight. 37 <2> ; 38 <2> global STACK_LEN, STACK_TOP, STACK_BASE 39 <2> STACK_LEN equ 4096 40 <2> %if IS_PXELINUX 41 <2> STACK_TOP equ 7000h 42 <2> %else 43 <2> STACK_TOP equ 7c00h 44 <2> %endif 45 <2> STACK_BASE equ STACK_TOP - STACK_LEN 46 <2> 47 <2> ; The secondary BSS section, above the text; we really wish we could 48 <2> ; just make it follow .bcopy32 or hang off the end, 49 <2> ; but it doesn't seem to work that way. 50 <2> LATEBSS_START equ 0B800h 51 <2> 52 <2> ; 53 <2> ; 32-bit stack layout 54 <2> ; 55 <2> STACK32_LEN equ 64*1024 56 <2> 57 <2> section .stack nobits write align=4096 58 00393000 <2> resb STACK32_LEN 59 <2> 60 <2> ; 61 <2> ; The various sections and their relationship 62 <2> ; 63 <2> ; Use .earlybss for things that MUST be in low memory. 64 <2> section .earlybss nobits write 65 <2> section .config write progbits align=4 66 <2> section .replacestub exec write progbits align=16 67 <2> section .gentextnr exec write nobits align=16 68 <2> section .stack16 write nobits align=16 69 <2> 70 <2> ; Use .bss16 for things that doesn't have to be in low memory; 71 <2> ; .earlybss should be used for things that absolutely have 72 <2> ; to be below 0x7c00. 73 <2> section .bss16 write nobits align=16 74 <2> 75 <2> %if 0 ; IS_PXELINUX 76 <2> ; Warning here: RBFG build 22 randomly overwrites 77 <2> ; memory location [0x5680,0x576c), possibly more. It 78 <2> ; seems that it gets confused and screws up the 79 <2> ; pointer to its own internal packet buffer and starts 80 <2> ; writing a received ARP packet into low memory. 81 <2> section .rbfg write nobits 82 <2> RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet... 83 <2> %endif 84 <2> 85 <2> section .init exec write progbits align=1 86 <2> section .text16 exec write progbits align=1 87 <2> section .textnr exec nowrite progbits align=1 88 <2> section .bcopyxx.text exec nowrite progbits align=16 89 <2> section .bcopyxx.data noexec write progbits align=16 90 <2> section .data16 noexec write progbits align=16 91 <2> 92 <2> section .adv write nobits align=512 93 <2> 94 <2> ; .uibss contains bss data which is guaranteed to be 95 <2> ; safe to clobber during the loading of the image. This 96 <2> ; is because while loading the primary image we will clobber 97 <2> ; the spillover from the last fractional sector load. 98 <2> section .uibss write nobits align=16 99 <2> 100 <2> section .savedata write nobits align=16 101 <2> 102 <2> ; Symbols from linker script 103 <2> %macro SECINFO 1 104 <2> extern __%1_start, __%1_end 105 <2> extern __%1_len, __%1_dwords 106 <2> %endmacro 107 <2> 108 <2> SECINFO bss16 108 <3> extern __%1_start, __%1_end 108 <3> extern __%1_len, __%1_dwords 109 <2> SECINFO uibss 109 <3> extern __%1_start, __%1_end 109 <3> extern __%1_len, __%1_dwords 110 <2> SECINFO config 110 <3> extern __%1_start, __%1_end 110 <3> extern __%1_len, __%1_dwords 111 <2> SECINFO replacestub 111 <3> extern __%1_start, __%1_end 111 <3> extern __%1_len, __%1_dwords 112 <2> SECINFO bcopyxx 112 <3> extern __%1_start, __%1_end 112 <3> extern __%1_len, __%1_dwords 113 <2> 114 <2> SECINFO pm_code 114 <3> extern __%1_start, __%1_end 114 <3> extern __%1_len, __%1_dwords 115 <2> SECINFO high_clear 115 <3> extern __%1_start, __%1_end 115 <3> extern __%1_len, __%1_dwords 116 <2> extern __pm_code_lma 117 <2> 118 <2> SECINFO bss 118 <3> extern __%1_start, __%1_end 118 <3> extern __%1_len, __%1_dwords 119 <2> 120 <2> extern free_high_memory 121 <2> 122 <2> global _start 123 <2> 124 <2> section .text16 125 <2> 126 <2> ; 127 <2> ; Segment assignments in the bottom 640K 128 <2> ; Keep the low-memory footprint as small as possible... overrun is a hard 129 <2> ; failure! 130 <2> ; 131 <2> 132 <2> serial_buf_size equ 4096 ; Should be a power of 2 133 <2> 134 <2> ; 135 <2> ; Transfer buffer segment: guaranteed to be aligned 64K, used for disk I/O 136 <2> ; One symbol for the segment number, one for the absolute address 137 <2> ; 138 <2> extern xfer_buf_seg 139 <2> section .xfer_buf write nobits align=65536 140 <2> global core_xfer_buf:data hidden 141 00010000 <2> core_xfer_buf resb 65536 142 <2> 143 <2> ; 144 <2> ; At the very end, the lowmem heap 145 <2> ; 146 <2> extern __lowmem_heap 147 <2> min_lowmem_heap equ 65536 148 <2> 149 <2> section .text16 32 <1> %include "pmcall.inc" 1 <2> ;; 2 <2> ;; pmcall.inc 3 <2> ;; 4 <2> ;; Macros for the stack frame set up by pm_call, assuming ebp is left 5 <2> ;; as the RM frame pointer. 6 <2> ;; 7 <2> 8 <2> %ifndef PMCALL_INC 9 <2> %define PMCALL_INC 10 <2> 11 <2> %define RM_GS word [ebp] 12 <2> %define RM_FS word [ebp+2] 13 <2> %define RM_ES word [ebp+4] 14 <2> %define RM_DS word [ebp+6] 15 <2> 16 <2> %define RM_EDI dword [ebp+8] 17 <2> %define RM_DI word [ebp+8] 18 <2> %define RM_HDI word [ebp+10] 19 <2> %define RM_DIL byte [ebp+8] 20 <2> %define RM_DIH byte [ebp+9] 21 <2> 22 <2> %define RM_ESI dword [ebp+12] 23 <2> %define RM_SI word [ebp+12] 24 <2> %define RM_HSI word [ebp+14] 25 <2> %define RM_SIL byte [ebp+12] 26 <2> %define RM_SIH byte [ebp+13] 27 <2> 28 <2> %define RM_EBP dword [ebp+16] 29 <2> %define RM_BP word [ebp+16] 30 <2> %define RM_HBP word [ebp+18] 31 <2> %define RM_BPL byte [ebp+16] 32 <2> %define RM_BPH byte [ebp+17] 33 <2> 34 <2> %define RM_EBX dword [ebp+24] 35 <2> %define RM_BX word [ebp+24] 36 <2> %define RM_HBX word [ebp+26] 37 <2> %define RM_BL byte [ebp+24] 38 <2> %define RM_BH byte [ebp+25] 39 <2> 40 <2> %define RM_EDX dword [ebp+28] 41 <2> %define RM_DX word [ebp+28] 42 <2> %define RM_HDX word [ebp+30] 43 <2> %define RM_DL byte [ebp+28] 44 <2> %define RM_DH byte [ebp+29] 45 <2> 46 <2> %define RM_ECX dword [ebp+32] 47 <2> %define RM_CX word [ebp+32] 48 <2> %define RM_HCX word [ebp+34] 49 <2> %define RM_CL byte [ebp+32] 50 <2> %define RM_CH byte [ebp+33] 51 <2> 52 <2> %define RM_EAX dword [ebp+36] 53 <2> %define RM_AX word [ebp+36] 54 <2> %define RM_HAX word [ebp+38] 55 <2> %define RM_AL byte [ebp+36] 56 <2> %define RM_AH byte [ebp+37] 57 <2> 58 <2> %define RM_EFLAGS dword [ebp+40] 59 <2> %define RM_FLAGS word [ebp+40] 60 <2> %define RM_HFLAGS word [ebp+42] 61 <2> %define RM_FLAGSL byte [ebp+40] 62 <2> %define RM_FLAGSH byte [ebp+41] 63 <2> 64 <2> ; Convenience macro to call a PM function 65 <2> %macro pm_call 1 66 <2> push dword %1 67 <2> call _pm_call 68 <2> %endmacro 69 <2> 70 <2> %endif ; PMCALL_INC 33 <1> %include "extern.inc" 1 <2> ; 2 <2> ; extern.inc 3 <2> ; 4 <2> ; Prototypes for external functions 5 <2> 6 <2> %ifndef EXTERN_INC 7 <2> %define EXTERN_INC 8 <2> 9 <2> ; rllpack.c 10 <2> extern rllpack, rllunpack 11 <2> 12 <2> ; hello.c 13 <2> extern hello 14 <2> 15 <2> ; elflink/load_env32.c 16 <2> extern load_env32, pm_env32_run 17 <2> 18 <2> extern mp1, mp2, mp3, mp4, mp5 19 <2> 20 <2> extern hexdump 21 <2> 22 <2> extern mem_init 23 <2> 24 <2> ; fs.c 25 <2> extern pm_fs_init 26 <2> extern SectorSize, SectorShift 27 <2> 28 <2> ; chdir.c 29 <2> extern pm_realpath 30 <2> 31 <2> ; readdir.c 32 <2> extern opendir, readdir, closedir 33 <2> 34 <2> ; idle.c 35 <2> extern __idle 36 <2> 37 <2> %ifdef DEBUG 38 <2> ; debug.c 39 <2> extern pm_debug_msg 40 <2> 41 <2> %macro dprint 1+ 42 <2> push ax 43 <2> call %%fwd 44 <2> db %1 45 <2> db 0 46 <2> %%fwd: pop ax 47 <2> pm_call pm_debug_msg 48 <2> pop ax 49 <2> %endmacro 50 <2> %else 51 <2> %macro dprint 1+ 52 <2> %endmacro 53 <2> %endif 54 <2> 55 <2> %if IS_PXELINUX 56 <2> ; pxe.c 57 <2> extern unload_pxe, reset_pxe 58 <2> %endif 59 <2> 60 <2> ; plaincon.c 61 <2> extern pm_writechr 62 <2> 63 <2> ; cleanup.c 64 <2> extern cleanup_hardware 65 <2> 66 <2> ; writestr.c 67 <2> extern pm_writestr, crlf 68 <2> 69 <2> ; writehex.c 70 <2> extern pm_writehex2, pm_writehex4, pm_writehex8 71 <2> 72 <2> ; graphics.c 73 <2> extern syslinux_force_text_mode, vgashowcursor, vgahidecursor, pm_using_vga 74 <2> 75 <2> ; conio.c 76 <2> extern pm_pollchar, pm_write_serial, pm_serialcfg 77 <2> 78 <2> ; font.c 79 <2> extern pm_getchar, pm_adjust_screen, pm_userfont 80 <2> 81 <2> %endif ; EXTERN_INC 34 <1> %include "kernel.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <2> ;; 5 <2> ;; This program is free software; you can redistribute it and/or modify 6 <2> ;; it under the terms of the GNU General Public License as published by 7 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 9 <2> ;; (at your option) any later version; incorporated herein by reference. 10 <2> ;; 11 <2> ;; ----------------------------------------------------------------------- 12 <2> 13 <2> ;; 14 <2> ;; kernel.inc 15 <2> ;; 16 <2> ;; Header file for the kernel interface definitions 17 <2> ;; 18 <2> 19 <2> %ifndef _KERNEL_INC 20 <2> %define _KERNEL_INC 21 <2> 22 <2> ;; 23 <2> ;; Structure of the real_mode_seg 24 <2> ;; 25 <2> 26 <2> struc real_mode_seg_t 27 00000000 <2> resb 20h-($-$$) ; org 20h 28 00000020 <2> kern_cmd_magic resw 1 ; 0020 Magic # for command line 29 00000022 <2> kern_cmd_offset resw 1 ; 0022 Offset for kernel command line 30 00000024 <2> resb 497-($-$$) ; org 497d 31 000001F1 <2> bs_setupsecs resb 1 ; 01F1 Sectors for setup code (0 -> 4) 32 000001F2 <2> bs_rootflags resw 1 ; 01F2 Root readonly flag 33 000001F4 <2> bs_syssize resw 1 ; 01F4 34 000001F6 <2> bs_swapdev resw 1 ; 01F6 Swap device (obsolete) 35 000001F8 <2> bs_ramsize resw 1 ; 01F8 Ramdisk flags, formerly ramdisk size 36 000001FA <2> bs_vidmode resw 1 ; 01FA Video mode 37 000001FC <2> bs_rootdev resw 1 ; 01FC Root device 38 000001FE <2> bs_bootsign resw 1 ; 01FE Boot sector signature (0AA55h) 39 00000200 <2> su_jump resb 1 ; 0200 0EBh 40 00000201 <2> su_jump2 resb 1 ; 0201 Size of following header 41 00000202 <2> su_header resd 1 ; 0202 New setup code: header 42 00000206 <2> su_version resw 1 ; 0206 See linux/arch/i386/boot/setup.S 43 00000208 <2> su_switch resw 1 ; 0208 44 0000020A <2> su_setupseg resw 1 ; 020A 45 0000020C <2> su_startsys resw 1 ; 020C 46 0000020E <2> su_kver resw 1 ; 020E Kernel version pointer 47 00000210 <2> su_loader resb 1 ; 0210 Loader ID 48 00000211 <2> su_loadflags resb 1 ; 0211 Load high flag 49 00000212 <2> su_movesize resw 1 ; 0212 50 00000214 <2> su_code32start resd 1 ; 0214 Start of code loaded high 51 00000218 <2> su_ramdiskat resd 1 ; 0218 Start of initial ramdisk 52 0000021C <2> su_ramdisklen resd 1 ; 021C Length of initial ramdisk 53 00000220 <2> su_bsklugeoffs resw 1 ; 0220 54 00000222 <2> su_bsklugeseg resw 1 ; 0222 55 00000224 <2> su_heapend resw 1 ; 0224 56 00000226 <2> su_pad1 resw 1 ; 0226 57 00000228 <2> su_cmd_line_ptr resd 1 ; 0228 58 0000022C <2> su_ramdisk_max resd 1 ; 022C 59 00000230 <2> resb (0f800h-12)-($-$$) 60 <2> linux_stack equ $ ; F7F4 61 0000F7F4 <2> linux_fdctab resb 12 62 <2> cmd_line_here equ $ ; F800 Should be out of the way 63 <2> endstruc 64 <2> 65 <2> ; 66 <2> ; Old kernel command line signature 67 <2> ; 68 <2> CMD_MAGIC equ 0A33Fh ; Command line magic 69 <2> 70 <2> ; 71 <2> ; If we're loading the command line old-style, we need a smaller 72 <2> ; heap. 73 <2> ; 74 <2> old_cmd_line_here equ 9800h 75 <2> old_max_cmd_len equ 2047 76 <2> old_linux_fdctab equ old_cmd_line_here-12 77 <2> old_linux_stack equ old_linux_fdctab 78 <2> 79 <2> ; 80 <2> ; Magic number of su_header field 81 <2> ; 82 <2> HEADER_ID equ 'HdrS' ; HdrS (in littleendian hex) 83 <2> 84 <2> ; 85 <2> ; Flags for the su_loadflags field 86 <2> ; 87 <2> LOAD_HIGH equ 01h ; Large kernel, load high 88 <2> QUIET_FLAG equ 20h ; Quiet the kernel 89 <2> KEEP_SEGMENTS equ 40h ; Don't reload segments 90 <2> CAN_USE_HEAP equ 80h ; Boot loader reports heap size 91 <2> 92 <2> ; 93 <2> ; ID codes for various modules 94 <2> ; 95 <2> syslinux_id equ 031h ; 3 = SYSLINUX family; 1 = SYSLINUX 96 <2> pxelinux_id equ 032h ; 3 = SYSLINUX family; 2 = PXELINUX 97 <2> isolinux_id equ 033h ; 3 = SYSLINUX family; 3 = ISOLINUX 98 <2> extlinux_id equ 034h ; 3 = SYSLINUX family; 4 = EXTLINUX 99 <2> 100 <2> ; 101 <2> ; Types of vkernels 102 <2> ; 103 <2> VK_LOCALBOOT equ -1 ; localboot (no actual kernel loaded) 104 <2> VK_KERNEL equ 0 ; Choose by filename 105 <2> VK_LINUX equ 1 ; Linux kernel image 106 <2> VK_BOOT equ 2 ; Boot sector 107 <2> VK_BSS equ 3 ; BSS boot sector 108 <2> VK_PXE equ 4 ; PXE NBP 109 <2> VK_FDIMAGE equ 5 ; Floppy disk image 110 <2> VK_COMBOOT equ 6 ; COMBOOT image 111 <2> VK_COM32 equ 7 ; COM32 image 112 <2> VK_CONFIG equ 8 ; Configuration file 113 <2> VK_TYPES equ 9 ; Number of VK types 114 <2> 115 <2> %endif ; _KERNEL_INC 35 <1> %include "bios.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <2> ;; 5 <2> ;; This program is free software; you can redistribute it and/or modify 6 <2> ;; it under the terms of the GNU General Public License as published by 7 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 9 <2> ;; (at your option) any later version; incorporated herein by reference. 10 <2> ;; 11 <2> ;; ----------------------------------------------------------------------- 12 <2> 13 <2> ;; 14 <2> ;; bios.inc 15 <2> ;; 16 <2> ;; Header file for the BIOS data structures etc. 17 <2> ;; 18 <2> 19 <2> %ifndef _BIOS_INC 20 <2> %define _BIOS_INC 21 <2> 22 <2> ; Interrupt vectors 23 <2> absolute 4*1Ch 24 00000070 <2> BIOS_timer_hook resd 1 25 <2> 26 <2> absolute 4*1Eh 27 <2> fdctab equ $ 28 00000078 <2> fdctab1 resw 1 29 0000007A <2> fdctab2 resw 1 30 <2> 31 <2> absolute 0400h 32 00000400 <2> serial_base resw 4 ; Base addresses for 4 serial ports 33 <2> absolute 0413h 34 00000413 <2> BIOS_fbm resw 1 ; Free Base Memory (kilobytes) 35 <2> absolute 0462h 36 00000462 <2> BIOS_page resb 1 ; Current video page 37 <2> absolute 046Ch 38 0000046C <2> BIOS_timer resw 1 ; Timer ticks 39 <2> absolute 0472h 40 00000472 <2> BIOS_magic resw 1 ; BIOS reset magic 41 <2> absolute 0484h 42 00000484 <2> BIOS_vidrows resb 1 ; Number of screen rows 43 <2> 44 <2> %endif ; _BIOS_INC 36 <1> %include "tracers.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <2> ;; 5 <2> ;; This program is free software; you can redistribute it and/or modify 6 <2> ;; it under the terms of the GNU General Public License as published by 7 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 9 <2> ;; (at your option) any later version; incorporated herein by reference. 10 <2> ;; 11 <2> ;; ----------------------------------------------------------------------- 12 <2> 13 <2> ;; 14 <2> ;; tracers.inc 15 <2> ;; 16 <2> ;; Debugging tracers 17 <2> ;; 18 <2> 19 <2> %ifndef _TRACERS_INC 20 <2> %define _TRACERS_INC 21 <2> 22 <2> ; Note: The Makefile builds one version with DEBUG_MESSAGES automatically. 23 <2> ; %define DEBUG_TRACERS 1 ; Uncomment to get debugging tracers 24 <2> ; %define DEBUG_MESSAGES ; Uncomment to get debugging messages 25 <2> 26 <2> %ifdef DEBUG_TRACERS 27 <2> 28 <2> %macro TRACER 1 29 <2> call debug_tracer 30 <2> db %1 31 <2> %endmacro 32 <2> 33 <2> %else ; DEBUG_TRACERS 34 <2> 35 <2> %macro TRACER 1 36 <2> %endmacro 37 <2> 38 <2> %endif ; DEBUG_TRACERS 39 <2> 40 <2> %endif ; _TRACERS_INC 37 <1> %include "stack.inc" 1 <2> ; ----------------------------------------------------------------------- 2 <2> ; 3 <2> ; Copyright 2005-2008 H. Peter Anvin - All Rights Reserved 4 <2> ; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin 5 <2> ; 6 <2> ; This program is free software; you can redistribute it and/or modify 7 <2> ; it under the terms of the GNU General Public License as published by 8 <2> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <2> ; (at your option) any later version; incorporated herein by reference. 11 <2> ; 12 <2> ; ----------------------------------------------------------------------- 13 <2> 14 <2> ; 15 <2> ; stack.inc 16 <2> ; 17 <2> ; How to reset the stack pointer 18 <2> ; 19 <2> 20 <2> %ifndef _STACK_INC 21 <2> %define _STACK_INC 22 <2> 23 <2> ; 24 <2> ; This macro resets the stack pointer (including SS), and sets 25 <2> ; DS == ES == 0, interrupts on, DF = 0. 26 <2> ; 27 <2> ; It takes a 16-bit register that can be safely clobbered as parameter. 28 <2> ; 29 <2> %macro RESET_STACK_AND_SEGS 1 30 <2> xor %1,%1 31 <2> mov ds,%1 32 <2> mov es,%1 33 <2> lss esp,[BaseStack] 34 <2> mov dword [PMESP],__stack_end ; Reset PM stack 35 <2> sti 36 <2> cld 37 <2> %endmacro 38 <2> 39 <2> section .data16 40 <2> alignz 4 41 <2> global BaseStack:data hidden 42 00008920 D46F0000 <2> BaseStack dd StackHome ; ESP of the "home" stack pointer 43 00008924 0000 <2> dw 0 ; SS of the "home" stack pointer 44 <2> 45 <2> section .text16 46 <2> 47 <2> %endif ; _STACK_INC 38 <1> %include "io.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <2> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 <2> ;; 6 <2> ;; This program is free software; you can redistribute it and/or modify 7 <2> ;; it under the terms of the GNU General Public License as published by 8 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <2> ;; (at your option) any later version; incorporated herein by reference. 11 <2> ;; 12 <2> ;; ----------------------------------------------------------------------- 13 <2> 14 <2> ;; 15 <2> ;; io.inc 16 <2> ;; 17 <2> ;; I/O related macros 18 <2> ;; 19 <2> 20 <2> %ifndef _IO_INC 21 <2> %define _IO_INC 22 <2> 23 <2> %define IO_DELAY_PORT 80h ; Invalid port (we hope!) 24 <2> 25 <2> %macro io_delay 0.nolist 26 <2> out IO_DELAY_PORT,al 27 <2> out IO_DELAY_PORT,al 28 <2> %endmacro 29 <2> 30 <2> %macro slow_out 2.nolist 31 <2> out %1,%2 32 <2> io_delay 33 <2> %endmacro 34 <2> 35 <2> %endif ; _IO_INC 39 <1> 40 <1> %endif ; _HEAD_INC 23 %include "pxe.inc" 1 <1> ;; ----------------------------------------------------------------------- 2 <1> ;; 3 <1> ;; Copyright 1999-2008 H. Peter Anvin - All Rights Reserved 4 <1> ;; 5 <1> ;; This program is free software; you can redistribute it and/or modify 6 <1> ;; it under the terms of the GNU General Public License as published by 7 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 9 <1> ;; (at your option) any later version; incorporated herein by reference. 10 <1> ;; 11 <1> ;; ----------------------------------------------------------------------- 12 <1> 13 <1> ;; 14 <1> ;; pxe.inc 15 <1> ;; 16 <1> ;; PXE opcodes 17 <1> ;; 18 <1> 19 <1> %ifndef _PXE_INC 20 <1> %define _PXE_INC 1 21 <1> 22 <1> %define PXENV_TFTP_OPEN 0x0020 23 <1> %define PXENV_TFTP_CLOSE 0x0021 24 <1> %define PXENV_TFTP_READ 0x0022 25 <1> %define PXENV_TFTP_READ_FILE 0x0023 26 <1> %define PXENV_TFTP_READ_FILE_PMODE 0x0024 27 <1> %define PXENV_TFTP_GET_FSIZE 0x0025 28 <1> 29 <1> %define PXENV_UDP_OPEN 0x0030 30 <1> %define PXENV_UDP_CLOSE 0x0031 31 <1> %define PXENV_UDP_READ 0x0032 32 <1> %define PXENV_UDP_WRITE 0x0033 33 <1> 34 <1> %define PXENV_START_UNDI 0x0000 35 <1> %define PXENV_UNDI_STARTUP 0x0001 36 <1> %define PXENV_UNDI_CLEANUP 0x0002 37 <1> %define PXENV_UNDI_INITIALIZE 0x0003 38 <1> %define PXENV_UNDI_RESET_NIC 0x0004 39 <1> %define PXENV_UNDI_SHUTDOWN 0x0005 40 <1> %define PXENV_UNDI_OPEN 0x0006 41 <1> %define PXENV_UNDI_CLOSE 0x0007 42 <1> %define PXENV_UNDI_TRANSMIT 0x0008 43 <1> %define PXENV_UNDI_SET_MCAST_ADDR 0x0009 44 <1> %define PXENV_UNDI_SET_STATION_ADDR 0x000A 45 <1> %define PXENV_UNDI_SET_PACKET_FILTER 0x000B 46 <1> %define PXENV_UNDI_GET_INFORMATION 0x000C 47 <1> %define PXENV_UNDI_GET_STATISTICS 0x000D 48 <1> %define PXENV_UNDI_CLEAR_STATISTICS 0x000E 49 <1> %define PXENV_UNDI_INITIATE_DIAGS 0x000F 50 <1> %define PXENV_UNDI_FORCE_INTERRUPT 0x0010 51 <1> %define PXENV_UNDI_GET_MCAST_ADDR 0x0011 52 <1> %define PXENV_UNDI_GET_NIC_TYPE 0x0012 53 <1> %define PXENV_UNDI_GET_IFACE_INFO 0x0013 54 <1> %define PXENV_UNDI_ISR 0x0014 55 <1> %define PXENV_STOP_UNDI 0x0015 ; Overlap...? 56 <1> %define PXENV_UNDI_GET_STATE 0x0015 ; Overlap...? 57 <1> 58 <1> %define PXENV_UNLOAD_STACK 0x0070 59 <1> %define PXENV_GET_CACHED_INFO 0x0071 60 <1> %define PXENV_RESTART_DHCP 0x0072 61 <1> %define PXENV_RESTART_TFTP 0x0073 62 <1> %define PXENV_MODE_SWITCH 0x0074 63 <1> %define PXENV_START_BASE 0x0075 64 <1> %define PXENV_STOP_BASE 0x0076 65 <1> 66 <1> ; gPXE extensions... 67 <1> %define PXENV_FILE_OPEN 0x00e0 68 <1> %define PXENV_FILE_CLOSE 0x00e1 69 <1> %define PXENV_FILE_SELECT 0x00e2 70 <1> %define PXENV_FILE_READ 0x00e3 71 <1> %define PXENV_GET_FILE_SIZE 0x00e4 72 <1> %define PXENV_FILE_EXEC 0x00e5 73 <1> %define PXENV_FILE_API_CHECK 0x00e6 74 <1> %define PXENV_FILE_EXIT_HOOK 0x00e7 75 <1> 76 <1> ; Exit codes 77 <1> %define PXENV_EXIT_SUCCESS 0x0000 78 <1> %define PXENV_EXIT_FAILURE 0x0001 79 <1> 80 <1> ; Status codes 81 <1> %define PXENV_STATUS_SUCCESS 0x00 82 <1> %define PXENV_STATUS_FAILURE 0x01 83 <1> %define PXENV_STATUS_BAD_FUNC 0x02 84 <1> %define PXENV_STATUS_UNSUPPORTED 0x03 85 <1> %define PXENV_STATUS_KEEP_UNDI 0x04 86 <1> %define PXENV_STATUS_KEEP_ALL 0x05 87 <1> %define PXENV_STATUS_OUT_OF_RESOURCES 0x06 88 <1> %define PXENV_STATUS_ARP_TIMEOUT 0x11 89 <1> %define PXENV_STATUS_UDP_CLOSED 0x18 90 <1> %define PXENV_STATUS_UDP_OPEN 0x19 91 <1> %define PXENV_STATUS_TFTP_CLOSED 0x1a 92 <1> %define PXENV_STATUS_TFTP_OPEN 0x1b 93 <1> %define PXENV_STATUS_MCOPY_PROBLEM 0x20 94 <1> %define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21 95 <1> %define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22 96 <1> %define PXENV_STATUS_BIS_INIT_FAILURE 0x23 97 <1> %define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24 98 <1> %define PXENV_STATUS_BIS_GBOA_FAILURE 0x25 99 <1> %define PXENV_STATUS_BIS_FREE_FAILURE 0x26 100 <1> %define PXENV_STATUS_BIS_GSI_FAILURE 0x27 101 <1> %define PXENV_STATUS_BIS_BAD_CKSUM 0x28 102 <1> %define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30 103 <1> %define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32 104 <1> 105 <1> %define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33 106 <1> %define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35 107 <1> %define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36 108 <1> %define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38 109 <1> %define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39 110 <1> %define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3a 111 <1> %define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3b 112 <1> %define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3c 113 <1> %define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3d 114 <1> %define PXENV_STATUS_TFTP_NO_FILESIZE 0x3e 115 <1> %define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3f 116 <1> %define PXENV_STATUS_DHCP_TIMEOUT 0x51 117 <1> %define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52 118 <1> %define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53 119 <1> %define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54 120 <1> %define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 121 <1> %define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 122 <1> %define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62 123 <1> %define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63 124 <1> %define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64 125 <1> %define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65 126 <1> %define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66 127 <1> %define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67 128 <1> %define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68 129 <1> %define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 130 <1> %define PXENV_STATUS_UNDI_INVALID_STATE 0x6a 131 <1> %define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6b 132 <1> %define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6c 133 <1> %define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74 134 <1> %define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76 135 <1> %define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77 136 <1> %define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78 137 <1> %define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79 138 <1> %define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xa0 139 <1> %define PXENV_STATUS_BINL_NO_PXE_SERVER 0xa1 140 <1> %define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xa2 141 <1> %define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xa3 142 <1> %define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xb0 143 <1> %define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xc0 144 <1> %define PXENV_STATUS_LOADER_NO_BC_ROMID 0xc1 145 <1> %define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xc2 146 <1> %define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xc3 147 <1> %define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xc4 148 <1> %define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xc5 149 <1> %define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xc6 150 <1> %define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xc8 151 <1> %define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xc9 152 <1> %define PXENV_STATUS_LOADER_UNDI_START 0xca 153 <1> %define PXENV_STATUS_LOADER_BC_START 0xcb 154 <1> 155 <1> ; UNDI ISR codes 156 <1> %define PXENV_UNDI_ISR_IN_START 1 157 <1> %define PXENV_UNDI_ISR_IN_PROCESS 2 158 <1> %define PXENV_UNDI_ISR_IN_GET_NEXT 3 159 <1> 160 <1> %define PXENV_UNDI_ISR_OUT_OURS 0 161 <1> %define PXENV_UNDI_ISR_OUT_NOT_OURS 1 162 <1> 163 <1> %endif ; _PXE_INC 24 25 ; gPXE extensions support 26 %define GPXE 1 27 28 ; 29 ; Some semi-configurable constants... change on your own risk. 30 ; 31 my_id equ pxelinux_id 32 NULLFILE equ 0 ; Zero byte == null file name 33 NULLOFFSET equ 0 ; Position in which to look 34 REBOOT_TIME equ 5*60 ; If failure, time until full reset 35 %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top 36 TFTP_BLOCKSIZE_LG2 equ 9 ; log2(bytes/block) 37 TFTP_BLOCKSIZE equ (1 << TFTP_BLOCKSIZE_LG2) 38 39 SECTOR_SHIFT equ TFTP_BLOCKSIZE_LG2 40 SECTOR_SIZE equ TFTP_BLOCKSIZE 41 42 ; --------------------------------------------------------------------------- 43 ; BEGIN CODE 44 ; --------------------------------------------------------------------------- 45 46 ; 47 ; Memory below this point is reserved for the BIOS and the MBR 48 ; 49 section .earlybss 50 global trackbuf 51 trackbufsize equ 8192 52 00001000 trackbuf resb trackbufsize ; Track buffer goes here 53 ; ends at 2800h 54 55 ; These fields save information from before the time 56 ; .bss is zeroed... must be in .earlybss 57 global InitStack 58 00003000 InitStack resd 1 59 60 section .bss16 61 alignb FILENAME_MAX 62 00003810 PXEStack resd 1 ; Saved stack during PXE call 63 64 alignb 4 65 global DHCPMagic, RebootTime, BIOSName 66 00003814 RebootTime resd 1 ; Reboot timeout, if set by option 67 00003818 LocalBootType resw 1 ; Local boot return code 68 0000381A DHCPMagic resb 1 ; PXELINUX magic flags 69 0000381B BIOSName resw 1 ; Dummy variable - always 0 70 71 section .text16 72 global StackBuf 73 StackBuf equ STACK_TOP-44 ; Base of stack if we use our own 74 StackHome equ StackBuf 75 76 ; PXE loads the whole file, but assume it can't be more 77 ; than (384-31)K in size. 78 MaxLMA equ 384*1024 79 80 ; 81 ; Primary entry point. 82 ; 83 bootsec equ $ 84 _start: 85 00007C00 EA[2400]0000 jmp 0:_start1 ; Canonicalize the address and skip 86 ; the patch header 87 88 ; 89 ; Patch area for adding hardwired DHCP options 90 ; 91 00007C05 90 align 4 92 93 00007C08 ACC88329 hcdhcp_magic dd 0x2983c8ac ; Magic number 94 00007C0C 1C000000 hcdhcp_len dd 7*4 ; Size of this structure 95 00007C10 00000000 hcdhcp_flags dd 0 ; Reserved for the future 96 global bdhcp_len, adhcp_len 97 ; Parameters to be parsed before the ones from PXE 98 00007C14 00000000 bdhcp_offset dd 0 ; Offset (entered by patcher) 99 00007C18 00000000 bdhcp_len dd 0 ; Length (entered by patcher) 100 ; Parameters to be parsed *after* the ones from PXE 101 00007C1C 00000000 adhcp_offset dd 0 ; Offset (entered by patcher) 102 00007C20 00000000 adhcp_len dd 0 ; Length (entered by patcher) 103 104 _start1: 105 00007C24 669C pushfd ; Paranoia... in case of return to PXE 106 00007C26 6660 pushad ; ... save as much state as possible 107 00007C28 1E push ds 108 00007C29 06 push es 109 00007C2A 0FA0 push fs 110 00007C2C 0FA8 push gs 111 112 00007C2E FC cld ; Copy upwards 113 00007C2F 31C0 xor ax,ax 114 00007C31 8ED8 mov ds,ax 115 00007C33 8EC0 mov es,ax 116 117 %if 0 ; debugging code only... not intended for production use 118 ; Clobber the stack segment, to test for specific pathologies 119 mov di,STACK_BASE 120 mov cx,STACK_LEN >> 1 121 mov ax,0xf4f4 122 rep stosw 123 124 ; Clobber the tail of the 64K segment, too 125 extern __bss1_end 126 mov di,__bss1_end 127 sub cx,di ; CX = 0 previously 128 shr cx,1 129 rep stosw 130 %endif 131 132 ; That is all pushed onto the PXE stack. Save the pointer 133 ; to it and switch to an internal stack. 134 00007C35 8926[0020] mov [InitStack],sp 135 00007C39 8C16[0220] mov [InitStack+2],ss 136 137 00007C3D 660FB226[0000] lss esp,[BaseStack] 138 00007C43 FB sti ; Stack set up and ready 139 140 ; 141 ; Initialize screen (if we're using one) 142 ; 143 %include "init.inc" 1 <1> ; -*- fundamental -*- 2 <1> ; ----------------------------------------------------------------------- 3 <1> ; 4 <1> ; Copyright 2004-2008 H. Peter Anvin - All Rights Reserved 5 <1> ; Copyright 2009 Intel Corporation; author: H. Peter Anvin 6 <1> ; 7 <1> ; This program is free software; you can redistribute it and/or modify 8 <1> ; it under the terms of the GNU General Public License as published by 9 <1> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 10 <1> ; Boston MA 02111-1307, USA; either version 2 of the License, or 11 <1> ; (at your option) any later version; incorporated herein by reference. 12 <1> ; 13 <1> ; ----------------------------------------------------------------------- 14 <1> 15 <1> ; 16 <1> ; init.inc 17 <1> ; 18 <1> ; Common initialization code (inline) 19 <1> ; 20 <1> 21 <1> section .text16 22 <1> common_init: 23 <1> ; Initialize PM invocation framework 24 00007C44 E84C04 <1> call pm_init 25 <1> 26 <1> %if IS_PXELINUX 27 <1> ; Save derivative-specific data 28 <1> pm_call pm_save_data 28 00007C47 6668[48000000] <2> push dword %1 28 00007C4D E8C002 <2> call _pm_call 29 <1> %endif 30 <1> 31 <1> ; Decompress PM code to its target location 32 <1> pm_call pm_decompress 32 00007C50 6668[00000000] <2> push dword %1 32 00007C56 E8B702 <2> call _pm_call 33 00007C59 663D[00000000] <1> cmp eax,__pm_code_len 34 00007C5F 7573 <1> jne kaboom 35 <1> 36 <1> extern syslinux_register_bios, init 37 <1> 38 <1> pm_call syslinux_register_bios 38 00007C61 6668[00000000] <2> push dword %1 38 00007C67 E8A602 <2> call _pm_call 39 <1> pm_call init 39 00007C6A 6668[00000000] <2> push dword %1 39 00007C70 E89D02 <2> call _pm_call 40 <1> 41 <1> ; 42 <1> ; The code to decompress the PM code and initialize other segments. 43 <1> ; 44 <1> extern _lzo1x_decompress_asm_fast_safe 45 <1> 46 <1> section .textnr 47 <1> bits 32 48 <1> pm_decompress: 49 000083D0 68[10000000] <1> push __pm_code_len + 16 ; Space for decompressed size 50 000083D5 54 <1> push esp ; Pointer to previous word 51 000083D6 68[00000000] <1> push __pm_code_start ; Target address 52 000083DB FF35[06000000] <1> push dword [lzo_data_size] ; Compressed size 53 000083E1 68[00000000] <1> push dword __pm_code_lma 54 000083E6 E8(00000000) <1> call _lzo1x_decompress_asm_fast_safe 55 000083EB 83C410 <1> add esp,16 56 000083EE 8F4524 <1> pop RM_EAX ; Decompressed size 57 <1> 58 <1> ; Zero bss sections (but not .earlybss, since it may 59 <1> ; contain already-live data.) 60 000083F1 31C0 <1> xor eax,eax 61 000083F3 BF[00000000] <1> mov edi,__bss_start 62 000083F8 B9[00000000] <1> mov ecx,__bss_dwords 63 000083FD F3AB <1> rep stosd 64 000083FF BF[00000000] <1> mov edi,__bss16_start 65 00008404 B9[00000000] <1> mov ecx,__bss16_dwords 66 00008409 F3AB <1> rep stosd 67 0000840B BF[00000000] <1> mov edi,__high_clear_start ; .uibss, .lowmem 68 00008410 B9[00000000] <1> mov ecx,__high_clear_dwords 69 00008415 F3AB <1> rep stosd 70 <1> 71 00008417 C3 <1> ret 72 <1> 73 <1> section .data16 74 00008926 00000000 <1> lzo_data_size dd 0 ; filled in by compressor 75 <1> 76 <1> section .text16 77 <1> bits 16 144 145 ; 146 ; Tell the user we got this far 147 ; 148 00007C73 BE[1E01] mov si,syslinux_banner 149 00007C76 E8A901 call writestr_early 150 151 00007C79 BE[9600] mov si,copyright_str 152 00007C7C E8A301 call writestr_early 153 154 ; 155 ; do fs initialize 156 ; 157 00007C7F 66B8[00000000] mov eax,ROOT_FS_OPS 158 00007C85 6631ED xor ebp,ebp 159 pm_call pm_fs_init 159 00007C88 6668[00000000] <1> push dword %1 159 00007C8E E87F02 <1> call _pm_call 160 161 section .rodata 162 alignz 4 163 ROOT_FS_OPS: 164 extern pxe_fs_ops 165 00116A40 [00000000] dd pxe_fs_ops 166 00116A44 00000000 dd 0 167 168 169 section .text16 170 ; 171 ; Initialize the idle mechanism 172 ; 173 extern reset_idle 174 pm_call reset_idle 174 00007C91 6668[00000000] <1> push dword %1 174 00007C97 E87602 <1> call _pm_call 175 176 ; 177 ; Now we're all set to start with our *real* business. 178 ; 179 ; In previous versions I avoided using 32-bit registers because of a 180 ; rumour some BIOSes clobbered the upper half of 32-bit registers at 181 ; random. I figure, though, that if there are any of those still left 182 ; they probably won't be trying to install Linux on them... 183 ; 184 ; The code is still ripe with 16-bitisms, though. Not worth the hassle 185 ; to take'm out. In fact, we may want to put them back if we're going 186 ; to boot ELKS at some point. 187 ; 188 189 ; 190 ; Linux kernel loading code is common. However, we need to define 191 ; a couple of helper macros... 192 ; 193 194 ; Unload PXE stack 195 %define HAVE_UNLOAD_PREP 196 %macro UNLOAD_PREP 0 197 pm_call unload_pxe 198 %endmacro 199 200 ; 201 ; Jump to 32-bit ELF space 202 ; 203 pm_call load_env32 203 00007C9A 6668[00000000] <1> push dword %1 203 00007CA0 E86D02 <1> call _pm_call 204 00007CA3 EB2F jmp kaboom ; load_env32() shouldn't return. If it does, then kaboom! 205 206 print_hello: 207 enter_command: 208 auto_boot: 209 pm_call hello 209 00007CA5 6668[00000000] <1> push dword %1 209 00007CAB E86202 <1> call _pm_call 210 211 ; 212 ; Save hardwired DHCP options. This is done before the C environment 213 ; is initialized, so it has to be done in assembly. 214 ; 215 %define MAX_DHCP_OPTS 4096 216 bits 32 217 218 section .savedata 219 global bdhcp_data, adhcp_data 220 00390610 bdhcp_data: resb MAX_DHCP_OPTS 221 00391610 adhcp_data: resb MAX_DHCP_OPTS 222 223 section .textnr 224 pm_save_data: 225 00008418 B800100000 mov eax,MAX_DHCP_OPTS 226 0000841D 0FB70D[18000000] movzx ecx,word [bdhcp_len] 227 00008424 39C1 cmp ecx,eax 228 00008426 7608 jna .oksize 229 00008428 89C1 mov ecx,eax 230 0000842A 66A3[18000000] mov [bdhcp_len],ax 231 .oksize: 232 00008430 8B35[14000000] mov esi,[bdhcp_offset] 233 00008436 81C6[00000000] add esi,_start 234 0000843C BF[00000000] mov edi,bdhcp_data 235 00008441 83C103 add ecx,3 236 00008444 C1E902 shr ecx,2 237 00008447 F3A5 rep movsd 238 239 adhcp_copy: 240 00008449 0FB70D[20000000] movzx ecx,word [adhcp_len] 241 00008450 39C1 cmp ecx,eax 242 00008452 7608 jna .oksize 243 00008454 89C1 mov ecx,eax 244 00008456 66A3[20000000] mov [adhcp_len],ax 245 .oksize: 246 0000845C 8B35[1C000000] mov esi,[adhcp_offset] 247 00008462 81C6[00000000] add esi,_start 248 00008468 BF[00100000] mov edi,adhcp_data 249 0000846D 83C103 add ecx,3 250 00008470 C1E902 shr ecx,2 251 00008473 F3A5 rep movsd 252 00008475 C3 ret 253 254 bits 16 255 256 ; As core/ui.inc used to be included here in core/pxelinux.asm, and it's no 257 ; longer used, its global variables that were previously used by 258 ; core/pxelinux.asm are now declared here. 259 section .bss16 260 0000381D alignb 4 261 00003820 Kernel_EAX resd 1 262 00003824 Kernel_SI resw 1 263 264 section .bss16 265 00003826 alignb 4 266 00003828 ThisKbdTo resd 1 ; Temporary holder for KbdTimeout 267 0000382C ThisTotalTo resd 1 ; Temporary holder for TotalTimeout 268 00003830 KernelExtPtr resw 1 ; During search, final null pointer 269 00003832 FuncFlag resb 1 ; Escape sequences received from keyboard 270 00003833 KernelType resb 1 ; Kernel type, from vkernel, if known 271 global KernelName 272 00003834 KernelName resb FILENAME_MAX ; Mangled name for kernel 273 274 section .text16 275 ; 276 ; COM32 vestigial data structure 277 ; 278 %include "com32.inc" 1 <1> ;; ----------------------------------------------------------------------- 2 <1> ;; 3 <1> ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <1> ;; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin 5 <1> ;; 6 <1> ;; This program is free software; you can redistribute it and/or modify 7 <1> ;; it under the terms of the GNU General Public License as published by 8 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <1> ;; (at your option) any later version; incorporated herein by reference. 11 <1> ;; 12 <1> ;; ----------------------------------------------------------------------- 13 <1> 14 <1> ;; 15 <1> ;; com32.inc 16 <1> ;; 17 <1> ;; Common code for running a COM32 image 18 <1> ;; 19 <1> 20 <1> extern pm_api_vector 21 <1> 22 <1> ; 23 <1> ; Load a COM32 image. A COM32 image is the 32-bit analogue to a DOS 24 <1> ; .com file. A COM32 image is loaded at address 0x101000, with %esp 25 <1> ; set to the high end of usable memory. 26 <1> ; 27 <1> ; A COM32 image should begin with the magic bytes: 28 <1> ; B8 FF 4C CD 21, which is "mov eax,0x21cd4cff" in 32-bit mode and 29 <1> ; "mov ax,0x4cff; int 0x21" in 16-bit mode. This will abort the 30 <1> ; program with an error if run in 16-bit mode. 31 <1> ; 32 <1> bits 16 33 <1> section .data16 34 <1> 35 <1> ; Ersatz com32 invocation structure, to make libcom32 36 <1> ; code run the same if linked to the core. This is in 37 <1> ; the .data16 segment so HighMemSize can live here. 38 <1> ; 39 <1> ; Danger, Will Robinson: it's not clear the use of 40 <1> ; core_xfer_buf is safe here. 41 <1> global __com32:data hidden 42 0000892A 00 <1> alignz 4 43 <1> __entry_esp: 44 0000892C 00000000 <1> dd 0 ; Dummy to avoid _exit issues 45 <1> __com32: 46 00008930 09000000 <1> dd 9 ; Argument count 47 00008934 00000000 <1> dd 0 ; No command line 48 00008938 [06000000] <1> dd core_intcall ; Intcall entry point 49 0000893C 00000000 <1> dd 0 ; Bounce buffer address 50 00008940 00000000 <1> dd 0 ; 64K bounce buffer 51 00008944 [00000000] <1> dd core_farcall ; Farcall entry point 52 00008948 [A6000000] <1> dd core_cfarcall ; Cfarcall entry point 53 0000894C 00000000 <1> HighMemSize dd 0 ; End of memory pointer (bytes) 54 00008950 00000000 <1> dd 0 ; No module name 55 00008954 [00000000] <1> dd pm_api_vector ; Protected mode functions 56 <1> 57 <1> section .uibss 58 00009000 <1> Com32Name resb FILENAME_MAX 59 <1> 60 <1> section .bss16 61 <1> %ifndef HAVE_CURRENTDIRNAME 62 <1> global CurrentDirName:data hidden 63 00003934 <1> CurrentDirName resb FILENAME_MAX 64 <1> %endif 65 <1> 66 <1> section .text16 279 280 section .text16 281 global local_boot16:function hidden 282 local_boot16: 283 00007CAE A3[0800] mov [LocalBootType],ax 284 00007CB1 0FB226[0020] lss sp,[InitStack] 285 00007CB6 0FA9 pop gs 286 00007CB8 0FA1 pop fs 287 00007CBA 07 pop es 288 00007CBB 1F pop ds 289 00007CBC 6661 popad 290 00007CBE 2EA1[0800] mov ax,[cs:LocalBootType] 291 00007CC2 83F8FF cmp ax,-1 ; localboot -1 == INT 18h 292 00007CC5 7403 je .int18 293 00007CC7 669D popfd 294 00007CC9 CB retf ; Return to PXE 295 .int18: 296 00007CCA 669D popfd 297 00007CCC CD18 int 18h 298 00007CCE EAF0FF00F0 jmp 0F000h:0FFF0h 299 00007CD3 F4 hlt 300 301 ; 302 ; kaboom: write a message and bail out. Wait for quite a while, 303 ; or a user keypress, then do a hard reboot. 304 ; 305 ; Note: use BIOS_timer here; we may not have jiffies set up. 306 ; 307 global kaboom 308 kaboom: 309 RESET_STACK_AND_SEGS AX 309 00007CD4 31C0 <1> xor %1,%1 309 00007CD6 8ED8 <1> mov ds,%1 309 00007CD8 8EC0 <1> mov es,%1 309 00007CDA 660FB226[0000] <1> lss esp,[BaseStack] 309 00007CE0 66C706[4400]- <1> mov dword [PMESP],__stack_end 309 00007CE5 [00000000] <1> 309 00007CE9 FB <1> sti 309 00007CEA FC <1> cld 310 00007CEB BE[C500] .patch: mov si,bailmsg 311 00007CEE E83101 call writestr_early ; Returns with AL = 0 312 00007CF1 E83801 .drain: call pollchar 313 00007CF4 7405 jz .drained 314 00007CF6 E83D01 call getchar 315 00007CF9 EBF6 jmp short .drain 316 .drained: 317 00007CFB 668B3E[0400] mov edi,[RebootTime] 318 00007D00 A0[0A00] mov al,[DHCPMagic] 319 00007D03 2409 and al,09h ; Magic+Timeout 320 00007D05 3C09 cmp al,09h 321 00007D07 7406 je .time_set 322 00007D09 66BF2C010000 mov edi,REBOOT_TIME 323 .time_set: 324 00007D0F B91200 mov cx,18 325 00007D12 51 .wait1: push cx 326 00007D13 6689F9 mov ecx,edi 327 00007D16 8B166C04 .wait2: mov dx,[BIOS_timer] 328 00007D1A E80F01 .wait3: call pollchar 329 00007D1D 7520 jnz .keypress 330 pm_call __idle 330 00007D1F 6668[00000000] <1> push dword %1 330 00007D25 E8E801 <1> call _pm_call 331 00007D28 3B166C04 cmp dx,[BIOS_timer] 332 00007D2C 74EC je .wait3 333 00007D2E 67E2E5 loop .wait2,ecx 334 00007D31 B02E mov al,'.' 335 pm_call pm_writechr 335 00007D33 6668[00000000] <1> push dword %1 335 00007D39 E8D401 <1> call _pm_call 336 00007D3C 59 pop cx 337 00007D3D E2D3 loop .wait1 338 .keypress: 339 pm_call crlf 339 00007D3F 6668[00000000] <1> push dword %1 339 00007D45 E8C801 <1> call _pm_call 340 00007D48 C70672040000 mov word [BIOS_magic],0 ; Cold reboot 341 00007D4E EAF0FF00F0 jmp 0F000h:0FFF0h ; Reset vector address 342 343 ; 344 ; pxenv 345 ; 346 ; This is the main PXENV+/!PXE entry point, using the PXENV+ 347 ; calling convention. This is a separate local routine so 348 ; we can hook special things from it if necessary. In particular, 349 ; some PXE stacks seem to not like being invoked from anything but 350 ; the initial stack, so humour it. 351 ; 352 ; While we're at it, save and restore all registers. 353 ; 354 global pxenv 355 pxenv: 356 00007D53 669C pushfd 357 00007D55 6660 pushad 358 359 ; We may be removing ourselves from memory 360 00007D57 83FB73 cmp bx,PXENV_RESTART_TFTP 361 00007D5A 7406 jz .disable_timer 362 00007D5C 81FBE500 cmp bx,PXENV_FILE_EXEC 363 00007D60 7503 jnz .store_stack 364 365 .disable_timer: 366 00007D62 E84606 call bios_timer_cleanup 367 368 .store_stack: 369 00007D65 9C pushf 370 00007D66 FA cli 371 00007D67 2EFF06[3800] inc word [cs:PXEStackLock] 372 00007D6C 7512 jnz .skip1 373 00007D6E 5D pop bp 374 00007D6F 2E8926[0000] mov [cs:PXEStack],sp 375 00007D74 2E8C16[0200] mov [cs:PXEStack+2],ss 376 00007D79 2E0FB226[0020] lss sp,[cs:InitStack] 377 00007D7F 55 push bp 378 .skip1: 379 00007D80 9D popf 380 381 ; Pre-clear the Status field 382 00007D81 268C0D mov word [es:di],cs 383 384 ; This works either for the PXENV+ or the !PXE calling 385 ; convention, as long as we ignore CF (which is redundant 386 ; with AX anyway.) 387 00007D84 06 push es 388 00007D85 57 push di 389 00007D86 53 push bx 390 00007D87 9A00000000 .jump: call 0:0 391 00007D8C 83C406 add sp,6 392 00007D8F 2EA3[2402] mov [cs:PXEStatus],ax 393 394 00007D93 9C pushf 395 00007D94 FA cli 396 00007D95 2EFF0E[3800] dec word [cs:PXEStackLock] 397 00007D9A 7908 jns .skip2 398 00007D9C 5D pop bp 399 00007D9D 2E0FB226[0000] lss sp,[cs:PXEStack] 400 00007DA3 55 push bp 401 .skip2: 402 00007DA4 9D popf 403 404 00007DA5 89E5 mov bp,sp 405 00007DA7 21C0 and ax,ax 406 00007DA9 0F954620 setnz [bp+32] ; If AX != 0 set CF on return 407 408 ; This clobbers the AX return, but we already saved it into 409 ; the PXEStatus variable. 410 00007DAD 6661 popad 411 412 ; If the call failed, it could return. 413 00007DAF 83FB73 cmp bx,PXENV_RESTART_TFTP 414 00007DB2 7406 jz .enable_timer 415 00007DB4 81FBE500 cmp bx,PXENV_FILE_EXEC 416 00007DB8 7503 jnz .pop_flags 417 418 .enable_timer: 419 00007DBA E8DC05 call timer_init 420 421 .pop_flags: 422 00007DBD 669D popfd ; Restore flags (incl. IF, DF) 423 00007DBF C3 ret 424 425 ; Must be after function def due to NASM bug 426 global PXEEntry 427 PXEEntry equ pxenv.jump+1 428 429 ; 430 ; The PXEStackLock keeps us from switching stacks if we take an interrupt 431 ; (which ends up calling pxenv) while we are already on the PXE stack. 432 ; It will be -1 normally, 0 inside a PXE call, and a positive value 433 ; inside a *nested* PXE call. 434 ; 435 section .data16 436 alignb 2 437 00008958 FFFF PXEStackLock dw -1 438 439 section .bss16 440 alignb 2 441 00003A34 PXEStatus resb 2 442 443 section .text16 444 ; 445 ; Invoke INT 1Ah on the PXE stack. This is used by the "Plan C" method 446 ; for finding the PXE entry point. 447 ; 448 global pxe_int1a 449 pxe_int1a: 450 00007DC0 2E8926[0000] mov [cs:PXEStack],sp 451 00007DC5 2E8C16[0200] mov [cs:PXEStack+2],ss 452 00007DCA 2E0FB226[0020] lss sp,[cs:InitStack] 453 454 00007DD0 CD1A int 1Ah ; May trash registers 455 456 00007DD2 2E0FB226[0000] lss sp,[cs:PXEStack] 457 00007DD8 C3 ret 458 459 ; 460 ; Special unload for gPXE: this switches the InitStack from 461 ; gPXE to the ROM PXE stack. 462 ; 463 %if GPXE 464 global gpxe_unload 465 gpxe_unload: 466 00007DD9 BBE700 mov bx,PXENV_FILE_EXIT_HOOK 467 00007DDC BF[3C00] mov di,pxe_file_exit_hook 468 00007DDF E871FF call pxenv 469 00007DE2 723D jc .plain 470 471 ; Now we actually need to exit back to gPXE, which will 472 ; give control back to us on the *new* "original stack"... 473 00007DE4 669C pushfd 474 00007DE6 1E push ds 475 00007DE7 06 push es 476 00007DE8 8926[0000] mov [PXEStack],sp 477 00007DEC 8C16[0200] mov [PXEStack+2],ss 478 00007DF0 0FB226[0020] lss sp,[InitStack] 479 00007DF5 0FA9 pop gs 480 00007DF7 0FA1 pop fs 481 00007DF9 07 pop es 482 00007DFA 1F pop ds 483 00007DFB 6661 popad 484 00007DFD 669D popfd 485 00007DFF 31C0 xor ax,ax 486 00007E01 CB retf 487 .resume: 488 00007E02 FA cli 489 490 ; gPXE will have a stack frame looking much like our 491 ; InitStack, except it has a magic cookie at the top, 492 ; and the segment registers are in reverse order. 493 00007E03 6658 pop eax 494 00007E05 58 pop ax 495 00007E06 5B pop bx 496 00007E07 59 pop cx 497 00007E08 5A pop dx 498 00007E09 50 push ax 499 00007E0A 53 push bx 500 00007E0B 51 push cx 501 00007E0C 52 push dx 502 00007E0D 2E8926[0020] mov [cs:InitStack],sp 503 00007E12 2E8C16[0220] mov [cs:InitStack+2],ss 504 00007E17 2E0FB226[0000] lss sp,[cs:PXEStack] 505 00007E1D 07 pop es 506 00007E1E 1F pop ds 507 00007E1F 669D popfd 508 509 .plain: 510 00007E21 C3 ret 511 512 writestr_early: 513 pm_call pm_writestr 513 00007E22 6668[00000000] <1> push dword %1 513 00007E28 E8E500 <1> call _pm_call 514 00007E2B C3 ret 515 516 pollchar: 517 pm_call pm_pollchar 517 00007E2C 6668[00000000] <1> push dword %1 517 00007E32 E8DB00 <1> call _pm_call 518 00007E35 C3 ret 519 520 getchar: 521 pm_call pm_getchar 521 00007E36 6668[00000000] <1> push dword %1 521 00007E3C E8D100 <1> call _pm_call 522 00007E3F C3 ret 523 524 section .data16 525 0000895A 00 alignz 4 526 pxe_file_exit_hook: 527 0000895C 0000 .status: dw 0 528 0000895E [0202] .offset: dw gpxe_unload.resume 529 00008960 0000 .seg: dw 0 530 %endif 531 532 section .text16 533 534 ; ----------------------------------------------------------------------------- 535 ; PXE modules 536 ; ----------------------------------------------------------------------------- 537 538 %if IS_LPXELINUX 539 %include "pxeisr.inc" 1 <1> ; 2 <1> ; Process a PXE interrupt 3 <1> ; 4 <1> section .text16 5 <1> 6 <1> PXEIRQ_MAX equ 100 ; Max spurious interrupts in a timer tick 7 <1> 8 <1> global pxe_isr 9 <1> pxe_isr: 10 00007E40 FC <1> cld 11 00007E41 60 <1> pusha 12 00007E42 1E <1> push ds 13 00007E43 06 <1> push es 14 00007E44 0FA0 <1> push fs 15 00007E46 0FA8 <1> push gs 16 <1> 17 00007E48 31C0 <1> xor ax,ax 18 00007E4A 8ED8 <1> mov ds,ax 19 00007E4C 8EC0 <1> mov es,ax 20 <1> 21 00007E4E BB1400 <1> mov bx,PXENV_UNDI_ISR 22 00007E51 BF[2802] <1> mov di,pxenv_undi_isr_buf 23 <1> 24 00007E54 B90800 <1> mov cx,pxenv_undi_isr_buf.size/2 25 00007E57 57 <1> push di 26 00007E58 F3AB <1> rep stosw 27 00007E5A 5F <1> pop di 28 <1> 29 00007E5B C606[2A02]01 <1> mov byte [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_IN_START 30 <1> 31 00007E60 E8F0FE <1> call pxenv 32 00007E63 A1[8C00] <1> mov ax,[__jiffies] 33 00007E66 722F <1> jc .notus 34 <1> 35 00007E68 833E[2A02]00 <1> cmp word [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_OUT_OURS 36 00007E6D 7528 <1> jne .notus 37 <1> 38 <1> ; Its ours - set the flag for the return to PM. 39 <1> ; We need to EOI this ourselves, so that the 40 <1> ; leftover BC doesn't get control. 41 00007E6F C606[4102]01 <1> mov byte [pxe_irq_pending],1 42 00007E74 66FF06[3C02] <1> inc dword [pxe_irq_count] 43 <1> 44 00007E79 803E[4002]08 <1> cmp byte [pxe_irq_vector], 8 45 00007E7E B020 <1> mov al,0x20 ; Non-specific EOI 46 00007E80 7202 <1> jb .pri_pic 47 <1> 48 00007E82 E6A0 <1> out 0xA0, al ; Secondary PIC 49 <1> .pri_pic: 50 00007E84 E620 <1> out 0x20,al ; Primary PIC 51 <1> 52 00007E86 A3[3802] <1> mov [pxeirq_last],ax 53 00007E89 C706[3A02]6400 <1> mov word [pxeirq_deadman],PXEIRQ_MAX 54 <1> 55 <1> .exit: 56 00007E8F 0FA9 <1> pop gs 57 00007E91 0FA1 <1> pop fs 58 00007E93 07 <1> pop es 59 00007E94 1F <1> pop ds 60 00007E95 61 <1> popa 61 00007E96 CF <1> iret 62 <1> 63 <1> .notus: 64 00007E97 3B06[3802] <1> cmp ax,[pxeirq_last] 65 00007E9B 7512 <1> jne .reset_timeout 66 00007E9D FF0E[3A02] <1> dec word [pxeirq_deadman] 67 00007EA1 7417 <1> jz .timeout 68 <1> 69 <1> .chain: 70 00007EA3 0FA9 <1> pop gs 71 00007EA5 0FA1 <1> pop fs 72 00007EA7 07 <1> pop es 73 00007EA8 1F <1> pop ds 74 00007EA9 61 <1> popa 75 00007EAA EA00000000 <1> jmp 0:0 76 <1> global pxe_irq_chain 77 <1> pxe_irq_chain equ $-4 78 <1> 79 <1> .reset_timeout: 80 00007EAF A3[3802] <1> mov [pxeirq_last],ax 81 00007EB2 C706[3A02]6400 <1> mov word [pxeirq_deadman],PXEIRQ_MAX 82 00007EB8 EBE9 <1> jmp .chain 83 <1> 84 <1> ; Too many spurious interrupts, shut off the interrupts 85 <1> ; and go to polling mode 86 <1> .timeout: 87 00007EBA A0[4002] <1> mov al,[pxe_irq_vector] 88 00007EBD BA2100 <1> mov dx,21h 89 00007EC0 0FB6C8 <1> movzx cx,al 90 00007EC3 C1E104 <1> shl cx,7-3 91 00007EC6 01CA <1> add dx,cx 92 00007EC8 2407 <1> and al,7 93 00007ECA 91 <1> xchg ax,cx 94 00007ECB B501 <1> mov ch,1 95 00007ECD D2E5 <1> shl ch,cl 96 00007ECF EC <1> in al,dx 97 00007ED0 08E8 <1> or al,ch 98 00007ED2 EE <1> out dx,al 99 00007ED3 800E[4202]01 <1> or byte [pxe_need_poll],1 100 00007ED8 EBB5 <1> jmp .exit 101 <1> 102 <1> 103 <1> ; Emulate a PXE interrupt from the polling thread 104 <1> global pxe_poll 105 <1> pxe_poll: 106 00007EDA 9C <1> pushf 107 00007EDB FA <1> cli 108 00007EDC FC <1> cld 109 00007EDD 60 <1> pusha 110 00007EDE 1E <1> push ds 111 00007EDF 06 <1> push es 112 00007EE0 0FA0 <1> push fs 113 00007EE2 0FA8 <1> push gs 114 <1> 115 00007EE4 BB1400 <1> mov bx,PXENV_UNDI_ISR 116 00007EE7 BF[2802] <1> mov di,pxenv_undi_isr_buf 117 <1> 118 00007EEA B90800 <1> mov cx,pxenv_undi_isr_buf.size/2 119 00007EED 57 <1> push di 120 00007EEE F3AB <1> rep stosw 121 00007EF0 5F <1> pop di 122 <1> 123 00007EF1 C606[2A02]01 <1> mov byte [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_IN_START 124 <1> 125 00007EF6 E85AFE <1> call pxenv 126 00007EF9 720C <1> jc .notus 127 <1> 128 00007EFB 833E[2A02]00 <1> cmp word [pxenv_undi_isr_buf.funcflag],PXENV_UNDI_ISR_OUT_OURS 129 00007F00 7505 <1> jne .notus 130 <1> 131 <1> ; Its ours - set the flag for the return to PM. 132 <1> ; We need to EOI this ourselves, so that the 133 <1> ; leftover BC doesn't get control. 134 00007F02 C606[4102]01 <1> mov byte [pxe_irq_pending],1 135 <1> 136 <1> .notus: 137 00007F07 0FA9 <1> pop gs 138 00007F09 0FA1 <1> pop fs 139 00007F0B 07 <1> pop es 140 00007F0C 1F <1> pop ds 141 00007F0D 61 <1> popa 142 00007F0E 9D <1> popf 143 00007F0F C3 <1> ret 144 <1> 145 <1> section .bss16 146 00003A36 <1> alignb 4 147 <1> pxenv_undi_isr_buf: 148 00003A38 <1> .status: resw 1 149 00003A3A <1> .funcflag: resw 1 150 00003A3C <1> .bufferlength: resw 1 151 00003A3E <1> .framelen: resw 1 152 00003A40 <1> .framehdrlen: resw 1 153 00003A42 <1> .frame: resw 2 154 00003A46 <1> .prottype: resb 1 155 00003A47 <1> .pkttype: resb 1 156 <1> .size equ $-pxenv_undi_isr_buf 157 <1> 158 <1> alignb 4 159 00003A48 <1> pxeirq_last resw 1 160 00003A4A <1> pxeirq_deadman resw 1 161 <1> 162 <1> global pxe_irq_count 163 00003A4C <1> pxe_irq_count resd 1 ; PXE IRQ counter 164 <1> global pxe_irq_vector 165 00003A50 <1> pxe_irq_vector resb 1 ; PXE IRQ vector 166 <1> global pxe_irq_pending 167 00003A51 <1> pxe_irq_pending resb 1 ; IRQ pending flag 168 <1> global pxe_need_poll 169 00003A52 <1> pxe_need_poll resb 1 ; Bit 0 = need polling 170 <1> ; Bit 1 = polling active 171 <1> 172 <1> section .text16 540 %endif 541 542 ; ----------------------------------------------------------------------------- 543 ; Common modules 544 ; ----------------------------------------------------------------------------- 545 546 %include "common.inc" ; Universal modules 1 <1> ; 2 <1> ; Modules common to all derivatives. Do not include modules in this list 3 <1> ; which have special section requirements (i.e. need to be in .init for 4 <1> ; some derivatives.) 5 <1> ; 6 <1> 7 <1> %include "pm.inc" ; Protected mode 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <2> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 <2> ;; 6 <2> ;; This program is free software; you can redistribute it and/or modify 7 <2> ;; it under the terms of the GNU General Public License as published by 8 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <2> ;; (at your option) any later version; incorporated herein by reference. 11 <2> ;; 12 <2> ;; ----------------------------------------------------------------------- 13 <2> 14 <2> ;; 15 <2> ;; pm.inc 16 <2> ;; 17 <2> ;; Functions to enter and exit 32-bit protected mode, handle interrupts 18 <2> ;; and cross-mode calls. 19 <2> ;; 20 <2> ;; PM refers to 32-bit flat protected mode; RM to 16-bit real mode. 21 <2> ;; 22 <2> 23 <2> bits 16 24 <2> section .text16 25 <2> ; 26 <2> ; _pm_call: call PM routine in low memory from RM 27 <2> ; 28 <2> ; on stack = PM routine to call (a 32-bit address) 29 <2> ; 30 <2> ; ECX, ESI, EDI passed to the called function; 31 <2> ; EAX = EBP in the called function points to the stack frame 32 <2> ; which includes all registers (which can be changed if desired.) 33 <2> ; 34 <2> ; All registers and the flags saved/restored 35 <2> ; 36 <2> ; This routine is invoked by the pm_call macro. 37 <2> ; 38 <2> _pm_call: 39 00007F10 669C <2> pushfd 40 00007F12 6660 <2> pushad 41 00007F14 1E <2> push ds 42 00007F15 06 <2> push es 43 00007F16 0FA0 <2> push fs 44 00007F18 0FA8 <2> push gs 45 00007F1A 89E5 <2> mov bp,sp 46 00007F1C 8CC8 <2> mov ax,cs 47 00007F1E 66BB[A6000000] <2> mov ebx,.pm 48 00007F24 8ED8 <2> mov ds,ax 49 00007F26 EB0D <2> jmp enter_pm 50 <2> 51 <2> bits 32 52 <2> section .textnr 53 <2> .pm: 54 <2> ; EAX points to the top of the RM stack, which is EFLAGS 55 00008476 F6452902 <2> test RM_FLAGSH,02h ; RM EFLAGS.IF 56 0000847A 7401 <2> jz .no_sti 57 0000847C FB <2> sti 58 <2> .no_sti: 59 0000847D FF552E <2> call [ebp+4*2+9*4+2] ; Entrypoint on RM stack 60 00008480 66BB[2803] <2> mov bx,.rm 61 00008484 EB20 <2> jmp enter_rm 62 <2> 63 <2> bits 16 64 <2> section .text16 65 <2> .rm: 66 00007F28 0FA9 <2> pop gs 67 00007F2A 0FA1 <2> pop fs 68 00007F2C 07 <2> pop es 69 00007F2D 1F <2> pop ds 70 00007F2E 6661 <2> popad 71 00007F30 669D <2> popfd 72 00007F32 C20400 <2> ret 4 ; Drop entrypoint 73 <2> 74 <2> ; 75 <2> ; enter_pm: Go to PM with interrupt service configured 76 <2> ; EBX = PM entry point 77 <2> ; EAX = EBP = on exit, points to the RM stack as a 32-bit value 78 <2> ; ECX, EDX, ESI, EDI preserved across this routine 79 <2> ; 80 <2> ; Assumes CS == DS 81 <2> ; 82 <2> ; This routine doesn't enable interrupts, but the target routine 83 <2> ; can enable interrupts by executing STI. 84 <2> ; 85 <2> bits 16 86 <2> section .text16 87 <2> enter_pm: 88 00007F35 FA <2> cli 89 00007F36 6631C0 <2> xor eax,eax 90 00007F39 8ED8 <2> mov ds,ax 91 00007F3B 8CD0 <2> mov ax,ss 92 00007F3D 8926[0828] <2> mov [RealModeSSSP],sp 93 00007F41 A3[0A28] <2> mov [RealModeSSSP+2],ax 94 00007F44 660FB7EC <2> movzx ebp,sp 95 00007F48 66C1E004 <2> shl eax,4 96 00007F4C 6601C5 <2> add ebp,eax ; EBP -> top of real-mode stack 97 00007F4F FC <2> cld 98 00007F50 E86400 <2> call enable_a20 99 <2> 100 <2> .a20ok: 101 00007F53 C606[0D00]89 <2> mov byte [bcopy_gdt.TSS+5],89h ; Mark TSS unbusy 102 <2> 103 00007F58 0F0116[0000] <2> lgdt [bcopy_gdt] ; We can use the same GDT just fine 104 00007F5D 0F011E[4800] <2> lidt [PM_IDT_ptr] ; Set up the IDT 105 00007F62 0F20C0 <2> mov eax,cr0 106 00007F65 0C01 <2> or al,1 107 00007F67 0F22C0 <2> mov cr0,eax ; Enter protected mode 108 00007F6A EA[B600]2000 <2> jmp PM_CS32:.in_pm 109 <2> 110 <2> bits 32 111 <2> section .textnr 112 <2> .in_pm: 113 00008486 31C0 <2> xor eax,eax ; Available for future use... 114 00008488 8EE0 <2> mov fs,eax 115 0000848A 8EE8 <2> mov gs,eax 116 0000848C 0F00D0 <2> lldt ax 117 <2> 118 0000848F B028 <2> mov al,PM_DS32 ; Set up data segments 119 00008491 8EC0 <2> mov es,eax 120 00008493 8ED8 <2> mov ds,eax 121 00008495 8ED0 <2> mov ss,eax 122 <2> 123 00008497 B008 <2> mov al,PM_TSS ; Be nice to Intel's VT by 124 00008499 0F00D8 <2> ltr ax ; giving it a valid TR 125 <2> 126 0000849C 8B25[44000000] <2> mov esp,[PMESP] ; Load protmode %esp 127 000084A2 89E8 <2> mov eax,ebp ; EAX -> top of real-mode stack 128 000084A4 FFE3 <2> jmp ebx ; Go to where we need to go 129 <2> 130 <2> ; 131 <2> ; enter_rm: Return to RM from PM 132 <2> ; 133 <2> ; BX = RM entry point (CS = 0) 134 <2> ; ECX, EDX, ESI, EDI preserved across this routine 135 <2> ; EAX clobbered 136 <2> ; EBP reserved 137 <2> ; 138 <2> ; This routine doesn't enable interrupts, but the target routine 139 <2> ; can enable interrupts by executing STI. 140 <2> ; 141 <2> bits 32 142 <2> section .textnr 143 <2> enter_rm: 144 000084A6 FA <2> cli 145 000084A7 FC <2> cld 146 000084A8 8925[44000000] <2> mov [PMESP],esp ; Save exit %esp 147 000084AE EA[6F030000]1000 <2> jmp PM_CS16:.in_pm16 ; Return to 16-bit mode first 148 <2> 149 <2> bits 16 150 <2> section .text16 151 <2> .in_pm16: 152 00007F6F B81800 <2> mov ax,PM_DS16 ; Real-mode-like segment 153 00007F72 8EC0 <2> mov es,ax 154 00007F74 8ED8 <2> mov ds,ax 155 00007F76 8ED0 <2> mov ss,ax 156 00007F78 8EE0 <2> mov fs,ax 157 00007F7A 8EE8 <2> mov gs,ax 158 <2> 159 00007F7C 0F011E[3000] <2> lidt [RM_IDT_ptr] ; Real-mode IDT (rm needs no GDT) 160 00007F81 31D2 <2> xor dx,dx 161 00007F83 0F20C0 <2> mov eax,cr0 162 00007F86 24FE <2> and al,~1 163 00007F88 0F22C0 <2> mov cr0,eax 164 00007F8B EA[9003]0000 <2> jmp 0:.in_rm 165 <2> 166 <2> .in_rm: ; Back in real mode 167 00007F90 2E0FB226[0828] <2> lss sp,[cs:RealModeSSSP] ; Restore stack 168 00007F96 660FB7E4 <2> movzx esp,sp ; Make sure the high bits are zero 169 00007F9A 8EDA <2> mov ds,dx ; Set up sane segments 170 00007F9C 8EC2 <2> mov es,dx 171 00007F9E 8EE2 <2> mov fs,dx 172 00007FA0 8EEA <2> mov gs,dx 173 00007FA2 FFE3 <2> jmp bx ; Go to whereever we need to go... 174 <2> 175 <2> section .data16 176 00008962 00 <2> alignz 4 177 <2> 178 <2> extern __stack_end 179 00008964 [00000000] <2> PMESP dd __stack_end ; Protected-mode ESP 180 <2> 181 00008968 FF07 <2> PM_IDT_ptr: dw 8*256-1 ; Length 182 0000896A [08200000] <2> dd IDT ; Offset 183 <2> 184 <2> ; 185 <2> ; This is invoked on getting an interrupt in protected mode. At 186 <2> ; this point, we need to context-switch to real mode and invoke 187 <2> ; the interrupt routine. 188 <2> ; 189 <2> ; When this gets invoked, the registers are saved on the stack and 190 <2> ; AL contains the register number. 191 <2> ; 192 <2> bits 32 193 <2> section .textnr 194 <2> pm_irq: 195 000084B5 60 <2> pushad 196 000084B6 0FB6742420 <2> movzx esi,byte [esp+8*4] ; Interrupt number 197 000084BB FF05[50020000] <2> inc dword [CallbackCtr] 198 000084C1 BB[A4030000] <2> mov ebx,.rm 199 000084C6 EBDE <2> jmp enter_rm ; Go to real mode 200 <2> 201 <2> bits 16 202 <2> section .text16 203 <2> .rm: 204 00007FA4 9C <2> pushf ; Flags on stack 205 00007FA5 2E67FF1CB500000000 <2> call far [cs:esi*4] ; Call IVT entry 206 00007FAE 66BB[F8000000] <2> mov ebx,.pm 207 00007FB4 E97EFF <2> jmp enter_pm ; Go back to PM 208 <2> 209 <2> bits 32 210 <2> section .textnr 211 <2> .pm: 212 000084C8 FF0D[50020000] <2> dec dword [CallbackCtr] 213 000084CE 7506 <2> jnz .skip 214 000084D0 FF15[50000000] <2> call [core_pm_hook] 215 <2> .skip: 216 000084D6 61 <2> popad 217 000084D7 83C404 <2> add esp,4 ; Drop interrupt number 218 000084DA CF <2> iretd 219 <2> 220 <2> ; 221 <2> ; Initially, the core_pm_hook does nothing; it is available for the 222 <2> ; threaded derivatives to run the scheduler, or examine the result from 223 <2> ; interrupt routines. 224 <2> ; 225 <2> global core_pm_null_hook 226 <2> core_pm_null_hook: 227 000084DB C3 <2> ret 228 <2> 229 <2> section .data16 230 0000896E 00 <2> alignz 4 231 <2> global core_pm_hook 232 00008970 [0B010000] <2> core_pm_hook: dd core_pm_null_hook 233 <2> 234 <2> bits 16 235 <2> section .text16 236 <2> ; 237 <2> ; Routines to enable and disable (yuck) A20. These routines are gathered 238 <2> ; from tips from a couple of sources, including the Linux kernel and 239 <2> ; http://www.x86.org/. The need for the delay to be as large as given here 240 <2> ; is indicated by Donnie Barnes of RedHat, the problematic system being an 241 <2> ; IBM ThinkPad 760EL. 242 <2> ; 243 <2> 244 <2> section .data16 245 <2> alignz 2 246 00008974 [C903] <2> A20Ptr dw a20_dunno 247 <2> 248 <2> section .bss16 249 00003A53 <2> alignb 4 250 00003A54 <2> A20Test resd 1 ; Counter for testing A20 status 251 00003A58 <2> A20Tries resb 1 ; Times until giving up on A20 252 <2> 253 <2> section .text16 254 <2> enable_a20: 255 00007FB7 6660 <2> pushad 256 00007FB9 2EC606[4802]FF <2> mov byte [cs:A20Tries],255 ; Times to try to make this work 257 <2> 258 <2> try_enable_a20: 259 <2> 260 <2> ; 261 <2> ; First, see if we are on a system with no A20 gate, or the A20 gate 262 <2> ; is already enabled for us... 263 <2> ; 264 <2> a20_none: 265 00007FBF E87C00 <2> call a20_test 266 00007FC2 7577 <2> jnz a20_done 267 <2> ; Otherwise, see if we had something memorized... 268 00007FC4 2EFF26[5400] <2> jmp word [cs:A20Ptr] 269 <2> 270 <2> ; 271 <2> ; Next, try the BIOS (INT 15h AX=2401h) 272 <2> ; 273 <2> a20_dunno: 274 <2> a20_bios: 275 00007FC9 2EC706[5400][C903] <2> mov word [cs:A20Ptr], a20_bios 276 00007FD0 B80124 <2> mov ax,2401h 277 00007FD3 9C <2> pushf ; Some BIOSes muck with IF 278 00007FD4 CD15 <2> int 15h 279 00007FD6 9D <2> popf 280 <2> 281 00007FD7 E86400 <2> call a20_test 282 00007FDA 755F <2> jnz a20_done 283 <2> 284 <2> ; 285 <2> ; Enable the keyboard controller A20 gate 286 <2> ; 287 <2> a20_kbc: 288 00007FDC B201 <2> mov dl, 1 ; Allow early exit 289 00007FDE E88E00 <2> call empty_8042 290 00007FE1 7558 <2> jnz a20_done ; A20 live, no need to use KBC 291 <2> 292 00007FE3 2EC706[5400][DC03] <2> mov word [cs:A20Ptr], a20_kbc ; Starting KBC command sequence 293 <2> 294 00007FEA B0D1 <2> mov al,0D1h ; Write output port 295 00007FEC E664 <2> out 064h, al 296 00007FEE E87C00 <2> call empty_8042_uncond 297 <2> 298 00007FF1 B0DF <2> mov al,0DFh ; A20 on 299 00007FF3 E660 <2> out 060h, al 300 00007FF5 E87500 <2> call empty_8042_uncond 301 <2> 302 <2> ; Apparently the UHCI spec assumes that A20 toggle 303 <2> ; ends with a null command (assumed to be for sychronization?) 304 <2> ; Put it here to see if it helps anything... 305 00007FF8 B0FF <2> mov al,0FFh ; Null command 306 00007FFA E664 <2> out 064h, al 307 00007FFC E86E00 <2> call empty_8042_uncond 308 <2> 309 <2> ; Verify that A20 actually is enabled. Do that by 310 <2> ; observing a word in low memory and the same word in 311 <2> ; the HMA until they are no longer coherent. Note that 312 <2> ; we don't do the same check in the disable case, because 313 <2> ; we don't want to *require* A20 masking (SYSLINUX should 314 <2> ; work fine without it, if the BIOS does.) 315 00007FFF 51 <2> .kbc_wait: push cx 316 00008000 31C9 <2> xor cx,cx 317 <2> .kbc_wait_loop: 318 00008002 E83900 <2> call a20_test 319 00008005 7533 <2> jnz a20_done_pop 320 00008007 E2F9 <2> loop .kbc_wait_loop 321 <2> 322 00008009 59 <2> pop cx 323 <2> ; 324 <2> ; Running out of options here. Final attempt: enable the "fast A20 gate" 325 <2> ; 326 <2> a20_fast: 327 0000800A 2EC706[5400][0A04] <2> mov word [cs:A20Ptr], a20_fast 328 00008011 E492 <2> in al, 092h 329 00008013 0C02 <2> or al,02h 330 00008015 24FE <2> and al,~01h ; Don't accidentally reset the machine! 331 00008017 E692 <2> out 092h, al 332 <2> 333 00008019 51 <2> .fast_wait: push cx 334 0000801A 31C9 <2> xor cx,cx 335 <2> .fast_wait_loop: 336 0000801C E81F00 <2> call a20_test 337 0000801F 7519 <2> jnz a20_done_pop 338 00008021 E2F9 <2> loop .fast_wait_loop 339 <2> 340 00008023 59 <2> pop cx 341 <2> 342 <2> ; 343 <2> ; Oh bugger. A20 is not responding. Try frobbing it again; eventually give up 344 <2> ; and report failure to the user. 345 <2> ; 346 00008024 2EFE0E[4802] <2> dec byte [cs:A20Tries] 347 00008029 759E <2> jnz a20_dunno ; Did we get the wrong type? 348 <2> 349 0000802B BE[5600] <2> mov si, err_a20 350 <2> pm_call pm_writestr 350 0000802E 6668[00000000] <3> push dword %1 350 00008034 E8D9FE <3> call _pm_call 351 00008037 E99AFC <2> jmp kaboom 352 <2> 353 <2> section .data16 354 00008976 0D0A41323020676174- <2> err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0 354 0000897F 65206E6F7420726573- <2> 354 00008988 706F6E64696E67210D- <2> 354 00008991 0A00 <2> 355 <2> section .text16 356 <2> 357 <2> ; 358 <2> ; A20 unmasked, proceed... 359 <2> ; 360 0000803A 59 <2> a20_done_pop: pop cx 361 0000803B 6661 <2> a20_done: popad 362 0000803D C3 <2> ret 363 <2> 364 <2> ; 365 <2> ; This routine tests if A20 is enabled (ZF = 0). This routine 366 <2> ; must not destroy any register contents. 367 <2> ; 368 <2> ; The no-write early out avoids the io_delay in the (presumably common) 369 <2> ; case of A20 already enabled (e.g. from a previous call.) 370 <2> ; 371 <2> a20_test: 372 0000803E 06 <2> push es 373 0000803F 51 <2> push cx 374 00008040 6650 <2> push eax 375 00008042 B9FFFF <2> mov cx,0FFFFh ; HMA = segment 0FFFFh 376 00008045 8EC1 <2> mov es,cx 377 00008047 2E66A1[4402] <2> mov eax,[cs:A20Test] 378 0000804C B92000 <2> mov cx,32 ; Loop count 379 0000804F EB0F <2> jmp .test ; First iteration = early out 380 00008051 660541EA0A43 <2> .wait: add eax,0x430aea41 ; A large prime number 381 00008057 2E66A3[4402] <2> mov [cs:A20Test],eax 382 0000805C E680E680 <2> io_delay ; Serialize, and fix delay 383 00008060 26663B06[5402] <2> .test: cmp eax,[es:A20Test+10h] 384 00008066 E1E9 <2> loopz .wait 385 00008068 6658 <2> .done: pop eax 386 0000806A 59 <2> pop cx 387 0000806B 07 <2> pop es 388 0000806C C3 <2> ret 389 <2> 390 <2> ; 391 <2> ; Routine to empty the 8042 KBC controller. If dl != 0 392 <2> ; then we will test A20 in the loop and exit if A20 is 393 <2> ; suddenly enabled. 394 <2> ; 395 <2> empty_8042_uncond: 396 0000806D 30D2 <2> xor dl,dl 397 <2> empty_8042: 398 0000806F E8CCFF <2> call a20_test 399 00008072 7404 <2> jz .a20_on 400 00008074 20D2 <2> and dl,dl 401 00008076 751A <2> jnz .done 402 00008078 E680E680 <2> .a20_on: io_delay 403 0000807C E464 <2> in al, 064h ; Status port 404 0000807E A801 <2> test al,1 405 00008080 7408 <2> jz .no_output 406 00008082 E680E680 <2> io_delay 407 00008086 E460 <2> in al, 060h ; Read input 408 00008088 EBE5 <2> jmp short empty_8042 409 <2> .no_output: 410 0000808A A802 <2> test al,2 411 0000808C 75E1 <2> jnz empty_8042 412 0000808E E680E680 <2> io_delay 413 00008092 C3 <2> .done: ret 414 <2> 415 <2> ; 416 <2> ; This initializes the protected-mode interrupt thunk set 417 <2> ; 418 <2> section .text16 419 <2> pm_init: 420 00008093 6631FF <2> xor edi,edi 421 00008096 BB[0820] <2> mov bx,IDT 422 00008099 BF[0000] <2> mov di,IRQStubs 423 <2> 424 0000809C 66B86A00EB7A <2> mov eax,7aeb006ah ; push byte .. jmp short .. 425 <2> 426 000080A2 B90800 <2> mov cx,8 ; 8 groups of 32 IRQs 427 <2> .gloop: 428 000080A5 51 <2> push cx 429 000080A6 B92000 <2> mov cx,32 ; 32 entries per group 430 <2> .eloop: 431 000080A9 893F <2> mov [bx],di ; IDT offset [15:0] 432 000080AB C747022000 <2> mov word [bx+2],PM_CS32 ; IDT segment 433 000080B0 66C74704008E0000 <2> mov dword [bx+4],08e00h ; IDT offset [31:16], 32-bit interrupt 434 <2> ; gate, CPL 0 (we don't have a TSS 435 <2> ; set up...) 436 000080B8 83C308 <2> add bx,8 437 <2> 438 000080BB 66AB <2> stosd 439 <2> ; Increment IRQ, decrement jmp short offset 440 000080BD 6605000100FC <2> add eax,(-4 << 24)+(1 << 8) 441 <2> 442 000080C3 E2E4 <2> loop .eloop 443 <2> 444 <2> ; At the end of each group, replace the EBxx with 445 <2> ; the final E9xxxxxxxx 446 000080C5 83C703 <2> add di,3 447 000080C8 C645FBE9 <2> mov byte [di-5],0E9h ; JMP NEAR 448 000080CC 66BA[E5000000] <2> mov edx,pm_irq 449 000080D2 6629FA <2> sub edx,edi 450 000080D5 668955FC <2> mov [di-4],edx 451 <2> 452 000080D9 660500000080 <2> add eax,(0x80 << 24) ; Proper offset for the next one 453 000080DF 59 <2> pop cx 454 000080E0 E2C3 <2> loop .gloop 455 <2> 456 000080E2 C3 <2> ret 457 <2> 458 <2> ; pm_init is called before bss clearing, so put these 459 <2> ; in .earlybss! 460 <2> section .earlybss 461 00003004 <2> alignb 8 462 00003008 <2> IDT: resq 256 463 <2> global RealModeSSSP 464 00003808 <2> RealModeSSSP resd 1 ; Real-mode SS:SP 465 <2> 466 <2> section .gentextnr ; Autogenerated 32-bit code 467 00003A80 <2> IRQStubs: resb 4*256+3*8 468 <2> 469 <2> section .text16 470 <2> 471 <2> %include "callback.inc" ; Real-mode callbacks 1 <3> ;; ----------------------------------------------------------------------- 2 <3> ;; 3 <3> ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <3> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 <3> ;; 6 <3> ;; This program is free software; you can redistribute it and/or modify 7 <3> ;; it under the terms of the GNU General Public License as published by 8 <3> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <3> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <3> ;; (at your option) any later version; incorporated herein by reference. 11 <3> ;; 12 <3> ;; ----------------------------------------------------------------------- 13 <3> 14 <3> ;; 15 <3> ;; callback.inc 16 <3> ;; 17 <3> ;; Callbacks from 32-bit mode to 16-bit mode 18 <3> ;; 19 <3> 20 <3> ; 21 <3> ; 16-bit intcall/farcall handling code 22 <3> ; 23 <3> 24 <3> ; 25 <3> ; 32-bit support code 26 <3> ; 27 <3> bits 32 28 <3> section .text 29 <3> 30 <3> ; 31 <3> ; Intcall/farcall invocation. We manifest a structure on the real-mode stack, 32 <3> ; containing the com32sys_t structure from as well as 33 <3> ; the following entries (from low to high address): 34 <3> ; - Target offset 35 <3> ; - Target segment 36 <3> ; - Return offset 37 <3> ; - Return segment (== real mode cs == 0) 38 <3> ; - Return flags 39 <3> ; 40 <3> global core_farcall:function hidden 41 <3> core_farcall: 42 00100000 8B442404 <3> mov eax,[esp+1*4] ; CS:IP 43 00100004 EB0C <3> jmp core_syscall 44 <3> 45 <3> global core_intcall:function hidden 46 <3> core_intcall: 47 00100006 0FB6442404 <3> movzx eax,byte [esp+1*4] ; INT number 48 0010000B 8B048500000000 <3> mov eax,[eax*4] ; Get CS:IP from low memory 49 <3> 50 <3> core_syscall: 51 00100012 9C <3> pushfd ; Save IF among other things... 52 00100013 FF05[50020000] <3> inc dword [CallbackCtr] 53 00100019 53 <3> push ebx 54 0010001A 55 <3> push ebp 55 0010001B 56 <3> push esi 56 0010001C 57 <3> push edi 57 0010001D FF35[4C020000] <3> push dword [CallbackSP] 58 <3> 59 00100023 FC <3> cld 60 <3> 61 00100024 670FB73E[0828] <3> movzx edi,word [word RealModeSSSP] 62 0010002A 670FB71E[0A28] <3> movzx ebx,word [word RealModeSSSP+2] 63 00100030 83EF36 <3> sub edi,54 ; Allocate 54 bytes 64 00100033 6667893E[0828] <3> mov [word RealModeSSSP],di 65 00100039 C1E304 <3> shl ebx,4 66 0010003C 01DF <3> add edi,ebx ; Create linear address 67 <3> 68 0010003E 8B742420 <3> mov esi,[esp+8*4] ; Source regs 69 00100042 31C9 <3> xor ecx,ecx 70 00100044 B10B <3> mov cl,11 ; 44 bytes to copy 71 00100046 F3A5 <3> rep movsd 72 <3> 73 <3> ; EAX is already set up to be CS:IP 74 00100048 AB <3> stosd ; Save in stack frame 75 00100049 B8[F6040000] <3> mov eax,.rm_return ; Return seg:offs 76 0010004E AB <3> stosd ; Save in stack frame 77 0010004F 8B47F4 <3> mov eax,[edi-12] ; Return flags 78 00100052 25D70E2000 <3> and eax,0x200ed7 ; Mask (potentially) unsafe flags 79 00100057 8947F4 <3> mov [edi-12],eax ; Primary flags entry 80 0010005A 66AB <3> stosw ; Return flags 81 <3> 82 0010005C 66BB[E304] <3> mov bx,.rm 83 00100060 E9(D6000000) <3> jmp enter_rm ; Go to real mode 84 <3> 85 <3> bits 16 86 <3> section .text16 87 <3> .rm: 88 000080E3 89E0 <3> mov ax,sp 89 000080E5 83C02C <3> add ax,9*4+4*2 90 000080E8 A3[4C02] <3> mov [CallbackSP],ax 91 000080EB 0FA9 <3> pop gs 92 000080ED 0FA1 <3> pop fs 93 000080EF 07 <3> pop es 94 000080F0 1F <3> pop ds 95 000080F1 6661 <3> popad 96 000080F3 669D <3> popfd 97 000080F5 CB <3> retf ; Invoke routine 98 <3> 99 <3> .rm_return: 100 <3> ; We clean up SP here because we don't know if the 101 <3> ; routine returned with RET, RETF or IRET 102 000080F6 2E8B26[4C02] <3> mov sp,[cs:CallbackSP] 103 000080FB 669C <3> pushfd 104 000080FD 6660 <3> pushad 105 000080FF 1E <3> push ds 106 00008100 06 <3> push es 107 00008101 0FA0 <3> push fs 108 00008103 0FA8 <3> push gs 109 00008105 66BB[65000000] <3> mov ebx,.pm_return 110 0000810B E927FE <3> jmp enter_pm 111 <3> 112 <3> ; On return, the 44-byte return structure is on the 113 <3> ; real-mode stack, plus the 10 additional bytes used 114 <3> ; by the target address (see above.) 115 <3> bits 32 116 <3> section .text 117 <3> .pm_return: 118 00100065 670FB736[0828] <3> movzx esi,word [word RealModeSSSP] 119 0010006B 670FB706[0A28] <3> movzx eax,word [word RealModeSSSP+2] 120 00100071 8B7C2424 <3> mov edi,[esp+9*4] ; Dest regs 121 00100075 C1E004 <3> shl eax,4 122 00100078 01C6 <3> add esi,eax ; Create linear address 123 0010007A 21FF <3> and edi,edi ; NULL pointer? 124 0010007C 7502 <3> jnz .do_copy 125 0010007E 89F7 <3> .no_copy: mov edi,esi ; Do a dummy copy-to-self 126 00100080 31C9 <3> .do_copy: xor ecx,ecx 127 00100082 B10B <3> mov cl,11 ; 44 bytes 128 00100084 F3A5 <3> rep movsd ; Copy register block 129 <3> 130 00100086 678306[0828]36 <3> add dword [word RealModeSSSP],54 131 <3> ; Remove from stack 132 <3> 133 0010008C 8F05[4C020000] <3> pop dword [CallbackSP] 134 00100092 FF0D[50020000] <3> dec dword [CallbackCtr] 135 00100098 7506 <3> jnz .skip 136 0010009A FF15[50000000] <3> call [core_pm_hook] 137 <3> .skip: 138 001000A0 5F <3> pop edi 139 001000A1 5E <3> pop esi 140 001000A2 5D <3> pop ebp 141 001000A3 5B <3> pop ebx 142 001000A4 9D <3> popfd 143 001000A5 C3 <3> ret ; Return to 32-bit program 144 <3> 145 <3> ; 146 <3> ; Cfarcall invocation. We copy the stack frame to the real-mode stack, 147 <3> ; followed by the return CS:IP and the CS:IP of the target function. 148 <3> ; The value of IF is copied from the calling routine. 149 <3> ; 150 <3> global core_cfarcall:function hidden 151 <3> core_cfarcall: 152 001000A6 9C <3> pushfd ; Save IF among other things... 153 001000A7 FF05[50020000] <3> inc dword [CallbackCtr] 154 001000AD 53 <3> push ebx 155 001000AE 55 <3> push ebp 156 001000AF 56 <3> push esi 157 001000B0 57 <3> push edi 158 001000B1 FF35[4C020000] <3> push dword [CallbackSP] 159 <3> 160 001000B7 FC <3> cld 161 001000B8 8B4C2424 <3> mov ecx,[esp+9*4] ; Size of stack frame 162 <3> 163 001000BC 670FB73E[0828] <3> movzx edi,word [word RealModeSSSP] 164 001000C2 670FB71E[0A28] <3> movzx ebx,word [word RealModeSSSP+2] 165 001000C8 6667893E[4C02] <3> mov [word CallbackSP],di 166 001000CE 29CF <3> sub edi,ecx ; Allocate space for stack frame 167 001000D0 83E7FC <3> and edi,~3 ; Round 168 001000D3 83EF0C <3> sub edi,4*3 ; Return pointer, return value, EFLAGS 169 001000D6 6667893E[0828] <3> mov [word RealModeSSSP],di 170 001000DC C1E304 <3> shl ebx,4 171 001000DF 01DF <3> add edi,ebx ; Create linear address 172 <3> 173 001000E1 8B442414 <3> mov eax,[esp+5*4] ; EFLAGS from entry 174 001000E5 2502020000 <3> and eax,0x202 ; IF only 175 001000EA AB <3> stosd 176 001000EB 8B44241C <3> mov eax,[esp+7*4] ; CS:IP 177 001000EF AB <3> stosd ; Save to stack frame 178 001000F0 B8[11050000] <3> mov eax,.rm_return ; Return seg:off 179 001000F5 AB <3> stosd 180 001000F6 8B742420 <3> mov esi,[esp+8*4] ; Stack frame 181 001000FA 89C8 <3> mov eax,ecx ; Copy the stack frame 182 001000FC C1E902 <3> shr ecx,2 183 001000FF F3A5 <3> rep movsd 184 00100101 89C1 <3> mov ecx,eax 185 00100103 83E103 <3> and ecx,3 186 00100106 F3A4 <3> rep movsb 187 <3> 188 00100108 66BB[0E05] <3> mov bx,.rm 189 0010010C E9(D6000000) <3> jmp enter_rm 190 <3> 191 <3> bits 16 192 <3> section .text16 193 <3> .rm: 194 0000810E 669D <3> popfd 195 00008110 CB <3> retf 196 <3> .rm_return: 197 00008111 2E8B26[4C02] <3> mov sp,[cs:CallbackSP] 198 00008116 6689C6 <3> mov esi,eax 199 00008119 66BB[11010000] <3> mov ebx,.pm_return 200 0000811F E913FE <3> jmp enter_pm 201 <3> 202 <3> bits 32 203 <3> section .text 204 <3> .pm_return: 205 00100111 89F0 <3> mov eax,esi 206 <3> ; EDX already set up to be the RM return value 207 00100113 8F05[4C020000] <3> pop dword [CallbackSP] 208 00100119 FF0D[50020000] <3> dec dword [CallbackCtr] 209 0010011F 7506 <3> jnz .skip 210 00100121 FF15[50000000] <3> call [core_pm_hook] 211 <3> .skip: 212 00100127 5B <3> pop ebx 213 00100128 5D <3> pop ebp 214 00100129 5E <3> pop esi 215 0010012A 5F <3> pop edi 216 0010012B 9D <3> popfd 217 0010012C C3 <3> ret 218 <3> 219 <3> section .bss16 220 00003A59 <3> alignb 4 221 <3> global core_pm_hook 222 00003A5C <3> CallbackSP resd 1 ; SP saved during callback 223 00003A60 <3> CallbackCtr resd 1 224 <3> 225 <3> bits 16 226 <3> section .text16 8 <1> %include "bcopy32.inc" ; 32-bit bcopy 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <2> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 <2> ;; 6 <2> ;; This program is free software; you can redistribute it and/or modify 7 <2> ;; it under the terms of the GNU General Public License as published by 8 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <2> ;; (at your option) any later version; incorporated herein by reference. 11 <2> ;; 12 <2> ;; ----------------------------------------------------------------------- 13 <2> 14 <2> ;; 15 <2> ;; bcopy32.inc 16 <2> ;; 17 <2> ;; 32-bit bcopy routine for real mode 18 <2> ;; 19 <2> 20 <2> ; 21 <2> ; 32-bit bcopy routine for real mode 22 <2> ; 23 <2> ; We enter protected mode, set up a flat 32-bit environment, run rep movsd 24 <2> ; and then exit. IMPORTANT: This code assumes cs == 0. 25 <2> ; 26 <2> ; This code is probably excessively anal-retentive in its handling of 27 <2> ; segments, but this stuff is painful enough as it is without having to rely 28 <2> ; on everything happening "as it ought to." 29 <2> ; 30 <2> 31 <2> bits 16 32 <2> section .text16 33 <2> 34 <2> ; 35 <2> ; bcopy: 36 <2> ; 32-bit copy, overlap safe 37 <2> ; 38 <2> ; Inputs: 39 <2> ; ESI - source pointer (-1 means do bzero rather than bcopy) 40 <2> ; EDI - target pointer 41 <2> ; ECX - byte count 42 <2> ; 43 <2> ; Outputs: 44 <2> ; ESI - first byte after source (garbage if ESI == -1 on entry) 45 <2> ; EDI - first byte after target 46 <2> ; 47 00008122 67E30F <2> bcopy: jecxz .ret 48 <2> pm_call pm_bcopy 48 00008125 6668[00000000] <3> push dword %1 48 0000812B E8E2FD <3> call _pm_call 49 0000812E 6601CF <2> add edi,ecx 50 00008131 6601CE <2> add esi,ecx 51 00008134 C3 <2> .ret: ret 52 <2> 53 <2> ; 54 <2> ; shuffle_and_boot_raw: 55 <2> ; The new version of shuffle and boot. 56 <2> ; Inputs: 57 <2> ; ESI -> Pointer to list of (dst, src, len) pairs(*) 58 <2> ; EDI -> Pointer to safe area for list + shuffler 59 <2> ; (must not overlap this code nor the RM stack) 60 <2> ; ECX -> Byte count of list area (for initial copy) 61 <2> ; 62 <2> ; If src == -1: then the memory pointed to by (dst, len) is bzeroed; 63 <2> ; this is handled inside the bcopy routine. 64 <2> ; 65 <2> ; If len == 0: this marks the end of the list; dst indicates 66 <2> ; the entry point and src the mode (0 = pm, 1 = rm) 67 <2> ; 68 <2> ; (*) dst, src, and len are four bytes each 69 <2> ; 70 <2> shuffle_and_boot_raw: 71 00008135 BB[BA00] <2> mov bx,pm_shuffle 72 00008138 E9FAFD <2> jmp enter_pm 73 <2> 74 <2> ; 75 <2> ; The 32-bit copy and shuffle code is "special", so it is in its own file 76 <2> ; 77 <2> %include "bcopyxx.inc" 1 <3> ;; ----------------------------------------------------------------------- 2 <3> ;; 3 <3> ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <3> ;; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin 5 <3> ;; 6 <3> ;; This program is free software; you can redistribute it and/or modify 7 <3> ;; it under the terms of the GNU General Public License as published by 8 <3> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <3> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <3> ;; (at your option) any later version; incorporated herein by reference. 11 <3> ;; 12 <3> ;; ----------------------------------------------------------------------- 13 <3> 14 <3> ;; 15 <3> ;; bcopy32xx.inc 16 <3> ;; 17 <3> 18 <3> 19 <3> ; 20 <3> ; 32-bit bcopy routine 21 <3> ; 22 <3> ; This is the actual 32-bit portion of the bcopy and shuffle and boot 23 <3> ; routines. ALL THIS CODE NEEDS TO BE POSITION-INDEPENDENT, with the 24 <3> ; sole exception being the actual relocation code at the beginning of 25 <3> ; pm_shuffle_boot. 26 <3> ; 27 <3> ; It also really needs to live all in a single segment, for the 28 <3> ; address calculcations to actually work. 29 <3> ; 30 <3> 31 <3> bits 32 32 <3> section .bcopyxx.text 33 <3> align 16 34 <3> ; 35 <3> ; pm_bcopy: 36 <3> ; 37 <3> ; This is the protected-mode core of the "bcopy" routine. 38 <3> ; Try to do aligned transfers; if the src and dst are relatively 39 <3> ; misaligned, align the dst. 40 <3> ; 41 <3> ; ECX is guaranteed to not be zero on entry. 42 <3> ; 43 <3> ; Clobbers ESI, EDI, ECX. 44 <3> ; 45 <3> 46 <3> pm_bcopy: 47 00008790 53 <3> push ebx 48 00008791 52 <3> push edx 49 00008792 50 <3> push eax 50 <3> 51 00008793 83FEFF <3> cmp esi,-1 52 00008796 747E <3> je .bzero 53 <3> 54 00008798 39FE <3> cmp esi,edi ; If source < destination, we might 55 0000879A 722E <3> jb .reverse ; have to copy backwards 56 <3> 57 <3> .forward: 58 <3> ; Initial alignment 59 0000879C 89FA <3> mov edx,edi 60 0000879E D1EA <3> shr edx,1 61 000087A0 7302 <3> jnc .faa1 62 000087A2 A4 <3> movsb 63 000087A3 49 <3> dec ecx 64 <3> .faa1: 65 000087A4 88C8 <3> mov al,cl 66 000087A6 83F902 <3> cmp ecx,2 67 000087A9 7216 <3> jb .f_tiny 68 <3> 69 000087AB D1EA <3> shr edx,1 70 000087AD 7305 <3> jnc .faa2 71 000087AF 66A5 <3> movsw 72 000087B1 83E902 <3> sub ecx,2 73 <3> .faa2: 74 <3> 75 <3> ; Bulk transfer 76 000087B4 88C8 <3> mov al,cl ; Save low bits 77 000087B6 C1E902 <3> shr ecx,2 ; Convert to dwords 78 000087B9 F3A5 <3> rep movsd ; Do our business 79 <3> ; At this point ecx == 0 80 <3> 81 000087BB A802 <3> test al,2 82 000087BD 7402 <3> jz .fab2 83 000087BF 66A5 <3> movsw 84 <3> .fab2: 85 <3> .f_tiny: 86 000087C1 A801 <3> test al,1 87 000087C3 7401 <3> jz .fab1 88 000087C5 A4 <3> movsb 89 <3> .fab1: 90 <3> .done: 91 000087C6 58 <3> pop eax 92 000087C7 5A <3> pop edx 93 000087C8 5B <3> pop ebx 94 000087C9 C3 <3> ret 95 <3> 96 <3> .reverse: 97 000087CA 8D440EFF <3> lea eax,[esi+ecx-1] ; Point to final byte 98 000087CE 39C7 <3> cmp edi,eax 99 000087D0 77CA <3> ja .forward ; No overlap, do forward copy 100 <3> 101 000087D2 FD <3> std ; Reverse copy 102 000087D3 8D7C0FFF <3> lea edi,[edi+ecx-1] 103 000087D7 89C6 <3> mov esi,eax 104 <3> 105 <3> ; Initial alignment 106 000087D9 89FA <3> mov edx,edi 107 000087DB D1EA <3> shr edx,1 108 000087DD 7202 <3> jc .raa1 109 000087DF A4 <3> movsb 110 000087E0 49 <3> dec ecx 111 <3> .raa1: 112 <3> 113 000087E1 4E <3> dec esi 114 000087E2 4F <3> dec edi 115 000087E3 88C8 <3> mov al,cl 116 000087E5 83F902 <3> cmp ecx,2 117 000087E8 7222 <3> jb .r_tiny 118 000087EA D1EA <3> shr edx,1 119 000087EC 7205 <3> jc .raa2 120 000087EE 66A5 <3> movsw 121 000087F0 83E902 <3> sub ecx,2 122 <3> .raa2: 123 <3> 124 <3> ; Bulk copy 125 000087F3 83EE02 <3> sub esi,2 126 000087F6 83EF02 <3> sub edi,2 127 000087F9 88C8 <3> mov al,cl ; Save low bits 128 000087FB C1E902 <3> shr ecx,2 129 000087FE F3A5 <3> rep movsd 130 <3> 131 <3> ; Final alignment 132 <3> .r_final: 133 00008800 83C602 <3> add esi,2 134 00008803 83C702 <3> add edi,2 135 00008806 A802 <3> test al,2 136 00008808 7402 <3> jz .rab2 137 0000880A 66A5 <3> movsw 138 <3> .rab2: 139 <3> .r_tiny: 140 0000880C 46 <3> inc esi 141 0000880D 47 <3> inc edi 142 0000880E A801 <3> test al,1 143 00008810 7401 <3> jz .rab1 144 00008812 A4 <3> movsb 145 <3> .rab1: 146 00008813 FC <3> cld 147 00008814 EBB0 <3> jmp short .done 148 <3> 149 <3> .bzero: 150 00008816 31C0 <3> xor eax,eax 151 <3> 152 <3> ; Initial alignment 153 00008818 89FA <3> mov edx,edi 154 0000881A D1EA <3> shr edx,1 155 0000881C 7302 <3> jnc .zaa1 156 0000881E AA <3> stosb 157 0000881F 49 <3> dec ecx 158 <3> .zaa1: 159 <3> 160 00008820 88CB <3> mov bl,cl 161 00008822 83F902 <3> cmp ecx,2 162 00008825 7217 <3> jb .z_tiny 163 00008827 D1EA <3> shr edx,1 164 00008829 7305 <3> jnc .zaa2 165 0000882B 66AB <3> stosw 166 0000882D 83E902 <3> sub ecx,2 167 <3> .zaa2: 168 <3> 169 <3> ; Bulk 170 00008830 88CB <3> mov bl,cl ; Save low bits 171 00008832 C1E902 <3> shr ecx,2 172 00008835 F3AB <3> rep stosd 173 <3> 174 00008837 F6C302 <3> test bl,2 175 0000883A 7402 <3> jz .zab2 176 0000883C 66AB <3> stosw 177 <3> .zab2: 178 <3> .z_tiny: 179 0000883E F6C301 <3> test bl,1 180 00008841 7401 <3> jz .zab1 181 00008843 AA <3> stosb 182 <3> .zab1: 183 00008844 EB80 <3> jmp short .done 184 <3> 185 <3> ; 186 <3> ; shuffle_and_boot: 187 <3> ; 188 <3> ; This routine is used to shuffle memory around, followed by 189 <3> ; invoking an entry point somewhere in low memory. This routine 190 <3> ; can clobber any memory outside the bcopy special area. 191 <3> ; 192 <3> ; IMPORTANT: This routine does not set up any registers. 193 <3> ; It is the responsibility of the caller to generate an appropriate entry 194 <3> ; stub; *especially* when going to real mode. 195 <3> ; 196 <3> ; Inputs: 197 <3> ; ESI -> Pointer to list of (dst, src, len) pairs(*) 198 <3> ; EDI -> Pointer to safe area for list + shuffler 199 <3> ; (must not overlap this code nor the RM stack) 200 <3> ; ECX -> Byte count of list area (for initial copy) 201 <3> ; 202 <3> ; If src == -1: then the memory pointed to by (dst, len) is bzeroed; 203 <3> ; this is handled inside the bcopy routine. 204 <3> ; 205 <3> ; If len == 0: this marks the end of the list; dst indicates 206 <3> ; the entry point and src the mode (0 = pm, 1 = rm) 207 <3> ; 208 <3> ; (*) dst, src, and len are four bytes each 209 <3> ; 210 <3> ; do_raw_shuffle_and_boot is the same entry point, but with a C ABI: 211 <3> ; do_raw_shuffle_and_boot(safearea, descriptors, bytecount) 212 <3> ; 213 <3> global do_raw_shuffle_and_boot 214 <3> do_raw_shuffle_and_boot: 215 00008846 89C7 <3> mov edi,eax 216 00008848 89D6 <3> mov esi,edx 217 <3> 218 <3> pm_shuffle: 219 0000884A FA <3> cli ; End interrupt service (for good) 220 0000884B 89FB <3> mov ebx,edi ; EBX <- descriptor list 221 0000884D 8D540F0F <3> lea edx,[edi+ecx+15] ; EDX <- where to relocate our code to 222 00008851 83E2F0 <3> and edx,~15 ; Align 16 to benefit the GDT 223 00008854 E837FFFFFF <3> call pm_bcopy 224 00008859 BE[00000000] <3> mov esi,__bcopyxx_start ; Absolute source address 225 0000885E 89D7 <3> mov edi,edx ; Absolute target address 226 00008860 29F2 <3> sub edx,esi ; EDX <- address delta 227 00008862 B9[00000000] <3> mov ecx,__bcopyxx_dwords 228 00008867 8D82[E1000000] <3> lea eax,[edx+.safe] ; Resume point 229 <3> ; Relocate this code 230 0000886D F3A5 <3> rep movsd 231 0000886F FFE0 <3> jmp eax ; Jump to safe location 232 <3> .safe: 233 <3> ; Give ourselves a safe stack 234 00008871 8DA2[80000000] <3> lea esp,[edx+bcopyxx_stack+__bcopyxx_end] 235 00008877 81C2[00000000] <3> add edx,bcopy_gdt ; EDX <- new GDT 236 0000887D 895202 <3> mov [edx+2],edx ; GDT self-pointer 237 00008880 0F0112 <3> lgdt [edx] ; Switch to local GDT 238 <3> 239 <3> ; Now for the actual shuffling... 240 <3> .loop: 241 00008883 8B3B <3> mov edi,[ebx] 242 00008885 8B7304 <3> mov esi,[ebx+4] 243 00008888 8B4B08 <3> mov ecx,[ebx+8] 244 0000888B 83C30C <3> add ebx,12 245 0000888E E307 <3> jecxz .done 246 00008890 E8FBFEFFFF <3> call pm_bcopy 247 00008895 EBEC <3> jmp .loop 248 <3> .done: 249 00008897 0F015A30 <3> lidt [edx+RM_IDT_ptr-bcopy_gdt] ; RM-like IDT 250 0000889B 51 <3> push ecx ; == 0, for cleaning the flags register 251 0000889C 21F6 <3> and esi,esi 252 0000889E 7403 <3> jz pm_shuffle_16 253 000088A0 9D <3> popfd ; Clean the flags 254 000088A1 FFE7 <3> jmp edi ; Protected mode entry 255 <3> 256 <3> ; We have a 16-bit entry point, so we need to return 257 <3> ; to 16-bit mode. Note: EDX already points to the GDT. 258 <3> pm_shuffle_16: 259 000088A3 89F8 <3> mov eax,edi 260 000088A5 66894212 <3> mov [edx+PM_CS16+2],ax 261 000088A9 6689421A <3> mov [edx+PM_DS16+2],ax 262 000088AD C1E810 <3> shr eax,16 263 000088B0 884214 <3> mov [edx+PM_CS16+4],al 264 000088B3 886217 <3> mov [edx+PM_CS16+7],ah 265 000088B6 88421C <3> mov [edx+PM_DS16+4],al 266 000088B9 88621F <3> mov [edx+PM_DS16+7],ah 267 000088BC 0F20C0 <3> mov eax,cr0 268 000088BF 24FE <3> and al,~1 269 000088C1 9D <3> popfd ; Clean the flags 270 <3> ; No flag-changing instructions below... 271 000088C2 66BA1800 <3> mov dx,PM_DS16 272 000088C6 8EDA <3> mov ds,edx 273 000088C8 8EC2 <3> mov es,edx 274 000088CA 8EE2 <3> mov fs,edx 275 000088CC 8EEA <3> mov gs,edx 276 000088CE 8ED2 <3> mov ss,edx 277 000088D0 EA000000001000 <3> jmp PM_CS16:0 278 <3> 279 <3> section .bcopyxx.data 280 <3> 281 <3> alignz 16 282 <3> ; GDT descriptor entry 283 <3> %macro desc 1 284 <3> bcopy_gdt.%1: 285 <3> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 286 <3> %endmacro 287 <3> 288 <3> bcopy_gdt: 289 000088E0 2F00 <3> dw bcopy_gdt_size-1 ; Null descriptor - contains GDT 290 000088E2 [00000000] <3> dd bcopy_gdt ; pointer for LGDT instruction 291 000088E6 0000 <3> dw 0 292 <3> 293 <3> ; TSS segment to keep Intel VT happy. Intel VT is 294 <3> ; unhappy about anything that doesn't smell like a 295 <3> ; full-blown 32-bit OS. 296 <3> desc TSS 296 <4> bcopy_gdt.%1: 296 <4> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 297 000088E8 67008005 <3> dw 104-1, DummyTSS ; 08h 32-bit task state segment 298 000088EC 00890000 <3> dd 00008900h ; present, dpl 0, 104 bytes @DummyTSS 299 <3> 300 <3> desc CS16 300 <4> bcopy_gdt.%1: 300 <4> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 301 000088F0 FFFF0000 <3> dd 0000ffffh ; 10h Code segment, use16, readable, 302 000088F4 009B0000 <3> dd 00009b00h ; present, dpl 0, cover 64K 303 <3> desc DS16 303 <4> bcopy_gdt.%1: 303 <4> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 304 000088F8 FFFF0000 <3> dd 0000ffffh ; 18h Data segment, use16, read/write, 305 000088FC 00930000 <3> dd 00009300h ; present, dpl 0, cover 64K 306 <3> desc CS32 306 <4> bcopy_gdt.%1: 306 <4> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 307 00008900 FFFF0000 <3> dd 0000ffffh ; 20h Code segment, use32, readable, 308 00008904 009BCF00 <3> dd 00cf9b00h ; present, dpl 0, cover all 4G 309 <3> desc DS32 309 <4> bcopy_gdt.%1: 309 <4> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 310 00008908 FFFF0000 <3> dd 0000ffffh ; 28h Data segment, use32, read/write, 311 0000890C 0093CF00 <3> dd 00cf9300h ; present, dpl 0, cover all 4G 312 <3> 313 <3> bcopy_gdt_size: equ $-bcopy_gdt 314 <3> ; 315 <3> ; Space for a dummy task state segment. It should never be actually 316 <3> ; accessed, but just in case it is, point to a chunk of memory that 317 <3> ; has a chance to not be used for anything real... 318 <3> ; 319 <3> DummyTSS equ 0x580 320 <3> 321 <3> align 4 322 00008910 FFFF <3> RM_IDT_ptr: dw 0FFFFh ; Length (nonsense, but matches CPU) 323 00008912 00000000 <3> dd 0 ; Offset 324 <3> 325 <3> bcopyxx_stack equ 128 ; We want this much stack 326 <3> 327 <3> section .rodata 328 <3> global __syslinux_shuffler_size 329 <3> extern __bcopyxx_len 330 <3> align 4 331 <3> __syslinux_shuffler_size: 332 00116A48 [00000000] <3> dd __bcopyxx_len 333 <3> 334 <3> bits 16 335 <3> section .text16 9 <1> %include "strcpy.inc" ; strcpy() 1 <2> ; 2 <2> ; strcpy: Copy DS:SI -> ES:DI up to and including a null byte; 3 <2> ; on exit SI and DI point to the byte *after* the null byte 4 <2> ; 5 <2> section .text16 6 <2> 7 0000813B 50 <2> strcpy: push ax 8 0000813C AC <2> .loop: lodsb 9 0000813D AA <2> stosb 10 0000813E 20C0 <2> and al,al 11 00008140 75FA <2> jnz .loop 12 00008142 58 <2> pop ax 13 00008143 C3 <2> ret 10 <1> %include "adv.inc" ; Auxiliary Data Vector 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 2007-2008 H. Peter Anvin - All Rights Reserved 4 <2> ;; 5 <2> ;; This program is free software; you can redistribute it and/or modify 6 <2> ;; it under the terms of the GNU General Public License as published by 7 <2> ;; the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 8 <2> ;; Boston MA 02110-1301, USA; either version 2 of the License, or 9 <2> ;; (at your option) any later version; incorporated herein by reference. 10 <2> ;; 11 <2> ;; ----------------------------------------------------------------------- 12 <2> 13 <2> ;; 14 <2> ;; adv.inc 15 <2> ;; 16 <2> ;; The auxiliary data vector and its routines 17 <2> ;; 18 <2> ;; The auxiliary data vector is a 512-byte aligned block that on the 19 <2> ;; disk-based derivatives can be part of the syslinux file itself. It 20 <2> ;; exists in two copies; when written, both copies are written (with a 21 <2> ;; sync in between, if from the operating system.) The first two 22 <2> ;; dwords are magic number and inverse checksum, then follows the data 23 <2> ;; area as a tagged array similar to BOOTP/DHCP, finally a tail 24 <2> ;; signature. 25 <2> ;; 26 <2> ;; Note that unlike BOOTP/DHCP, zero terminates the chain, and FF 27 <2> ;; has no special meaning. 28 <2> ;; 29 <2> 30 <2> ;; 31 <2> ;; List of ADV tags... 32 <2> ;; 33 <2> ADV_BOOTONCE equ 1 34 <2> 35 <2> ;; 36 <2> ;; Other ADV data... 37 <2> ;; 38 <2> ADV_MAGIC1 equ 0x5a2d2fa5 ; Head signature 39 <2> ADV_MAGIC2 equ 0xa3041767 ; Total checksum 40 <2> ADV_MAGIC3 equ 0xdd28bf64 ; Tail signature 41 <2> 42 <2> ADV_LEN equ 500 ; Data bytes 43 <2> 44 <2> adv_retries equ 6 ; Disk retries 45 <2> 46 <2> section .data 47 <2> global __syslinux_adv_ptr, __syslinux_adv_size 48 <2> __syslinux_adv_ptr: 49 00123E80 [08000000] <2> dd adv0.data 50 <2> __syslinux_adv_size: 51 00123E84 F4010000 <2> dd ADV_LEN 52 <2> 53 <2> section .adv 54 <2> ; Introduce the ADVs to valid but blank 55 <2> adv0: 56 00008C00 <2> .head resd 1 57 00008C04 <2> .csum resd 1 58 00008C08 <2> .data resb ADV_LEN 59 00008DFC <2> .tail resd 1 60 <2> .end equ $ 61 <2> adv1: 62 00008E00 <2> .head resd 1 63 00008E04 <2> .csum resd 1 64 00008E08 <2> .data resb ADV_LEN 65 00008FFC <2> .tail resd 1 66 <2> .end equ $ 67 <2> section .text16 68 <2> 69 <2> ; 70 <2> ; This is called after config file parsing, so we know 71 <2> ; the intended location of the ADV 72 <2> ; 73 <2> global adv_init 74 <2> adv_init: 75 00008144 803E[8800]FF <2> cmp byte [ADVDrive],-1 76 00008149 0F855901 <2> jne adv_read 77 <2> 78 <2> %if IS_SYSLINUX || IS_EXTLINUX 79 <2> cmp word [ADVSectors],2 ; Not present? 80 <2> jb adv_verify 81 <2> 82 <2> mov eax,[Hidden] 83 <2> mov edx,[Hidden+4] 84 <2> add [ADVSec0],eax 85 <2> adc [ADVSec0+4],edx 86 <2> add [ADVSec1],eax 87 <2> adc [ADVSec1+4],edx 88 <2> mov al,[DriveNumber] 89 <2> mov [ADVDrive],al 90 <2> jmp adv_read 91 <2> %endif 92 <2> 93 <2> ; 94 <2> ; Initialize the ADV data structure in memory 95 <2> ; 96 <2> adv_verify: 97 0000814D 803E[8800]FF <2> cmp byte [ADVDrive],-1 ; No ADV configured, still? 98 00008152 7410 <2> je .reset ; Then unconditionally reset 99 <2> 100 00008154 BE[0000] <2> mov si,adv0 101 00008157 E83900 <2> call .check_adv 102 0000815A 742C <2> jz .ok ; Primary ADV okay 103 0000815C BE[0002] <2> mov si,adv1 104 0000815F E83100 <2> call .check_adv 105 00008162 7425 <2> jz .adv1ok 106 <2> 107 <2> ; Neither ADV is usable; initialize to blank 108 <2> .reset: 109 00008164 BF[0000] <2> mov di,adv0 110 00008167 66B8A52F2D5A <2> mov eax,ADV_MAGIC1 111 0000816D 66AB <2> stosd 112 0000816F 66B8671704A3 <2> mov eax,ADV_MAGIC2 113 00008175 66AB <2> stosd 114 00008177 6631C0 <2> xor eax,eax 115 0000817A B97D00 <2> mov cx,ADV_LEN/4 116 0000817D F366AB <2> rep stosd 117 00008180 66B864BF28DD <2> mov eax,ADV_MAGIC3 118 00008186 66AB <2> stosd 119 <2> 120 <2> .ok: 121 00008188 C3 <2> ret 122 <2> 123 <2> ; The primary ADV is bad, but the backup is OK 124 <2> .adv1ok: 125 00008189 BF[0000] <2> mov di,adv0 126 0000818C B98000 <2> mov cx,512/4 127 0000818F F366A5 <2> rep movsd 128 00008192 C3 <2> ret 129 <2> 130 <2> 131 <2> ; SI points to the putative ADV; unchanged by routine 132 <2> ; ZF=1 on return if good 133 <2> .check_adv: 134 00008193 56 <2> push si 135 00008194 66AD <2> lodsd 136 00008196 663DA52F2D5A <2> cmp eax,ADV_MAGIC1 137 0000819C 751E <2> jne .done ; ZF=0, i.e. bad 138 0000819E 6631D2 <2> xor edx,edx 139 000081A1 B97E00 <2> mov cx,ADV_LEN/4+1 ; Remaining dwords 140 <2> .csum: 141 000081A4 66AD <2> lodsd 142 000081A6 6601C2 <2> add edx,eax 143 000081A9 E2F9 <2> loop .csum 144 000081AB 6681FA671704A3 <2> cmp edx,ADV_MAGIC2 145 000081B2 7508 <2> jne .done 146 000081B4 66AD <2> lodsd 147 000081B6 663D64BF28DD <2> cmp eax,ADV_MAGIC3 148 <2> .done: 149 000081BC 5E <2> pop si 150 000081BD C3 <2> ret 151 <2> 152 <2> ; 153 <2> ; adv_get: find an ADV string if present 154 <2> ; 155 <2> ; Input: DL = ADV ID 156 <2> ; Output: CX = byte count (zero on not found) 157 <2> ; SI = pointer to data 158 <2> ; DL = unchanged 159 <2> ; 160 <2> ; Assumes CS == DS. 161 <2> ; 162 <2> 163 <2> adv_get: 164 000081BE 50 <2> push ax 165 000081BF BE[0800] <2> mov si,adv0.data 166 000081C2 31C0 <2> xor ax,ax ; Keep AH=0 at all times 167 <2> .loop: 168 000081C4 AC <2> lodsb ; Read ID 169 000081C5 38D0 <2> cmp al,dl 170 000081C7 740F <2> je .found 171 000081C9 20C0 <2> and al,al 172 000081CB 7415 <2> jz .end 173 000081CD AC <2> lodsb ; Read length 174 000081CE 01C6 <2> add si,ax 175 000081D0 81FE[FC01] <2> cmp si,adv0.tail 176 000081D4 72EE <2> jb .loop 177 000081D6 EB0A <2> jmp .end 178 <2> 179 <2> .found: 180 000081D8 AC <2> lodsb 181 000081D9 89C1 <2> mov cx,ax 182 000081DB 01F0 <2> add ax,si ; Make sure it fits 183 000081DD 3D[FC01] <2> cmp ax,adv0.tail 184 000081E0 7602 <2> jbe .ok 185 <2> .end: 186 000081E2 31C9 <2> xor cx,cx 187 <2> .ok: 188 000081E4 58 <2> pop ax 189 000081E5 C3 <2> ret 190 <2> 191 <2> ; 192 <2> ; adv_set: insert a string into the ADV in memory 193 <2> ; 194 <2> ; Input: DL = ADV ID 195 <2> ; FS:BX = input buffer 196 <2> ; CX = byte count (max = 255!) 197 <2> ; Output: CF=1 on error 198 <2> ; CX clobbered 199 <2> ; 200 <2> ; Assumes CS == DS == ES. 201 <2> ; 202 <2> adv_set: 203 000081E6 50 <2> push ax 204 000081E7 56 <2> push si 205 000081E8 57 <2> push di 206 000081E9 20ED <2> and ch,ch 207 000081EB 7559 <2> jnz .overflow 208 <2> 209 000081ED 51 <2> push cx 210 000081EE BE[0800] <2> mov si,adv0.data 211 000081F1 31C0 <2> xor ax,ax 212 <2> .loop: 213 000081F3 AC <2> lodsb 214 000081F4 38D0 <2> cmp al,dl 215 000081F6 740F <2> je .found 216 000081F8 20C0 <2> and al,al 217 000081FA 7423 <2> jz .endz 218 000081FC AC <2> lodsb 219 000081FD 01C6 <2> add si,ax 220 000081FF 81FE[FC01] <2> cmp si,adv0.tail 221 00008203 72EE <2> jb .loop 222 00008205 EB19 <2> jmp .end 223 <2> 224 <2> .found: ; Found, need to delete old copy 225 00008207 AC <2> lodsb 226 00008208 8D7CFE <2> lea di,[si-2] 227 0000820B 57 <2> push di 228 0000820C 01C6 <2> add si,ax 229 0000820E B9[FC01] <2> mov cx,adv0.tail 230 00008211 29F1 <2> sub cx,si 231 00008213 7207 <2> jb .nukeit 232 00008215 F3A4 <2> rep movsb ; Remove the old one 233 00008217 8825 <2> mov [di],ah ; Termination zero 234 00008219 5E <2> pop si 235 0000821A EBD7 <2> jmp .loop 236 <2> .nukeit: 237 0000821C 5E <2> pop si 238 0000821D EB01 <2> jmp .end 239 <2> .endz: 240 0000821F 4E <2> dec si 241 <2> .end: 242 <2> ; Now SI points to where we want to put our data 243 00008220 59 <2> pop cx 244 00008221 89F7 <2> mov di,si 245 00008223 E313 <2> jcxz .empty 246 00008225 01CE <2> add si,cx 247 00008227 81FE[FA01] <2> cmp si,adv0.tail-2 248 0000822B 7319 <2> jae .overflow ; CF=0 249 <2> 250 0000822D 89DE <2> mov si,bx 251 0000822F 88D0 <2> mov al,dl 252 00008231 AA <2> stosb 253 00008232 88C8 <2> mov al,cl 254 00008234 AA <2> stosb 255 00008235 F364A4 <2> fs rep movsb 256 <2> 257 <2> .empty: 258 00008238 B9[FC01] <2> mov cx,adv0.tail 259 0000823B 29F9 <2> sub cx,di 260 0000823D 31C0 <2> xor ax,ax 261 0000823F F3AA <2> rep stosb ; Zero-fill remainder 262 <2> 263 00008241 F8 <2> clc 264 <2> .done: 265 00008242 5F <2> pop di 266 00008243 5E <2> pop si 267 00008244 58 <2> pop ax 268 00008245 C3 <2> ret 269 <2> .overflow: 270 00008246 F9 <2> stc 271 00008247 EBF9 <2> jmp .done 272 <2> 273 <2> ; 274 <2> ; adv_cleanup: checksum adv0 and copy to adv1 275 <2> ; Assumes CS == DS == ES. 276 <2> ; 277 <2> adv_cleanup: 278 00008249 6660 <2> pushad 279 0000824B BE[0800] <2> mov si,adv0.data 280 0000824E B97D00 <2> mov cx,ADV_LEN/4 281 00008251 6631D2 <2> xor edx,edx 282 <2> .loop: 283 00008254 66AD <2> lodsd 284 00008256 6601C2 <2> add edx,eax 285 00008259 E2F9 <2> loop .loop 286 0000825B 66B8671704A3 <2> mov eax,ADV_MAGIC2 287 00008261 6629D0 <2> sub eax,edx 288 00008264 8D7C04 <2> lea di,[si+4] ; adv1 289 00008267 BE[0000] <2> mov si,adv0 290 0000826A 66894404 <2> mov [si+4],eax ; Store checksum 291 0000826E B98000 <2> mov cx,(ADV_LEN+12)/4 292 00008271 F366A5 <2> rep movsd 293 00008274 6661 <2> popad 294 00008276 C3 <2> ret 295 <2> 296 <2> ; 297 <2> ; adv_write: write the ADV to disk. 298 <2> ; 299 <2> ; Location is in memory variables. 300 <2> ; Assumes CS == DS == ES. 301 <2> ; 302 <2> ; Returns CF=1 if the ADV cannot be written. 303 <2> ; 304 <2> global adv_write 305 <2> adv_write: 306 00008277 6650 <2> push eax 307 00008279 66A1[7800] <2> mov eax,[ADVSec0] 308 0000827D 660B06[7C00] <2> or eax,[ADVSec0+4] 309 00008282 741E <2> je .bad 310 00008284 66A1[8000] <2> mov eax,[ADVSec1] 311 00008288 660B06[8400] <2> or eax,[ADVSec1+4] 312 0000828D 7413 <2> je .bad 313 0000828F 803E[8800]FF <2> cmp byte [ADVDrive],-1 314 00008294 740C <2> je .bad 315 <2> 316 00008296 E8B0FF <2> call adv_cleanup 317 00008299 B403 <2> mov ah,3 ; Write 318 0000829B E81300 <2> call adv_read_write 319 <2> 320 0000829E F8 <2> clc 321 0000829F 6658 <2> pop eax 322 000082A1 C3 <2> ret 323 <2> .bad: ; No location for ADV set 324 000082A2 F9 <2> stc 325 000082A3 6658 <2> pop eax 326 000082A5 C3 <2> ret 327 <2> 328 <2> ; 329 <2> ; adv_read: read the ADV from disk 330 <2> ; 331 <2> ; Location is in memory variables. 332 <2> ; Assumes CS == DS == ES. 333 <2> ; 334 <2> adv_read: 335 000082A6 50 <2> push ax 336 000082A7 B402 <2> mov ah,2 ; Read 337 000082A9 E80500 <2> call adv_read_write 338 000082AC E89EFE <2> call adv_verify 339 000082AF 58 <2> pop ax 340 000082B0 C3 <2> ret 341 <2> 342 <2> ; 343 <2> ; adv_read_write: disk I/O for the ADV 344 <2> ; 345 <2> ; On input, AH=2 for read, AH=3 for write. 346 <2> ; Assumes CS == DS == ES. 347 <2> ; 348 <2> adv_read_write: 349 000082B1 8826[5402] <2> mov [ADVOp],ah 350 000082B5 6660 <2> pushad 351 <2> 352 <2> ; Check for EDD 353 000082B7 BBAA55 <2> mov bx,55AAh 354 000082BA B441 <2> mov ah,41h ; EDD existence query 355 000082BC 8A16[8800] <2> mov dl,[ADVDrive] 356 000082C0 CD13 <2> int 13h 357 000082C2 BE[2907] <2> mov si,.cbios 358 000082C5 720E <2> jc .noedd 359 000082C7 81FB55AA <2> cmp bx,0AA55h 360 000082CB 7508 <2> jne .noedd 361 000082CD F6C101 <2> test cl,1 362 000082D0 7403 <2> jz .noedd 363 000082D2 BE[F906] <2> mov si,.ebios 364 <2> .noedd: 365 <2> 366 000082D5 66A1[7800] <2> mov eax,[ADVSec0] 367 000082D9 668B16[7C00] <2> mov edx,[ADVSec0+4] 368 000082DE BB[0000] <2> mov bx,adv0 369 000082E1 E81200 <2> call .doone 370 <2> 371 000082E4 66A1[8000] <2> mov eax,[ADVSec1] 372 000082E8 668B16[8400] <2> mov edx,[ADVSec1+4] 373 000082ED BB[0002] <2> mov bx,adv1 374 000082F0 E80300 <2> call .doone 375 <2> 376 000082F3 6661 <2> popad 377 000082F5 C3 <2> ret 378 <2> 379 <2> .doone: 380 000082F6 56 <2> push si 381 000082F7 FFE6 <2> jmp si 382 <2> 383 <2> .ebios: 384 000082F9 B90600 <2> mov cx,adv_retries 385 <2> .eb_retry: 386 <2> ; Form DAPA on stack 387 000082FC 6652 <2> push edx 388 000082FE 6650 <2> push eax 389 00008300 06 <2> push es 390 00008301 53 <2> push bx 391 00008302 6A01 <2> push word 1 ; Sector count 392 00008304 6A10 <2> push word 16 ; DAPA size 393 00008306 89E6 <2> mov si,sp 394 00008308 6660 <2> pushad 395 0000830A 8A16[8800] <2> mov dl,[ADVDrive] 396 0000830E B80040 <2> mov ax,4000h 397 00008311 0A26[5402] <2> or ah,[ADVOp] 398 00008315 1E <2> push ds 399 00008316 16 <2> push ss 400 00008317 1F <2> pop ds 401 00008318 CD13 <2> int 13h 402 0000831A 1F <2> pop ds 403 0000831B 6661 <2> popad 404 0000831D 8D6410 <2> lea sp,[si+16] ; Remove DAPA 405 00008320 7202 <2> jc .eb_error 406 00008322 5E <2> pop si 407 00008323 C3 <2> ret 408 <2> .eb_error: 409 00008324 E2D6 <2> loop .eb_retry 410 00008326 F9 <2> stc 411 00008327 5E <2> pop si 412 00008328 C3 <2> ret 413 <2> 414 <2> .cbios: 415 00008329 6652 <2> push edx 416 0000832B 6650 <2> push eax 417 0000832D 55 <2> push bp 418 <2> 419 0000832E 6621D2 <2> and edx,edx ; > 2 TiB not possible 420 00008331 7563 <2> jnz .cb_overflow 421 <2> 422 00008333 8A16[8800] <2> mov dl,[ADVDrive] 423 00008337 20D2 <2> and dl,dl 424 <2> ; Floppies: can't trust INT 13h 08h, we better know 425 <2> ; the geometry a priori, which means it better be our 426 <2> ; boot device... 427 00008339 791B <2> jns .noparm ; Floppy drive... urk 428 <2> 429 0000833B B408 <2> mov ah,08h ; Get disk parameters 430 0000833D CD13 <2> int 13h 431 0000833F 7215 <2> jc .noparm 432 00008341 20E4 <2> and ah,ah 433 00008343 7511 <2> jnz .noparm 434 00008345 C1EA08 <2> shr dx,8 435 00008348 42 <2> inc dx 436 00008349 660FB7FA <2> movzx edi,dx ; EDI = heads 437 0000834D 83E13F <2> and cx,3fh 438 00008350 660FB7F1 <2> movzx esi,cx ; ESI = sectors/track 439 00008354 EB02 <2> jmp .parmok 440 <2> 441 <2> .noparm: 442 <2> ; No CHS info... this better be our boot drive, then 443 <2> %if IS_SYSLINUX || IS_EXTLINUX 444 <2> cmp dl,[DriveNumber] 445 <2> jne .cb_overflow ; Fatal error! 446 <2> movzx esi,word [bsSecPerTrack] 447 <2> movzx edi,word [bsHeads] 448 <2> %else 449 <2> ; Not a disk-based derivative... there is no hope 450 00008356 EB3E <2> jmp .cb_overflow 451 <2> %endif 452 <2> 453 <2> .parmok: 454 <2> ; 455 <2> ; Dividing by sectors to get (track,sector): we may have 456 <2> ; up to 2^18 tracks, so we need to use 32-bit arithmetric. 457 <2> ; 458 00008358 6631D2 <2> xor edx,edx 459 0000835B 66F7F6 <2> div esi 460 0000835E 31C9 <2> xor cx,cx 461 00008360 87CA <2> xchg cx,dx ; CX <- sector index (0-based) 462 <2> ; EDX <- 0 463 <2> ; eax = track # 464 00008362 66F7F7 <2> div edi ; Convert track to head/cyl 465 <2> 466 <2> ; Watch out for overflow, we might be writing! 467 00008365 663DFF030000 <2> cmp eax,1023 468 0000836B 7729 <2> ja .cb_overflow 469 <2> 470 <2> ; 471 <2> ; Now we have AX = cyl, DX = head, CX = sector (0-based), 472 <2> ; BP = sectors to transfer, SI = bsSecPerTrack, 473 <2> ; ES:BX = data target 474 <2> ; 475 <2> 476 0000836D C0E406 <2> shl ah,6 ; Because IBM was STOOPID 477 <2> ; and thought 8 bits were enough 478 <2> ; then thought 10 bits were enough... 479 00008370 41 <2> inc cx ; Sector numbers are 1-based, sigh 480 00008371 08E1 <2> or cl,ah 481 00008373 88C5 <2> mov ch,al 482 00008375 88D6 <2> mov dh,dl 483 00008377 8A16[8800] <2> mov dl,[ADVDrive] 484 0000837B B001 <2> mov al,01h ; Transfer one sector 485 0000837D 8A26[5402] <2> mov ah,[ADVOp] ; Operation 486 <2> 487 00008381 BD0600 <2> mov bp,adv_retries 488 <2> .cb_retry: 489 00008384 6660 <2> pushad 490 00008386 CD13 <2> int 13h 491 00008388 6661 <2> popad 492 0000838A 7207 <2> jc .cb_error 493 <2> 494 <2> .cb_done: 495 0000838C 5D <2> pop bp 496 0000838D 6658 <2> pop eax 497 0000838F 665A <2> pop edx 498 00008391 5E <2> pop si 499 00008392 C3 <2> ret 500 <2> 501 <2> .cb_error: 502 00008393 4D <2> dec bp 503 00008394 75EE <2> jnz .cb_retry 504 <2> .cb_overflow: 505 00008396 F9 <2> stc 506 00008397 EBF3 <2> jmp .cb_done 507 <2> 508 <2> section .data16 509 00008993 00 <2> alignz 8 510 00008998 0000000000000000 <2> ADVSec0 dq 0 ; Not specified 511 000089A0 0000000000000000 <2> ADVSec1 dq 0 ; Not specified 512 000089A8 FF <2> ADVDrive db -1 ; No ADV defined 513 000089A9 FF <2> ADVCHSInfo db -1 ; We have CHS info for this drive 514 <2> 515 <2> section .bss16 516 00003A64 <2> ADVOp resb 1 517 <2> 518 <2> section .text16 11 <1> %include "timer.inc" ; Timer handling 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 4 <2> ;; 5 <2> ;; This program is free software; you can redistribute it and/or modify 6 <2> ;; it under the terms of the GNU General Public License as published by 7 <2> ;; the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 8 <2> ;; Boston MA 02110-1301, USA; either version 2 of the License, or 9 <2> ;; (at your option) any later version; incorporated herein by reference. 10 <2> ;; 11 <2> ;; ----------------------------------------------------------------------- 12 <2> 13 <2> ;; 14 <2> ;; timer.inc 15 <2> ;; 16 <2> ;; Very simple counting timer 17 <2> ;; 18 <2> ;; This lets us have a simple incrementing variable without worrying 19 <2> ;; about the BIOS_timer variable wrapping around at "midnight" and other 20 <2> ;; weird things. 21 <2> ;; 22 <2> ;; This also maintains a timer variable calibrated in milliseconds 23 <2> ;; (wraparound time = 49.7 days!) 24 <2> ;; 25 <2> 26 <2> section .text16 27 <2> 28 <2> timer_init: 29 <2> ; Hook INT 1Ch 30 00008399 66A17000 <2> mov eax,[BIOS_timer_hook] 31 0000839D 66A3[C907] <2> mov [BIOS_timer_next],eax 32 000083A1 66C7067000- <2> mov dword [BIOS_timer_hook],timer_irq 32 000083A6 [B4070000] <2> 33 000083AA C3 <2> ret 34 <2> 35 <2> global bios_timer_cleanup:function hidden 36 <2> bios_timer_cleanup: 37 <2> ; Unhook INT 1Ch 38 000083AB 66A1[C907] <2> mov eax,[BIOS_timer_next] 39 000083AF 66A37000 <2> mov [BIOS_timer_hook],eax 40 000083B3 C3 <2> ret 41 <2> 42 <2> ; 43 <2> ; The specified frequency is 14.31818 MHz/12/65536; this turns out 44 <2> ; to be a period of 54.92542 ms, or 0x36.ece8(187c) hexadecimal. 45 <2> ; 46 <2> global timer_irq:function hidden 47 <2> timer_irq: 48 000083B4 2E66FF06[8C00] <2> inc dword [cs:__jiffies] 49 000083BA 2E8106[9400]E8EC <2> add word [cs:__ms_timer_adj],0xece8 50 000083C1 2E668316[9000]36 <2> adc dword [cs:__ms_timer],0x36 51 000083C8 EA00000000 <2> jmp 0:0 52 <2> global BIOS_timer_next:data hidden 53 <2> BIOS_timer_next equ $-4 54 <2> 55 <2> section .data16 56 000089AA 00 <2> alignz 4 57 <2> global __jiffies:data hidden, __ms_timer 58 000089AC 00000000 <2> __jiffies dd 0 ; Clock tick timer 59 000089B0 00000000 <2> __ms_timer dd 0 ; Millisecond timer 60 000089B4 0000 <2> __ms_timer_adj dw 0 ; Millisecond timer correction factor 12 <1> 13 <1> ; Note: the prefix section is included late, to avoid problems with some 14 <1> ; versions of NASM that had issues with forward references to EQU symbols. 15 <1> %include "prefix.inc" ; Prefix section for prepcore 1 <2> ; 2 <2> ; The prefix is a small structure that prefaces the actual code; 3 <2> ; it gives the compression program necessary information. 4 <2> ; 5 <2> 6 <2> section .prefix nowrite progbits align=16 7 00000000 [00000000] <2> pfx_start dd _start ; Start of raw chunk 8 00000004 [00000000] <2> pfx_compressed dd __pm_code_lma ; Start of compressed chunk 9 00000008 [06000000] <2> pfx_cdatalen dd lzo_data_size ; Pointer to compressed size field 10 <2> %if IS_ISOLINUX 11 <2> pfx_checksum dd bi_length ; File length and checksum fields 12 <2> %else 13 0000000C 00000000 <2> pfx_checksum dd 0 ; No checksum 14 <2> %endif 15 00000010 00000600 <2> pfx_maxlma dd MaxLMA ; Maximum size 16 <2> 17 <2> section .text16 547 548 ; ----------------------------------------------------------------------------- 549 ; Begin data section 550 ; ----------------------------------------------------------------------------- 551 552 section .data16 553 554 global copyright_str, syslinux_banner 555 000089B6 436F70797269676874- copyright_str db 'Copyright (C) 1994-' 555 000089BF 202843292031393934- 555 000089C8 2D 556 000089C9 32303135 asciidec YEAR 557 000089CD 20482E205065746572- db ' H. Peter Anvin et al', CR, LF, 0 557 000089D6 20416E76696E206574- 557 000089DF 20616C0D0A00 558 000089E5 0D0A426F6F74206661- err_bootfailed db CR, LF, 'Boot failed: press a key to retry, or wait for reset...', CR, LF, 0 558 000089EE 696C65643A20707265- 558 000089F7 73732061206B657920- 558 00008A00 746F2072657472792C- 558 00008A09 206F72207761697420- 558 00008A12 666F72207265736574- 558 00008A1B 2E2E2E0D0A00 559 bailmsg equ err_bootfailed 560 00008A21 426F6F74696E672066- localboot_msg db 'Booting from local disk...', CR, LF, 0 560 00008A2A 726F6D206C6F63616C- 560 00008A33 206469736B2E2E2E0D- 560 00008A3C 0A00 561 00008A3E 0D0A5058454C494E55- syslinux_banner db CR, LF, MY_NAME, ' ', VERSION_STR, ' ', MY_TYPE, ' ' 561 00008A47 5820362E3034206C77- 561 00008A50 495020 562 00008A53 362E30342D70726532- db DATE_STR, ' ', 0 562 00008A5C 2A2000 563 564 ; 565 ; Misc initialized (data) variables 566 ; 567 section .data16 568 global KeepPXE 569 00008A5F 00 KeepPXE db 0 ; Should PXE be kept around? 570 571 section .bss16 572 global OrigFDCTabPtr 573 00003A65 OrigFDCTabPtr resd 1 ; Keep bios_cleanup_hardware() honest