1 ; -*- fundamental -*- (asm-mode sucks) 2 ; **************************************************************************** 3 ; 4 ; isolinux.asm 5 ; 6 ; A program to boot Linux kernels off a CD-ROM using the El Torito 7 ; boot standard in "no emulation" mode, making the entire filesystem 8 ; available. It is based on the SYSLINUX boot loader for MS-DOS 9 ; floppies. 10 ; 11 ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 12 ; Copyright 2009 Intel Corporation; author: H. Peter Anvin 13 ; 14 ; This program is free software; you can redistribute it and/or modify 15 ; it under the terms of the GNU General Public License as published by 16 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 17 ; Boston MA 02111-1307, USA; either version 2 of the License, or 18 ; (at your option) any later version; incorporated herein by reference. 19 ; 20 ; **************************************************************************** 21 22 %define IS_ISOLINUX 1 23 %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 00313000 <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 00008E40 D07B0000 <2> BaseStack dd StackHome ; ESP of the "home" stack pointer 43 00008E44 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 24 25 ; 26 ; Some semi-configurable constants... change on your own risk. 27 ; 28 my_id equ isolinux_id 29 NULLFILE equ 0 ; Zero byte == null file name 30 NULLOFFSET equ 0 ; Position in which to look 31 retry_count equ 6 ; How patient are we with the BIOS? 32 %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top 33 SECTOR_SHIFT equ 11 ; 2048 bytes/sector (El Torito requirement) 34 SECTOR_SIZE equ (1 << SECTOR_SHIFT) 35 36 ROOT_DIR_WORD equ 0x002F 37 38 ; --------------------------------------------------------------------------- 39 ; BEGIN CODE 40 ; --------------------------------------------------------------------------- 41 42 ; 43 ; Memory below this point is reserved for the BIOS and the MBR 44 ; 45 section .earlybss 46 global trackbuf 47 trackbufsize equ 8192 48 00001000 trackbuf resb trackbufsize ; Track buffer goes here 49 ; ends at 2800h 50 51 ; Some of these are touched before the whole image 52 ; is loaded. DO NOT move this to .bss16/.uibss. 53 section .earlybss 54 global BIOSName 55 alignb 4 56 00003000 FirstSecSum resd 1 ; Checksum of bytes 64-2048 57 00003004 ImageDwords resd 1 ; isolinux.bin size, dwords 58 00003008 InitStack resd 1 ; Initial stack pointer (SS:SP) 59 0000300C DiskSys resw 1 ; Last INT 13h call 60 0000300E ImageSectors resw 1 ; isolinux.bin size, sectors 61 ; These following two are accessed as a single dword... 62 00003010 GetlinsecPtr resw 1 ; The sector-read pointer 63 00003012 BIOSName resw 1 ; Display string for BIOS type 64 %define HAVE_BIOSNAME 1 65 global BIOSType 66 00003014 BIOSType resw 1 67 00003016 DiskError resb 1 ; Error code for disk I/O 68 global DriveNumber 69 00003017 DriveNumber resb 1 ; CD-ROM BIOS drive number 70 00003018 ISOFlags resb 1 ; Flags for ISO directory search 71 00003019 RetryCount resb 1 ; Used for disk access retries 72 73 0000301A alignb 8 74 global Hidden 75 00003020 Hidden resq 1 ; Used in hybrid mode 76 00003028 bsSecPerTrack resw 1 ; Used in hybrid mode 77 0000302A bsHeads resw 1 ; Used in hybrid mode 78 79 80 ; 81 ; El Torito spec packet 82 ; 83 84 0000302C alignb 8 85 _spec_start equ $ 86 global spec_packet 87 00003030 spec_packet: resb 1 ; Size of packet 88 00003031 sp_media: resb 1 ; Media type 89 00003032 sp_drive: resb 1 ; Drive number 90 00003033 sp_controller: resb 1 ; Controller index 91 00003034 sp_lba: resd 1 ; LBA for emulated disk image 92 00003038 sp_devspec: resw 1 ; IDE/SCSI information 93 0000303A sp_buffer: resw 1 ; User-provided buffer 94 0000303C sp_loadseg: resw 1 ; Load segment 95 0000303E sp_sectors: resw 1 ; Sector count 96 00003040 sp_chs: resb 3 ; Simulated CHS geometry 97 00003043 sp_dummy: resb 1 ; Scratch, safe to overwrite 98 99 ; 100 ; EBIOS drive parameter packet 101 ; 102 00003044 alignb 8 103 00003048 drive_params: resw 1 ; Buffer size 104 0000304A dp_flags: resw 1 ; Information flags 105 0000304C dp_cyl: resd 1 ; Physical cylinders 106 00003050 dp_head: resd 1 ; Physical heads 107 00003054 dp_sec: resd 1 ; Physical sectors/track 108 00003058 dp_totalsec: resd 2 ; Total sectors 109 00003060 dp_secsize: resw 1 ; Bytes per sector 110 00003062 dp_dpte: resd 1 ; Device Parameter Table 111 00003066 dp_dpi_key: resw 1 ; 0BEDDh if rest valid 112 00003068 dp_dpi_len: resb 1 ; DPI len 113 00003069 resb 1 114 0000306A resw 1 115 0000306C dp_bus: resb 4 ; Host bus type 116 00003070 dp_interface: resb 8 ; Interface type 117 00003078 db_i_path: resd 2 ; Interface path 118 00003080 db_d_path: resd 2 ; Device path 119 00003088 resb 1 120 00003089 db_dpi_csum: resb 1 ; Checksum for DPI info 121 122 ; 123 ; EBIOS disk address packet 124 ; 125 0000308A alignb 8 126 00003090 dapa: resw 1 ; Packet size 127 00003092 .count: resw 1 ; Block count 128 00003094 .off: resw 1 ; Offset of buffer 129 00003096 .seg: resw 1 ; Segment of buffer 130 00003098 .lba: resd 2 ; LBA (LSW, MSW) 131 132 ; 133 ; Spec packet for disk image emulation 134 ; 135 alignb 8 136 000030A0 dspec_packet: resb 1 ; Size of packet 137 000030A1 dsp_media: resb 1 ; Media type 138 000030A2 dsp_drive: resb 1 ; Drive number 139 000030A3 dsp_controller: resb 1 ; Controller index 140 000030A4 dsp_lba: resd 1 ; LBA for emulated disk image 141 000030A8 dsp_devspec: resw 1 ; IDE/SCSI information 142 000030AA dsp_buffer: resw 1 ; User-provided buffer 143 000030AC dsp_loadseg: resw 1 ; Load segment 144 000030AE dsp_sectors: resw 1 ; Sector count 145 000030B0 dsp_chs: resb 3 ; Simulated CHS geometry 146 000030B3 dsp_dummy: resb 1 ; Scratch, safe to overwrite 147 148 alignb 4 149 _spec_end equ $ 150 _spec_len equ _spec_end - _spec_start 151 152 section .init 153 ;; 154 ;; Primary entry point. Because BIOSes are buggy, we only load the first 155 ;; CD-ROM sector (2K) of the file, so the number one priority is actually 156 ;; loading the rest. 157 ;; 158 global StackBuf 159 StackBuf equ STACK_TOP-44 ; 44 bytes needed for 160 ; the bootsector chainloading 161 ; code! 162 global OrigESDI 163 OrigESDI equ StackBuf-4 ; The high dword on the stack 164 StackHome equ OrigESDI 165 166 bootsec equ $ 167 168 _start: ; Far jump makes sure we canonicalize the address 169 00007C00 FA cli 170 00007C01 EA[6C00]0000 jmp 0:_start1 171 00007C06 90 times 8-($-$$) nop ; Pad to file offset 8 172 173 ; This table hopefully gets filled in by mkisofs using the 174 ; -boot-info-table option. If not, the values in this 175 ; table are default values that we can use to get us what 176 ; we need, at least under a certain set of assumptions. 177 global iso_boot_info 178 iso_boot_info: 179 00007C08 10000000 bi_pvd: dd 16 ; LBA of primary volume descriptor 180 00007C0C 00000000 bi_file: dd 0 ; LBA of boot file 181 00007C10 EFBEADDE bi_length: dd 0xdeadbeef ; Length of boot file 182 00007C14 EFBEADDE bi_csum: dd 0xdeadbeef ; Checksum of boot file 183 00007C18 EFBEADDE bi_reserved: times 10 dd 0xdeadbeef ; Reserved 184 bi_end: 185 186 ; Custom entry point for the hybrid-mode disk. 187 ; The following values will have been pushed onto the 188 ; entry stack: 189 ; - partition offset (qword) 190 ; - ES 191 ; - DI 192 ; - DX (including drive number) 193 ; - CBIOS Heads 194 ; - CBIOS Sectors 195 ; - EBIOS flag 196 ; (top of stack) 197 ; 198 ; If we had an old isohybrid, the partition offset will 199 ; be missing; we can check for that with sp >= 0x7c00. 200 ; Serious hack alert. 201 %ifndef DEBUG_MESSAGES 202 _hybrid_signature: 203 00007C40 FBC07870 dd 0x7078c0fb ; An arbitrary number... 204 205 _start_hybrid: 206 00007C44 59 pop cx ; EBIOS flag 207 00007C45 2E8F06[2820] pop word [cs:bsSecPerTrack] 208 00007C4A 2E8F06[2A20] pop word [cs:bsHeads] 209 00007C4F 5A pop dx 210 00007C50 5F pop di 211 00007C51 07 pop es 212 00007C52 6631C0 xor eax,eax 213 00007C55 6631DB xor ebx,ebx 214 00007C58 81FC007C cmp sp,7C00h 215 00007C5C 7304 jae .nooffset 216 00007C5E 6658 pop eax 217 00007C60 665B pop ebx 218 .nooffset: 219 00007C62 BE[9407] mov si,bios_cbios 220 00007C65 E30E jcxz _start_common 221 00007C67 BE[9807] mov si,bios_ebios 222 00007C6A EB09 jmp _start_common 223 %endif 224 225 _start1: 226 00007C6C BE[9007] mov si,bios_cdrom 227 00007C6F 6631C0 xor eax,eax 228 00007C72 6631DB xor ebx,ebx 229 _start_common: 230 00007C75 2E8926[0820] mov [cs:InitStack],sp ; Save initial stack pointer 231 00007C7A 2E8C16[0A20] mov [cs:InitStack+2],ss 232 00007C7F 31C9 xor cx,cx 233 00007C81 8ED1 mov ss,cx 234 00007C83 BCD47B mov sp,StackBuf ; Set up stack 235 00007C86 06 push es ; Save initial ES:DI -> $PnP pointer 236 00007C87 57 push di 237 00007C88 8ED9 mov ds,cx 238 00007C8A 8EC1 mov es,cx 239 00007C8C 8EE1 mov fs,cx 240 00007C8E 8EE9 mov gs,cx 241 00007C90 FB sti 242 00007C91 FC cld 243 244 00007C92 66A3[2020] mov [Hidden],eax 245 00007C96 66891E[2420] mov [Hidden+4],ebx 246 247 00007C9B 8936[1420] mov [BIOSType],si 248 00007C9F 668B04 mov eax,[si] 249 00007CA2 66A3[1020] mov [GetlinsecPtr],eax 250 251 ; Show signs of life 252 00007CA6 BE[3A05] mov si,syslinux_banner 253 00007CA9 E82A02 call writestr_early 254 %ifdef DEBUG_MESSAGES 255 mov si,copyright_str 256 %else 257 00007CAC 8B36[1220] mov si,[BIOSName] 258 %endif 259 00007CB0 E82302 call writestr_early 260 261 ; 262 ; Before modifying any memory, get the checksum of bytes 263 ; 64-2048 264 ; 265 00007CB3 6631FF initial_csum: xor edi,edi 266 00007CB6 BE[4000] mov si,bi_end 267 00007CB9 B9F001 mov cx,(SECTOR_SIZE-64) >> 2 268 00007CBC 66AD .loop: lodsd 269 00007CBE 6601C7 add edi,eax 270 00007CC1 E2F9 loop .loop 271 00007CC3 66893E[0020] mov [FirstSecSum],edi 272 273 00007CC8 8816[1720] mov [DriveNumber],dl 274 %ifdef DEBUG_MESSAGES 275 mov si,startup_msg 276 call writemsg 277 mov al,dl 278 call writehex2 279 call crlf_early 280 %endif 281 ; 282 ; Initialize spec packet buffers 283 ; 284 00007CCC BF[3020] mov di,_spec_start 285 00007CCF B92100 mov cx,_spec_len >> 2 286 00007CD2 6631C0 xor eax,eax 287 00007CD5 F366AB rep stosd 288 289 ; Initialize length field of the various packets 290 00007CD8 C606[3020]13 mov byte [spec_packet],13h 291 00007CDD C606[4820]1E mov byte [drive_params],30 292 00007CE2 C606[9020]10 mov byte [dapa],16 293 00007CE7 C606[A020]13 mov byte [dspec_packet],13h 294 295 ; Other nonzero fields 296 00007CEC FF06[AE20] inc word [dsp_sectors] 297 298 ; Are we just pretending to be a CD-ROM? 299 00007CF0 813E[1420][9007] cmp word [BIOSType],bios_cdrom 300 00007CF6 751D jne found_drive ; If so, no spec packet... 301 302 ; Now figure out what we're actually doing 303 ; Note: use passed-in DL value rather than 7Fh because 304 ; at least some BIOSes will get the wrong value otherwise 305 00007CF8 B8014B mov ax,4B01h ; Get disk emulation status 306 00007CFB 8A16[1720] mov dl,[DriveNumber] 307 00007CFF BE[3020] mov si,spec_packet 308 00007D02 E80002 call int13 309 00007D05 0F82FA00 jc award_hack ; changed for BrokenAwardHack 310 00007D09 8A16[1720] mov dl,[DriveNumber] 311 00007D0D 3816[3220] cmp [sp_drive],dl ; Should contain the drive number 312 00007D11 0F854601 jne spec_query_failed 313 314 %ifdef DEBUG_MESSAGES 315 mov si,spec_ok_msg 316 call writemsg 317 mov al,byte [sp_drive] 318 call writehex2 319 call crlf_early 320 %endif 321 322 found_drive: 323 ; Alright, we have found the drive. Now, try to find the 324 ; boot file itself. If we have a boot info table, life is 325 ; good; if not, we have to make some assumptions, and try 326 ; to figure things out ourselves. In particular, the 327 ; assumptions we have to make are: 328 ; - single session only 329 ; - only one boot entry (no menu or other alternatives) 330 331 00007D15 66833E[0C00]00 cmp dword [bi_file],0 ; Address of code to load 332 00007D1B 7527 jne found_file ; Boot info table present :) 333 334 %ifdef DEBUG_MESSAGES 335 mov si,noinfotable_msg 336 call writemsg 337 %endif 338 339 ; No such luck. See if the spec packet contained one. 340 00007D1D 66A1[3420] mov eax,[sp_lba] 341 00007D21 6621C0 and eax,eax 342 00007D24 741A jz set_file ; Good enough 343 344 %ifdef DEBUG_MESSAGES 345 mov si,noinfoinspec_msg 346 call writemsg 347 %endif 348 349 ; No such luck. Get the Boot Record Volume, assuming single 350 ; session disk, and that we're the first entry in the chain. 351 00007D26 66B811000000 mov eax,17 ; Assumed address of BRV 352 00007D2C BB[0000] mov bx,trackbuf 353 00007D2F E8EC01 call getonesec 354 355 00007D32 66A1[4700] mov eax,[trackbuf+47h] ; Get boot catalog address 356 00007D36 BB[0000] mov bx,trackbuf 357 00007D39 E8E201 call getonesec ; Get boot catalog 358 359 00007D3C 66A1[2800] mov eax,[trackbuf+28h] ; First boot entry 360 ; And hope and pray this is us... 361 362 ; Some BIOSes apparently have limitations on the size 363 ; that may be loaded (despite the El Torito spec being very 364 ; clear on the fact that it must all be loaded.) Therefore, 365 ; we load it ourselves, and *bleep* the BIOS. 366 367 set_file: 368 00007D40 66A3[0C00] mov [bi_file],eax 369 370 found_file: 371 ; Set up boot file sizes 372 00007D44 66A1[1000] mov eax,[bi_length] 373 00007D48 662DFD070000 sub eax,SECTOR_SIZE-3 ; ... minus sector loaded 374 00007D4E 66C1E802 shr eax,2 ; bytes->dwords 375 00007D52 66A3[0420] mov [ImageDwords],eax ; boot file dwords 376 00007D56 6605FF010000 add eax,((SECTOR_SIZE-1) >> 2) 377 00007D5C 66C1E809 shr eax,SECTOR_SHIFT-2 ; dwords->sectors 378 00007D60 A3[0E20] mov [ImageSectors],ax ; boot file sectors 379 380 00007D63 66A1[0C00] mov eax,[bi_file] ; Address of code to load 381 00007D67 6640 inc eax ; Don't reload bootstrap code 382 %ifdef DEBUG_MESSAGES 383 mov si,offset_msg 384 call writemsg 385 call writehex8 386 call crlf_early 387 %endif 388 389 ; Load the rest of the file. However, just in case there 390 ; are still BIOSes with 64K wraparound problems, we have to 391 ; take some extra precautions. Since the normal load 392 ; address (TEXT_START) is *not* 2K-sector-aligned, we round 393 ; the target address upward to a sector boundary, 394 ; and then move the entire thing down as a unit. 395 MaxLMA equ 384*1024 ; Reasonable limit (384K) 396 397 00007D69 BB8008 mov bx,((TEXT_START+2*SECTOR_SIZE-1) & ~(SECTOR_SIZE-1)) >> 4 398 00007D6C 8B2E[0E20] mov bp,[ImageSectors] 399 00007D70 53 push bx ; Load segment address 400 401 .more: 402 00007D71 53 push bx ; Segment address 403 00007D72 55 push bp ; Sector count 404 00007D73 8EC3 mov es,bx 405 00007D75 B9FF0F mov cx,0xfff 406 00007D78 21CB and bx,cx 407 00007D7A 41 inc cx 408 00007D7B 29D9 sub cx,bx 409 00007D7D C1E907 shr cx,SECTOR_SHIFT - 4 410 00007D80 7503 jnz .notaligned 411 00007D82 B92000 mov cx,0x10000 >> SECTOR_SHIFT ; Full 64K segment possible 412 .notaligned: 413 00007D85 39CD cmp bp,cx 414 00007D87 7602 jbe .ok 415 00007D89 89CD mov bp,cx 416 .ok: 417 00007D8B 31DB xor bx,bx 418 00007D8D 55 push bp 419 00007D8E 6650 push eax 420 00007D90 E88E01 call getlinsec 421 00007D93 6658 pop eax 422 00007D95 59 pop cx 423 00007D96 660FB7D1 movzx edx,cx 424 00007D9A 5D pop bp 425 00007D9B 5B pop bx 426 427 00007D9C C1E107 shl cx,SECTOR_SHIFT - 4 428 00007D9F 01CB add bx,cx 429 00007DA1 6601D0 add eax,edx 430 00007DA4 29D5 sub bp,dx 431 00007DA6 75C9 jnz .more 432 433 ; Move the image into place, and also verify the 434 ; checksum 435 00007DA8 58 pop ax ; Load segment address 436 00007DA9 BB4008 mov bx,(TEXT_START + SECTOR_SIZE) >> 4 437 00007DAC 668B0E[0420] mov ecx,[ImageDwords] 438 00007DB1 668B3E[0020] mov edi,[FirstSecSum] ; First sector checksum 439 00007DB6 31F6 xor si,si 440 441 move_verify_image: 442 .setseg: 443 00007DB8 8ED8 mov ds,ax 444 00007DBA 8EC3 mov es,bx 445 .loop: 446 00007DBC 668B14 mov edx,[si] 447 00007DBF 6601D7 add edi,edx 448 00007DC2 6649 dec ecx 449 00007DC4 26668914 mov [es:si],edx 450 00007DC8 740E jz .done 451 00007DCA 83C604 add si,4 452 00007DCD 75ED jnz .loop 453 00007DCF 050010 add ax,1000h 454 00007DD2 81C30010 add bx,1000h 455 00007DD6 EBE0 jmp .setseg 456 .done: 457 00007DD8 8CC8 mov ax,cs 458 00007DDA 8ED8 mov ds,ax 459 00007DDC 8EC0 mov es,ax 460 461 ; Verify the checksum on the loaded image. 462 00007DDE 66393E[1400] cmp [bi_csum],edi 463 00007DE3 7409 je integrity_ok 464 465 00007DE5 BE[3407] mov si,checkerr_msg 466 00007DE8 E8DD00 call writemsg 467 00007DEB E9D502 jmp kaboom 468 469 integrity_ok: 470 %ifdef DEBUG_MESSAGES 471 mov si,allread_msg 472 call writemsg 473 %endif 474 00007DEE E9(0000) jmp all_read ; Jump to main code 475 476 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 477 ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de 478 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 479 ;; 480 ;; There is a problem with certain versions of the AWARD BIOS ... 481 ;; the boot sector will be loaded and executed correctly, but, because the 482 ;; int 13 vector points to the wrong code in the BIOS, every attempt to 483 ;; load the spec packet will fail. We scan for the equivalent of 484 ;; 485 ;; mov ax,0201h 486 ;; mov bx,7c00h 487 ;; mov cx,0006h 488 ;; mov dx,0180h 489 ;; pushf 490 ;; call 491 ;; 492 ;; and use as the new vector for int 13. The code above is 493 ;; used to load the boot code into ram, and there should be no reason 494 ;; for anybody to change it now or in the future. There are no opcodes 495 ;; that use encodings relativ to IP, so scanning is easy. If we find the 496 ;; code above in the BIOS code we can be pretty sure to run on a machine 497 ;; with an broken AWARD BIOS ... 498 ;; 499 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 500 ;; 501 %ifdef DEBUG_MESSAGES ;; 502 ;; 503 award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;; 504 award_not_orig db "BAH: Original Int 13 vector : ",0 ;; 505 award_not_new db "BAH: Int 13 vector changed to : ",0 ;; 506 award_not_succ db "BAH: SUCCESS",CR,LF,0 ;; 507 award_not_fail db "BAH: FAILURE" ;; 508 award_not_crlf db CR,LF,0 ;; 509 ;; 510 %endif ;; 511 ;; 512 00007DF1 00000000 award_oldint13 dd 0 ;; 513 00007DF5 B80102BB007CB90600- award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;; 513 00007DFE BA80019C9A 514 ;; 515 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 516 00007E03 BE[0306] award_hack: mov si,spec_err_msg ; Moved to this place from 517 00007E06 E8BF00 call writemsg ; spec_query_failed 518 ; 519 %ifdef DEBUG_MESSAGES ; 520 ; 521 mov si,award_notice ; display our plan 522 call writemsg ; 523 mov si,award_not_orig ; display original int 13 524 call writemsg ; vector 525 %endif ; 526 00007E09 66A14C00 mov eax,[13h*4] ; 527 00007E0D 66A3[F101] mov [award_oldint13],eax ; 528 ; 529 %ifdef DEBUG_MESSAGES ; 530 ; 531 call writehex8 ; 532 mov si,award_not_crlf ; 533 call writestr_early ; 534 %endif ; 535 00007E11 06 push es ; save ES 536 00007E12 B800F0 mov ax,0f000h ; ES = BIOS Seg 537 00007E15 8EC0 mov es,ax ; 538 00007E17 FC cld ; 539 00007E18 31FF xor di,di ; start at ES:DI = f000:0 540 00007E1A 57 award_loop: push di ; save DI 541 00007E1B BE[F501] mov si,award_string ; scan for award_string 542 00007E1E B90700 mov cx,7 ; length of award_string = 7dw 543 00007E21 F3A7 repz cmpsw ; compare 544 00007E23 5F pop di ; restore DI 545 00007E24 E313 jcxz award_found ; jmp if found 546 00007E26 47 inc di ; not found, inc di 547 00007E27 71F1 jno award_loop ; 548 ; 549 00007E29 07 award_failed: pop es ; No, not this way :-(( 550 award_fail2: ; 551 ; 552 %ifdef DEBUG_MESSAGES ; 553 ; 554 mov si,award_not_fail ; display failure ... 555 call writemsg ; 556 %endif ; 557 00007E2A 66A1[F101] mov eax,[award_oldint13] ; restore the original int 558 00007E2E 6609C0 or eax,eax ; 13 vector if there is one 559 00007E31 7428 jz spec_query_failed ; and try other workarounds 560 00007E33 66A34C00 mov [13h*4],eax ; 561 00007E37 EB22 jmp spec_query_failed ; 562 ; 563 00007E39 26668B450E award_found: mov eax,[es:di+0eh] ; load possible int 13 addr 564 00007E3E 07 pop es ; restore ES 565 ; 566 00007E3F 663B06[F101] cmp eax,[award_oldint13] ; give up if this is the 567 00007E44 74E3 jz award_failed ; active int 13 vector, 568 00007E46 66A34C00 mov [13h*4],eax ; otherwise change 0:13h*4 569 ; 570 ; 571 %ifdef DEBUG_MESSAGES ; 572 ; 573 push eax ; display message and 574 mov si,award_not_new ; new vector address 575 call writemsg ; 576 pop eax ; 577 call writehex8 ; 578 mov si,award_not_crlf ; 579 call writestr_early ; 580 %endif ; 581 00007E4A B8014B mov ax,4B01h ; try to read the spec packet 582 00007E4D 8A16[1720] mov dl,[DriveNumber] ; now ... it should not fail 583 00007E51 BE[3020] mov si,spec_packet ; any longer 584 00007E54 CD13 int 13h ; 585 00007E56 72D2 jc award_fail2 ; 586 ; 587 %ifdef DEBUG_MESSAGES ; 588 ; 589 mov si,award_not_succ ; display our SUCCESS 590 call writemsg ; 591 %endif ; 592 00007E58 E9BAFE jmp found_drive ; and leave error recovery code 593 ; 594 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 595 ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de 596 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 597 598 599 ; INT 13h, AX=4B01h, DL= failed. 600 ; Try to scan the entire 80h-FFh from the end. 601 602 spec_query_failed: 603 604 ; some code moved to BrokenAwardHack 605 606 00007E5B B2FF mov dl,0FFh 607 00007E5D 60 .test_loop: pusha 608 00007E5E B8014B mov ax,4B01h 609 00007E61 BE[3020] mov si,spec_packet 610 00007E64 C60413 mov byte [si],13h ; Size of buffer 611 00007E67 E89B00 call int13 612 00007E6A 61 popa 613 00007E6B 722E jc .still_broken 614 615 00007E6D BE[3606] mov si,maybe_msg 616 00007E70 E85500 call writemsg 617 00007E73 88D0 mov al,dl 618 00007E75 E88302 call writehex2 619 00007E78 E86E00 call crlf_early 620 621 00007E7B 3816[3220] cmp byte [sp_drive],dl 622 00007E7F 750D jne .maybe_broken 623 624 ; Okay, good enough... 625 00007E81 BE[5206] mov si,alright_msg 626 00007E84 E84100 call writemsg 627 00007E87 8816[1720] .found_drive0: mov [DriveNumber],dl 628 00007E8B E987FE .found_drive: jmp found_drive 629 630 ; Award BIOS 4.51 apparently passes garbage in sp_drive, 631 ; but if this was the drive number originally passed in 632 ; DL then consider it "good enough" 633 .maybe_broken: 634 00007E8E A0[1720] mov al,[DriveNumber] 635 00007E91 38D0 cmp al,dl 636 00007E93 74F6 je .found_drive 637 638 ; Intel Classic R+ computer with Adaptec 1542CP BIOS 1.02 639 ; passes garbage in sp_drive, and the drive number originally 640 ; passed in DL does not have 80h bit set. 641 00007E95 0C80 or al,80h 642 00007E97 38D0 cmp al,dl 643 00007E99 74EC je .found_drive0 644 645 00007E9B 4A .still_broken: dec dx 646 00007E9C 80FA80 cmp dl, 80h 647 00007E9F 73BC jnb .test_loop 648 649 ; No spec packet anywhere. Some particularly pathetic 650 ; BIOSes apparently don't even implement function 651 ; 4B01h, so we can't query a spec packet no matter 652 ; what. If we got a drive number in DL, then try to 653 ; use it, and if it works, then well... 654 00007EA1 8A16[1720] mov dl,[DriveNumber] 655 00007EA5 80FA81 cmp dl,81h ; Should be 81-FF at least 656 00007EA8 7216 jb fatal_error ; If not, it's hopeless 657 658 ; Write a warning to indicate we're on *very* thin ice now 659 00007EAA BE[7406] mov si,nospec_msg 660 00007EAD E81800 call writemsg 661 00007EB0 88D0 mov al,dl 662 00007EB2 E84602 call writehex2 663 00007EB5 E83100 call crlf_early 664 00007EB8 BE[DD06] mov si,trysbm_msg 665 00007EBB E80A00 call writemsg 666 00007EBE EBCB jmp .found_drive ; Pray that this works... 667 668 fatal_error: 669 00007EC0 BE[AF06] mov si,nothing_msg 670 00007EC3 E80200 call writemsg 671 672 00007EC6 EBFE .norge: jmp short .norge 673 674 ; Information message (DS:SI) output 675 ; Prefix with "isolinux: " 676 ; 677 00007EC8 50 writemsg: push ax 678 00007EC9 56 push si 679 00007ECA BE[8605] mov si,isolinux_str 680 00007ECD E80600 call writestr_early 681 00007ED0 5E pop si 682 00007ED1 E80200 call writestr_early 683 00007ED4 58 pop ax 684 00007ED5 C3 ret 685 686 writestr_early: 687 00007ED6 669C pushfd 688 00007ED8 6660 pushad 689 00007EDA AC .top: lodsb 690 00007EDB 20C0 and al,al 691 00007EDD 7405 jz .end 692 00007EDF E81400 call writechr 693 00007EE2 EBF6 jmp short .top 694 00007EE4 6661 .end: popad 695 00007EE6 669D popfd 696 00007EE8 C3 ret 697 698 00007EE9 50 crlf_early: push ax 699 00007EEA B00D mov al,CR 700 00007EEC E80700 call writechr 701 00007EEF B00A mov al,LF 702 00007EF1 E80200 call writechr 703 00007EF4 58 pop ax 704 00007EF5 C3 ret 705 706 ; 707 ; Write a character to the screen. There is a more "sophisticated" 708 ; version of this in the subsequent code, so we patch the pointer 709 ; when appropriate. 710 ; 711 712 writechr: 713 .simple: 714 00007EF6 669C pushfd 715 00007EF8 6660 pushad 716 00007EFA B40E mov ah,0Eh 717 00007EFC 31DB xor bx,bx 718 00007EFE CD10 int 10h 719 00007F00 6661 popad 720 00007F02 669D popfd 721 00007F04 C3 ret 722 723 ; 724 ; int13: save all the segment registers and call INT 13h. 725 ; Some CD-ROM BIOSes have been found to corrupt segment registers 726 ; and/or disable interrupts. 727 ; 728 int13: 729 00007F05 9C pushf 730 00007F06 55 push bp 731 00007F07 1E push ds 732 00007F08 06 push es 733 00007F09 0FA0 push fs 734 00007F0B 0FA8 push gs 735 00007F0D CD13 int 13h 736 00007F0F 89E5 mov bp,sp 737 00007F11 0F92460A setc [bp+10] ; Propagate CF to the caller 738 00007F15 0FA9 pop gs 739 00007F17 0FA1 pop fs 740 00007F19 07 pop es 741 00007F1A 1F pop ds 742 00007F1B 5D pop bp 743 00007F1C 9D popf 744 00007F1D C3 ret 745 746 ; 747 ; Get one sector. Convenience entry point. 748 ; 749 getonesec: 750 00007F1E BD0100 mov bp,1 751 ; Fall through to getlinsec 752 753 ; 754 ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors. 755 ; 756 ; Input: 757 ; EAX - Linear sector number 758 ; ES:BX - Target buffer 759 ; BP - Sector count 760 ; 761 global getlinsec 762 00007F21 2EFF26[1020] getlinsec: jmp word [cs:GetlinsecPtr] 763 764 %ifndef DEBUG_MESSAGES 765 766 ; 767 ; First, the variants that we use when actually loading off a disk 768 ; (hybrid mode.) These are adapted versions of the equivalent routines 769 ; in ldlinux.asm. 770 ; 771 772 ; 773 ; getlinsec_ebios: 774 ; 775 ; getlinsec implementation for floppy/HDD EBIOS (EDD) 776 ; 777 getlinsec_ebios: 778 00007F26 6631D2 xor edx,edx 779 00007F29 660FA4C202 shld edx,eax,2 780 00007F2E 66C1E002 shl eax,2 ; Convert to HDD sectors 781 00007F32 660306[2020] add eax,[Hidden] 782 00007F37 661316[2420] adc edx,[Hidden+4] 783 00007F3C C1E502 shl bp,2 784 785 .loop: 786 00007F3F 55 push bp ; Sectors left 787 .retry2: 788 00007F40 E8CB00 call maxtrans ; Enforce maximum transfer size 789 00007F43 660FB7FD movzx edi,bp ; Sectors we are about to read 790 00007F47 B90600 mov cx,retry_count 791 .retry: 792 793 ; Form DAPA on stack 794 00007F4A 6652 push edx 795 00007F4C 6650 push eax 796 00007F4E 06 push es 797 00007F4F 53 push bx 798 00007F50 57 push di 799 00007F51 6A10 push word 16 800 00007F53 89E6 mov si,sp 801 00007F55 6660 pushad 802 00007F57 8A16[1720] mov dl,[DriveNumber] 803 00007F5B 1E push ds 804 00007F5C 16 push ss 805 00007F5D 1F pop ds ; DS <- SS 806 00007F5E B442 mov ah,42h ; Extended Read 807 00007F60 E8A2FF call int13 808 00007F63 1F pop ds 809 00007F64 6661 popad 810 00007F66 8D6410 lea sp,[si+16] ; Remove DAPA 811 00007F69 7214 jc .error 812 00007F6B 5D pop bp 813 00007F6C 6601F8 add eax,edi ; Advance sector pointer 814 00007F6F 6683D200 adc edx,0 815 00007F73 29FD sub bp,di ; Sectors left 816 00007F75 C1E709 shl di,9 ; 512-byte sectors 817 00007F78 01FB add bx,di ; Advance buffer pointer 818 00007F7A 21ED and bp,bp 819 00007F7C 75C1 jnz .loop 820 821 00007F7E C3 ret 822 823 .error: 824 ; Some systems seem to get "stuck" in an error state when 825 ; using EBIOS. Doesn't happen when using CBIOS, which is 826 ; good, since some other systems get timeout failures 827 ; waiting for the floppy disk to spin up. 828 829 00007F7F 6660 pushad ; Try resetting the device 830 00007F81 31C0 xor ax,ax 831 00007F83 8A16[1720] mov dl,[DriveNumber] 832 00007F87 E87BFF call int13 833 00007F8A 6661 popad 834 00007F8C E2BC loop .retry ; CX-- and jump if not zero 835 836 ;shr word [MaxTransfer],1 ; Reduce the transfer size 837 ;jnz .retry2 838 839 ; Total failure. Try falling back to CBIOS. 840 00007F8E C706[1020][9703] mov word [GetlinsecPtr], getlinsec_cbios 841 ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer 842 843 00007F94 5D pop bp 844 00007F95 EB0F jmp getlinsec_cbios.loop 845 846 ; 847 ; getlinsec_cbios: 848 ; 849 ; getlinsec implementation for legacy CBIOS 850 ; 851 getlinsec_cbios: 852 00007F97 6631D2 xor edx,edx 853 00007F9A 66C1E002 shl eax,2 ; Convert to HDD sectors 854 00007F9E 660306[2020] add eax,[Hidden] 855 00007FA3 C1E502 shl bp,2 856 857 .loop: 858 00007FA6 6652 push edx 859 00007FA8 6650 push eax 860 00007FAA 55 push bp 861 00007FAB 53 push bx 862 863 00007FAC 660FB736[2820] movzx esi,word [bsSecPerTrack] 864 00007FB2 660FB73E[2A20] movzx edi,word [bsHeads] 865 ; 866 ; Dividing by sectors to get (track,sector): we may have 867 ; up to 2^18 tracks, so we need to use 32-bit arithmetric. 868 ; 869 00007FB8 66F7F6 div esi 870 00007FBB 31C9 xor cx,cx 871 00007FBD 87CA xchg cx,dx ; CX <- sector index (0-based) 872 ; EDX <- 0 873 ; eax = track # 874 00007FBF 66F7F7 div edi ; Convert track to head/cyl 875 876 ; We should test this, but it doesn't fit... 877 ; cmp eax,1023 878 ; ja .error 879 880 ; 881 ; Now we have AX = cyl, DX = head, CX = sector (0-based), 882 ; BP = sectors to transfer, SI = bsSecPerTrack, 883 ; ES:BX = data target 884 ; 885 886 00007FC2 E84900 call maxtrans ; Enforce maximum transfer size 887 888 ; Must not cross track boundaries, so BP <= SI-CX 889 00007FC5 29CE sub si,cx 890 00007FC7 39F5 cmp bp,si 891 00007FC9 7602 jna .bp_ok 892 00007FCB 89F5 mov bp,si 893 .bp_ok: 894 895 00007FCD C0E406 shl ah,6 ; Because IBM was STOOPID 896 ; and thought 8 bits were enough 897 ; then thought 10 bits were enough... 898 00007FD0 41 inc cx ; Sector numbers are 1-based, sigh 899 00007FD1 08E1 or cl,ah 900 00007FD3 88C5 mov ch,al 901 00007FD5 88D6 mov dh,dl 902 00007FD7 8A16[1720] mov dl,[DriveNumber] 903 00007FDB 95 xchg ax,bp ; Sector to transfer count 904 00007FDC B402 mov ah,02h ; Read sectors 905 00007FDE BD0600 mov bp,retry_count 906 .retry: 907 00007FE1 6660 pushad 908 00007FE3 E81FFF call int13 909 00007FE6 6661 popad 910 00007FE8 7217 jc .error 911 .resume: 912 00007FEA 660FB6C8 movzx ecx,al ; ECX <- sectors transferred 913 00007FEE C1E009 shl ax,9 ; Convert sectors in AL to bytes in AX 914 00007FF1 5B pop bx 915 00007FF2 01C3 add bx,ax 916 00007FF4 5D pop bp 917 00007FF5 6658 pop eax 918 00007FF7 665A pop edx 919 00007FF9 6601C8 add eax,ecx 920 00007FFC 29CD sub bp,cx 921 00007FFE 75A6 jnz .loop 922 00008000 C3 ret 923 924 .error: 925 00008001 4D dec bp 926 00008002 75DD jnz .retry 927 928 00008004 95 xchg ax,bp ; Sectors transferred <- 0 929 00008005 D12E[9C07] shr word [MaxTransfer],1 930 00008009 75DF jnz .resume 931 0000800B E9B500 jmp disk_error 932 933 ; 934 ; Truncate BP to MaxTransfer 935 ; 936 maxtrans: 937 0000800E 3B2E[9C07] cmp bp,[MaxTransfer] 938 00008012 7604 jna .ok 939 00008014 8B2E[9C07] mov bp,[MaxTransfer] 940 00008018 C3 .ok: ret 941 942 %endif 943 944 ; 945 ; This is the variant we use for real CD-ROMs: 946 ; LBA, 2K sectors, some special error handling. 947 ; 948 getlinsec_cdrom: 949 00008019 BE[9020] mov si,dapa ; Load up the DAPA 950 0000801C 895C04 mov [si+4],bx 951 0000801F 8C4406 mov [si+6],es 952 00008022 66894408 mov [si+8],eax 953 .loop: 954 00008026 55 push bp ; Sectors left 955 00008027 3B2E[9E07] cmp bp,[MaxTransferCD] 956 0000802B 7604 jbe .bp_ok 957 0000802D 8B2E[9E07] mov bp,[MaxTransferCD] 958 .bp_ok: 959 00008031 896C02 mov [si+2],bp 960 00008034 56 push si 961 00008035 8A16[1720] mov dl,[DriveNumber] 962 00008039 B442 mov ah,42h ; Extended Read 963 0000803B E81C00 call xint13 964 0000803E 5E pop si 965 0000803F 5D pop bp 966 00008040 660FB74402 movzx eax,word [si+2] ; Sectors we read 967 00008045 66014408 add [si+8],eax ; Advance sector pointer 968 00008049 29C5 sub bp,ax ; Sectors left 969 0000804B C1E007 shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment 970 0000804E 014406 add [si+6],ax ; Advance buffer pointer 971 00008051 21ED and bp,bp 972 00008053 75D1 jnz .loop 973 00008055 668B4408 mov eax,[si+8] ; Next sector 974 00008059 C3 ret 975 976 ; INT 13h with retry 977 0000805A C606[1920]06 xint13: mov byte [RetryCount],retry_count 978 0000805F 6660 .try: pushad 979 00008061 E8A1FE call int13 980 00008064 7204 jc .error 981 00008066 83C420 add sp,byte 8*4 ; Clean up stack 982 00008069 C3 ret 983 .error: 984 0000806A 8826[1620] mov [DiskError],ah ; Save error code 985 0000806E 6661 popad 986 00008070 A3[0C20] mov [DiskSys],ax ; Save system call number 987 00008073 FE0E[1920] dec byte [RetryCount] 988 00008077 7424 jz .real_error 989 00008079 50 push ax 990 0000807A A0[1920] mov al,[RetryCount] 991 0000807D 8A26[9220] mov ah,[dapa+2] ; Sector transfer count 992 00008081 3C02 cmp al,2 ; Only 2 attempts left 993 00008083 7704 ja .nodanger 994 00008085 B401 mov ah,1 ; Drop transfer size to 1 995 00008087 EB09 jmp short .setsize 996 .nodanger: 997 00008089 3C04 cmp al,retry_count-2 998 0000808B 770D ja .again ; First time, just try again 999 0000808D D0EC shr ah,1 ; Otherwise, try to reduce 1000 0000808F 80D400 adc ah,0 ; the max transfer size, but not to 0 1001 .setsize: 1002 00008092 8826[9E07] mov [MaxTransferCD],ah 1003 00008096 8826[9220] mov [dapa+2],ah 1004 .again: 1005 0000809A 58 pop ax 1006 0000809B EBC2 jmp .try 1007 1008 0000809D BE[1707] .real_error: mov si,diskerr_msg 1009 000080A0 E825FE call writemsg 1010 000080A3 A0[1620] mov al,[DiskError] 1011 000080A6 E85200 call writehex2 1012 000080A9 BE[2307] mov si,oncall_str 1013 000080AC E827FE call writestr_early 1014 000080AF A1[0C20] mov ax,[DiskSys] 1015 000080B2 E85300 call writehex4 1016 000080B5 BE[2B07] mov si,ondrive_str 1017 000080B8 E81BFE call writestr_early 1018 000080BB 88D0 mov al,dl 1019 000080BD E83B00 call writehex2 1020 000080C0 E826FE call crlf_early 1021 ; Fall through to kaboom 1022 1023 ; 1024 ; kaboom: write a message and bail out. Wait for a user keypress, 1025 ; then do a hard reboot. 1026 ; 1027 global kaboom 1028 disk_error: 1029 kaboom: 1030 RESET_STACK_AND_SEGS AX 1030 000080C3 31C0 <1> xor %1,%1 1030 000080C5 8ED8 <1> mov ds,%1 1030 000080C7 8EC0 <1> mov es,%1 1030 000080C9 660FB226[0000] <1> lss esp,[BaseStack] 1030 000080CF 66C706[3800]- <1> mov dword [PMESP],__stack_end 1030 000080D4 [00000000] <1> 1030 000080D8 FB <1> sti 1030 000080D9 FC <1> cld 1031 000080DA BE[5507] mov si,bailmsg 1032 pm_call pm_writestr 1032 000080DD 6668[00000000] <1> push dword %1 1032 000080E3 E8(8F00) <1> call _pm_call 1033 pm_call pm_getchar 1033 000080E6 6668[00000000] <1> push dword %1 1033 000080EC E8(8F00) <1> call _pm_call 1034 000080EF FA cli 1035 000080F0 C70672040000 mov word [BIOS_magic],0 ; Cold reboot 1036 000080F6 EAF0FF00F0 jmp 0F000h:0FFF0h ; Reset vector address 1037 1038 ; ----------------------------------------------------------------------------- 1039 ; Common modules needed in the first sector 1040 ; ----------------------------------------------------------------------------- 1041 1042 %include "writehex.inc" ; Hexadecimal output 1 <1> ;; ----------------------------------------------------------------------- 2 <1> ;; 3 <1> ;; Copyright 1994-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> ;; writehex.inc 15 <1> ;; 16 <1> ;; Write hexadecimal numbers to the console 17 <1> ;; 18 <1> 19 <1> ; 20 <1> ; writehex[248]: Write a hex number in (AL, AX, EAX) to the console 21 <1> ; 22 <1> writehex2: 23 000080FB 669C <1> pushfd 24 000080FD 6660 <1> pushad 25 000080FF 66C1C018 <1> rol eax,24 26 00008103 B90200 <1> mov cx,2 27 00008106 EB14 <1> jmp short writehex_common 28 <1> writehex4: 29 00008108 669C <1> pushfd 30 0000810A 6660 <1> pushad 31 0000810C 66C1C010 <1> rol eax,16 32 00008110 B90400 <1> mov cx,4 33 00008113 EB07 <1> jmp short writehex_common 34 <1> writehex8: 35 00008115 669C <1> pushfd 36 00008117 6660 <1> pushad 37 00008119 B90800 <1> mov cx,8 38 <1> writehex_common: 39 0000811C 66C1C004 <1> .loop: rol eax,4 40 00008120 6650 <1> push eax 41 00008122 240F <1> and al,0Fh 42 00008124 3C0A <1> cmp al,10 43 00008126 7304 <1> jae .high 44 00008128 0430 <1> .low: add al,'0' 45 0000812A EB02 <1> jmp short .ischar 46 0000812C 0437 <1> .high: add al,'A'-10 47 0000812E E8C5FD <1> .ischar: call writechr 48 00008131 6658 <1> pop eax 49 00008133 E2E7 <1> loop .loop 50 00008135 6661 <1> popad 51 00008137 669D <1> popfd 52 00008139 C3 <1> ret 1043 1044 ; ----------------------------------------------------------------------------- 1045 ; Data that needs to be in the first sector 1046 ; ----------------------------------------------------------------------------- 1047 1048 global syslinux_banner, copyright_str 1049 0000813A 0D0A49534F4C494E55- syslinux_banner db CR, LF, MY_NAME, ' ', VERSION_STR, ' ', DATE_STR, ' ', 0 1049 00008143 5820362E303420362E- 1049 0000814C 30342D707265322A20- 1049 00008155 00 1050 00008156 20436F707972696768- copyright_str db ' Copyright (C) 1994-' 1050 0000815F 742028432920313939- 1050 00008168 342D 1051 0000816A 32303135 asciidec YEAR 1052 0000816E 20482E205065746572- db ' H. Peter Anvin et al', CR, LF, 0 1052 00008177 20416E76696E206574- 1052 00008180 20616C0D0A00 1053 00008186 69736F6C696E75783A- isolinux_str db 'isolinux: ', 0 1053 0000818F 2000 1054 %ifdef DEBUG_MESSAGES 1055 startup_msg: db 'Starting up, DL = ', 0 1056 spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0 1057 secsize_msg: db 'Sector size ', 0 1058 offset_msg: db 'Main image LBA = ', 0 1059 verify_msg: db 'Image csum verified.', CR, LF, 0 1060 allread_msg db 'Image read, jumping to main code...', CR, LF, 0 1061 %endif 1062 00008191 4E6F20626F6F742069- noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0 1062 0000819A 6E666F207461626C65- 1062 000081A3 2C20617373756D696E- 1062 000081AC 672073696E676C6520- 1062 000081B5 73657373696F6E2064- 1062 000081BE 69736B2E2E2E0D0A00 1063 000081C7 53706563207061636B- noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0 1063 000081D0 6574206D697373696E- 1063 000081D9 67204C424120696E66- 1063 000081E2 6F726D6174696F6E2C- 1063 000081EB 20747279696E672074- 1063 000081F4 6F2077696E67206974- 1063 000081FD 2E2E2E0D0A00 1064 00008203 4C6F6164696E672073- spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0 1064 0000820C 706563207061636B65- 1064 00008215 74206661696C65642C- 1064 0000821E 20747279696E672074- 1064 00008227 6F2077696E67206974- 1064 00008230 2E2E2E0D0A00 1065 00008236 466F756E6420736F6D- maybe_msg: db 'Found something at drive = ', 0 1065 0000823F 657468696E67206174- 1065 00008248 206472697665203D20- 1065 00008251 00 1066 00008252 4C6F6F6B7320726561- alright_msg: db 'Looks reasonable, continuing...', CR, LF, 0 1066 0000825B 736F6E61626C652C20- 1066 00008264 636F6E74696E75696E- 1066 0000826D 672E2E2E0D0A00 1067 00008274 45787472656D656C79- nospec_msg db 'Extremely broken BIOS detected, last attempt with drive = ', 0 1067 0000827D 2062726F6B656E2042- 1067 00008286 494F53206465746563- 1067 0000828F 7465642C206C617374- 1067 00008298 20617474656D707420- 1067 000082A1 776974682064726976- 1067 000082AA 65203D2000 1068 000082AF 4661696C656420746F- nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF 1068 000082B8 206C6F636174652043- 1068 000082C1 442D524F4D20646576- 1068 000082CA 6963653B20626F6F74- 1068 000082D3 206661696C65642E0D- 1068 000082DC 0A 1069 000082DD 53656520687474703A- trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0 1069 000082E6 2F2F7379736C696E75- 1069 000082EF 782E7A79746F722E63- 1069 000082F8 6F6D2F73626D20666F- 1069 00008301 72206D6F726520696E- 1069 0000830A 666F726D6174696F6E- 1069 00008313 2E0D0A00 1070 00008317 4469736B206572726F- diskerr_msg: db 'Disk error ', 0 1070 00008320 722000 1071 00008323 2C204158203D2000 oncall_str: db ', AX = ',0 1072 0000832B 2C2064726976652000 ondrive_str: db ', drive ', 0 1073 00008334 496D61676520636865- checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0 1073 0000833D 636B73756D20657272- 1073 00008346 6F722C20736F727279- 1073 0000834F 2E2E2E0D0A00 1074 1075 00008355 0D0A426F6F74206661- err_bootfailed db CR, LF, 'Boot failed: press a key to retry...' 1075 0000835E 696C65643A20707265- 1075 00008367 73732061206B657920- 1075 00008370 746F2072657472792E- 1075 00008379 2E2E 1076 bailmsg equ err_bootfailed 1077 0000837B 0D0A crlf_msg db CR, LF 1078 0000837D 00 null_msg db 0 1079 1080 0000837E 4554434400 bios_cdrom_str db 'ETCD', 0 1081 %ifndef DEBUG_MESSAGES 1082 00008383 4348444400 bios_cbios_str db 'CHDD', 0 1083 00008388 4548444400 bios_ebios_str db 'EHDD' ,0 1084 %endif 1085 1086 0000838D 00 alignz 4 1087 global bios_cdrom 1088 00008390 [1904][7E07] bios_cdrom: dw getlinsec_cdrom, bios_cdrom_str 1089 %ifndef DEBUG_MESSAGES 1090 00008394 [9703][8307] bios_cbios: dw getlinsec_cbios, bios_cbios_str 1091 00008398 [2603][8807] bios_ebios: dw getlinsec_ebios, bios_ebios_str 1092 %endif 1093 1094 ; Maximum transfer size 1095 0000839C 7F00 MaxTransfer dw 127 ; Hard disk modes 1096 0000839E 2000 MaxTransferCD dw 32 ; CD mode 1097 1098 rl_checkpt equ $ ; Must be <= 800h 1099 1100 ; This pads to the end of sector 0 and errors out on 1101 ; overflow. 1102 000083A0 00 times 2048-($-$$) db 0 1103 1104 ; ---------------------------------------------------------------------------- 1105 ; End of code and data that have to be in the first sector 1106 ; ---------------------------------------------------------------------------- 1107 1108 section .text16 1109 1110 all_read: 1111 1112 ; Test tracers 1113 TRACER 'T' 1114 TRACER '>' 1115 1116 ; 1117 ; Common initialization code 1118 ; 1119 %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 00008400 E80F02 <1> call pm_init 25 <1> 26 <1> %if IS_PXELINUX 27 <1> ; Save derivative-specific data 28 <1> pm_call pm_save_data 29 <1> %endif 30 <1> 31 <1> ; Decompress PM code to its target location 32 <1> pm_call pm_decompress 32 00008403 6668[00000000] <2> push dword %1 32 00008409 E88300 <2> call _pm_call 33 0000840C 663D[00000000] <1> cmp eax,__pm_code_len 34 00008412 0F85(C304) <1> jne kaboom 35 <1> 36 <1> extern syslinux_register_bios, init 37 <1> 38 <1> pm_call syslinux_register_bios 38 00008416 6668[00000000] <2> push dword %1 38 0000841C E87000 <2> call _pm_call 39 <1> pm_call init 39 0000841F 6668[00000000] <2> push dword %1 39 00008425 E86700 <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 00008950 68[10000000] <1> push __pm_code_len + 16 ; Space for decompressed size 50 00008955 54 <1> push esp ; Pointer to previous word 51 00008956 68[00000000] <1> push __pm_code_start ; Target address 52 0000895B FF35[06000000] <1> push dword [lzo_data_size] ; Compressed size 53 00008961 68[00000000] <1> push dword __pm_code_lma 54 00008966 E8(00000000) <1> call _lzo1x_decompress_asm_fast_safe 55 0000896B 83C410 <1> add esp,16 56 0000896E 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 00008971 31C0 <1> xor eax,eax 61 00008973 BF[00000000] <1> mov edi,__bss_start 62 00008978 B9[00000000] <1> mov ecx,__bss_dwords 63 0000897D F3AB <1> rep stosd 64 0000897F BF[00000000] <1> mov edi,__bss16_start 65 00008984 B9[00000000] <1> mov ecx,__bss16_dwords 66 00008989 F3AB <1> rep stosd 67 0000898B BF[00000000] <1> mov edi,__high_clear_start ; .uibss, .lowmem 68 00008990 B9[00000000] <1> mov ecx,__high_clear_dwords 69 00008995 F3AB <1> rep stosd 70 <1> 71 00008997 C3 <1> ret 72 <1> 73 <1> section .data16 74 00008E46 00000000 <1> lzo_data_size dd 0 ; filled in by compressor 75 <1> 76 <1> section .text16 77 <1> bits 16 1120 1121 ; Tell the user we got this far... 1122 %ifndef DEBUG_MESSAGES ; Gets messy with debugging on 1123 00008428 BE[5605] mov si,copyright_str 1124 pm_call pm_writestr 1124 0000842B 6668[00000000] <1> push dword %1 1124 00008431 E85B00 <1> call _pm_call 1125 %endif 1126 1127 ; 1128 ; Now we're all set to start with our *real* business. First load the 1129 ; configuration file (if any) and parse it. 1130 ; 1131 ; In previous versions I avoided using 32-bit registers because of a 1132 ; rumour some BIOSes clobbered the upper half of 32-bit registers at 1133 ; random. I figure, though, that if there are any of those still left 1134 ; they probably won't be trying to install Linux on them... 1135 ; 1136 ; The code is still ripe with 16-bitisms, though. Not worth the hassle 1137 ; to take'm out. In fact, we may want to put them back if we're going 1138 ; to boot ELKS at some point. 1139 ; 1140 1141 ; 1142 ; Now, we need to sniff out the actual filesystem data structures. 1143 ; mkisofs gave us a pointer to the primary volume descriptor 1144 ; (which will be at 16 only for a single-session disk!); from the PVD 1145 ; we should be able to find the rest of what we need to know. 1146 ; 1147 init_fs: 1148 00008434 6660 pushad 1149 00008436 66B8[00000000] mov eax,ROOT_FS_OPS 1150 0000843C 8A16[1720] mov dl,[DriveNumber] 1151 00008440 813E[1420][9007] cmp word [BIOSType],bios_cdrom 1152 00008446 0F94C6 sete dh ; 1 for cdrom, 0 for hybrid mode 1153 00008449 7508 jne .hybrid 1154 0000844B 660FB72E[9E07] movzx ebp,word [MaxTransferCD] 1155 00008451 EB06 jmp .common 1156 .hybrid: 1157 00008453 660FB72E[9C07] movzx ebp,word [MaxTransfer] 1158 .common: 1159 00008459 668B0E[2020] mov ecx,[Hidden] 1160 0000845E 668B1E[2420] mov ebx,[Hidden+4] 1161 00008463 8B36[2A20] mov si,[bsHeads] 1162 00008467 8B3E[2820] mov di,[bsSecPerTrack] 1163 pm_call pm_fs_init 1163 0000846B 6668[00000000] <1> push dword %1 1163 00008471 E81B00 <1> call _pm_call 1164 pm_call load_env32 1164 00008474 6668[00000000] <1> push dword %1 1164 0000847A E81200 <1> call _pm_call 1165 enter_command: 1166 auto_boot: 1167 0000847D E9(C304) jmp kaboom ; load_env32() should never return. If 1168 ; it does, then kaboom! 1169 00008480 6661 popad 1170 1171 section .rodata 1172 alignz 4 1173 ROOT_FS_OPS: 1174 extern iso_fs_ops 1175 00108900 [00000000] dd iso_fs_ops 1176 00108904 00000000 dd 0 1177 1178 section .text16 1179 1180 %ifdef DEBUG_TRACERS 1181 ; 1182 ; debug hack to print a character with minimal code impact 1183 ; 1184 debug_tracer: pushad 1185 pushfd 1186 mov bp,sp 1187 mov bx,[bp+9*4] ; Get return address 1188 mov al,[cs:bx] ; Get data byte 1189 inc word [bp+9*4] ; Return to after data byte 1190 call writechr 1191 popfd 1192 popad 1193 ret 1194 %endif ; DEBUG_TRACERS 1195 1196 section .bss16 1197 alignb 4 1198 000038C0 ThisKbdTo resd 1 ; Temporary holder for KbdTimeout 1199 000038C4 ThisTotalTo resd 1 ; Temporary holder for TotalTimeout 1200 000038C8 KernelExtPtr resw 1 ; During search, final null pointer 1201 000038CA FuncFlag resb 1 ; Escape sequences received from keyboard 1202 000038CB KernelType resb 1 ; Kernel type, from vkernel, if known 1203 global KernelName 1204 000038CC KernelName resb FILENAME_MAX ; Mangled name for kernel 1205 1206 section .text16 1207 ; 1208 ; COM32 vestigial data structure 1209 ; 1210 %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 00008E4A 00 <1> alignz 4 43 <1> __entry_esp: 44 00008E4C 00000000 <1> dd 0 ; Dummy to avoid _exit issues 45 <1> __com32: 46 00008E50 09000000 <1> dd 9 ; Argument count 47 00008E54 00000000 <1> dd 0 ; No command line 48 00008E58 [06000000] <1> dd core_intcall ; Intcall entry point 49 00008E5C 00000000 <1> dd 0 ; Bounce buffer address 50 00008E60 00000000 <1> dd 0 ; 64K bounce buffer 51 00008E64 [00000000] <1> dd core_farcall ; Farcall entry point 52 00008E68 [A6000000] <1> dd core_cfarcall ; Cfarcall entry point 53 00008E6C 00000000 <1> HighMemSize dd 0 ; End of memory pointer (bytes) 54 00008E70 00000000 <1> dd 0 ; No module name 55 00008E74 [00000000] <1> dd pm_api_vector ; Protected mode functions 56 <1> 57 <1> section .uibss 58 00009400 <1> Com32Name resb FILENAME_MAX 59 <1> 60 <1> section .bss16 61 <1> %ifndef HAVE_CURRENTDIRNAME 62 <1> global CurrentDirName:data hidden 63 000039CC <1> CurrentDirName resb FILENAME_MAX 64 <1> %endif 65 <1> 66 <1> section .text16 1211 1212 ; 1213 ; Common local boot code 1214 ; 1215 %include "localboot.inc" 1 <1> section .text16 2 <1> global local_boot16:function hidden 3 <1> local_boot16: 4 00008482 B90000 <1> mov cx,0 5 00008485 8ED1 <1> mov ss,cx 6 00008487 BC007C <1> mov sp,7C00h 7 0000848A EA007C0000 <1> jmp 0:07C00h 1216 1217 ; ----------------------------------------------------------------------------- 1218 ; Common modules 1219 ; ----------------------------------------------------------------------------- 1220 1221 %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 0000848F 669C <2> pushfd 40 00008491 6660 <2> pushad 41 00008493 1E <2> push ds 42 00008494 06 <2> push es 43 00008495 0FA0 <2> push fs 44 00008497 0FA8 <2> push gs 45 00008499 89E5 <2> mov bp,sp 46 0000849B 8CC8 <2> mov ax,cs 47 0000849D 66BB[48000000] <2> mov ebx,.pm 48 000084A3 8ED8 <2> mov ds,ax 49 000084A5 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 00008998 F6452902 <2> test RM_FLAGSH,02h ; RM EFLAGS.IF 56 0000899C 7401 <2> jz .no_sti 57 0000899E FB <2> sti 58 <2> .no_sti: 59 0000899F FF552E <2> call [ebp+4*2+9*4+2] ; Entrypoint on RM stack 60 000089A2 66BB[A700] <2> mov bx,.rm 61 000089A6 EB20 <2> jmp enter_rm 62 <2> 63 <2> bits 16 64 <2> section .text16 65 <2> .rm: 66 000084A7 0FA9 <2> pop gs 67 000084A9 0FA1 <2> pop fs 68 000084AB 07 <2> pop es 69 000084AC 1F <2> pop ds 70 000084AD 6661 <2> popad 71 000084AF 669D <2> popfd 72 000084B1 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 000084B4 FA <2> cli 89 000084B5 6631C0 <2> xor eax,eax 90 000084B8 8ED8 <2> mov ds,ax 91 000084BA 8CD0 <2> mov ax,ss 92 000084BC 8926[B828] <2> mov [RealModeSSSP],sp 93 000084C0 A3[BA28] <2> mov [RealModeSSSP+2],ax 94 000084C3 660FB7EC <2> movzx ebp,sp 95 000084C7 66C1E004 <2> shl eax,4 96 000084CB 6601C5 <2> add ebp,eax ; EBP -> top of real-mode stack 97 000084CE FC <2> cld 98 000084CF E86400 <2> call enable_a20 99 <2> 100 <2> .a20ok: 101 000084D2 C606[0D00]89 <2> mov byte [bcopy_gdt.TSS+5],89h ; Mark TSS unbusy 102 <2> 103 000084D7 0F0116[0000] <2> lgdt [bcopy_gdt] ; We can use the same GDT just fine 104 000084DC 0F011E[3C00] <2> lidt [PM_IDT_ptr] ; Set up the IDT 105 000084E1 0F20C0 <2> mov eax,cr0 106 000084E4 0C01 <2> or al,1 107 000084E6 0F22C0 <2> mov cr0,eax ; Enter protected mode 108 000084E9 EA[5800]2000 <2> jmp PM_CS32:.in_pm 109 <2> 110 <2> bits 32 111 <2> section .textnr 112 <2> .in_pm: 113 000089A8 31C0 <2> xor eax,eax ; Available for future use... 114 000089AA 8EE0 <2> mov fs,eax 115 000089AC 8EE8 <2> mov gs,eax 116 000089AE 0F00D0 <2> lldt ax 117 <2> 118 000089B1 B028 <2> mov al,PM_DS32 ; Set up data segments 119 000089B3 8EC0 <2> mov es,eax 120 000089B5 8ED8 <2> mov ds,eax 121 000089B7 8ED0 <2> mov ss,eax 122 <2> 123 000089B9 B008 <2> mov al,PM_TSS ; Be nice to Intel's VT by 124 000089BB 0F00D8 <2> ltr ax ; giving it a valid TR 125 <2> 126 000089BE 8B25[38000000] <2> mov esp,[PMESP] ; Load protmode %esp 127 000089C4 89E8 <2> mov eax,ebp ; EAX -> top of real-mode stack 128 000089C6 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 000089C8 FA <2> cli 145 000089C9 FC <2> cld 146 000089CA 8925[38000000] <2> mov [PMESP],esp ; Save exit %esp 147 000089D0 EA[EE000000]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 000084EE B81800 <2> mov ax,PM_DS16 ; Real-mode-like segment 153 000084F1 8EC0 <2> mov es,ax 154 000084F3 8ED8 <2> mov ds,ax 155 000084F5 8ED0 <2> mov ss,ax 156 000084F7 8EE0 <2> mov fs,ax 157 000084F9 8EE8 <2> mov gs,ax 158 <2> 159 000084FB 0F011E[3000] <2> lidt [RM_IDT_ptr] ; Real-mode IDT (rm needs no GDT) 160 00008500 31D2 <2> xor dx,dx 161 00008502 0F20C0 <2> mov eax,cr0 162 00008505 24FE <2> and al,~1 163 00008507 0F22C0 <2> mov cr0,eax 164 0000850A EA[0F01]0000 <2> jmp 0:.in_rm 165 <2> 166 <2> .in_rm: ; Back in real mode 167 0000850F 2E0FB226[B828] <2> lss sp,[cs:RealModeSSSP] ; Restore stack 168 00008515 660FB7E4 <2> movzx esp,sp ; Make sure the high bits are zero 169 00008519 8EDA <2> mov ds,dx ; Set up sane segments 170 0000851B 8EC2 <2> mov es,dx 171 0000851D 8EE2 <2> mov fs,dx 172 0000851F 8EEA <2> mov gs,dx 173 00008521 FFE3 <2> jmp bx ; Go to whereever we need to go... 174 <2> 175 <2> section .data16 176 <2> alignz 4 177 <2> 178 <2> extern __stack_end 179 00008E78 [00000000] <2> PMESP dd __stack_end ; Protected-mode ESP 180 <2> 181 00008E7C FF07 <2> PM_IDT_ptr: dw 8*256-1 ; Length 182 00008E7E [B8200000] <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 000089D7 60 <2> pushad 196 000089D8 0FB6742420 <2> movzx esi,byte [esp+8*4] ; Interrupt number 197 000089DD FF05[18020000] <2> inc dword [CallbackCtr] 198 000089E3 BB[23010000] <2> mov ebx,.rm 199 000089E8 EBDE <2> jmp enter_rm ; Go to real mode 200 <2> 201 <2> bits 16 202 <2> section .text16 203 <2> .rm: 204 00008523 9C <2> pushf ; Flags on stack 205 00008524 2E67FF1CB500000000 <2> call far [cs:esi*4] ; Call IVT entry 206 0000852D 66BB[9A000000] <2> mov ebx,.pm 207 00008533 E97EFF <2> jmp enter_pm ; Go back to PM 208 <2> 209 <2> bits 32 210 <2> section .textnr 211 <2> .pm: 212 000089EA FF0D[18020000] <2> dec dword [CallbackCtr] 213 000089F0 7506 <2> jnz .skip 214 000089F2 FF15[44000000] <2> call [core_pm_hook] 215 <2> .skip: 216 000089F8 61 <2> popad 217 000089F9 83C404 <2> add esp,4 ; Drop interrupt number 218 000089FC 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 000089FD C3 <2> ret 228 <2> 229 <2> section .data16 230 00008E82 00 <2> alignz 4 231 <2> global core_pm_hook 232 00008E84 [AD000000] <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 00008E88 [4801] <2> A20Ptr dw a20_dunno 247 <2> 248 <2> section .bss16 249 <2> alignb 4 250 00003ACC <2> A20Test resd 1 ; Counter for testing A20 status 251 00003AD0 <2> A20Tries resb 1 ; Times until giving up on A20 252 <2> 253 <2> section .text16 254 <2> enable_a20: 255 00008536 6660 <2> pushad 256 00008538 2EC606[1002]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 0000853E E87C00 <2> call a20_test 266 00008541 7577 <2> jnz a20_done 267 <2> ; Otherwise, see if we had something memorized... 268 00008543 2EFF26[4800] <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 00008548 2EC706[4800][4801] <2> mov word [cs:A20Ptr], a20_bios 276 0000854F B80124 <2> mov ax,2401h 277 00008552 9C <2> pushf ; Some BIOSes muck with IF 278 00008553 CD15 <2> int 15h 279 00008555 9D <2> popf 280 <2> 281 00008556 E86400 <2> call a20_test 282 00008559 755F <2> jnz a20_done 283 <2> 284 <2> ; 285 <2> ; Enable the keyboard controller A20 gate 286 <2> ; 287 <2> a20_kbc: 288 0000855B B201 <2> mov dl, 1 ; Allow early exit 289 0000855D E88E00 <2> call empty_8042 290 00008560 7558 <2> jnz a20_done ; A20 live, no need to use KBC 291 <2> 292 00008562 2EC706[4800][5B01] <2> mov word [cs:A20Ptr], a20_kbc ; Starting KBC command sequence 293 <2> 294 00008569 B0D1 <2> mov al,0D1h ; Write output port 295 0000856B E664 <2> out 064h, al 296 0000856D E87C00 <2> call empty_8042_uncond 297 <2> 298 00008570 B0DF <2> mov al,0DFh ; A20 on 299 00008572 E660 <2> out 060h, al 300 00008574 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 00008577 B0FF <2> mov al,0FFh ; Null command 306 00008579 E664 <2> out 064h, al 307 0000857B 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 0000857E 51 <2> .kbc_wait: push cx 316 0000857F 31C9 <2> xor cx,cx 317 <2> .kbc_wait_loop: 318 00008581 E83900 <2> call a20_test 319 00008584 7533 <2> jnz a20_done_pop 320 00008586 E2F9 <2> loop .kbc_wait_loop 321 <2> 322 00008588 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 00008589 2EC706[4800][8901] <2> mov word [cs:A20Ptr], a20_fast 328 00008590 E492 <2> in al, 092h 329 00008592 0C02 <2> or al,02h 330 00008594 24FE <2> and al,~01h ; Don't accidentally reset the machine! 331 00008596 E692 <2> out 092h, al 332 <2> 333 00008598 51 <2> .fast_wait: push cx 334 00008599 31C9 <2> xor cx,cx 335 <2> .fast_wait_loop: 336 0000859B E81F00 <2> call a20_test 337 0000859E 7519 <2> jnz a20_done_pop 338 000085A0 E2F9 <2> loop .fast_wait_loop 339 <2> 340 000085A2 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 000085A3 2EFE0E[1002] <2> dec byte [cs:A20Tries] 347 000085A8 759E <2> jnz a20_dunno ; Did we get the wrong type? 348 <2> 349 000085AA BE[4A00] <2> mov si, err_a20 350 <2> pm_call pm_writestr 350 000085AD 6668[00000000] <3> push dword %1 350 000085B3 E8D9FE <3> call _pm_call 351 000085B6 E9(C304) <2> jmp kaboom 352 <2> 353 <2> section .data16 354 00008E8A 0D0A41323020676174- <2> err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0 354 00008E93 65206E6F7420726573- <2> 354 00008E9C 706F6E64696E67210D- <2> 354 00008EA5 0A00 <2> 355 <2> section .text16 356 <2> 357 <2> ; 358 <2> ; A20 unmasked, proceed... 359 <2> ; 360 000085B9 59 <2> a20_done_pop: pop cx 361 000085BA 6661 <2> a20_done: popad 362 000085BC 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 000085BD 06 <2> push es 373 000085BE 51 <2> push cx 374 000085BF 6650 <2> push eax 375 000085C1 B9FFFF <2> mov cx,0FFFFh ; HMA = segment 0FFFFh 376 000085C4 8EC1 <2> mov es,cx 377 000085C6 2E66A1[0C02] <2> mov eax,[cs:A20Test] 378 000085CB B92000 <2> mov cx,32 ; Loop count 379 000085CE EB0F <2> jmp .test ; First iteration = early out 380 000085D0 660541EA0A43 <2> .wait: add eax,0x430aea41 ; A large prime number 381 000085D6 2E66A3[0C02] <2> mov [cs:A20Test],eax 382 000085DB E680E680 <2> io_delay ; Serialize, and fix delay 383 000085DF 26663B06[1C02] <2> .test: cmp eax,[es:A20Test+10h] 384 000085E5 E1E9 <2> loopz .wait 385 000085E7 6658 <2> .done: pop eax 386 000085E9 59 <2> pop cx 387 000085EA 07 <2> pop es 388 000085EB 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 000085EC 30D2 <2> xor dl,dl 397 <2> empty_8042: 398 000085EE E8CCFF <2> call a20_test 399 000085F1 7404 <2> jz .a20_on 400 000085F3 20D2 <2> and dl,dl 401 000085F5 751A <2> jnz .done 402 000085F7 E680E680 <2> .a20_on: io_delay 403 000085FB E464 <2> in al, 064h ; Status port 404 000085FD A801 <2> test al,1 405 000085FF 7408 <2> jz .no_output 406 00008601 E680E680 <2> io_delay 407 00008605 E460 <2> in al, 060h ; Read input 408 00008607 EBE5 <2> jmp short empty_8042 409 <2> .no_output: 410 00008609 A802 <2> test al,2 411 0000860B 75E1 <2> jnz empty_8042 412 0000860D E680E680 <2> io_delay 413 00008611 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 00008612 6631FF <2> xor edi,edi 421 00008615 BB[B820] <2> mov bx,IDT 422 00008618 BF[0000] <2> mov di,IRQStubs 423 <2> 424 0000861B 66B86A00EB7A <2> mov eax,7aeb006ah ; push byte .. jmp short .. 425 <2> 426 00008621 B90800 <2> mov cx,8 ; 8 groups of 32 IRQs 427 <2> .gloop: 428 00008624 51 <2> push cx 429 00008625 B92000 <2> mov cx,32 ; 32 entries per group 430 <2> .eloop: 431 00008628 893F <2> mov [bx],di ; IDT offset [15:0] 432 0000862A C747022000 <2> mov word [bx+2],PM_CS32 ; IDT segment 433 0000862F 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 00008637 83C308 <2> add bx,8 437 <2> 438 0000863A 66AB <2> stosd 439 <2> ; Increment IRQ, decrement jmp short offset 440 0000863C 6605000100FC <2> add eax,(-4 << 24)+(1 << 8) 441 <2> 442 00008642 E2E4 <2> loop .eloop 443 <2> 444 <2> ; At the end of each group, replace the EBxx with 445 <2> ; the final E9xxxxxxxx 446 00008644 83C703 <2> add di,3 447 00008647 C645FBE9 <2> mov byte [di-5],0E9h ; JMP NEAR 448 0000864B 66BA[87000000] <2> mov edx,pm_irq 449 00008651 6629FA <2> sub edx,edi 450 00008654 668955FC <2> mov [di-4],edx 451 <2> 452 00008658 660500000080 <2> add eax,(0x80 << 24) ; Proper offset for the next one 453 0000865E 59 <2> pop cx 454 0000865F E2C3 <2> loop .gloop 455 <2> 456 00008661 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 000030B4 <2> alignb 8 462 000030B8 <2> IDT: resq 256 463 <2> global RealModeSSSP 464 000038B8 <2> RealModeSSSP resd 1 ; Real-mode SS:SP 465 <2> 466 <2> section .gentextnr ; Autogenerated 32-bit code 467 00003B00 <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[18020000] <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[14020000] <3> push dword [CallbackSP] 58 <3> 59 00100023 FC <3> cld 60 <3> 61 00100024 670FB73E[B828] <3> movzx edi,word [word RealModeSSSP] 62 0010002A 670FB71E[BA28] <3> movzx ebx,word [word RealModeSSSP+2] 63 00100030 83EF36 <3> sub edi,54 ; Allocate 54 bytes 64 00100033 6667893E[B828] <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[75020000] <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[6202] <3> mov bx,.rm 83 00100060 E9(78000000) <3> jmp enter_rm ; Go to real mode 84 <3> 85 <3> bits 16 86 <3> section .text16 87 <3> .rm: 88 00008662 89E0 <3> mov ax,sp 89 00008664 83C02C <3> add ax,9*4+4*2 90 00008667 A3[1402] <3> mov [CallbackSP],ax 91 0000866A 0FA9 <3> pop gs 92 0000866C 0FA1 <3> pop fs 93 0000866E 07 <3> pop es 94 0000866F 1F <3> pop ds 95 00008670 6661 <3> popad 96 00008672 669D <3> popfd 97 00008674 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 00008675 2E8B26[1402] <3> mov sp,[cs:CallbackSP] 103 0000867A 669C <3> pushfd 104 0000867C 6660 <3> pushad 105 0000867E 1E <3> push ds 106 0000867F 06 <3> push es 107 00008680 0FA0 <3> push fs 108 00008682 0FA8 <3> push gs 109 00008684 66BB[65000000] <3> mov ebx,.pm_return 110 0000868A 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[B828] <3> movzx esi,word [word RealModeSSSP] 119 0010006B 670FB706[BA28] <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[B828]36 <3> add dword [word RealModeSSSP],54 131 <3> ; Remove from stack 132 <3> 133 0010008C 8F05[14020000] <3> pop dword [CallbackSP] 134 00100092 FF0D[18020000] <3> dec dword [CallbackCtr] 135 00100098 7506 <3> jnz .skip 136 0010009A FF15[44000000] <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[18020000] <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[14020000] <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[B828] <3> movzx edi,word [word RealModeSSSP] 164 001000C2 670FB71E[BA28] <3> movzx ebx,word [word RealModeSSSP+2] 165 001000C8 6667893E[1402] <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[B828] <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[90020000] <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[8D02] <3> mov bx,.rm 189 0010010C E9(78000000) <3> jmp enter_rm 190 <3> 191 <3> bits 16 192 <3> section .text16 193 <3> .rm: 194 0000868D 669D <3> popfd 195 0000868F CB <3> retf 196 <3> .rm_return: 197 00008690 2E8B26[1402] <3> mov sp,[cs:CallbackSP] 198 00008695 6689C6 <3> mov esi,eax 199 00008698 66BB[11010000] <3> mov ebx,.pm_return 200 0000869E 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[14020000] <3> pop dword [CallbackSP] 208 00100119 FF0D[18020000] <3> dec dword [CallbackCtr] 209 0010011F 7506 <3> jnz .skip 210 00100121 FF15[44000000] <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 00003AD1 <3> alignb 4 221 <3> global core_pm_hook 222 00003AD4 <3> CallbackSP resd 1 ; SP saved during callback 223 00003AD8 <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 000086A1 67E30F <2> bcopy: jecxz .ret 48 <2> pm_call pm_bcopy 48 000086A4 6668[00000000] <3> push dword %1 48 000086AA E8E2FD <3> call _pm_call 49 000086AD 6601CF <2> add edi,ecx 50 000086B0 6601CE <2> add esi,ecx 51 000086B3 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 000086B4 BB[BA00] <2> mov bx,pm_shuffle 72 000086B7 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 00008CB0 53 <3> push ebx 48 00008CB1 52 <3> push edx 49 00008CB2 50 <3> push eax 50 <3> 51 00008CB3 83FEFF <3> cmp esi,-1 52 00008CB6 747E <3> je .bzero 53 <3> 54 00008CB8 39FE <3> cmp esi,edi ; If source < destination, we might 55 00008CBA 722E <3> jb .reverse ; have to copy backwards 56 <3> 57 <3> .forward: 58 <3> ; Initial alignment 59 00008CBC 89FA <3> mov edx,edi 60 00008CBE D1EA <3> shr edx,1 61 00008CC0 7302 <3> jnc .faa1 62 00008CC2 A4 <3> movsb 63 00008CC3 49 <3> dec ecx 64 <3> .faa1: 65 00008CC4 88C8 <3> mov al,cl 66 00008CC6 83F902 <3> cmp ecx,2 67 00008CC9 7216 <3> jb .f_tiny 68 <3> 69 00008CCB D1EA <3> shr edx,1 70 00008CCD 7305 <3> jnc .faa2 71 00008CCF 66A5 <3> movsw 72 00008CD1 83E902 <3> sub ecx,2 73 <3> .faa2: 74 <3> 75 <3> ; Bulk transfer 76 00008CD4 88C8 <3> mov al,cl ; Save low bits 77 00008CD6 C1E902 <3> shr ecx,2 ; Convert to dwords 78 00008CD9 F3A5 <3> rep movsd ; Do our business 79 <3> ; At this point ecx == 0 80 <3> 81 00008CDB A802 <3> test al,2 82 00008CDD 7402 <3> jz .fab2 83 00008CDF 66A5 <3> movsw 84 <3> .fab2: 85 <3> .f_tiny: 86 00008CE1 A801 <3> test al,1 87 00008CE3 7401 <3> jz .fab1 88 00008CE5 A4 <3> movsb 89 <3> .fab1: 90 <3> .done: 91 00008CE6 58 <3> pop eax 92 00008CE7 5A <3> pop edx 93 00008CE8 5B <3> pop ebx 94 00008CE9 C3 <3> ret 95 <3> 96 <3> .reverse: 97 00008CEA 8D440EFF <3> lea eax,[esi+ecx-1] ; Point to final byte 98 00008CEE 39C7 <3> cmp edi,eax 99 00008CF0 77CA <3> ja .forward ; No overlap, do forward copy 100 <3> 101 00008CF2 FD <3> std ; Reverse copy 102 00008CF3 8D7C0FFF <3> lea edi,[edi+ecx-1] 103 00008CF7 89C6 <3> mov esi,eax 104 <3> 105 <3> ; Initial alignment 106 00008CF9 89FA <3> mov edx,edi 107 00008CFB D1EA <3> shr edx,1 108 00008CFD 7202 <3> jc .raa1 109 00008CFF A4 <3> movsb 110 00008D00 49 <3> dec ecx 111 <3> .raa1: 112 <3> 113 00008D01 4E <3> dec esi 114 00008D02 4F <3> dec edi 115 00008D03 88C8 <3> mov al,cl 116 00008D05 83F902 <3> cmp ecx,2 117 00008D08 7222 <3> jb .r_tiny 118 00008D0A D1EA <3> shr edx,1 119 00008D0C 7205 <3> jc .raa2 120 00008D0E 66A5 <3> movsw 121 00008D10 83E902 <3> sub ecx,2 122 <3> .raa2: 123 <3> 124 <3> ; Bulk copy 125 00008D13 83EE02 <3> sub esi,2 126 00008D16 83EF02 <3> sub edi,2 127 00008D19 88C8 <3> mov al,cl ; Save low bits 128 00008D1B C1E902 <3> shr ecx,2 129 00008D1E F3A5 <3> rep movsd 130 <3> 131 <3> ; Final alignment 132 <3> .r_final: 133 00008D20 83C602 <3> add esi,2 134 00008D23 83C702 <3> add edi,2 135 00008D26 A802 <3> test al,2 136 00008D28 7402 <3> jz .rab2 137 00008D2A 66A5 <3> movsw 138 <3> .rab2: 139 <3> .r_tiny: 140 00008D2C 46 <3> inc esi 141 00008D2D 47 <3> inc edi 142 00008D2E A801 <3> test al,1 143 00008D30 7401 <3> jz .rab1 144 00008D32 A4 <3> movsb 145 <3> .rab1: 146 00008D33 FC <3> cld 147 00008D34 EBB0 <3> jmp short .done 148 <3> 149 <3> .bzero: 150 00008D36 31C0 <3> xor eax,eax 151 <3> 152 <3> ; Initial alignment 153 00008D38 89FA <3> mov edx,edi 154 00008D3A D1EA <3> shr edx,1 155 00008D3C 7302 <3> jnc .zaa1 156 00008D3E AA <3> stosb 157 00008D3F 49 <3> dec ecx 158 <3> .zaa1: 159 <3> 160 00008D40 88CB <3> mov bl,cl 161 00008D42 83F902 <3> cmp ecx,2 162 00008D45 7217 <3> jb .z_tiny 163 00008D47 D1EA <3> shr edx,1 164 00008D49 7305 <3> jnc .zaa2 165 00008D4B 66AB <3> stosw 166 00008D4D 83E902 <3> sub ecx,2 167 <3> .zaa2: 168 <3> 169 <3> ; Bulk 170 00008D50 88CB <3> mov bl,cl ; Save low bits 171 00008D52 C1E902 <3> shr ecx,2 172 00008D55 F3AB <3> rep stosd 173 <3> 174 00008D57 F6C302 <3> test bl,2 175 00008D5A 7402 <3> jz .zab2 176 00008D5C 66AB <3> stosw 177 <3> .zab2: 178 <3> .z_tiny: 179 00008D5E F6C301 <3> test bl,1 180 00008D61 7401 <3> jz .zab1 181 00008D63 AA <3> stosb 182 <3> .zab1: 183 00008D64 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 00008D66 89C7 <3> mov edi,eax 216 00008D68 89D6 <3> mov esi,edx 217 <3> 218 <3> pm_shuffle: 219 00008D6A FA <3> cli ; End interrupt service (for good) 220 00008D6B 89FB <3> mov ebx,edi ; EBX <- descriptor list 221 00008D6D 8D540F0F <3> lea edx,[edi+ecx+15] ; EDX <- where to relocate our code to 222 00008D71 83E2F0 <3> and edx,~15 ; Align 16 to benefit the GDT 223 00008D74 E837FFFFFF <3> call pm_bcopy 224 00008D79 BE[00000000] <3> mov esi,__bcopyxx_start ; Absolute source address 225 00008D7E 89D7 <3> mov edi,edx ; Absolute target address 226 00008D80 29F2 <3> sub edx,esi ; EDX <- address delta 227 00008D82 B9[00000000] <3> mov ecx,__bcopyxx_dwords 228 00008D87 8D82[E1000000] <3> lea eax,[edx+.safe] ; Resume point 229 <3> ; Relocate this code 230 00008D8D F3A5 <3> rep movsd 231 00008D8F FFE0 <3> jmp eax ; Jump to safe location 232 <3> .safe: 233 <3> ; Give ourselves a safe stack 234 00008D91 8DA2[80000000] <3> lea esp,[edx+bcopyxx_stack+__bcopyxx_end] 235 00008D97 81C2[00000000] <3> add edx,bcopy_gdt ; EDX <- new GDT 236 00008D9D 895202 <3> mov [edx+2],edx ; GDT self-pointer 237 00008DA0 0F0112 <3> lgdt [edx] ; Switch to local GDT 238 <3> 239 <3> ; Now for the actual shuffling... 240 <3> .loop: 241 00008DA3 8B3B <3> mov edi,[ebx] 242 00008DA5 8B7304 <3> mov esi,[ebx+4] 243 00008DA8 8B4B08 <3> mov ecx,[ebx+8] 244 00008DAB 83C30C <3> add ebx,12 245 00008DAE E307 <3> jecxz .done 246 00008DB0 E8FBFEFFFF <3> call pm_bcopy 247 00008DB5 EBEC <3> jmp .loop 248 <3> .done: 249 00008DB7 0F015A30 <3> lidt [edx+RM_IDT_ptr-bcopy_gdt] ; RM-like IDT 250 00008DBB 51 <3> push ecx ; == 0, for cleaning the flags register 251 00008DBC 21F6 <3> and esi,esi 252 00008DBE 7403 <3> jz pm_shuffle_16 253 00008DC0 9D <3> popfd ; Clean the flags 254 00008DC1 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 00008DC3 89F8 <3> mov eax,edi 260 00008DC5 66894212 <3> mov [edx+PM_CS16+2],ax 261 00008DC9 6689421A <3> mov [edx+PM_DS16+2],ax 262 00008DCD C1E810 <3> shr eax,16 263 00008DD0 884214 <3> mov [edx+PM_CS16+4],al 264 00008DD3 886217 <3> mov [edx+PM_CS16+7],ah 265 00008DD6 88421C <3> mov [edx+PM_DS16+4],al 266 00008DD9 88621F <3> mov [edx+PM_DS16+7],ah 267 00008DDC 0F20C0 <3> mov eax,cr0 268 00008DDF 24FE <3> and al,~1 269 00008DE1 9D <3> popfd ; Clean the flags 270 <3> ; No flag-changing instructions below... 271 00008DE2 66BA1800 <3> mov dx,PM_DS16 272 00008DE6 8EDA <3> mov ds,edx 273 00008DE8 8EC2 <3> mov es,edx 274 00008DEA 8EE2 <3> mov fs,edx 275 00008DEC 8EEA <3> mov gs,edx 276 00008DEE 8ED2 <3> mov ss,edx 277 00008DF0 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 00008E00 2F00 <3> dw bcopy_gdt_size-1 ; Null descriptor - contains GDT 290 00008E02 [00000000] <3> dd bcopy_gdt ; pointer for LGDT instruction 291 00008E06 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 00008E08 67008005 <3> dw 104-1, DummyTSS ; 08h 32-bit task state segment 298 00008E0C 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 00008E10 FFFF0000 <3> dd 0000ffffh ; 10h Code segment, use16, readable, 302 00008E14 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 00008E18 FFFF0000 <3> dd 0000ffffh ; 18h Data segment, use16, read/write, 305 00008E1C 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 00008E20 FFFF0000 <3> dd 0000ffffh ; 20h Code segment, use32, readable, 308 00008E24 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 00008E28 FFFF0000 <3> dd 0000ffffh ; 28h Data segment, use32, read/write, 311 00008E2C 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 00008E30 FFFF <3> RM_IDT_ptr: dw 0FFFFh ; Length (nonsense, but matches CPU) 323 00008E32 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 00108908 [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 000086BA 50 <2> strcpy: push ax 8 000086BB AC <2> .loop: lodsb 9 000086BC AA <2> stosb 10 000086BD 20C0 <2> and al,al 11 000086BF 75FA <2> jnz .loop 12 000086C1 58 <2> pop ax 13 000086C2 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 0010EB80 [08000000] <2> dd adv0.data 50 <2> __syslinux_adv_size: 51 0010EB84 F4010000 <2> dd ADV_LEN 52 <2> 53 <2> section .adv 54 <2> ; Introduce the ADVs to valid but blank 55 <2> adv0: 56 00009000 <2> .head resd 1 57 00009004 <2> .csum resd 1 58 00009008 <2> .data resb ADV_LEN 59 000091FC <2> .tail resd 1 60 <2> .end equ $ 61 <2> adv1: 62 00009200 <2> .head resd 1 63 00009204 <2> .csum resd 1 64 00009208 <2> .data resb ADV_LEN 65 000093FC <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 000086C3 803E[7800]FF <2> cmp byte [ADVDrive],-1 76 000086C8 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 000086CC 803E[7800]FF <2> cmp byte [ADVDrive],-1 ; No ADV configured, still? 98 000086D1 7410 <2> je .reset ; Then unconditionally reset 99 <2> 100 000086D3 BE[0000] <2> mov si,adv0 101 000086D6 E83900 <2> call .check_adv 102 000086D9 742C <2> jz .ok ; Primary ADV okay 103 000086DB BE[0002] <2> mov si,adv1 104 000086DE E83100 <2> call .check_adv 105 000086E1 7425 <2> jz .adv1ok 106 <2> 107 <2> ; Neither ADV is usable; initialize to blank 108 <2> .reset: 109 000086E3 BF[0000] <2> mov di,adv0 110 000086E6 66B8A52F2D5A <2> mov eax,ADV_MAGIC1 111 000086EC 66AB <2> stosd 112 000086EE 66B8671704A3 <2> mov eax,ADV_MAGIC2 113 000086F4 66AB <2> stosd 114 000086F6 6631C0 <2> xor eax,eax 115 000086F9 B97D00 <2> mov cx,ADV_LEN/4 116 000086FC F366AB <2> rep stosd 117 000086FF 66B864BF28DD <2> mov eax,ADV_MAGIC3 118 00008705 66AB <2> stosd 119 <2> 120 <2> .ok: 121 00008707 C3 <2> ret 122 <2> 123 <2> ; The primary ADV is bad, but the backup is OK 124 <2> .adv1ok: 125 00008708 BF[0000] <2> mov di,adv0 126 0000870B B98000 <2> mov cx,512/4 127 0000870E F366A5 <2> rep movsd 128 00008711 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 00008712 56 <2> push si 135 00008713 66AD <2> lodsd 136 00008715 663DA52F2D5A <2> cmp eax,ADV_MAGIC1 137 0000871B 751E <2> jne .done ; ZF=0, i.e. bad 138 0000871D 6631D2 <2> xor edx,edx 139 00008720 B97E00 <2> mov cx,ADV_LEN/4+1 ; Remaining dwords 140 <2> .csum: 141 00008723 66AD <2> lodsd 142 00008725 6601C2 <2> add edx,eax 143 00008728 E2F9 <2> loop .csum 144 0000872A 6681FA671704A3 <2> cmp edx,ADV_MAGIC2 145 00008731 7508 <2> jne .done 146 00008733 66AD <2> lodsd 147 00008735 663D64BF28DD <2> cmp eax,ADV_MAGIC3 148 <2> .done: 149 0000873B 5E <2> pop si 150 0000873C 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 0000873D 50 <2> push ax 165 0000873E BE[0800] <2> mov si,adv0.data 166 00008741 31C0 <2> xor ax,ax ; Keep AH=0 at all times 167 <2> .loop: 168 00008743 AC <2> lodsb ; Read ID 169 00008744 38D0 <2> cmp al,dl 170 00008746 740F <2> je .found 171 00008748 20C0 <2> and al,al 172 0000874A 7415 <2> jz .end 173 0000874C AC <2> lodsb ; Read length 174 0000874D 01C6 <2> add si,ax 175 0000874F 81FE[FC01] <2> cmp si,adv0.tail 176 00008753 72EE <2> jb .loop 177 00008755 EB0A <2> jmp .end 178 <2> 179 <2> .found: 180 00008757 AC <2> lodsb 181 00008758 89C1 <2> mov cx,ax 182 0000875A 01F0 <2> add ax,si ; Make sure it fits 183 0000875C 3D[FC01] <2> cmp ax,adv0.tail 184 0000875F 7602 <2> jbe .ok 185 <2> .end: 186 00008761 31C9 <2> xor cx,cx 187 <2> .ok: 188 00008763 58 <2> pop ax 189 00008764 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 00008765 50 <2> push ax 204 00008766 56 <2> push si 205 00008767 57 <2> push di 206 00008768 20ED <2> and ch,ch 207 0000876A 7559 <2> jnz .overflow 208 <2> 209 0000876C 51 <2> push cx 210 0000876D BE[0800] <2> mov si,adv0.data 211 00008770 31C0 <2> xor ax,ax 212 <2> .loop: 213 00008772 AC <2> lodsb 214 00008773 38D0 <2> cmp al,dl 215 00008775 740F <2> je .found 216 00008777 20C0 <2> and al,al 217 00008779 7423 <2> jz .endz 218 0000877B AC <2> lodsb 219 0000877C 01C6 <2> add si,ax 220 0000877E 81FE[FC01] <2> cmp si,adv0.tail 221 00008782 72EE <2> jb .loop 222 00008784 EB19 <2> jmp .end 223 <2> 224 <2> .found: ; Found, need to delete old copy 225 00008786 AC <2> lodsb 226 00008787 8D7CFE <2> lea di,[si-2] 227 0000878A 57 <2> push di 228 0000878B 01C6 <2> add si,ax 229 0000878D B9[FC01] <2> mov cx,adv0.tail 230 00008790 29F1 <2> sub cx,si 231 00008792 7207 <2> jb .nukeit 232 00008794 F3A4 <2> rep movsb ; Remove the old one 233 00008796 8825 <2> mov [di],ah ; Termination zero 234 00008798 5E <2> pop si 235 00008799 EBD7 <2> jmp .loop 236 <2> .nukeit: 237 0000879B 5E <2> pop si 238 0000879C EB01 <2> jmp .end 239 <2> .endz: 240 0000879E 4E <2> dec si 241 <2> .end: 242 <2> ; Now SI points to where we want to put our data 243 0000879F 59 <2> pop cx 244 000087A0 89F7 <2> mov di,si 245 000087A2 E313 <2> jcxz .empty 246 000087A4 01CE <2> add si,cx 247 000087A6 81FE[FA01] <2> cmp si,adv0.tail-2 248 000087AA 7319 <2> jae .overflow ; CF=0 249 <2> 250 000087AC 89DE <2> mov si,bx 251 000087AE 88D0 <2> mov al,dl 252 000087B0 AA <2> stosb 253 000087B1 88C8 <2> mov al,cl 254 000087B3 AA <2> stosb 255 000087B4 F364A4 <2> fs rep movsb 256 <2> 257 <2> .empty: 258 000087B7 B9[FC01] <2> mov cx,adv0.tail 259 000087BA 29F9 <2> sub cx,di 260 000087BC 31C0 <2> xor ax,ax 261 000087BE F3AA <2> rep stosb ; Zero-fill remainder 262 <2> 263 000087C0 F8 <2> clc 264 <2> .done: 265 000087C1 5F <2> pop di 266 000087C2 5E <2> pop si 267 000087C3 58 <2> pop ax 268 000087C4 C3 <2> ret 269 <2> .overflow: 270 000087C5 F9 <2> stc 271 000087C6 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 000087C8 6660 <2> pushad 279 000087CA BE[0800] <2> mov si,adv0.data 280 000087CD B97D00 <2> mov cx,ADV_LEN/4 281 000087D0 6631D2 <2> xor edx,edx 282 <2> .loop: 283 000087D3 66AD <2> lodsd 284 000087D5 6601C2 <2> add edx,eax 285 000087D8 E2F9 <2> loop .loop 286 000087DA 66B8671704A3 <2> mov eax,ADV_MAGIC2 287 000087E0 6629D0 <2> sub eax,edx 288 000087E3 8D7C04 <2> lea di,[si+4] ; adv1 289 000087E6 BE[0000] <2> mov si,adv0 290 000087E9 66894404 <2> mov [si+4],eax ; Store checksum 291 000087ED B98000 <2> mov cx,(ADV_LEN+12)/4 292 000087F0 F366A5 <2> rep movsd 293 000087F3 6661 <2> popad 294 000087F5 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 000087F6 6650 <2> push eax 307 000087F8 66A1[6800] <2> mov eax,[ADVSec0] 308 000087FC 660B06[6C00] <2> or eax,[ADVSec0+4] 309 00008801 741E <2> je .bad 310 00008803 66A1[7000] <2> mov eax,[ADVSec1] 311 00008807 660B06[7400] <2> or eax,[ADVSec1+4] 312 0000880C 7413 <2> je .bad 313 0000880E 803E[7800]FF <2> cmp byte [ADVDrive],-1 314 00008813 740C <2> je .bad 315 <2> 316 00008815 E8B0FF <2> call adv_cleanup 317 00008818 B403 <2> mov ah,3 ; Write 318 0000881A E81300 <2> call adv_read_write 319 <2> 320 0000881D F8 <2> clc 321 0000881E 6658 <2> pop eax 322 00008820 C3 <2> ret 323 <2> .bad: ; No location for ADV set 324 00008821 F9 <2> stc 325 00008822 6658 <2> pop eax 326 00008824 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 00008825 50 <2> push ax 336 00008826 B402 <2> mov ah,2 ; Read 337 00008828 E80500 <2> call adv_read_write 338 0000882B E89EFE <2> call adv_verify 339 0000882E 58 <2> pop ax 340 0000882F 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 00008830 8826[1C02] <2> mov [ADVOp],ah 350 00008834 6660 <2> pushad 351 <2> 352 <2> ; Check for EDD 353 00008836 BBAA55 <2> mov bx,55AAh 354 00008839 B441 <2> mov ah,41h ; EDD existence query 355 0000883B 8A16[7800] <2> mov dl,[ADVDrive] 356 0000883F CD13 <2> int 13h 357 00008841 BE[A804] <2> mov si,.cbios 358 00008844 720E <2> jc .noedd 359 00008846 81FB55AA <2> cmp bx,0AA55h 360 0000884A 7508 <2> jne .noedd 361 0000884C F6C101 <2> test cl,1 362 0000884F 7403 <2> jz .noedd 363 00008851 BE[7804] <2> mov si,.ebios 364 <2> .noedd: 365 <2> 366 00008854 66A1[6800] <2> mov eax,[ADVSec0] 367 00008858 668B16[6C00] <2> mov edx,[ADVSec0+4] 368 0000885D BB[0000] <2> mov bx,adv0 369 00008860 E81200 <2> call .doone 370 <2> 371 00008863 66A1[7000] <2> mov eax,[ADVSec1] 372 00008867 668B16[7400] <2> mov edx,[ADVSec1+4] 373 0000886C BB[0002] <2> mov bx,adv1 374 0000886F E80300 <2> call .doone 375 <2> 376 00008872 6661 <2> popad 377 00008874 C3 <2> ret 378 <2> 379 <2> .doone: 380 00008875 56 <2> push si 381 00008876 FFE6 <2> jmp si 382 <2> 383 <2> .ebios: 384 00008878 B90600 <2> mov cx,adv_retries 385 <2> .eb_retry: 386 <2> ; Form DAPA on stack 387 0000887B 6652 <2> push edx 388 0000887D 6650 <2> push eax 389 0000887F 06 <2> push es 390 00008880 53 <2> push bx 391 00008881 6A01 <2> push word 1 ; Sector count 392 00008883 6A10 <2> push word 16 ; DAPA size 393 00008885 89E6 <2> mov si,sp 394 00008887 6660 <2> pushad 395 00008889 8A16[7800] <2> mov dl,[ADVDrive] 396 0000888D B80040 <2> mov ax,4000h 397 00008890 0A26[1C02] <2> or ah,[ADVOp] 398 00008894 1E <2> push ds 399 00008895 16 <2> push ss 400 00008896 1F <2> pop ds 401 00008897 CD13 <2> int 13h 402 00008899 1F <2> pop ds 403 0000889A 6661 <2> popad 404 0000889C 8D6410 <2> lea sp,[si+16] ; Remove DAPA 405 0000889F 7202 <2> jc .eb_error 406 000088A1 5E <2> pop si 407 000088A2 C3 <2> ret 408 <2> .eb_error: 409 000088A3 E2D6 <2> loop .eb_retry 410 000088A5 F9 <2> stc 411 000088A6 5E <2> pop si 412 000088A7 C3 <2> ret 413 <2> 414 <2> .cbios: 415 000088A8 6652 <2> push edx 416 000088AA 6650 <2> push eax 417 000088AC 55 <2> push bp 418 <2> 419 000088AD 6621D2 <2> and edx,edx ; > 2 TiB not possible 420 000088B0 7563 <2> jnz .cb_overflow 421 <2> 422 000088B2 8A16[7800] <2> mov dl,[ADVDrive] 423 000088B6 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 000088B8 791B <2> jns .noparm ; Floppy drive... urk 428 <2> 429 000088BA B408 <2> mov ah,08h ; Get disk parameters 430 000088BC CD13 <2> int 13h 431 000088BE 7215 <2> jc .noparm 432 000088C0 20E4 <2> and ah,ah 433 000088C2 7511 <2> jnz .noparm 434 000088C4 C1EA08 <2> shr dx,8 435 000088C7 42 <2> inc dx 436 000088C8 660FB7FA <2> movzx edi,dx ; EDI = heads 437 000088CC 83E13F <2> and cx,3fh 438 000088CF 660FB7F1 <2> movzx esi,cx ; ESI = sectors/track 439 000088D3 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 000088D5 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 000088D7 6631D2 <2> xor edx,edx 459 000088DA 66F7F6 <2> div esi 460 000088DD 31C9 <2> xor cx,cx 461 000088DF 87CA <2> xchg cx,dx ; CX <- sector index (0-based) 462 <2> ; EDX <- 0 463 <2> ; eax = track # 464 000088E1 66F7F7 <2> div edi ; Convert track to head/cyl 465 <2> 466 <2> ; Watch out for overflow, we might be writing! 467 000088E4 663DFF030000 <2> cmp eax,1023 468 000088EA 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 000088EC 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 000088EF 41 <2> inc cx ; Sector numbers are 1-based, sigh 480 000088F0 08E1 <2> or cl,ah 481 000088F2 88C5 <2> mov ch,al 482 000088F4 88D6 <2> mov dh,dl 483 000088F6 8A16[7800] <2> mov dl,[ADVDrive] 484 000088FA B001 <2> mov al,01h ; Transfer one sector 485 000088FC 8A26[1C02] <2> mov ah,[ADVOp] ; Operation 486 <2> 487 00008900 BD0600 <2> mov bp,adv_retries 488 <2> .cb_retry: 489 00008903 6660 <2> pushad 490 00008905 CD13 <2> int 13h 491 00008907 6661 <2> popad 492 00008909 7207 <2> jc .cb_error 493 <2> 494 <2> .cb_done: 495 0000890B 5D <2> pop bp 496 0000890C 6658 <2> pop eax 497 0000890E 665A <2> pop edx 498 00008910 5E <2> pop si 499 00008911 C3 <2> ret 500 <2> 501 <2> .cb_error: 502 00008912 4D <2> dec bp 503 00008913 75EE <2> jnz .cb_retry 504 <2> .cb_overflow: 505 00008915 F9 <2> stc 506 00008916 EBF3 <2> jmp .cb_done 507 <2> 508 <2> section .data16 509 00008EA7 00 <2> alignz 8 510 00008EA8 0000000000000000 <2> ADVSec0 dq 0 ; Not specified 511 00008EB0 0000000000000000 <2> ADVSec1 dq 0 ; Not specified 512 00008EB8 FF <2> ADVDrive db -1 ; No ADV defined 513 00008EB9 FF <2> ADVCHSInfo db -1 ; We have CHS info for this drive 514 <2> 515 <2> section .bss16 516 00003ADC <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 00008918 66A17000 <2> mov eax,[BIOS_timer_hook] 31 0000891C 66A3[4805] <2> mov [BIOS_timer_next],eax 32 00008920 66C7067000- <2> mov dword [BIOS_timer_hook],timer_irq 32 00008925 [33050000] <2> 33 00008929 C3 <2> ret 34 <2> 35 <2> global bios_timer_cleanup:function hidden 36 <2> bios_timer_cleanup: 37 <2> ; Unhook INT 1Ch 38 0000892A 66A1[4805] <2> mov eax,[BIOS_timer_next] 39 0000892E 66A37000 <2> mov [BIOS_timer_hook],eax 40 00008932 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 00008933 2E66FF06[7C00] <2> inc dword [cs:__jiffies] 49 00008939 2E8106[8400]E8EC <2> add word [cs:__ms_timer_adj],0xece8 50 00008940 2E668316[8000]36 <2> adc dword [cs:__ms_timer],0x36 51 00008947 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 00008EBA 00 <2> alignz 4 57 <2> global __jiffies:data hidden, __ms_timer 58 00008EBC 00000000 <2> __jiffies dd 0 ; Clock tick timer 59 00008EC0 00000000 <2> __ms_timer dd 0 ; Millisecond timer 60 00008EC4 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 0000000C [10000000] <2> pfx_checksum dd bi_length ; File length and checksum fields 12 <2> %else 13 <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 1222 1223 ; ----------------------------------------------------------------------------- 1224 ; Begin data section 1225 ; ----------------------------------------------------------------------------- 1226 1227 section .data16 1228 00008EC6 43616E6E6F74206C6F- err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0 1228 00008ECF 6164206469736B2069- 1228 00008ED8 6D6167652028696E76- 1228 00008EE1 616C69642066696C65- 1228 00008EEA 293F0D0A00 1229 1230 section .bss16 1231 global OrigFDCTabPtr 1232 00003ADD OrigFDCTabPtr resd 1 ; Keep bios_cleanup_hardware() honest