1 %define DEBUG_MESSAGES 1 2 %include "isolinux.asm" 1 <1> ; -*- fundamental -*- (asm-mode sucks) 2 <1> ; **************************************************************************** 3 <1> ; 4 <1> ; isolinux.asm 5 <1> ; 6 <1> ; A program to boot Linux kernels off a CD-ROM using the El Torito 7 <1> ; boot standard in "no emulation" mode, making the entire filesystem 8 <1> ; available. It is based on the SYSLINUX boot loader for MS-DOS 9 <1> ; floppies. 10 <1> ; 11 <1> ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 12 <1> ; Copyright 2009 Intel Corporation; author: H. Peter Anvin 13 <1> ; 14 <1> ; This program is free software; you can redistribute it and/or modify 15 <1> ; it under the terms of the GNU General Public License as published by 16 <1> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 17 <1> ; Boston MA 02111-1307, USA; either version 2 of the License, or 18 <1> ; (at your option) any later version; incorporated herein by reference. 19 <1> ; 20 <1> ; **************************************************************************** 21 <1> 22 <1> %define IS_ISOLINUX 1 23 <1> %include "head.inc" 1 <2> ; -*- fundamental -*- (asm-mode sucks) 2 <2> ; ----------------------------------------------------------------------- 3 <2> ; 4 <2> ; Copyright 2006-2008 H. Peter Anvin - All Rights Reserved 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> ; head.inc 16 <2> ; 17 <2> ; Common header includes 18 <2> ; 19 <2> 20 <2> %ifndef _HEAD_INC 21 <2> %define _HEAD_INC 22 <2> 23 <2> %if __NASM_MAJOR__ < 2 || (__NASM_MAJOR__ == 2 && __NASM_MINOR__ < 3) 24 <2> %error "NASM 2.03 or later required to compile correctly" 25 <2> %elif __NASM_VERSION_ID__ == 0x020b0600 26 <2> %fatal "NASM 2.11.06 is known to miscompile Syslinux" 27 <2> %endif 28 <2> 29 <2> %include "macros.inc" 1 <3> ;; ----------------------------------------------------------------------- 2 <3> ;; 3 <3> ;; Copyright 1994-2008 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> ;; macros.inc 16 <3> ;; 17 <3> ;; Convenient macros 18 <3> ;; 19 <3> 20 <3> %ifndef _MACROS_INC 21 <3> %define _MACROS_INC 22 <3> 23 <3> ; 24 <3> ; Identify the module we're compiling; the "correct" should be defined 25 <3> ; in the module itself to 1 26 <3> ; 27 <3> %ifdef IS_SYSLINUX 28 <3> %define MY_NAME 'SYSLINUX' 29 <3> %else 30 <3> %define IS_SYSLINUX 0 31 <3> %endif 32 <3> %ifdef IS_PXELINUX 33 <3> %define MY_NAME 'PXELINUX' 34 <3> %if IS_LPXELINUX > 0 35 <3> %define MY_TYPE 'lwIP' 36 <3> %else 37 <3> %define MY_TYPE 'PXE' 38 <3> %endif 39 <3> %else 40 <3> %define IS_PXELINUX 0 41 <3> %endif 42 <3> %ifdef IS_ISOLINUX 43 <3> %define MY_NAME 'ISOLINUX' 44 <3> %else 45 <3> %define IS_ISOLINUX 0 46 <3> %endif 47 <3> %ifdef IS_EXTLINUX 48 <3> %define MY_NAME 'EXTLINUX' 49 <3> %else 50 <3> %define IS_EXTLINUX 0 51 <3> %endif 52 <3> 53 <3> ; 54 <3> ; Macros similar to res[bwd], but which works in the code segment (after 55 <3> ; section .text16) or the data segment (section .data16) 56 <3> ; 57 <3> %macro zb 1.nolist 58 <3> times %1 db 0 59 <3> %endmacro 60 <3> 61 <3> %macro zw 1.nolist 62 <3> times %1 dw 0 63 <3> %endmacro 64 <3> 65 <3> %macro zd 1.nolist 66 <3> times %1 dd 0 67 <3> %endmacro 68 <3> 69 <3> ; 70 <3> ; Align with zero bytes in a progbits segment 71 <3> ; 72 <3> %macro alignz 1.nolist 73 <3> times (((%1) - (($-$$) % (%1))) % (%1)) db 0 74 <3> %endmacro 75 <3> 76 <3> ; 77 <3> ; Macro to emit an unsigned decimal number as a string 78 <3> ; 79 <3> %macro asciidec 1.nolist 80 <3> %ifndef DEPEND ; Not safe for "depend" 81 <3> %push asciidec 82 <3> %assign %$v %1 83 <3> %if %$v == 0 84 <3> db '0' 85 <3> %else 86 <3> %assign %$dcount 0 87 <3> %assign %$n %$v 88 <3> %assign %$d 1 89 <3> %rep 20 90 <3> %if %$n != 0 91 <3> %assign %$dcount %$dcount + 1 92 <3> %assign %$n %$n / 10 93 <3> %assign %$d %$d * 10 94 <3> %endif 95 <3> %endrep 96 <3> %rep %$dcount 97 <3> %assign %$d %$d / 10 98 <3> db ((%$v / %$d) % 10) + '0' 99 <3> %endrep 100 <3> %endif 101 <3> %pop 102 <3> %endif 103 <3> %endmacro 104 <3> 105 <3> ; 106 <3> ; Macros for network byte order of constants 107 <3> ; 108 <3> %define htons(x) ( ( ((x) & 0FFh) << 8 ) + ( ((x) & 0FF00h) >> 8 ) ) 109 <3> %define ntohs(x) htons(x) 110 <3> %define htonl(x) ( ( ((x) & 0FFh) << 24) + ( ((x) & 0FF00h) << 8 ) + ( ((x) & 0FF0000h) >> 8 ) + ( ((x) & 0FF000000h) >> 24) ) 111 <3> %define ntohl(x) htonl(x) 112 <3> 113 <3> ; 114 <3> ; ASCII 115 <3> ; 116 <3> CR equ 13 ; Carriage Return 117 <3> LF equ 10 ; Line Feed 118 <3> FF equ 12 ; Form Feed 119 <3> BS equ 8 ; Backspace 120 <3> 121 <3> %endif ; _MACROS_INC 30 <2> %include "config.inc" 1 <3> ;; ----------------------------------------------------------------------- 2 <3> ;; 3 <3> ;; Copyright 2002-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> ;; config.inc 16 <3> ;; 17 <3> ;; Common configuration options. Some of these are imposed by the kernel. 18 <3> ;; 19 <3> 20 <3> %ifndef _CONFIG_INC 21 <3> %define _CONFIG_INC 22 <3> 23 <3> max_cmd_len equ 2047 ; Must be &3; 2047 is the kernel limit 24 <3> HIGHMEM_MAX equ 037FFFFFFh ; DEFAULT highest address for an initrd 25 <3> DEFAULT_BAUD equ 9600 ; Default baud rate for serial port 26 <3> BAUD_DIVISOR equ 115200 ; Serial port parameter 27 <3> MAX_FKEYS equ 12 ; Number of F-key help files 28 <3> 29 <3> ; 30 <3> ; log2(Max filename size Including final null) 31 <3> ; 32 <3> FILENAME_MAX_LG2 equ 8 33 <3> FILENAME_MAX equ (1 << FILENAME_MAX_LG2) ; Max mangled filename size 34 <3> 35 <3> ; 36 <3> ; Version number definitinons 37 <3> ; 38 <3> %include "../version.gen" 1 <4> %define VERSION 6.04 2 <4> %define VERSION_STR "6.04" 3 <4> %define VERSION_MAJOR 6 4 <4> %define VERSION_MINOR 4 5 <4> %define YEAR 2015 6 <4> %define YEAR_STR "2015" 39 <3> 40 <3> %endif ; _CONFIG_INC 31 <2> %include "layout.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> ; Bostom 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> ; layout.inc 16 <3> ; 17 <3> ; Memory layout of segments 18 <3> ; 19 <3> 20 <3> ; Default to 16-bit code 21 <3> bits 16 22 <3> 23 <3> ; Memory below 0800h is reserved for the BIOS and the MBR. 24 <3> BSS_START equ 0800h 25 <3> 26 <3> ; Text starts at the load address of 07C00h. 27 <3> TEXT_START equ 7C00h 28 <3> 29 <3> ; 30 <3> ; 16-bit stack layout 31 <3> ; 32 <3> ; PXELINUX: There are apparently some AMI BIOSes in the field which 33 <3> ; put their BEV stack somewhere below 7C00h (and therefore don't 34 <3> ; handle localboot properly), so avoid that immediate memory region. 35 <3> ; The range that is known to be bad is approximately 75E8..7C00; the 36 <3> ; lower bound is tight. 37 <3> ; 38 <3> global STACK_LEN, STACK_TOP, STACK_BASE 39 <3> STACK_LEN equ 4096 40 <3> %if IS_PXELINUX 41 <3> STACK_TOP equ 7000h 42 <3> %else 43 <3> STACK_TOP equ 7c00h 44 <3> %endif 45 <3> STACK_BASE equ STACK_TOP - STACK_LEN 46 <3> 47 <3> ; The secondary BSS section, above the text; we really wish we could 48 <3> ; just make it follow .bcopy32 or hang off the end, 49 <3> ; but it doesn't seem to work that way. 50 <3> LATEBSS_START equ 0B800h 51 <3> 52 <3> ; 53 <3> ; 32-bit stack layout 54 <3> ; 55 <3> STACK32_LEN equ 64*1024 56 <3> 57 <3> section .stack nobits write align=4096 58 00313000 <3> resb STACK32_LEN 59 <3> 60 <3> ; 61 <3> ; The various sections and their relationship 62 <3> ; 63 <3> ; Use .earlybss for things that MUST be in low memory. 64 <3> section .earlybss nobits write 65 <3> section .config write progbits align=4 66 <3> section .replacestub exec write progbits align=16 67 <3> section .gentextnr exec write nobits align=16 68 <3> section .stack16 write nobits align=16 69 <3> 70 <3> ; Use .bss16 for things that doesn't have to be in low memory; 71 <3> ; .earlybss should be used for things that absolutely have 72 <3> ; to be below 0x7c00. 73 <3> section .bss16 write nobits align=16 74 <3> 75 <3> %if 0 ; IS_PXELINUX 76 <3> ; Warning here: RBFG build 22 randomly overwrites 77 <3> ; memory location [0x5680,0x576c), possibly more. It 78 <3> ; seems that it gets confused and screws up the 79 <3> ; pointer to its own internal packet buffer and starts 80 <3> ; writing a received ARP packet into low memory. 81 <3> section .rbfg write nobits 82 <3> RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet... 83 <3> %endif 84 <3> 85 <3> section .init exec write progbits align=1 86 <3> section .text16 exec write progbits align=1 87 <3> section .textnr exec nowrite progbits align=1 88 <3> section .bcopyxx.text exec nowrite progbits align=16 89 <3> section .bcopyxx.data noexec write progbits align=16 90 <3> section .data16 noexec write progbits align=16 91 <3> 92 <3> section .adv write nobits align=512 93 <3> 94 <3> ; .uibss contains bss data which is guaranteed to be 95 <3> ; safe to clobber during the loading of the image. This 96 <3> ; is because while loading the primary image we will clobber 97 <3> ; the spillover from the last fractional sector load. 98 <3> section .uibss write nobits align=16 99 <3> 100 <3> section .savedata write nobits align=16 101 <3> 102 <3> ; Symbols from linker script 103 <3> %macro SECINFO 1 104 <3> extern __%1_start, __%1_end 105 <3> extern __%1_len, __%1_dwords 106 <3> %endmacro 107 <3> 108 <3> SECINFO bss16 108 <4> extern __%1_start, __%1_end 108 <4> extern __%1_len, __%1_dwords 109 <3> SECINFO uibss 109 <4> extern __%1_start, __%1_end 109 <4> extern __%1_len, __%1_dwords 110 <3> SECINFO config 110 <4> extern __%1_start, __%1_end 110 <4> extern __%1_len, __%1_dwords 111 <3> SECINFO replacestub 111 <4> extern __%1_start, __%1_end 111 <4> extern __%1_len, __%1_dwords 112 <3> SECINFO bcopyxx 112 <4> extern __%1_start, __%1_end 112 <4> extern __%1_len, __%1_dwords 113 <3> 114 <3> SECINFO pm_code 114 <4> extern __%1_start, __%1_end 114 <4> extern __%1_len, __%1_dwords 115 <3> SECINFO high_clear 115 <4> extern __%1_start, __%1_end 115 <4> extern __%1_len, __%1_dwords 116 <3> extern __pm_code_lma 117 <3> 118 <3> SECINFO bss 118 <4> extern __%1_start, __%1_end 118 <4> extern __%1_len, __%1_dwords 119 <3> 120 <3> extern free_high_memory 121 <3> 122 <3> global _start 123 <3> 124 <3> section .text16 125 <3> 126 <3> ; 127 <3> ; Segment assignments in the bottom 640K 128 <3> ; Keep the low-memory footprint as small as possible... overrun is a hard 129 <3> ; failure! 130 <3> ; 131 <3> 132 <3> serial_buf_size equ 4096 ; Should be a power of 2 133 <3> 134 <3> ; 135 <3> ; Transfer buffer segment: guaranteed to be aligned 64K, used for disk I/O 136 <3> ; One symbol for the segment number, one for the absolute address 137 <3> ; 138 <3> extern xfer_buf_seg 139 <3> section .xfer_buf write nobits align=65536 140 <3> global core_xfer_buf:data hidden 141 00010000 <3> core_xfer_buf resb 65536 142 <3> 143 <3> ; 144 <3> ; At the very end, the lowmem heap 145 <3> ; 146 <3> extern __lowmem_heap 147 <3> min_lowmem_heap equ 65536 148 <3> 149 <3> section .text16 32 <2> %include "pmcall.inc" 1 <3> ;; 2 <3> ;; pmcall.inc 3 <3> ;; 4 <3> ;; Macros for the stack frame set up by pm_call, assuming ebp is left 5 <3> ;; as the RM frame pointer. 6 <3> ;; 7 <3> 8 <3> %ifndef PMCALL_INC 9 <3> %define PMCALL_INC 10 <3> 11 <3> %define RM_GS word [ebp] 12 <3> %define RM_FS word [ebp+2] 13 <3> %define RM_ES word [ebp+4] 14 <3> %define RM_DS word [ebp+6] 15 <3> 16 <3> %define RM_EDI dword [ebp+8] 17 <3> %define RM_DI word [ebp+8] 18 <3> %define RM_HDI word [ebp+10] 19 <3> %define RM_DIL byte [ebp+8] 20 <3> %define RM_DIH byte [ebp+9] 21 <3> 22 <3> %define RM_ESI dword [ebp+12] 23 <3> %define RM_SI word [ebp+12] 24 <3> %define RM_HSI word [ebp+14] 25 <3> %define RM_SIL byte [ebp+12] 26 <3> %define RM_SIH byte [ebp+13] 27 <3> 28 <3> %define RM_EBP dword [ebp+16] 29 <3> %define RM_BP word [ebp+16] 30 <3> %define RM_HBP word [ebp+18] 31 <3> %define RM_BPL byte [ebp+16] 32 <3> %define RM_BPH byte [ebp+17] 33 <3> 34 <3> %define RM_EBX dword [ebp+24] 35 <3> %define RM_BX word [ebp+24] 36 <3> %define RM_HBX word [ebp+26] 37 <3> %define RM_BL byte [ebp+24] 38 <3> %define RM_BH byte [ebp+25] 39 <3> 40 <3> %define RM_EDX dword [ebp+28] 41 <3> %define RM_DX word [ebp+28] 42 <3> %define RM_HDX word [ebp+30] 43 <3> %define RM_DL byte [ebp+28] 44 <3> %define RM_DH byte [ebp+29] 45 <3> 46 <3> %define RM_ECX dword [ebp+32] 47 <3> %define RM_CX word [ebp+32] 48 <3> %define RM_HCX word [ebp+34] 49 <3> %define RM_CL byte [ebp+32] 50 <3> %define RM_CH byte [ebp+33] 51 <3> 52 <3> %define RM_EAX dword [ebp+36] 53 <3> %define RM_AX word [ebp+36] 54 <3> %define RM_HAX word [ebp+38] 55 <3> %define RM_AL byte [ebp+36] 56 <3> %define RM_AH byte [ebp+37] 57 <3> 58 <3> %define RM_EFLAGS dword [ebp+40] 59 <3> %define RM_FLAGS word [ebp+40] 60 <3> %define RM_HFLAGS word [ebp+42] 61 <3> %define RM_FLAGSL byte [ebp+40] 62 <3> %define RM_FLAGSH byte [ebp+41] 63 <3> 64 <3> ; Convenience macro to call a PM function 65 <3> %macro pm_call 1 66 <3> push dword %1 67 <3> call _pm_call 68 <3> %endmacro 69 <3> 70 <3> %endif ; PMCALL_INC 33 <2> %include "extern.inc" 1 <3> ; 2 <3> ; extern.inc 3 <3> ; 4 <3> ; Prototypes for external functions 5 <3> 6 <3> %ifndef EXTERN_INC 7 <3> %define EXTERN_INC 8 <3> 9 <3> ; rllpack.c 10 <3> extern rllpack, rllunpack 11 <3> 12 <3> ; hello.c 13 <3> extern hello 14 <3> 15 <3> ; elflink/load_env32.c 16 <3> extern load_env32, pm_env32_run 17 <3> 18 <3> extern mp1, mp2, mp3, mp4, mp5 19 <3> 20 <3> extern hexdump 21 <3> 22 <3> extern mem_init 23 <3> 24 <3> ; fs.c 25 <3> extern pm_fs_init 26 <3> extern SectorSize, SectorShift 27 <3> 28 <3> ; chdir.c 29 <3> extern pm_realpath 30 <3> 31 <3> ; readdir.c 32 <3> extern opendir, readdir, closedir 33 <3> 34 <3> ; idle.c 35 <3> extern __idle 36 <3> 37 <3> %ifdef DEBUG 38 <3> ; debug.c 39 <3> extern pm_debug_msg 40 <3> 41 <3> %macro dprint 1+ 42 <3> push ax 43 <3> call %%fwd 44 <3> db %1 45 <3> db 0 46 <3> %%fwd: pop ax 47 <3> pm_call pm_debug_msg 48 <3> pop ax 49 <3> %endmacro 50 <3> %else 51 <3> %macro dprint 1+ 52 <3> %endmacro 53 <3> %endif 54 <3> 55 <3> %if IS_PXELINUX 56 <3> ; pxe.c 57 <3> extern unload_pxe, reset_pxe 58 <3> %endif 59 <3> 60 <3> ; plaincon.c 61 <3> extern pm_writechr 62 <3> 63 <3> ; cleanup.c 64 <3> extern cleanup_hardware 65 <3> 66 <3> ; writestr.c 67 <3> extern pm_writestr, crlf 68 <3> 69 <3> ; writehex.c 70 <3> extern pm_writehex2, pm_writehex4, pm_writehex8 71 <3> 72 <3> ; graphics.c 73 <3> extern syslinux_force_text_mode, vgashowcursor, vgahidecursor, pm_using_vga 74 <3> 75 <3> ; conio.c 76 <3> extern pm_pollchar, pm_write_serial, pm_serialcfg 77 <3> 78 <3> ; font.c 79 <3> extern pm_getchar, pm_adjust_screen, pm_userfont 80 <3> 81 <3> %endif ; EXTERN_INC 34 <2> %include "kernel.inc" 1 <3> ;; ----------------------------------------------------------------------- 2 <3> ;; 3 <3> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <3> ;; 5 <3> ;; This program is free software; you can redistribute it and/or modify 6 <3> ;; it under the terms of the GNU General Public License as published by 7 <3> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 <3> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 9 <3> ;; (at your option) any later version; incorporated herein by reference. 10 <3> ;; 11 <3> ;; ----------------------------------------------------------------------- 12 <3> 13 <3> ;; 14 <3> ;; kernel.inc 15 <3> ;; 16 <3> ;; Header file for the kernel interface definitions 17 <3> ;; 18 <3> 19 <3> %ifndef _KERNEL_INC 20 <3> %define _KERNEL_INC 21 <3> 22 <3> ;; 23 <3> ;; Structure of the real_mode_seg 24 <3> ;; 25 <3> 26 <3> struc real_mode_seg_t 27 00000000 <3> resb 20h-($-$$) ; org 20h 28 00000020 <3> kern_cmd_magic resw 1 ; 0020 Magic # for command line 29 00000022 <3> kern_cmd_offset resw 1 ; 0022 Offset for kernel command line 30 00000024 <3> resb 497-($-$$) ; org 497d 31 000001F1 <3> bs_setupsecs resb 1 ; 01F1 Sectors for setup code (0 -> 4) 32 000001F2 <3> bs_rootflags resw 1 ; 01F2 Root readonly flag 33 000001F4 <3> bs_syssize resw 1 ; 01F4 34 000001F6 <3> bs_swapdev resw 1 ; 01F6 Swap device (obsolete) 35 000001F8 <3> bs_ramsize resw 1 ; 01F8 Ramdisk flags, formerly ramdisk size 36 000001FA <3> bs_vidmode resw 1 ; 01FA Video mode 37 000001FC <3> bs_rootdev resw 1 ; 01FC Root device 38 000001FE <3> bs_bootsign resw 1 ; 01FE Boot sector signature (0AA55h) 39 00000200 <3> su_jump resb 1 ; 0200 0EBh 40 00000201 <3> su_jump2 resb 1 ; 0201 Size of following header 41 00000202 <3> su_header resd 1 ; 0202 New setup code: header 42 00000206 <3> su_version resw 1 ; 0206 See linux/arch/i386/boot/setup.S 43 00000208 <3> su_switch resw 1 ; 0208 44 0000020A <3> su_setupseg resw 1 ; 020A 45 0000020C <3> su_startsys resw 1 ; 020C 46 0000020E <3> su_kver resw 1 ; 020E Kernel version pointer 47 00000210 <3> su_loader resb 1 ; 0210 Loader ID 48 00000211 <3> su_loadflags resb 1 ; 0211 Load high flag 49 00000212 <3> su_movesize resw 1 ; 0212 50 00000214 <3> su_code32start resd 1 ; 0214 Start of code loaded high 51 00000218 <3> su_ramdiskat resd 1 ; 0218 Start of initial ramdisk 52 0000021C <3> su_ramdisklen resd 1 ; 021C Length of initial ramdisk 53 00000220 <3> su_bsklugeoffs resw 1 ; 0220 54 00000222 <3> su_bsklugeseg resw 1 ; 0222 55 00000224 <3> su_heapend resw 1 ; 0224 56 00000226 <3> su_pad1 resw 1 ; 0226 57 00000228 <3> su_cmd_line_ptr resd 1 ; 0228 58 0000022C <3> su_ramdisk_max resd 1 ; 022C 59 00000230 <3> resb (0f800h-12)-($-$$) 60 <3> linux_stack equ $ ; F7F4 61 0000F7F4 <3> linux_fdctab resb 12 62 <3> cmd_line_here equ $ ; F800 Should be out of the way 63 <3> endstruc 64 <3> 65 <3> ; 66 <3> ; Old kernel command line signature 67 <3> ; 68 <3> CMD_MAGIC equ 0A33Fh ; Command line magic 69 <3> 70 <3> ; 71 <3> ; If we're loading the command line old-style, we need a smaller 72 <3> ; heap. 73 <3> ; 74 <3> old_cmd_line_here equ 9800h 75 <3> old_max_cmd_len equ 2047 76 <3> old_linux_fdctab equ old_cmd_line_here-12 77 <3> old_linux_stack equ old_linux_fdctab 78 <3> 79 <3> ; 80 <3> ; Magic number of su_header field 81 <3> ; 82 <3> HEADER_ID equ 'HdrS' ; HdrS (in littleendian hex) 83 <3> 84 <3> ; 85 <3> ; Flags for the su_loadflags field 86 <3> ; 87 <3> LOAD_HIGH equ 01h ; Large kernel, load high 88 <3> QUIET_FLAG equ 20h ; Quiet the kernel 89 <3> KEEP_SEGMENTS equ 40h ; Don't reload segments 90 <3> CAN_USE_HEAP equ 80h ; Boot loader reports heap size 91 <3> 92 <3> ; 93 <3> ; ID codes for various modules 94 <3> ; 95 <3> syslinux_id equ 031h ; 3 = SYSLINUX family; 1 = SYSLINUX 96 <3> pxelinux_id equ 032h ; 3 = SYSLINUX family; 2 = PXELINUX 97 <3> isolinux_id equ 033h ; 3 = SYSLINUX family; 3 = ISOLINUX 98 <3> extlinux_id equ 034h ; 3 = SYSLINUX family; 4 = EXTLINUX 99 <3> 100 <3> ; 101 <3> ; Types of vkernels 102 <3> ; 103 <3> VK_LOCALBOOT equ -1 ; localboot (no actual kernel loaded) 104 <3> VK_KERNEL equ 0 ; Choose by filename 105 <3> VK_LINUX equ 1 ; Linux kernel image 106 <3> VK_BOOT equ 2 ; Boot sector 107 <3> VK_BSS equ 3 ; BSS boot sector 108 <3> VK_PXE equ 4 ; PXE NBP 109 <3> VK_FDIMAGE equ 5 ; Floppy disk image 110 <3> VK_COMBOOT equ 6 ; COMBOOT image 111 <3> VK_COM32 equ 7 ; COM32 image 112 <3> VK_CONFIG equ 8 ; Configuration file 113 <3> VK_TYPES equ 9 ; Number of VK types 114 <3> 115 <3> %endif ; _KERNEL_INC 35 <2> %include "bios.inc" 1 <3> ;; ----------------------------------------------------------------------- 2 <3> ;; 3 <3> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <3> ;; 5 <3> ;; This program is free software; you can redistribute it and/or modify 6 <3> ;; it under the terms of the GNU General Public License as published by 7 <3> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 <3> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 9 <3> ;; (at your option) any later version; incorporated herein by reference. 10 <3> ;; 11 <3> ;; ----------------------------------------------------------------------- 12 <3> 13 <3> ;; 14 <3> ;; bios.inc 15 <3> ;; 16 <3> ;; Header file for the BIOS data structures etc. 17 <3> ;; 18 <3> 19 <3> %ifndef _BIOS_INC 20 <3> %define _BIOS_INC 21 <3> 22 <3> ; Interrupt vectors 23 <3> absolute 4*1Ch 24 00000070 <3> BIOS_timer_hook resd 1 25 <3> 26 <3> absolute 4*1Eh 27 <3> fdctab equ $ 28 00000078 <3> fdctab1 resw 1 29 0000007A <3> fdctab2 resw 1 30 <3> 31 <3> absolute 0400h 32 00000400 <3> serial_base resw 4 ; Base addresses for 4 serial ports 33 <3> absolute 0413h 34 00000413 <3> BIOS_fbm resw 1 ; Free Base Memory (kilobytes) 35 <3> absolute 0462h 36 00000462 <3> BIOS_page resb 1 ; Current video page 37 <3> absolute 046Ch 38 0000046C <3> BIOS_timer resw 1 ; Timer ticks 39 <3> absolute 0472h 40 00000472 <3> BIOS_magic resw 1 ; BIOS reset magic 41 <3> absolute 0484h 42 00000484 <3> BIOS_vidrows resb 1 ; Number of screen rows 43 <3> 44 <3> %endif ; _BIOS_INC 36 <2> %include "tracers.inc" 1 <3> ;; ----------------------------------------------------------------------- 2 <3> ;; 3 <3> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <3> ;; 5 <3> ;; This program is free software; you can redistribute it and/or modify 6 <3> ;; it under the terms of the GNU General Public License as published by 7 <3> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 <3> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 9 <3> ;; (at your option) any later version; incorporated herein by reference. 10 <3> ;; 11 <3> ;; ----------------------------------------------------------------------- 12 <3> 13 <3> ;; 14 <3> ;; tracers.inc 15 <3> ;; 16 <3> ;; Debugging tracers 17 <3> ;; 18 <3> 19 <3> %ifndef _TRACERS_INC 20 <3> %define _TRACERS_INC 21 <3> 22 <3> ; Note: The Makefile builds one version with DEBUG_MESSAGES automatically. 23 <3> ; %define DEBUG_TRACERS 1 ; Uncomment to get debugging tracers 24 <3> ; %define DEBUG_MESSAGES ; Uncomment to get debugging messages 25 <3> 26 <3> %ifdef DEBUG_TRACERS 27 <3> 28 <3> %macro TRACER 1 29 <3> call debug_tracer 30 <3> db %1 31 <3> %endmacro 32 <3> 33 <3> %else ; DEBUG_TRACERS 34 <3> 35 <3> %macro TRACER 1 36 <3> %endmacro 37 <3> 38 <3> %endif ; DEBUG_TRACERS 39 <3> 40 <3> %endif ; _TRACERS_INC 37 <2> %include "stack.inc" 1 <3> ; ----------------------------------------------------------------------- 2 <3> ; 3 <3> ; Copyright 2005-2008 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> ; stack.inc 16 <3> ; 17 <3> ; How to reset the stack pointer 18 <3> ; 19 <3> 20 <3> %ifndef _STACK_INC 21 <3> %define _STACK_INC 22 <3> 23 <3> ; 24 <3> ; This macro resets the stack pointer (including SS), and sets 25 <3> ; DS == ES == 0, interrupts on, DF = 0. 26 <3> ; 27 <3> ; It takes a 16-bit register that can be safely clobbered as parameter. 28 <3> ; 29 <3> %macro RESET_STACK_AND_SEGS 1 30 <3> xor %1,%1 31 <3> mov ds,%1 32 <3> mov es,%1 33 <3> lss esp,[BaseStack] 34 <3> mov dword [PMESP],__stack_end ; Reset PM stack 35 <3> sti 36 <3> cld 37 <3> %endmacro 38 <3> 39 <3> section .data16 40 <3> alignz 4 41 <3> global BaseStack:data hidden 42 00008E30 D07B0000 <3> BaseStack dd StackHome ; ESP of the "home" stack pointer 43 00008E34 0000 <3> dw 0 ; SS of the "home" stack pointer 44 <3> 45 <3> section .text16 46 <3> 47 <3> %endif ; _STACK_INC 38 <2> %include "io.inc" 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> ;; io.inc 16 <3> ;; 17 <3> ;; I/O related macros 18 <3> ;; 19 <3> 20 <3> %ifndef _IO_INC 21 <3> %define _IO_INC 22 <3> 23 <3> %define IO_DELAY_PORT 80h ; Invalid port (we hope!) 24 <3> 25 <3> %macro io_delay 0.nolist 26 <3> out IO_DELAY_PORT,al 27 <3> out IO_DELAY_PORT,al 28 <3> %endmacro 29 <3> 30 <3> %macro slow_out 2.nolist 31 <3> out %1,%2 32 <3> io_delay 33 <3> %endmacro 34 <3> 35 <3> %endif ; _IO_INC 39 <2> 40 <2> %endif ; _HEAD_INC 24 <1> 25 <1> ; 26 <1> ; Some semi-configurable constants... change on your own risk. 27 <1> ; 28 <1> my_id equ isolinux_id 29 <1> NULLFILE equ 0 ; Zero byte == null file name 30 <1> NULLOFFSET equ 0 ; Position in which to look 31 <1> retry_count equ 6 ; How patient are we with the BIOS? 32 <1> %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top 33 <1> SECTOR_SHIFT equ 11 ; 2048 bytes/sector (El Torito requirement) 34 <1> SECTOR_SIZE equ (1 << SECTOR_SHIFT) 35 <1> 36 <1> ROOT_DIR_WORD equ 0x002F 37 <1> 38 <1> ; --------------------------------------------------------------------------- 39 <1> ; BEGIN CODE 40 <1> ; --------------------------------------------------------------------------- 41 <1> 42 <1> ; 43 <1> ; Memory below this point is reserved for the BIOS and the MBR 44 <1> ; 45 <1> section .earlybss 46 <1> global trackbuf 47 <1> trackbufsize equ 8192 48 00001000 <1> trackbuf resb trackbufsize ; Track buffer goes here 49 <1> ; ends at 2800h 50 <1> 51 <1> ; Some of these are touched before the whole image 52 <1> ; is loaded. DO NOT move this to .bss16/.uibss. 53 <1> section .earlybss 54 <1> global BIOSName 55 <1> alignb 4 56 00003000 <1> FirstSecSum resd 1 ; Checksum of bytes 64-2048 57 00003004 <1> ImageDwords resd 1 ; isolinux.bin size, dwords 58 00003008 <1> InitStack resd 1 ; Initial stack pointer (SS:SP) 59 0000300C <1> DiskSys resw 1 ; Last INT 13h call 60 0000300E <1> ImageSectors resw 1 ; isolinux.bin size, sectors 61 <1> ; These following two are accessed as a single dword... 62 00003010 <1> GetlinsecPtr resw 1 ; The sector-read pointer 63 00003012 <1> BIOSName resw 1 ; Display string for BIOS type 64 <1> %define HAVE_BIOSNAME 1 65 <1> global BIOSType 66 00003014 <1> BIOSType resw 1 67 00003016 <1> DiskError resb 1 ; Error code for disk I/O 68 <1> global DriveNumber 69 00003017 <1> DriveNumber resb 1 ; CD-ROM BIOS drive number 70 00003018 <1> ISOFlags resb 1 ; Flags for ISO directory search 71 00003019 <1> RetryCount resb 1 ; Used for disk access retries 72 <1> 73 0000301A <1> alignb 8 74 <1> global Hidden 75 00003020 <1> Hidden resq 1 ; Used in hybrid mode 76 00003028 <1> bsSecPerTrack resw 1 ; Used in hybrid mode 77 0000302A <1> bsHeads resw 1 ; Used in hybrid mode 78 <1> 79 <1> 80 <1> ; 81 <1> ; El Torito spec packet 82 <1> ; 83 <1> 84 0000302C <1> alignb 8 85 <1> _spec_start equ $ 86 <1> global spec_packet 87 00003030 <1> spec_packet: resb 1 ; Size of packet 88 00003031 <1> sp_media: resb 1 ; Media type 89 00003032 <1> sp_drive: resb 1 ; Drive number 90 00003033 <1> sp_controller: resb 1 ; Controller index 91 00003034 <1> sp_lba: resd 1 ; LBA for emulated disk image 92 00003038 <1> sp_devspec: resw 1 ; IDE/SCSI information 93 0000303A <1> sp_buffer: resw 1 ; User-provided buffer 94 0000303C <1> sp_loadseg: resw 1 ; Load segment 95 0000303E <1> sp_sectors: resw 1 ; Sector count 96 00003040 <1> sp_chs: resb 3 ; Simulated CHS geometry 97 00003043 <1> sp_dummy: resb 1 ; Scratch, safe to overwrite 98 <1> 99 <1> ; 100 <1> ; EBIOS drive parameter packet 101 <1> ; 102 00003044 <1> alignb 8 103 00003048 <1> drive_params: resw 1 ; Buffer size 104 0000304A <1> dp_flags: resw 1 ; Information flags 105 0000304C <1> dp_cyl: resd 1 ; Physical cylinders 106 00003050 <1> dp_head: resd 1 ; Physical heads 107 00003054 <1> dp_sec: resd 1 ; Physical sectors/track 108 00003058 <1> dp_totalsec: resd 2 ; Total sectors 109 00003060 <1> dp_secsize: resw 1 ; Bytes per sector 110 00003062 <1> dp_dpte: resd 1 ; Device Parameter Table 111 00003066 <1> dp_dpi_key: resw 1 ; 0BEDDh if rest valid 112 00003068 <1> dp_dpi_len: resb 1 ; DPI len 113 00003069 <1> resb 1 114 0000306A <1> resw 1 115 0000306C <1> dp_bus: resb 4 ; Host bus type 116 00003070 <1> dp_interface: resb 8 ; Interface type 117 00003078 <1> db_i_path: resd 2 ; Interface path 118 00003080 <1> db_d_path: resd 2 ; Device path 119 00003088 <1> resb 1 120 00003089 <1> db_dpi_csum: resb 1 ; Checksum for DPI info 121 <1> 122 <1> ; 123 <1> ; EBIOS disk address packet 124 <1> ; 125 0000308A <1> alignb 8 126 00003090 <1> dapa: resw 1 ; Packet size 127 00003092 <1> .count: resw 1 ; Block count 128 00003094 <1> .off: resw 1 ; Offset of buffer 129 00003096 <1> .seg: resw 1 ; Segment of buffer 130 00003098 <1> .lba: resd 2 ; LBA (LSW, MSW) 131 <1> 132 <1> ; 133 <1> ; Spec packet for disk image emulation 134 <1> ; 135 <1> alignb 8 136 000030A0 <1> dspec_packet: resb 1 ; Size of packet 137 000030A1 <1> dsp_media: resb 1 ; Media type 138 000030A2 <1> dsp_drive: resb 1 ; Drive number 139 000030A3 <1> dsp_controller: resb 1 ; Controller index 140 000030A4 <1> dsp_lba: resd 1 ; LBA for emulated disk image 141 000030A8 <1> dsp_devspec: resw 1 ; IDE/SCSI information 142 000030AA <1> dsp_buffer: resw 1 ; User-provided buffer 143 000030AC <1> dsp_loadseg: resw 1 ; Load segment 144 000030AE <1> dsp_sectors: resw 1 ; Sector count 145 000030B0 <1> dsp_chs: resb 3 ; Simulated CHS geometry 146 000030B3 <1> dsp_dummy: resb 1 ; Scratch, safe to overwrite 147 <1> 148 <1> alignb 4 149 <1> _spec_end equ $ 150 <1> _spec_len equ _spec_end - _spec_start 151 <1> 152 <1> section .init 153 <1> ;; 154 <1> ;; Primary entry point. Because BIOSes are buggy, we only load the first 155 <1> ;; CD-ROM sector (2K) of the file, so the number one priority is actually 156 <1> ;; loading the rest. 157 <1> ;; 158 <1> global StackBuf 159 <1> StackBuf equ STACK_TOP-44 ; 44 bytes needed for 160 <1> ; the bootsector chainloading 161 <1> ; code! 162 <1> global OrigESDI 163 <1> OrigESDI equ StackBuf-4 ; The high dword on the stack 164 <1> StackHome equ OrigESDI 165 <1> 166 <1> bootsec equ $ 167 <1> 168 <1> _start: ; Far jump makes sure we canonicalize the address 169 00007C00 FA <1> cli 170 00007C01 EA[4000]0000 <1> jmp 0:_start1 171 00007C06 90 <1> times 8-($-$$) nop ; Pad to file offset 8 172 <1> 173 <1> ; This table hopefully gets filled in by mkisofs using the 174 <1> ; -boot-info-table option. If not, the values in this 175 <1> ; table are default values that we can use to get us what 176 <1> ; we need, at least under a certain set of assumptions. 177 <1> global iso_boot_info 178 <1> iso_boot_info: 179 00007C08 10000000 <1> bi_pvd: dd 16 ; LBA of primary volume descriptor 180 00007C0C 00000000 <1> bi_file: dd 0 ; LBA of boot file 181 00007C10 EFBEADDE <1> bi_length: dd 0xdeadbeef ; Length of boot file 182 00007C14 EFBEADDE <1> bi_csum: dd 0xdeadbeef ; Checksum of boot file 183 00007C18 EFBEADDE <1> bi_reserved: times 10 dd 0xdeadbeef ; Reserved 184 <1> bi_end: 185 <1> 186 <1> ; Custom entry point for the hybrid-mode disk. 187 <1> ; The following values will have been pushed onto the 188 <1> ; entry stack: 189 <1> ; - partition offset (qword) 190 <1> ; - ES 191 <1> ; - DI 192 <1> ; - DX (including drive number) 193 <1> ; - CBIOS Heads 194 <1> ; - CBIOS Sectors 195 <1> ; - EBIOS flag 196 <1> ; (top of stack) 197 <1> ; 198 <1> ; If we had an old isohybrid, the partition offset will 199 <1> ; be missing; we can check for that with sp >= 0x7c00. 200 <1> ; Serious hack alert. 201 <1> %ifndef DEBUG_MESSAGES 202 <1> _hybrid_signature: 203 <1> dd 0x7078c0fb ; An arbitrary number... 204 <1> 205 <1> _start_hybrid: 206 <1> pop cx ; EBIOS flag 207 <1> pop word [cs:bsSecPerTrack] 208 <1> pop word [cs:bsHeads] 209 <1> pop dx 210 <1> pop di 211 <1> pop es 212 <1> xor eax,eax 213 <1> xor ebx,ebx 214 <1> cmp sp,7C00h 215 <1> jae .nooffset 216 <1> pop eax 217 <1> pop ebx 218 <1> .nooffset: 219 <1> mov si,bios_cbios 220 <1> jcxz _start_common 221 <1> mov si,bios_ebios 222 <1> jmp _start_common 223 <1> %endif 224 <1> 225 <1> _start1: 226 00007C40 BE[E407] <1> mov si,bios_cdrom 227 00007C43 6631C0 <1> xor eax,eax 228 00007C46 6631DB <1> xor ebx,ebx 229 <1> _start_common: 230 00007C49 2E8926[0820] <1> mov [cs:InitStack],sp ; Save initial stack pointer 231 00007C4E 2E8C16[0A20] <1> mov [cs:InitStack+2],ss 232 00007C53 31C9 <1> xor cx,cx 233 00007C55 8ED1 <1> mov ss,cx 234 00007C57 BCD47B <1> mov sp,StackBuf ; Set up stack 235 00007C5A 06 <1> push es ; Save initial ES:DI -> $PnP pointer 236 00007C5B 57 <1> push di 237 00007C5C 8ED9 <1> mov ds,cx 238 00007C5E 8EC1 <1> mov es,cx 239 00007C60 8EE1 <1> mov fs,cx 240 00007C62 8EE9 <1> mov gs,cx 241 00007C64 FB <1> sti 242 00007C65 FC <1> cld 243 <1> 244 00007C66 66A3[2020] <1> mov [Hidden],eax 245 00007C6A 66891E[2420] <1> mov [Hidden+4],ebx 246 <1> 247 00007C6F 8936[1420] <1> mov [BIOSType],si 248 00007C73 668B04 <1> mov eax,[si] 249 00007C76 66A3[1020] <1> mov [GetlinsecPtr],eax 250 <1> 251 <1> ; Show signs of life 252 00007C7A BE[0C05] <1> mov si,syslinux_banner 253 00007C7D E81B03 <1> call writestr_early 254 <1> %ifdef DEBUG_MESSAGES 255 00007C80 BE[2805] <1> mov si,copyright_str 256 <1> %else 257 <1> mov si,[BIOSName] 258 <1> %endif 259 00007C83 E81503 <1> call writestr_early 260 <1> 261 <1> ; 262 <1> ; Before modifying any memory, get the checksum of bytes 263 <1> ; 64-2048 264 <1> ; 265 00007C86 6631FF <1> initial_csum: xor edi,edi 266 00007C89 BE[4000] <1> mov si,bi_end 267 00007C8C B9F001 <1> mov cx,(SECTOR_SIZE-64) >> 2 268 00007C8F 66AD <1> .loop: lodsd 269 00007C91 6601C7 <1> add edi,eax 270 00007C94 E2F9 <1> loop .loop 271 00007C96 66893E[0020] <1> mov [FirstSecSum],edi 272 <1> 273 00007C9B 8816[1720] <1> mov [DriveNumber],dl 274 <1> %ifdef DEBUG_MESSAGES 275 00007C9F BE[6305] <1> mov si,startup_msg 276 00007CA2 E8E802 <1> call writemsg 277 00007CA5 88D0 <1> mov al,dl 278 00007CA7 E82304 <1> call writehex2 279 00007CAA E80103 <1> call crlf_early 280 <1> %endif 281 <1> ; 282 <1> ; Initialize spec packet buffers 283 <1> ; 284 00007CAD BF[3020] <1> mov di,_spec_start 285 00007CB0 B92100 <1> mov cx,_spec_len >> 2 286 00007CB3 6631C0 <1> xor eax,eax 287 00007CB6 F366AB <1> rep stosd 288 <1> 289 <1> ; Initialize length field of the various packets 290 00007CB9 C606[3020]13 <1> mov byte [spec_packet],13h 291 00007CBE C606[4820]1E <1> mov byte [drive_params],30 292 00007CC3 C606[9020]10 <1> mov byte [dapa],16 293 00007CC8 C606[A020]13 <1> mov byte [dspec_packet],13h 294 <1> 295 <1> ; Other nonzero fields 296 00007CCD FF06[AE20] <1> inc word [dsp_sectors] 297 <1> 298 <1> ; Are we just pretending to be a CD-ROM? 299 00007CD1 813E[1420][E407] <1> cmp word [BIOSType],bios_cdrom 300 00007CD7 752C <1> jne found_drive ; If so, no spec packet... 301 <1> 302 <1> ; Now figure out what we're actually doing 303 <1> ; Note: use passed-in DL value rather than 7Fh because 304 <1> ; at least some BIOSes will get the wrong value otherwise 305 00007CD9 B8014B <1> mov ax,4B01h ; Get disk emulation status 306 00007CDC 8A16[1720] <1> mov dl,[DriveNumber] 307 00007CE0 BE[3020] <1> mov si,spec_packet 308 00007CE3 E8E402 <1> call int13 309 00007CE6 0F82AA01 <1> jc award_hack ; changed for BrokenAwardHack 310 00007CEA 8A16[1720] <1> mov dl,[DriveNumber] 311 00007CEE 3816[3220] <1> cmp [sp_drive],dl ; Should contain the drive number 312 00007CF2 0F852A02 <1> jne spec_query_failed 313 <1> 314 <1> %ifdef DEBUG_MESSAGES 315 00007CF6 BE[7605] <1> mov si,spec_ok_msg 316 00007CF9 E89102 <1> call writemsg 317 00007CFC A0[3220] <1> mov al,byte [sp_drive] 318 00007CFF E8CB03 <1> call writehex2 319 00007D02 E8A902 <1> call crlf_early 320 <1> %endif 321 <1> 322 <1> found_drive: 323 <1> ; Alright, we have found the drive. Now, try to find the 324 <1> ; boot file itself. If we have a boot info table, life is 325 <1> ; good; if not, we have to make some assumptions, and try 326 <1> ; to figure things out ourselves. In particular, the 327 <1> ; assumptions we have to make are: 328 <1> ; - single session only 329 <1> ; - only one boot entry (no menu or other alternatives) 330 <1> 331 00007D05 66833E[0C00]00 <1> cmp dword [bi_file],0 ; Address of code to load 332 00007D0B 7533 <1> jne found_file ; Boot info table present :) 333 <1> 334 <1> %ifdef DEBUG_MESSAGES 335 00007D0D BE[F205] <1> mov si,noinfotable_msg 336 00007D10 E87A02 <1> call writemsg 337 <1> %endif 338 <1> 339 <1> ; No such luck. See if the spec packet contained one. 340 00007D13 66A1[3420] <1> mov eax,[sp_lba] 341 00007D17 6621C0 <1> and eax,eax 342 00007D1A 7420 <1> jz set_file ; Good enough 343 <1> 344 <1> %ifdef DEBUG_MESSAGES 345 00007D1C BE[2806] <1> mov si,noinfoinspec_msg 346 00007D1F E86B02 <1> call writemsg 347 <1> %endif 348 <1> 349 <1> ; No such luck. Get the Boot Record Volume, assuming single 350 <1> ; session disk, and that we're the first entry in the chain. 351 00007D22 66B811000000 <1> mov eax,17 ; Assumed address of BRV 352 00007D28 BB[0000] <1> mov bx,trackbuf 353 00007D2B E8B502 <1> call getonesec 354 <1> 355 00007D2E 66A1[4700] <1> mov eax,[trackbuf+47h] ; Get boot catalog address 356 00007D32 BB[0000] <1> mov bx,trackbuf 357 00007D35 E8AB02 <1> call getonesec ; Get boot catalog 358 <1> 359 00007D38 66A1[2800] <1> mov eax,[trackbuf+28h] ; First boot entry 360 <1> ; And hope and pray this is us... 361 <1> 362 <1> ; Some BIOSes apparently have limitations on the size 363 <1> ; that may be loaded (despite the El Torito spec being very 364 <1> ; clear on the fact that it must all be loaded.) Therefore, 365 <1> ; we load it ourselves, and *bleep* the BIOS. 366 <1> 367 <1> set_file: 368 00007D3C 66A3[0C00] <1> mov [bi_file],eax 369 <1> 370 <1> found_file: 371 <1> ; Set up boot file sizes 372 00007D40 66A1[1000] <1> mov eax,[bi_length] 373 00007D44 662DFD070000 <1> sub eax,SECTOR_SIZE-3 ; ... minus sector loaded 374 00007D4A 66C1E802 <1> shr eax,2 ; bytes->dwords 375 00007D4E 66A3[0420] <1> mov [ImageDwords],eax ; boot file dwords 376 00007D52 6605FF010000 <1> add eax,((SECTOR_SIZE-1) >> 2) 377 00007D58 66C1E809 <1> shr eax,SECTOR_SHIFT-2 ; dwords->sectors 378 00007D5C A3[0E20] <1> mov [ImageSectors],ax ; boot file sectors 379 <1> 380 00007D5F 66A1[0C00] <1> mov eax,[bi_file] ; Address of code to load 381 00007D63 6640 <1> inc eax ; Don't reload bootstrap code 382 <1> %ifdef DEBUG_MESSAGES 383 00007D65 BE[A305] <1> mov si,offset_msg 384 00007D68 E82202 <1> call writemsg 385 00007D6B E87903 <1> call writehex8 386 00007D6E E83D02 <1> call crlf_early 387 <1> %endif 388 <1> 389 <1> ; Load the rest of the file. However, just in case there 390 <1> ; are still BIOSes with 64K wraparound problems, we have to 391 <1> ; take some extra precautions. Since the normal load 392 <1> ; address (TEXT_START) is *not* 2K-sector-aligned, we round 393 <1> ; the target address upward to a sector boundary, 394 <1> ; and then move the entire thing down as a unit. 395 <1> MaxLMA equ 384*1024 ; Reasonable limit (384K) 396 <1> 397 00007D71 BB8008 <1> mov bx,((TEXT_START+2*SECTOR_SIZE-1) & ~(SECTOR_SIZE-1)) >> 4 398 00007D74 8B2E[0E20] <1> mov bp,[ImageSectors] 399 00007D78 53 <1> push bx ; Load segment address 400 <1> 401 <1> .more: 402 00007D79 53 <1> push bx ; Segment address 403 00007D7A 55 <1> push bp ; Sector count 404 00007D7B 8EC3 <1> mov es,bx 405 00007D7D B9FF0F <1> mov cx,0xfff 406 00007D80 21CB <1> and bx,cx 407 00007D82 41 <1> inc cx 408 00007D83 29D9 <1> sub cx,bx 409 00007D85 C1E907 <1> shr cx,SECTOR_SHIFT - 4 410 00007D88 7503 <1> jnz .notaligned 411 00007D8A B92000 <1> mov cx,0x10000 >> SECTOR_SHIFT ; Full 64K segment possible 412 <1> .notaligned: 413 00007D8D 39CD <1> cmp bp,cx 414 00007D8F 7602 <1> jbe .ok 415 00007D91 89CD <1> mov bp,cx 416 <1> .ok: 417 00007D93 31DB <1> xor bx,bx 418 00007D95 55 <1> push bp 419 00007D96 6650 <1> push eax 420 00007D98 E84B02 <1> call getlinsec 421 00007D9B 6658 <1> pop eax 422 00007D9D 59 <1> pop cx 423 00007D9E 660FB7D1 <1> movzx edx,cx 424 00007DA2 5D <1> pop bp 425 00007DA3 5B <1> pop bx 426 <1> 427 00007DA4 C1E107 <1> shl cx,SECTOR_SHIFT - 4 428 00007DA7 01CB <1> add bx,cx 429 00007DA9 6601D0 <1> add eax,edx 430 00007DAC 29D5 <1> sub bp,dx 431 00007DAE 75C9 <1> jnz .more 432 <1> 433 <1> ; Move the image into place, and also verify the 434 <1> ; checksum 435 00007DB0 58 <1> pop ax ; Load segment address 436 00007DB1 BB4008 <1> mov bx,(TEXT_START + SECTOR_SIZE) >> 4 437 00007DB4 668B0E[0420] <1> mov ecx,[ImageDwords] 438 00007DB9 668B3E[0020] <1> mov edi,[FirstSecSum] ; First sector checksum 439 00007DBE 31F6 <1> xor si,si 440 <1> 441 <1> move_verify_image: 442 <1> .setseg: 443 00007DC0 8ED8 <1> mov ds,ax 444 00007DC2 8EC3 <1> mov es,bx 445 <1> .loop: 446 00007DC4 668B14 <1> mov edx,[si] 447 00007DC7 6601D7 <1> add edi,edx 448 00007DCA 6649 <1> dec ecx 449 00007DCC 26668914 <1> mov [es:si],edx 450 00007DD0 740E <1> jz .done 451 00007DD2 83C604 <1> add si,4 452 00007DD5 75ED <1> jnz .loop 453 00007DD7 050010 <1> add ax,1000h 454 00007DDA 81C30010 <1> add bx,1000h 455 00007DDE EBE0 <1> jmp .setseg 456 <1> .done: 457 00007DE0 8CC8 <1> mov ax,cs 458 00007DE2 8ED8 <1> mov ds,ax 459 00007DE4 8EC0 <1> mov es,ax 460 <1> 461 <1> ; Verify the checksum on the loaded image. 462 00007DE6 66393E[1400] <1> cmp [bi_csum],edi 463 00007DEB 7409 <1> je integrity_ok 464 <1> 465 00007DED BE[9507] <1> mov si,checkerr_msg 466 00007DF0 E89A01 <1> call writemsg 467 00007DF3 E99F02 <1> jmp kaboom 468 <1> 469 <1> integrity_ok: 470 <1> %ifdef DEBUG_MESSAGES 471 00007DF6 BE[CC05] <1> mov si,allread_msg 472 00007DF9 E89101 <1> call writemsg 473 <1> %endif 474 00007DFC E9(0000) <1> jmp all_read ; Jump to main code 475 <1> 476 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 477 <1> ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de 478 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 479 <1> ;; 480 <1> ;; There is a problem with certain versions of the AWARD BIOS ... 481 <1> ;; the boot sector will be loaded and executed correctly, but, because the 482 <1> ;; int 13 vector points to the wrong code in the BIOS, every attempt to 483 <1> ;; load the spec packet will fail. We scan for the equivalent of 484 <1> ;; 485 <1> ;; mov ax,0201h 486 <1> ;; mov bx,7c00h 487 <1> ;; mov cx,0006h 488 <1> ;; mov dx,0180h 489 <1> ;; pushf 490 <1> ;; call 491 <1> ;; 492 <1> ;; and use as the new vector for int 13. The code above is 493 <1> ;; used to load the boot code into ram, and there should be no reason 494 <1> ;; for anybody to change it now or in the future. There are no opcodes 495 <1> ;; that use encodings relativ to IP, so scanning is easy. If we find the 496 <1> ;; code above in the BIOS code we can be pretty sure to run on a machine 497 <1> ;; with an broken AWARD BIOS ... 498 <1> ;; 499 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 500 <1> ;; 501 <1> %ifdef DEBUG_MESSAGES ;; 502 <1> ;; 503 00007DFF 547279696E67204272- <1> award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;; 503 00007E08 6F6B656E4177617264- <1> 503 00007E11 4861636B2066697273- <1> 503 00007E1A 74202E2E2E0D0A00 <1> 504 00007E22 4241483A204F726967- <1> award_not_orig db "BAH: Original Int 13 vector : ",0 ;; 504 00007E2B 696E616C20496E7420- <1> 504 00007E34 313320766563746F72- <1> 504 00007E3D 2020203A2000 <1> 505 00007E43 4241483A20496E7420- <1> award_not_new db "BAH: Int 13 vector changed to : ",0 ;; 505 00007E4C 313320766563746F72- <1> 505 00007E55 206368616E67656420- <1> 505 00007E5E 746F203A2000 <1> 506 00007E64 4241483A2053554343- <1> award_not_succ db "BAH: SUCCESS",CR,LF,0 ;; 506 00007E6D 4553530D0A00 <1> 507 00007E73 4241483A204641494C- <1> award_not_fail db "BAH: FAILURE" ;; 507 00007E7C 555245 <1> 508 00007E7F 0D0A00 <1> award_not_crlf db CR,LF,0 ;; 509 <1> ;; 510 <1> %endif ;; 511 <1> ;; 512 00007E82 00000000 <1> award_oldint13 dd 0 ;; 513 00007E86 B80102BB007CB90600- <1> award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;; 513 00007E8F BA80019C9A <1> 514 <1> ;; 515 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 516 00007E94 BE[6406] <1> award_hack: mov si,spec_err_msg ; Moved to this place from 517 00007E97 E8F300 <1> call writemsg ; spec_query_failed 518 <1> ; 519 <1> %ifdef DEBUG_MESSAGES ; 520 <1> ; 521 00007E9A BE[FF01] <1> mov si,award_notice ; display our plan 522 00007E9D E8ED00 <1> call writemsg ; 523 00007EA0 BE[2202] <1> mov si,award_not_orig ; display original int 13 524 00007EA3 E8E700 <1> call writemsg ; vector 525 <1> %endif ; 526 00007EA6 66A14C00 <1> mov eax,[13h*4] ; 527 00007EAA 66A3[8202] <1> mov [award_oldint13],eax ; 528 <1> ; 529 <1> %ifdef DEBUG_MESSAGES ; 530 <1> ; 531 00007EAE E83602 <1> call writehex8 ; 532 00007EB1 BE[7F02] <1> mov si,award_not_crlf ; 533 00007EB4 E8E400 <1> call writestr_early ; 534 <1> %endif ; 535 00007EB7 06 <1> push es ; save ES 536 00007EB8 B800F0 <1> mov ax,0f000h ; ES = BIOS Seg 537 00007EBB 8EC0 <1> mov es,ax ; 538 00007EBD FC <1> cld ; 539 00007EBE 31FF <1> xor di,di ; start at ES:DI = f000:0 540 00007EC0 57 <1> award_loop: push di ; save DI 541 00007EC1 BE[8602] <1> mov si,award_string ; scan for award_string 542 00007EC4 B90700 <1> mov cx,7 ; length of award_string = 7dw 543 00007EC7 F3A7 <1> repz cmpsw ; compare 544 00007EC9 5F <1> pop di ; restore DI 545 00007ECA E319 <1> jcxz award_found ; jmp if found 546 00007ECC 47 <1> inc di ; not found, inc di 547 00007ECD 71F1 <1> jno award_loop ; 548 <1> ; 549 00007ECF 07 <1> award_failed: pop es ; No, not this way :-(( 550 <1> award_fail2: ; 551 <1> ; 552 <1> %ifdef DEBUG_MESSAGES ; 553 <1> ; 554 00007ED0 BE[7302] <1> mov si,award_not_fail ; display failure ... 555 00007ED3 E8B700 <1> call writemsg ; 556 <1> %endif ; 557 00007ED6 66A1[8202] <1> mov eax,[award_oldint13] ; restore the original int 558 00007EDA 6609C0 <1> or eax,eax ; 13 vector if there is one 559 00007EDD 7441 <1> jz spec_query_failed ; and try other workarounds 560 00007EDF 66A34C00 <1> mov [13h*4],eax ; 561 00007EE3 EB3B <1> jmp spec_query_failed ; 562 <1> ; 563 00007EE5 26668B450E <1> award_found: mov eax,[es:di+0eh] ; load possible int 13 addr 564 00007EEA 07 <1> pop es ; restore ES 565 <1> ; 566 00007EEB 663B06[8202] <1> cmp eax,[award_oldint13] ; give up if this is the 567 00007EF0 74DD <1> jz award_failed ; active int 13 vector, 568 00007EF2 66A34C00 <1> mov [13h*4],eax ; otherwise change 0:13h*4 569 <1> ; 570 <1> ; 571 <1> %ifdef DEBUG_MESSAGES ; 572 <1> ; 573 00007EF6 6650 <1> push eax ; display message and 574 00007EF8 BE[4302] <1> mov si,award_not_new ; new vector address 575 00007EFB E88F00 <1> call writemsg ; 576 00007EFE 6658 <1> pop eax ; 577 00007F00 E8E401 <1> call writehex8 ; 578 00007F03 BE[7F02] <1> mov si,award_not_crlf ; 579 00007F06 E89200 <1> call writestr_early ; 580 <1> %endif ; 581 00007F09 B8014B <1> mov ax,4B01h ; try to read the spec packet 582 00007F0C 8A16[1720] <1> mov dl,[DriveNumber] ; now ... it should not fail 583 00007F10 BE[3020] <1> mov si,spec_packet ; any longer 584 00007F13 CD13 <1> int 13h ; 585 00007F15 72B9 <1> jc award_fail2 ; 586 <1> ; 587 <1> %ifdef DEBUG_MESSAGES ; 588 <1> ; 589 00007F17 BE[6402] <1> mov si,award_not_succ ; display our SUCCESS 590 00007F1A E87000 <1> call writemsg ; 591 <1> %endif ; 592 00007F1D E9E5FD <1> jmp found_drive ; and leave error recovery code 593 <1> ; 594 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 595 <1> ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de 596 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 597 <1> 598 <1> 599 <1> ; INT 13h, AX=4B01h, DL= failed. 600 <1> ; Try to scan the entire 80h-FFh from the end. 601 <1> 602 <1> spec_query_failed: 603 <1> 604 <1> ; some code moved to BrokenAwardHack 605 <1> 606 00007F20 B2FF <1> mov dl,0FFh 607 00007F22 60 <1> .test_loop: pusha 608 00007F23 B8014B <1> mov ax,4B01h 609 00007F26 BE[3020] <1> mov si,spec_packet 610 00007F29 C60413 <1> mov byte [si],13h ; Size of buffer 611 00007F2C E89B00 <1> call int13 612 00007F2F 61 <1> popa 613 00007F30 722E <1> jc .still_broken 614 <1> 615 00007F32 BE[9706] <1> mov si,maybe_msg 616 00007F35 E85500 <1> call writemsg 617 00007F38 88D0 <1> mov al,dl 618 00007F3A E89001 <1> call writehex2 619 00007F3D E86E00 <1> call crlf_early 620 <1> 621 00007F40 3816[3220] <1> cmp byte [sp_drive],dl 622 00007F44 750D <1> jne .maybe_broken 623 <1> 624 <1> ; Okay, good enough... 625 00007F46 BE[B306] <1> mov si,alright_msg 626 00007F49 E84100 <1> call writemsg 627 00007F4C 8816[1720] <1> .found_drive0: mov [DriveNumber],dl 628 00007F50 E9B2FD <1> .found_drive: jmp found_drive 629 <1> 630 <1> ; Award BIOS 4.51 apparently passes garbage in sp_drive, 631 <1> ; but if this was the drive number originally passed in 632 <1> ; DL then consider it "good enough" 633 <1> .maybe_broken: 634 00007F53 A0[1720] <1> mov al,[DriveNumber] 635 00007F56 38D0 <1> cmp al,dl 636 00007F58 74F6 <1> je .found_drive 637 <1> 638 <1> ; Intel Classic R+ computer with Adaptec 1542CP BIOS 1.02 639 <1> ; passes garbage in sp_drive, and the drive number originally 640 <1> ; passed in DL does not have 80h bit set. 641 00007F5A 0C80 <1> or al,80h 642 00007F5C 38D0 <1> cmp al,dl 643 00007F5E 74EC <1> je .found_drive0 644 <1> 645 00007F60 4A <1> .still_broken: dec dx 646 00007F61 80FA80 <1> cmp dl, 80h 647 00007F64 73BC <1> jnb .test_loop 648 <1> 649 <1> ; No spec packet anywhere. Some particularly pathetic 650 <1> ; BIOSes apparently don't even implement function 651 <1> ; 4B01h, so we can't query a spec packet no matter 652 <1> ; what. If we got a drive number in DL, then try to 653 <1> ; use it, and if it works, then well... 654 00007F66 8A16[1720] <1> mov dl,[DriveNumber] 655 00007F6A 80FA81 <1> cmp dl,81h ; Should be 81-FF at least 656 00007F6D 7216 <1> jb fatal_error ; If not, it's hopeless 657 <1> 658 <1> ; Write a warning to indicate we're on *very* thin ice now 659 00007F6F BE[D506] <1> mov si,nospec_msg 660 00007F72 E81800 <1> call writemsg 661 00007F75 88D0 <1> mov al,dl 662 00007F77 E85301 <1> call writehex2 663 00007F7A E83100 <1> call crlf_early 664 00007F7D BE[3E07] <1> mov si,trysbm_msg 665 00007F80 E80A00 <1> call writemsg 666 00007F83 EBCB <1> jmp .found_drive ; Pray that this works... 667 <1> 668 <1> fatal_error: 669 00007F85 BE[1007] <1> mov si,nothing_msg 670 00007F88 E80200 <1> call writemsg 671 <1> 672 00007F8B EBFE <1> .norge: jmp short .norge 673 <1> 674 <1> ; Information message (DS:SI) output 675 <1> ; Prefix with "isolinux: " 676 <1> ; 677 00007F8D 50 <1> writemsg: push ax 678 00007F8E 56 <1> push si 679 00007F8F BE[5805] <1> mov si,isolinux_str 680 00007F92 E80600 <1> call writestr_early 681 00007F95 5E <1> pop si 682 00007F96 E80200 <1> call writestr_early 683 00007F99 58 <1> pop ax 684 00007F9A C3 <1> ret 685 <1> 686 <1> writestr_early: 687 00007F9B 669C <1> pushfd 688 00007F9D 6660 <1> pushad 689 00007F9F AC <1> .top: lodsb 690 00007FA0 20C0 <1> and al,al 691 00007FA2 7405 <1> jz .end 692 00007FA4 E81400 <1> call writechr 693 00007FA7 EBF6 <1> jmp short .top 694 00007FA9 6661 <1> .end: popad 695 00007FAB 669D <1> popfd 696 00007FAD C3 <1> ret 697 <1> 698 00007FAE 50 <1> crlf_early: push ax 699 00007FAF B00D <1> mov al,CR 700 00007FB1 E80700 <1> call writechr 701 00007FB4 B00A <1> mov al,LF 702 00007FB6 E80200 <1> call writechr 703 00007FB9 58 <1> pop ax 704 00007FBA C3 <1> ret 705 <1> 706 <1> ; 707 <1> ; Write a character to the screen. There is a more "sophisticated" 708 <1> ; version of this in the subsequent code, so we patch the pointer 709 <1> ; when appropriate. 710 <1> ; 711 <1> 712 <1> writechr: 713 <1> .simple: 714 00007FBB 669C <1> pushfd 715 00007FBD 6660 <1> pushad 716 00007FBF B40E <1> mov ah,0Eh 717 00007FC1 31DB <1> xor bx,bx 718 00007FC3 CD10 <1> int 10h 719 00007FC5 6661 <1> popad 720 00007FC7 669D <1> popfd 721 00007FC9 C3 <1> ret 722 <1> 723 <1> ; 724 <1> ; int13: save all the segment registers and call INT 13h. 725 <1> ; Some CD-ROM BIOSes have been found to corrupt segment registers 726 <1> ; and/or disable interrupts. 727 <1> ; 728 <1> int13: 729 00007FCA 9C <1> pushf 730 00007FCB 55 <1> push bp 731 00007FCC 1E <1> push ds 732 00007FCD 06 <1> push es 733 00007FCE 0FA0 <1> push fs 734 00007FD0 0FA8 <1> push gs 735 00007FD2 CD13 <1> int 13h 736 00007FD4 89E5 <1> mov bp,sp 737 00007FD6 0F92460A <1> setc [bp+10] ; Propagate CF to the caller 738 00007FDA 0FA9 <1> pop gs 739 00007FDC 0FA1 <1> pop fs 740 00007FDE 07 <1> pop es 741 00007FDF 1F <1> pop ds 742 00007FE0 5D <1> pop bp 743 00007FE1 9D <1> popf 744 00007FE2 C3 <1> ret 745 <1> 746 <1> ; 747 <1> ; Get one sector. Convenience entry point. 748 <1> ; 749 <1> getonesec: 750 00007FE3 BD0100 <1> mov bp,1 751 <1> ; Fall through to getlinsec 752 <1> 753 <1> ; 754 <1> ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors. 755 <1> ; 756 <1> ; Input: 757 <1> ; EAX - Linear sector number 758 <1> ; ES:BX - Target buffer 759 <1> ; BP - Sector count 760 <1> ; 761 <1> global getlinsec 762 00007FE6 2EFF26[1020] <1> getlinsec: jmp word [cs:GetlinsecPtr] 763 <1> 764 <1> %ifndef DEBUG_MESSAGES 765 <1> 766 <1> ; 767 <1> ; First, the variants that we use when actually loading off a disk 768 <1> ; (hybrid mode.) These are adapted versions of the equivalent routines 769 <1> ; in ldlinux.asm. 770 <1> ; 771 <1> 772 <1> ; 773 <1> ; getlinsec_ebios: 774 <1> ; 775 <1> ; getlinsec implementation for floppy/HDD EBIOS (EDD) 776 <1> ; 777 <1> getlinsec_ebios: 778 <1> xor edx,edx 779 <1> shld edx,eax,2 780 <1> shl eax,2 ; Convert to HDD sectors 781 <1> add eax,[Hidden] 782 <1> adc edx,[Hidden+4] 783 <1> shl bp,2 784 <1> 785 <1> .loop: 786 <1> push bp ; Sectors left 787 <1> .retry2: 788 <1> call maxtrans ; Enforce maximum transfer size 789 <1> movzx edi,bp ; Sectors we are about to read 790 <1> mov cx,retry_count 791 <1> .retry: 792 <1> 793 <1> ; Form DAPA on stack 794 <1> push edx 795 <1> push eax 796 <1> push es 797 <1> push bx 798 <1> push di 799 <1> push word 16 800 <1> mov si,sp 801 <1> pushad 802 <1> mov dl,[DriveNumber] 803 <1> push ds 804 <1> push ss 805 <1> pop ds ; DS <- SS 806 <1> mov ah,42h ; Extended Read 807 <1> call int13 808 <1> pop ds 809 <1> popad 810 <1> lea sp,[si+16] ; Remove DAPA 811 <1> jc .error 812 <1> pop bp 813 <1> add eax,edi ; Advance sector pointer 814 <1> adc edx,0 815 <1> sub bp,di ; Sectors left 816 <1> shl di,9 ; 512-byte sectors 817 <1> add bx,di ; Advance buffer pointer 818 <1> and bp,bp 819 <1> jnz .loop 820 <1> 821 <1> ret 822 <1> 823 <1> .error: 824 <1> ; Some systems seem to get "stuck" in an error state when 825 <1> ; using EBIOS. Doesn't happen when using CBIOS, which is 826 <1> ; good, since some other systems get timeout failures 827 <1> ; waiting for the floppy disk to spin up. 828 <1> 829 <1> pushad ; Try resetting the device 830 <1> xor ax,ax 831 <1> mov dl,[DriveNumber] 832 <1> call int13 833 <1> popad 834 <1> loop .retry ; CX-- and jump if not zero 835 <1> 836 <1> ;shr word [MaxTransfer],1 ; Reduce the transfer size 837 <1> ;jnz .retry2 838 <1> 839 <1> ; Total failure. Try falling back to CBIOS. 840 <1> mov word [GetlinsecPtr], getlinsec_cbios 841 <1> ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer 842 <1> 843 <1> pop bp 844 <1> jmp getlinsec_cbios.loop 845 <1> 846 <1> ; 847 <1> ; getlinsec_cbios: 848 <1> ; 849 <1> ; getlinsec implementation for legacy CBIOS 850 <1> ; 851 <1> getlinsec_cbios: 852 <1> xor edx,edx 853 <1> shl eax,2 ; Convert to HDD sectors 854 <1> add eax,[Hidden] 855 <1> shl bp,2 856 <1> 857 <1> .loop: 858 <1> push edx 859 <1> push eax 860 <1> push bp 861 <1> push bx 862 <1> 863 <1> movzx esi,word [bsSecPerTrack] 864 <1> movzx edi,word [bsHeads] 865 <1> ; 866 <1> ; Dividing by sectors to get (track,sector): we may have 867 <1> ; up to 2^18 tracks, so we need to use 32-bit arithmetric. 868 <1> ; 869 <1> div esi 870 <1> xor cx,cx 871 <1> xchg cx,dx ; CX <- sector index (0-based) 872 <1> ; EDX <- 0 873 <1> ; eax = track # 874 <1> div edi ; Convert track to head/cyl 875 <1> 876 <1> ; We should test this, but it doesn't fit... 877 <1> ; cmp eax,1023 878 <1> ; ja .error 879 <1> 880 <1> ; 881 <1> ; Now we have AX = cyl, DX = head, CX = sector (0-based), 882 <1> ; BP = sectors to transfer, SI = bsSecPerTrack, 883 <1> ; ES:BX = data target 884 <1> ; 885 <1> 886 <1> call maxtrans ; Enforce maximum transfer size 887 <1> 888 <1> ; Must not cross track boundaries, so BP <= SI-CX 889 <1> sub si,cx 890 <1> cmp bp,si 891 <1> jna .bp_ok 892 <1> mov bp,si 893 <1> .bp_ok: 894 <1> 895 <1> shl ah,6 ; Because IBM was STOOPID 896 <1> ; and thought 8 bits were enough 897 <1> ; then thought 10 bits were enough... 898 <1> inc cx ; Sector numbers are 1-based, sigh 899 <1> or cl,ah 900 <1> mov ch,al 901 <1> mov dh,dl 902 <1> mov dl,[DriveNumber] 903 <1> xchg ax,bp ; Sector to transfer count 904 <1> mov ah,02h ; Read sectors 905 <1> mov bp,retry_count 906 <1> .retry: 907 <1> pushad 908 <1> call int13 909 <1> popad 910 <1> jc .error 911 <1> .resume: 912 <1> movzx ecx,al ; ECX <- sectors transferred 913 <1> shl ax,9 ; Convert sectors in AL to bytes in AX 914 <1> pop bx 915 <1> add bx,ax 916 <1> pop bp 917 <1> pop eax 918 <1> pop edx 919 <1> add eax,ecx 920 <1> sub bp,cx 921 <1> jnz .loop 922 <1> ret 923 <1> 924 <1> .error: 925 <1> dec bp 926 <1> jnz .retry 927 <1> 928 <1> xchg ax,bp ; Sectors transferred <- 0 929 <1> shr word [MaxTransfer],1 930 <1> jnz .resume 931 <1> jmp disk_error 932 <1> 933 <1> ; 934 <1> ; Truncate BP to MaxTransfer 935 <1> ; 936 <1> maxtrans: 937 <1> cmp bp,[MaxTransfer] 938 <1> jna .ok 939 <1> mov bp,[MaxTransfer] 940 <1> .ok: ret 941 <1> 942 <1> %endif 943 <1> 944 <1> ; 945 <1> ; This is the variant we use for real CD-ROMs: 946 <1> ; LBA, 2K sectors, some special error handling. 947 <1> ; 948 <1> getlinsec_cdrom: 949 00007FEB BE[9020] <1> mov si,dapa ; Load up the DAPA 950 00007FEE 895C04 <1> mov [si+4],bx 951 00007FF1 8C4406 <1> mov [si+6],es 952 00007FF4 66894408 <1> mov [si+8],eax 953 <1> .loop: 954 00007FF8 55 <1> push bp ; Sectors left 955 00007FF9 3B2E[EA07] <1> cmp bp,[MaxTransferCD] 956 00007FFD 7604 <1> jbe .bp_ok 957 00007FFF 8B2E[EA07] <1> mov bp,[MaxTransferCD] 958 <1> .bp_ok: 959 00008003 896C02 <1> mov [si+2],bp 960 00008006 56 <1> push si 961 00008007 8A16[1720] <1> mov dl,[DriveNumber] 962 0000800B B442 <1> mov ah,42h ; Extended Read 963 0000800D E81C00 <1> call xint13 964 00008010 5E <1> pop si 965 00008011 5D <1> pop bp 966 00008012 660FB74402 <1> movzx eax,word [si+2] ; Sectors we read 967 00008017 66014408 <1> add [si+8],eax ; Advance sector pointer 968 0000801B 29C5 <1> sub bp,ax ; Sectors left 969 0000801D C1E007 <1> shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment 970 00008020 014406 <1> add [si+6],ax ; Advance buffer pointer 971 00008023 21ED <1> and bp,bp 972 00008025 75D1 <1> jnz .loop 973 00008027 668B4408 <1> mov eax,[si+8] ; Next sector 974 0000802B C3 <1> ret 975 <1> 976 <1> ; INT 13h with retry 977 0000802C C606[1920]06 <1> xint13: mov byte [RetryCount],retry_count 978 00008031 6660 <1> .try: pushad 979 00008033 E894FF <1> call int13 980 00008036 7204 <1> jc .error 981 00008038 83C420 <1> add sp,byte 8*4 ; Clean up stack 982 0000803B C3 <1> ret 983 <1> .error: 984 0000803C 8826[1620] <1> mov [DiskError],ah ; Save error code 985 00008040 6661 <1> popad 986 00008042 A3[0C20] <1> mov [DiskSys],ax ; Save system call number 987 00008045 FE0E[1920] <1> dec byte [RetryCount] 988 00008049 7424 <1> jz .real_error 989 0000804B 50 <1> push ax 990 0000804C A0[1920] <1> mov al,[RetryCount] 991 0000804F 8A26[9220] <1> mov ah,[dapa+2] ; Sector transfer count 992 00008053 3C02 <1> cmp al,2 ; Only 2 attempts left 993 00008055 7704 <1> ja .nodanger 994 00008057 B401 <1> mov ah,1 ; Drop transfer size to 1 995 00008059 EB09 <1> jmp short .setsize 996 <1> .nodanger: 997 0000805B 3C04 <1> cmp al,retry_count-2 998 0000805D 770D <1> ja .again ; First time, just try again 999 0000805F D0EC <1> shr ah,1 ; Otherwise, try to reduce 1000 00008061 80D400 <1> adc ah,0 ; the max transfer size, but not to 0 1001 <1> .setsize: 1002 00008064 8826[EA07] <1> mov [MaxTransferCD],ah 1003 00008068 8826[9220] <1> mov [dapa+2],ah 1004 <1> .again: 1005 0000806C 58 <1> pop ax 1006 0000806D EBC2 <1> jmp .try 1007 <1> 1008 0000806F BE[7807] <1> .real_error: mov si,diskerr_msg 1009 00008072 E818FF <1> call writemsg 1010 00008075 A0[1620] <1> mov al,[DiskError] 1011 00008078 E85200 <1> call writehex2 1012 0000807B BE[8407] <1> mov si,oncall_str 1013 0000807E E81AFF <1> call writestr_early 1014 00008081 A1[0C20] <1> mov ax,[DiskSys] 1015 00008084 E85300 <1> call writehex4 1016 00008087 BE[8C07] <1> mov si,ondrive_str 1017 0000808A E80EFF <1> call writestr_early 1018 0000808D 88D0 <1> mov al,dl 1019 0000808F E83B00 <1> call writehex2 1020 00008092 E819FF <1> call crlf_early 1021 <1> ; Fall through to kaboom 1022 <1> 1023 <1> ; 1024 <1> ; kaboom: write a message and bail out. Wait for a user keypress, 1025 <1> ; then do a hard reboot. 1026 <1> ; 1027 <1> global kaboom 1028 <1> disk_error: 1029 <1> kaboom: 1030 <1> RESET_STACK_AND_SEGS AX 1030 00008095 31C0 <2> xor %1,%1 1030 00008097 8ED8 <2> mov ds,%1 1030 00008099 8EC0 <2> mov es,%1 1030 0000809B 660FB226[0000] <2> lss esp,[BaseStack] 1030 000080A1 66C706[3800]- <2> mov dword [PMESP],__stack_end 1030 000080A6 [00000000] <2> 1030 000080AA FB <2> sti 1030 000080AB FC <2> cld 1031 000080AC BE[B607] <1> mov si,bailmsg 1032 <1> pm_call pm_writestr 1032 000080AF 6668[00000000] <2> push dword %1 1032 000080B5 E8(8300) <2> call _pm_call 1033 <1> pm_call pm_getchar 1033 000080B8 6668[00000000] <2> push dword %1 1033 000080BE E8(8300) <2> call _pm_call 1034 000080C1 FA <1> cli 1035 000080C2 C70672040000 <1> mov word [BIOS_magic],0 ; Cold reboot 1036 000080C8 EAF0FF00F0 <1> jmp 0F000h:0FFF0h ; Reset vector address 1037 <1> 1038 <1> ; ----------------------------------------------------------------------------- 1039 <1> ; Common modules needed in the first sector 1040 <1> ; ----------------------------------------------------------------------------- 1041 <1> 1042 <1> %include "writehex.inc" ; Hexadecimal output 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> ;; writehex.inc 15 <2> ;; 16 <2> ;; Write hexadecimal numbers to the console 17 <2> ;; 18 <2> 19 <2> ; 20 <2> ; writehex[248]: Write a hex number in (AL, AX, EAX) to the console 21 <2> ; 22 <2> writehex2: 23 000080CD 669C <2> pushfd 24 000080CF 6660 <2> pushad 25 000080D1 66C1C018 <2> rol eax,24 26 000080D5 B90200 <2> mov cx,2 27 000080D8 EB14 <2> jmp short writehex_common 28 <2> writehex4: 29 000080DA 669C <2> pushfd 30 000080DC 6660 <2> pushad 31 000080DE 66C1C010 <2> rol eax,16 32 000080E2 B90400 <2> mov cx,4 33 000080E5 EB07 <2> jmp short writehex_common 34 <2> writehex8: 35 000080E7 669C <2> pushfd 36 000080E9 6660 <2> pushad 37 000080EB B90800 <2> mov cx,8 38 <2> writehex_common: 39 000080EE 66C1C004 <2> .loop: rol eax,4 40 000080F2 6650 <2> push eax 41 000080F4 240F <2> and al,0Fh 42 000080F6 3C0A <2> cmp al,10 43 000080F8 7304 <2> jae .high 44 000080FA 0430 <2> .low: add al,'0' 45 000080FC EB02 <2> jmp short .ischar 46 000080FE 0437 <2> .high: add al,'A'-10 47 00008100 E8B8FE <2> .ischar: call writechr 48 00008103 6658 <2> pop eax 49 00008105 E2E7 <2> loop .loop 50 00008107 6661 <2> popad 51 00008109 669D <2> popfd 52 0000810B C3 <2> ret 1043 <1> 1044 <1> ; ----------------------------------------------------------------------------- 1045 <1> ; Data that needs to be in the first sector 1046 <1> ; ----------------------------------------------------------------------------- 1047 <1> 1048 <1> global syslinux_banner, copyright_str 1049 0000810C 0D0A49534F4C494E55- <1> syslinux_banner db CR, LF, MY_NAME, ' ', VERSION_STR, ' ', DATE_STR, ' ', 0 1049 00008115 5820362E303420362E- <1> 1049 0000811E 30342D707265322A20- <1> 1049 00008127 00 <1> 1050 00008128 20436F707972696768- <1> copyright_str db ' Copyright (C) 1994-' 1050 00008131 742028432920313939- <1> 1050 0000813A 342D <1> 1051 0000813C 32303135 <1> asciidec YEAR 1052 00008140 20482E205065746572- <1> db ' H. Peter Anvin et al', CR, LF, 0 1052 00008149 20416E76696E206574- <1> 1052 00008152 20616C0D0A00 <1> 1053 00008158 69736F6C696E75783A- <1> isolinux_str db 'isolinux: ', 0 1053 00008161 2000 <1> 1054 <1> %ifdef DEBUG_MESSAGES 1055 00008163 5374617274696E6720- <1> startup_msg: db 'Starting up, DL = ', 0 1055 0000816C 75702C20444C203D20- <1> 1055 00008175 00 <1> 1056 00008176 4C6F61646564207370- <1> spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0 1056 0000817F 6563207061636B6574- <1> 1056 00008188 204F4B2C2064726976- <1> 1056 00008191 65203D2000 <1> 1057 00008196 536563746F72207369- <1> secsize_msg: db 'Sector size ', 0 1057 0000819F 7A652000 <1> 1058 000081A3 4D61696E20696D6167- <1> offset_msg: db 'Main image LBA = ', 0 1058 000081AC 65204C4241203D2000 <1> 1059 000081B5 496D61676520637375- <1> verify_msg: db 'Image csum verified.', CR, LF, 0 1059 000081BE 6D2076657269666965- <1> 1059 000081C7 642E0D0A00 <1> 1060 000081CC 496D61676520726561- <1> allread_msg db 'Image read, jumping to main code...', CR, LF, 0 1060 000081D5 642C206A756D70696E- <1> 1060 000081DE 6720746F206D61696E- <1> 1060 000081E7 20636F64652E2E2E0D- <1> 1060 000081F0 0A00 <1> 1061 <1> %endif 1062 000081F2 4E6F20626F6F742069- <1> noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0 1062 000081FB 6E666F207461626C65- <1> 1062 00008204 2C20617373756D696E- <1> 1062 0000820D 672073696E676C6520- <1> 1062 00008216 73657373696F6E2064- <1> 1062 0000821F 69736B2E2E2E0D0A00 <1> 1063 00008228 53706563207061636B- <1> noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0 1063 00008231 6574206D697373696E- <1> 1063 0000823A 67204C424120696E66- <1> 1063 00008243 6F726D6174696F6E2C- <1> 1063 0000824C 20747279696E672074- <1> 1063 00008255 6F2077696E67206974- <1> 1063 0000825E 2E2E2E0D0A00 <1> 1064 00008264 4C6F6164696E672073- <1> spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0 1064 0000826D 706563207061636B65- <1> 1064 00008276 74206661696C65642C- <1> 1064 0000827F 20747279696E672074- <1> 1064 00008288 6F2077696E67206974- <1> 1064 00008291 2E2E2E0D0A00 <1> 1065 00008297 466F756E6420736F6D- <1> maybe_msg: db 'Found something at drive = ', 0 1065 000082A0 657468696E67206174- <1> 1065 000082A9 206472697665203D20- <1> 1065 000082B2 00 <1> 1066 000082B3 4C6F6F6B7320726561- <1> alright_msg: db 'Looks reasonable, continuing...', CR, LF, 0 1066 000082BC 736F6E61626C652C20- <1> 1066 000082C5 636F6E74696E75696E- <1> 1066 000082CE 672E2E2E0D0A00 <1> 1067 000082D5 45787472656D656C79- <1> nospec_msg db 'Extremely broken BIOS detected, last attempt with drive = ', 0 1067 000082DE 2062726F6B656E2042- <1> 1067 000082E7 494F53206465746563- <1> 1067 000082F0 7465642C206C617374- <1> 1067 000082F9 20617474656D707420- <1> 1067 00008302 776974682064726976- <1> 1067 0000830B 65203D2000 <1> 1068 00008310 4661696C656420746F- <1> nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF 1068 00008319 206C6F636174652043- <1> 1068 00008322 442D524F4D20646576- <1> 1068 0000832B 6963653B20626F6F74- <1> 1068 00008334 206661696C65642E0D- <1> 1068 0000833D 0A <1> 1069 0000833E 53656520687474703A- <1> trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0 1069 00008347 2F2F7379736C696E75- <1> 1069 00008350 782E7A79746F722E63- <1> 1069 00008359 6F6D2F73626D20666F- <1> 1069 00008362 72206D6F726520696E- <1> 1069 0000836B 666F726D6174696F6E- <1> 1069 00008374 2E0D0A00 <1> 1070 00008378 4469736B206572726F- <1> diskerr_msg: db 'Disk error ', 0 1070 00008381 722000 <1> 1071 00008384 2C204158203D2000 <1> oncall_str: db ', AX = ',0 1072 0000838C 2C2064726976652000 <1> ondrive_str: db ', drive ', 0 1073 00008395 496D61676520636865- <1> checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0 1073 0000839E 636B73756D20657272- <1> 1073 000083A7 6F722C20736F727279- <1> 1073 000083B0 2E2E2E0D0A00 <1> 1074 <1> 1075 000083B6 0D0A426F6F74206661- <1> err_bootfailed db CR, LF, 'Boot failed: press a key to retry...' 1075 000083BF 696C65643A20707265- <1> 1075 000083C8 73732061206B657920- <1> 1075 000083D1 746F2072657472792E- <1> 1075 000083DA 2E2E <1> 1076 <1> bailmsg equ err_bootfailed 1077 000083DC 0D0A <1> crlf_msg db CR, LF 1078 000083DE 00 <1> null_msg db 0 1079 <1> 1080 000083DF 4554434400 <1> bios_cdrom_str db 'ETCD', 0 1081 <1> %ifndef DEBUG_MESSAGES 1082 <1> bios_cbios_str db 'CHDD', 0 1083 <1> bios_ebios_str db 'EHDD' ,0 1084 <1> %endif 1085 <1> 1086 <1> alignz 4 1087 <1> global bios_cdrom 1088 000083E4 [EB03][DF07] <1> bios_cdrom: dw getlinsec_cdrom, bios_cdrom_str 1089 <1> %ifndef DEBUG_MESSAGES 1090 <1> bios_cbios: dw getlinsec_cbios, bios_cbios_str 1091 <1> bios_ebios: dw getlinsec_ebios, bios_ebios_str 1092 <1> %endif 1093 <1> 1094 <1> ; Maximum transfer size 1095 000083E8 7F00 <1> MaxTransfer dw 127 ; Hard disk modes 1096 000083EA 2000 <1> MaxTransferCD dw 32 ; CD mode 1097 <1> 1098 <1> rl_checkpt equ $ ; Must be <= 800h 1099 <1> 1100 <1> ; This pads to the end of sector 0 and errors out on 1101 <1> ; overflow. 1102 000083EC 00 <1> times 2048-($-$$) db 0 1103 <1> 1104 <1> ; ---------------------------------------------------------------------------- 1105 <1> ; End of code and data that have to be in the first sector 1106 <1> ; ---------------------------------------------------------------------------- 1107 <1> 1108 <1> section .text16 1109 <1> 1110 <1> all_read: 1111 <1> 1112 <1> ; Test tracers 1113 <1> TRACER 'T' 1114 <1> TRACER '>' 1115 <1> 1116 <1> ; 1117 <1> ; Common initialization code 1118 <1> ; 1119 <1> %include "init.inc" 1 <2> ; -*- fundamental -*- 2 <2> ; ----------------------------------------------------------------------- 3 <2> ; 4 <2> ; Copyright 2004-2008 H. Peter Anvin - All Rights Reserved 5 <2> ; Copyright 2009 Intel Corporation; author: H. Peter Anvin 6 <2> ; 7 <2> ; This program is free software; you can redistribute it and/or modify 8 <2> ; it under the terms of the GNU General Public License as published by 9 <2> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 10 <2> ; Boston MA 02111-1307, USA; either version 2 of the License, or 11 <2> ; (at your option) any later version; incorporated herein by reference. 12 <2> ; 13 <2> ; ----------------------------------------------------------------------- 14 <2> 15 <2> ; 16 <2> ; init.inc 17 <2> ; 18 <2> ; Common initialization code (inline) 19 <2> ; 20 <2> 21 <2> section .text16 22 <2> common_init: 23 <2> ; Initialize PM invocation framework 24 00008400 E80302 <2> call pm_init 25 <2> 26 <2> %if IS_PXELINUX 27 <2> ; Save derivative-specific data 28 <2> pm_call pm_save_data 29 <2> %endif 30 <2> 31 <2> ; Decompress PM code to its target location 32 <2> pm_call pm_decompress 32 00008403 6668[00000000] <3> push dword %1 32 00008409 E87700 <3> call _pm_call 33 0000840C 663D[00000000] <2> cmp eax,__pm_code_len 34 00008412 0F85(9504) <2> jne kaboom 35 <2> 36 <2> extern syslinux_register_bios, init 37 <2> 38 <2> pm_call syslinux_register_bios 38 00008416 6668[00000000] <3> push dword %1 38 0000841C E86400 <3> call _pm_call 39 <2> pm_call init 39 0000841F 6668[00000000] <3> push dword %1 39 00008425 E85B00 <3> call _pm_call 40 <2> 41 <2> ; 42 <2> ; The code to decompress the PM code and initialize other segments. 43 <2> ; 44 <2> extern _lzo1x_decompress_asm_fast_safe 45 <2> 46 <2> section .textnr 47 <2> bits 32 48 <2> pm_decompress: 49 00008940 68[10000000] <2> push __pm_code_len + 16 ; Space for decompressed size 50 00008945 54 <2> push esp ; Pointer to previous word 51 00008946 68[00000000] <2> push __pm_code_start ; Target address 52 0000894B FF35[06000000] <2> push dword [lzo_data_size] ; Compressed size 53 00008951 68[00000000] <2> push dword __pm_code_lma 54 00008956 E8(00000000) <2> call _lzo1x_decompress_asm_fast_safe 55 0000895B 83C410 <2> add esp,16 56 0000895E 8F4524 <2> pop RM_EAX ; Decompressed size 57 <2> 58 <2> ; Zero bss sections (but not .earlybss, since it may 59 <2> ; contain already-live data.) 60 00008961 31C0 <2> xor eax,eax 61 00008963 BF[00000000] <2> mov edi,__bss_start 62 00008968 B9[00000000] <2> mov ecx,__bss_dwords 63 0000896D F3AB <2> rep stosd 64 0000896F BF[00000000] <2> mov edi,__bss16_start 65 00008974 B9[00000000] <2> mov ecx,__bss16_dwords 66 00008979 F3AB <2> rep stosd 67 0000897B BF[00000000] <2> mov edi,__high_clear_start ; .uibss, .lowmem 68 00008980 B9[00000000] <2> mov ecx,__high_clear_dwords 69 00008985 F3AB <2> rep stosd 70 <2> 71 00008987 C3 <2> ret 72 <2> 73 <2> section .data16 74 00008E36 00000000 <2> lzo_data_size dd 0 ; filled in by compressor 75 <2> 76 <2> section .text16 77 <2> bits 16 1120 <1> 1121 <1> ; Tell the user we got this far... 1122 <1> %ifndef DEBUG_MESSAGES ; Gets messy with debugging on 1123 <1> mov si,copyright_str 1124 <1> pm_call pm_writestr 1125 <1> %endif 1126 <1> 1127 <1> ; 1128 <1> ; Now we're all set to start with our *real* business. First load the 1129 <1> ; configuration file (if any) and parse it. 1130 <1> ; 1131 <1> ; In previous versions I avoided using 32-bit registers because of a 1132 <1> ; rumour some BIOSes clobbered the upper half of 32-bit registers at 1133 <1> ; random. I figure, though, that if there are any of those still left 1134 <1> ; they probably won't be trying to install Linux on them... 1135 <1> ; 1136 <1> ; The code is still ripe with 16-bitisms, though. Not worth the hassle 1137 <1> ; to take'm out. In fact, we may want to put them back if we're going 1138 <1> ; to boot ELKS at some point. 1139 <1> ; 1140 <1> 1141 <1> ; 1142 <1> ; Now, we need to sniff out the actual filesystem data structures. 1143 <1> ; mkisofs gave us a pointer to the primary volume descriptor 1144 <1> ; (which will be at 16 only for a single-session disk!); from the PVD 1145 <1> ; we should be able to find the rest of what we need to know. 1146 <1> ; 1147 <1> init_fs: 1148 00008428 6660 <1> pushad 1149 0000842A 66B8[00000000] <1> mov eax,ROOT_FS_OPS 1150 00008430 8A16[1720] <1> mov dl,[DriveNumber] 1151 00008434 813E[1420][E407] <1> cmp word [BIOSType],bios_cdrom 1152 0000843A 0F94C6 <1> sete dh ; 1 for cdrom, 0 for hybrid mode 1153 0000843D 7508 <1> jne .hybrid 1154 0000843F 660FB72E[EA07] <1> movzx ebp,word [MaxTransferCD] 1155 00008445 EB06 <1> jmp .common 1156 <1> .hybrid: 1157 00008447 660FB72E[E807] <1> movzx ebp,word [MaxTransfer] 1158 <1> .common: 1159 0000844D 668B0E[2020] <1> mov ecx,[Hidden] 1160 00008452 668B1E[2420] <1> mov ebx,[Hidden+4] 1161 00008457 8B36[2A20] <1> mov si,[bsHeads] 1162 0000845B 8B3E[2820] <1> mov di,[bsSecPerTrack] 1163 <1> pm_call pm_fs_init 1163 0000845F 6668[00000000] <2> push dword %1 1163 00008465 E81B00 <2> call _pm_call 1164 <1> pm_call load_env32 1164 00008468 6668[00000000] <2> push dword %1 1164 0000846E E81200 <2> call _pm_call 1165 <1> enter_command: 1166 <1> auto_boot: 1167 00008471 E9(9504) <1> jmp kaboom ; load_env32() should never return. If 1168 <1> ; it does, then kaboom! 1169 00008474 6661 <1> popad 1170 <1> 1171 <1> section .rodata 1172 <1> alignz 4 1173 <1> ROOT_FS_OPS: 1174 <1> extern iso_fs_ops 1175 00108900 [00000000] <1> dd iso_fs_ops 1176 00108904 00000000 <1> dd 0 1177 <1> 1178 <1> section .text16 1179 <1> 1180 <1> %ifdef DEBUG_TRACERS 1181 <1> ; 1182 <1> ; debug hack to print a character with minimal code impact 1183 <1> ; 1184 <1> debug_tracer: pushad 1185 <1> pushfd 1186 <1> mov bp,sp 1187 <1> mov bx,[bp+9*4] ; Get return address 1188 <1> mov al,[cs:bx] ; Get data byte 1189 <1> inc word [bp+9*4] ; Return to after data byte 1190 <1> call writechr 1191 <1> popfd 1192 <1> popad 1193 <1> ret 1194 <1> %endif ; DEBUG_TRACERS 1195 <1> 1196 <1> section .bss16 1197 <1> alignb 4 1198 000038C0 <1> ThisKbdTo resd 1 ; Temporary holder for KbdTimeout 1199 000038C4 <1> ThisTotalTo resd 1 ; Temporary holder for TotalTimeout 1200 000038C8 <1> KernelExtPtr resw 1 ; During search, final null pointer 1201 000038CA <1> FuncFlag resb 1 ; Escape sequences received from keyboard 1202 000038CB <1> KernelType resb 1 ; Kernel type, from vkernel, if known 1203 <1> global KernelName 1204 000038CC <1> KernelName resb FILENAME_MAX ; Mangled name for kernel 1205 <1> 1206 <1> section .text16 1207 <1> ; 1208 <1> ; COM32 vestigial data structure 1209 <1> ; 1210 <1> %include "com32.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> ;; 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> ;; com32.inc 16 <2> ;; 17 <2> ;; Common code for running a COM32 image 18 <2> ;; 19 <2> 20 <2> extern pm_api_vector 21 <2> 22 <2> ; 23 <2> ; Load a COM32 image. A COM32 image is the 32-bit analogue to a DOS 24 <2> ; .com file. A COM32 image is loaded at address 0x101000, with %esp 25 <2> ; set to the high end of usable memory. 26 <2> ; 27 <2> ; A COM32 image should begin with the magic bytes: 28 <2> ; B8 FF 4C CD 21, which is "mov eax,0x21cd4cff" in 32-bit mode and 29 <2> ; "mov ax,0x4cff; int 0x21" in 16-bit mode. This will abort the 30 <2> ; program with an error if run in 16-bit mode. 31 <2> ; 32 <2> bits 16 33 <2> section .data16 34 <2> 35 <2> ; Ersatz com32 invocation structure, to make libcom32 36 <2> ; code run the same if linked to the core. This is in 37 <2> ; the .data16 segment so HighMemSize can live here. 38 <2> ; 39 <2> ; Danger, Will Robinson: it's not clear the use of 40 <2> ; core_xfer_buf is safe here. 41 <2> global __com32:data hidden 42 00008E3A 00 <2> alignz 4 43 <2> __entry_esp: 44 00008E3C 00000000 <2> dd 0 ; Dummy to avoid _exit issues 45 <2> __com32: 46 00008E40 09000000 <2> dd 9 ; Argument count 47 00008E44 00000000 <2> dd 0 ; No command line 48 00008E48 [06000000] <2> dd core_intcall ; Intcall entry point 49 00008E4C 00000000 <2> dd 0 ; Bounce buffer address 50 00008E50 00000000 <2> dd 0 ; 64K bounce buffer 51 00008E54 [00000000] <2> dd core_farcall ; Farcall entry point 52 00008E58 [A6000000] <2> dd core_cfarcall ; Cfarcall entry point 53 00008E5C 00000000 <2> HighMemSize dd 0 ; End of memory pointer (bytes) 54 00008E60 00000000 <2> dd 0 ; No module name 55 00008E64 [00000000] <2> dd pm_api_vector ; Protected mode functions 56 <2> 57 <2> section .uibss 58 00009400 <2> Com32Name resb FILENAME_MAX 59 <2> 60 <2> section .bss16 61 <2> %ifndef HAVE_CURRENTDIRNAME 62 <2> global CurrentDirName:data hidden 63 000039CC <2> CurrentDirName resb FILENAME_MAX 64 <2> %endif 65 <2> 66 <2> section .text16 1211 <1> 1212 <1> ; 1213 <1> ; Common local boot code 1214 <1> ; 1215 <1> %include "localboot.inc" 1 <2> section .text16 2 <2> global local_boot16:function hidden 3 <2> local_boot16: 4 00008476 B90000 <2> mov cx,0 5 00008479 8ED1 <2> mov ss,cx 6 0000847B BC007C <2> mov sp,7C00h 7 0000847E EA007C0000 <2> jmp 0:07C00h 1216 <1> 1217 <1> ; ----------------------------------------------------------------------------- 1218 <1> ; Common modules 1219 <1> ; ----------------------------------------------------------------------------- 1220 <1> 1221 <1> %include "common.inc" ; Universal modules 1 <2> ; 2 <2> ; Modules common to all derivatives. Do not include modules in this list 3 <2> ; which have special section requirements (i.e. need to be in .init for 4 <2> ; some derivatives.) 5 <2> ; 6 <2> 7 <2> %include "pm.inc" ; Protected mode 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> ;; pm.inc 16 <3> ;; 17 <3> ;; Functions to enter and exit 32-bit protected mode, handle interrupts 18 <3> ;; and cross-mode calls. 19 <3> ;; 20 <3> ;; PM refers to 32-bit flat protected mode; RM to 16-bit real mode. 21 <3> ;; 22 <3> 23 <3> bits 16 24 <3> section .text16 25 <3> ; 26 <3> ; _pm_call: call PM routine in low memory from RM 27 <3> ; 28 <3> ; on stack = PM routine to call (a 32-bit address) 29 <3> ; 30 <3> ; ECX, ESI, EDI passed to the called function; 31 <3> ; EAX = EBP in the called function points to the stack frame 32 <3> ; which includes all registers (which can be changed if desired.) 33 <3> ; 34 <3> ; All registers and the flags saved/restored 35 <3> ; 36 <3> ; This routine is invoked by the pm_call macro. 37 <3> ; 38 <3> _pm_call: 39 00008483 669C <3> pushfd 40 00008485 6660 <3> pushad 41 00008487 1E <3> push ds 42 00008488 06 <3> push es 43 00008489 0FA0 <3> push fs 44 0000848B 0FA8 <3> push gs 45 0000848D 89E5 <3> mov bp,sp 46 0000848F 8CC8 <3> mov ax,cs 47 00008491 66BB[48000000] <3> mov ebx,.pm 48 00008497 8ED8 <3> mov ds,ax 49 00008499 EB0D <3> jmp enter_pm 50 <3> 51 <3> bits 32 52 <3> section .textnr 53 <3> .pm: 54 <3> ; EAX points to the top of the RM stack, which is EFLAGS 55 00008988 F6452902 <3> test RM_FLAGSH,02h ; RM EFLAGS.IF 56 0000898C 7401 <3> jz .no_sti 57 0000898E FB <3> sti 58 <3> .no_sti: 59 0000898F FF552E <3> call [ebp+4*2+9*4+2] ; Entrypoint on RM stack 60 00008992 66BB[9B00] <3> mov bx,.rm 61 00008996 EB20 <3> jmp enter_rm 62 <3> 63 <3> bits 16 64 <3> section .text16 65 <3> .rm: 66 0000849B 0FA9 <3> pop gs 67 0000849D 0FA1 <3> pop fs 68 0000849F 07 <3> pop es 69 000084A0 1F <3> pop ds 70 000084A1 6661 <3> popad 71 000084A3 669D <3> popfd 72 000084A5 C20400 <3> ret 4 ; Drop entrypoint 73 <3> 74 <3> ; 75 <3> ; enter_pm: Go to PM with interrupt service configured 76 <3> ; EBX = PM entry point 77 <3> ; EAX = EBP = on exit, points to the RM stack as a 32-bit value 78 <3> ; ECX, EDX, ESI, EDI preserved across this routine 79 <3> ; 80 <3> ; Assumes CS == DS 81 <3> ; 82 <3> ; This routine doesn't enable interrupts, but the target routine 83 <3> ; can enable interrupts by executing STI. 84 <3> ; 85 <3> bits 16 86 <3> section .text16 87 <3> enter_pm: 88 000084A8 FA <3> cli 89 000084A9 6631C0 <3> xor eax,eax 90 000084AC 8ED8 <3> mov ds,ax 91 000084AE 8CD0 <3> mov ax,ss 92 000084B0 8926[B828] <3> mov [RealModeSSSP],sp 93 000084B4 A3[BA28] <3> mov [RealModeSSSP+2],ax 94 000084B7 660FB7EC <3> movzx ebp,sp 95 000084BB 66C1E004 <3> shl eax,4 96 000084BF 6601C5 <3> add ebp,eax ; EBP -> top of real-mode stack 97 000084C2 FC <3> cld 98 000084C3 E86400 <3> call enable_a20 99 <3> 100 <3> .a20ok: 101 000084C6 C606[0D00]89 <3> mov byte [bcopy_gdt.TSS+5],89h ; Mark TSS unbusy 102 <3> 103 000084CB 0F0116[0000] <3> lgdt [bcopy_gdt] ; We can use the same GDT just fine 104 000084D0 0F011E[3C00] <3> lidt [PM_IDT_ptr] ; Set up the IDT 105 000084D5 0F20C0 <3> mov eax,cr0 106 000084D8 0C01 <3> or al,1 107 000084DA 0F22C0 <3> mov cr0,eax ; Enter protected mode 108 000084DD EA[5800]2000 <3> jmp PM_CS32:.in_pm 109 <3> 110 <3> bits 32 111 <3> section .textnr 112 <3> .in_pm: 113 00008998 31C0 <3> xor eax,eax ; Available for future use... 114 0000899A 8EE0 <3> mov fs,eax 115 0000899C 8EE8 <3> mov gs,eax 116 0000899E 0F00D0 <3> lldt ax 117 <3> 118 000089A1 B028 <3> mov al,PM_DS32 ; Set up data segments 119 000089A3 8EC0 <3> mov es,eax 120 000089A5 8ED8 <3> mov ds,eax 121 000089A7 8ED0 <3> mov ss,eax 122 <3> 123 000089A9 B008 <3> mov al,PM_TSS ; Be nice to Intel's VT by 124 000089AB 0F00D8 <3> ltr ax ; giving it a valid TR 125 <3> 126 000089AE 8B25[38000000] <3> mov esp,[PMESP] ; Load protmode %esp 127 000089B4 89E8 <3> mov eax,ebp ; EAX -> top of real-mode stack 128 000089B6 FFE3 <3> jmp ebx ; Go to where we need to go 129 <3> 130 <3> ; 131 <3> ; enter_rm: Return to RM from PM 132 <3> ; 133 <3> ; BX = RM entry point (CS = 0) 134 <3> ; ECX, EDX, ESI, EDI preserved across this routine 135 <3> ; EAX clobbered 136 <3> ; EBP reserved 137 <3> ; 138 <3> ; This routine doesn't enable interrupts, but the target routine 139 <3> ; can enable interrupts by executing STI. 140 <3> ; 141 <3> bits 32 142 <3> section .textnr 143 <3> enter_rm: 144 000089B8 FA <3> cli 145 000089B9 FC <3> cld 146 000089BA 8925[38000000] <3> mov [PMESP],esp ; Save exit %esp 147 000089C0 EA[E2000000]1000 <3> jmp PM_CS16:.in_pm16 ; Return to 16-bit mode first 148 <3> 149 <3> bits 16 150 <3> section .text16 151 <3> .in_pm16: 152 000084E2 B81800 <3> mov ax,PM_DS16 ; Real-mode-like segment 153 000084E5 8EC0 <3> mov es,ax 154 000084E7 8ED8 <3> mov ds,ax 155 000084E9 8ED0 <3> mov ss,ax 156 000084EB 8EE0 <3> mov fs,ax 157 000084ED 8EE8 <3> mov gs,ax 158 <3> 159 000084EF 0F011E[3000] <3> lidt [RM_IDT_ptr] ; Real-mode IDT (rm needs no GDT) 160 000084F4 31D2 <3> xor dx,dx 161 000084F6 0F20C0 <3> mov eax,cr0 162 000084F9 24FE <3> and al,~1 163 000084FB 0F22C0 <3> mov cr0,eax 164 000084FE EA[0301]0000 <3> jmp 0:.in_rm 165 <3> 166 <3> .in_rm: ; Back in real mode 167 00008503 2E0FB226[B828] <3> lss sp,[cs:RealModeSSSP] ; Restore stack 168 00008509 660FB7E4 <3> movzx esp,sp ; Make sure the high bits are zero 169 0000850D 8EDA <3> mov ds,dx ; Set up sane segments 170 0000850F 8EC2 <3> mov es,dx 171 00008511 8EE2 <3> mov fs,dx 172 00008513 8EEA <3> mov gs,dx 173 00008515 FFE3 <3> jmp bx ; Go to whereever we need to go... 174 <3> 175 <3> section .data16 176 <3> alignz 4 177 <3> 178 <3> extern __stack_end 179 00008E68 [00000000] <3> PMESP dd __stack_end ; Protected-mode ESP 180 <3> 181 00008E6C FF07 <3> PM_IDT_ptr: dw 8*256-1 ; Length 182 00008E6E [B8200000] <3> dd IDT ; Offset 183 <3> 184 <3> ; 185 <3> ; This is invoked on getting an interrupt in protected mode. At 186 <3> ; this point, we need to context-switch to real mode and invoke 187 <3> ; the interrupt routine. 188 <3> ; 189 <3> ; When this gets invoked, the registers are saved on the stack and 190 <3> ; AL contains the register number. 191 <3> ; 192 <3> bits 32 193 <3> section .textnr 194 <3> pm_irq: 195 000089C7 60 <3> pushad 196 000089C8 0FB6742420 <3> movzx esi,byte [esp+8*4] ; Interrupt number 197 000089CD FF05[18020000] <3> inc dword [CallbackCtr] 198 000089D3 BB[17010000] <3> mov ebx,.rm 199 000089D8 EBDE <3> jmp enter_rm ; Go to real mode 200 <3> 201 <3> bits 16 202 <3> section .text16 203 <3> .rm: 204 00008517 9C <3> pushf ; Flags on stack 205 00008518 2E67FF1CB500000000 <3> call far [cs:esi*4] ; Call IVT entry 206 00008521 66BB[9A000000] <3> mov ebx,.pm 207 00008527 E97EFF <3> jmp enter_pm ; Go back to PM 208 <3> 209 <3> bits 32 210 <3> section .textnr 211 <3> .pm: 212 000089DA FF0D[18020000] <3> dec dword [CallbackCtr] 213 000089E0 7506 <3> jnz .skip 214 000089E2 FF15[44000000] <3> call [core_pm_hook] 215 <3> .skip: 216 000089E8 61 <3> popad 217 000089E9 83C404 <3> add esp,4 ; Drop interrupt number 218 000089EC CF <3> iretd 219 <3> 220 <3> ; 221 <3> ; Initially, the core_pm_hook does nothing; it is available for the 222 <3> ; threaded derivatives to run the scheduler, or examine the result from 223 <3> ; interrupt routines. 224 <3> ; 225 <3> global core_pm_null_hook 226 <3> core_pm_null_hook: 227 000089ED C3 <3> ret 228 <3> 229 <3> section .data16 230 00008E72 00 <3> alignz 4 231 <3> global core_pm_hook 232 00008E74 [AD000000] <3> core_pm_hook: dd core_pm_null_hook 233 <3> 234 <3> bits 16 235 <3> section .text16 236 <3> ; 237 <3> ; Routines to enable and disable (yuck) A20. These routines are gathered 238 <3> ; from tips from a couple of sources, including the Linux kernel and 239 <3> ; http://www.x86.org/. The need for the delay to be as large as given here 240 <3> ; is indicated by Donnie Barnes of RedHat, the problematic system being an 241 <3> ; IBM ThinkPad 760EL. 242 <3> ; 243 <3> 244 <3> section .data16 245 <3> alignz 2 246 00008E78 [3C01] <3> A20Ptr dw a20_dunno 247 <3> 248 <3> section .bss16 249 <3> alignb 4 250 00003ACC <3> A20Test resd 1 ; Counter for testing A20 status 251 00003AD0 <3> A20Tries resb 1 ; Times until giving up on A20 252 <3> 253 <3> section .text16 254 <3> enable_a20: 255 0000852A 6660 <3> pushad 256 0000852C 2EC606[1002]FF <3> mov byte [cs:A20Tries],255 ; Times to try to make this work 257 <3> 258 <3> try_enable_a20: 259 <3> 260 <3> ; 261 <3> ; First, see if we are on a system with no A20 gate, or the A20 gate 262 <3> ; is already enabled for us... 263 <3> ; 264 <3> a20_none: 265 00008532 E87C00 <3> call a20_test 266 00008535 7577 <3> jnz a20_done 267 <3> ; Otherwise, see if we had something memorized... 268 00008537 2EFF26[4800] <3> jmp word [cs:A20Ptr] 269 <3> 270 <3> ; 271 <3> ; Next, try the BIOS (INT 15h AX=2401h) 272 <3> ; 273 <3> a20_dunno: 274 <3> a20_bios: 275 0000853C 2EC706[4800][3C01] <3> mov word [cs:A20Ptr], a20_bios 276 00008543 B80124 <3> mov ax,2401h 277 00008546 9C <3> pushf ; Some BIOSes muck with IF 278 00008547 CD15 <3> int 15h 279 00008549 9D <3> popf 280 <3> 281 0000854A E86400 <3> call a20_test 282 0000854D 755F <3> jnz a20_done 283 <3> 284 <3> ; 285 <3> ; Enable the keyboard controller A20 gate 286 <3> ; 287 <3> a20_kbc: 288 0000854F B201 <3> mov dl, 1 ; Allow early exit 289 00008551 E88E00 <3> call empty_8042 290 00008554 7558 <3> jnz a20_done ; A20 live, no need to use KBC 291 <3> 292 00008556 2EC706[4800][4F01] <3> mov word [cs:A20Ptr], a20_kbc ; Starting KBC command sequence 293 <3> 294 0000855D B0D1 <3> mov al,0D1h ; Write output port 295 0000855F E664 <3> out 064h, al 296 00008561 E87C00 <3> call empty_8042_uncond 297 <3> 298 00008564 B0DF <3> mov al,0DFh ; A20 on 299 00008566 E660 <3> out 060h, al 300 00008568 E87500 <3> call empty_8042_uncond 301 <3> 302 <3> ; Apparently the UHCI spec assumes that A20 toggle 303 <3> ; ends with a null command (assumed to be for sychronization?) 304 <3> ; Put it here to see if it helps anything... 305 0000856B B0FF <3> mov al,0FFh ; Null command 306 0000856D E664 <3> out 064h, al 307 0000856F E86E00 <3> call empty_8042_uncond 308 <3> 309 <3> ; Verify that A20 actually is enabled. Do that by 310 <3> ; observing a word in low memory and the same word in 311 <3> ; the HMA until they are no longer coherent. Note that 312 <3> ; we don't do the same check in the disable case, because 313 <3> ; we don't want to *require* A20 masking (SYSLINUX should 314 <3> ; work fine without it, if the BIOS does.) 315 00008572 51 <3> .kbc_wait: push cx 316 00008573 31C9 <3> xor cx,cx 317 <3> .kbc_wait_loop: 318 00008575 E83900 <3> call a20_test 319 00008578 7533 <3> jnz a20_done_pop 320 0000857A E2F9 <3> loop .kbc_wait_loop 321 <3> 322 0000857C 59 <3> pop cx 323 <3> ; 324 <3> ; Running out of options here. Final attempt: enable the "fast A20 gate" 325 <3> ; 326 <3> a20_fast: 327 0000857D 2EC706[4800][7D01] <3> mov word [cs:A20Ptr], a20_fast 328 00008584 E492 <3> in al, 092h 329 00008586 0C02 <3> or al,02h 330 00008588 24FE <3> and al,~01h ; Don't accidentally reset the machine! 331 0000858A E692 <3> out 092h, al 332 <3> 333 0000858C 51 <3> .fast_wait: push cx 334 0000858D 31C9 <3> xor cx,cx 335 <3> .fast_wait_loop: 336 0000858F E81F00 <3> call a20_test 337 00008592 7519 <3> jnz a20_done_pop 338 00008594 E2F9 <3> loop .fast_wait_loop 339 <3> 340 00008596 59 <3> pop cx 341 <3> 342 <3> ; 343 <3> ; Oh bugger. A20 is not responding. Try frobbing it again; eventually give up 344 <3> ; and report failure to the user. 345 <3> ; 346 00008597 2EFE0E[1002] <3> dec byte [cs:A20Tries] 347 0000859C 759E <3> jnz a20_dunno ; Did we get the wrong type? 348 <3> 349 0000859E BE[4A00] <3> mov si, err_a20 350 <3> pm_call pm_writestr 350 000085A1 6668[00000000] <4> push dword %1 350 000085A7 E8D9FE <4> call _pm_call 351 000085AA E9(9504) <3> jmp kaboom 352 <3> 353 <3> section .data16 354 00008E7A 0D0A41323020676174- <3> err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0 354 00008E83 65206E6F7420726573- <3> 354 00008E8C 706F6E64696E67210D- <3> 354 00008E95 0A00 <3> 355 <3> section .text16 356 <3> 357 <3> ; 358 <3> ; A20 unmasked, proceed... 359 <3> ; 360 000085AD 59 <3> a20_done_pop: pop cx 361 000085AE 6661 <3> a20_done: popad 362 000085B0 C3 <3> ret 363 <3> 364 <3> ; 365 <3> ; This routine tests if A20 is enabled (ZF = 0). This routine 366 <3> ; must not destroy any register contents. 367 <3> ; 368 <3> ; The no-write early out avoids the io_delay in the (presumably common) 369 <3> ; case of A20 already enabled (e.g. from a previous call.) 370 <3> ; 371 <3> a20_test: 372 000085B1 06 <3> push es 373 000085B2 51 <3> push cx 374 000085B3 6650 <3> push eax 375 000085B5 B9FFFF <3> mov cx,0FFFFh ; HMA = segment 0FFFFh 376 000085B8 8EC1 <3> mov es,cx 377 000085BA 2E66A1[0C02] <3> mov eax,[cs:A20Test] 378 000085BF B92000 <3> mov cx,32 ; Loop count 379 000085C2 EB0F <3> jmp .test ; First iteration = early out 380 000085C4 660541EA0A43 <3> .wait: add eax,0x430aea41 ; A large prime number 381 000085CA 2E66A3[0C02] <3> mov [cs:A20Test],eax 382 000085CF E680E680 <3> io_delay ; Serialize, and fix delay 383 000085D3 26663B06[1C02] <3> .test: cmp eax,[es:A20Test+10h] 384 000085D9 E1E9 <3> loopz .wait 385 000085DB 6658 <3> .done: pop eax 386 000085DD 59 <3> pop cx 387 000085DE 07 <3> pop es 388 000085DF C3 <3> ret 389 <3> 390 <3> ; 391 <3> ; Routine to empty the 8042 KBC controller. If dl != 0 392 <3> ; then we will test A20 in the loop and exit if A20 is 393 <3> ; suddenly enabled. 394 <3> ; 395 <3> empty_8042_uncond: 396 000085E0 30D2 <3> xor dl,dl 397 <3> empty_8042: 398 000085E2 E8CCFF <3> call a20_test 399 000085E5 7404 <3> jz .a20_on 400 000085E7 20D2 <3> and dl,dl 401 000085E9 751A <3> jnz .done 402 000085EB E680E680 <3> .a20_on: io_delay 403 000085EF E464 <3> in al, 064h ; Status port 404 000085F1 A801 <3> test al,1 405 000085F3 7408 <3> jz .no_output 406 000085F5 E680E680 <3> io_delay 407 000085F9 E460 <3> in al, 060h ; Read input 408 000085FB EBE5 <3> jmp short empty_8042 409 <3> .no_output: 410 000085FD A802 <3> test al,2 411 000085FF 75E1 <3> jnz empty_8042 412 00008601 E680E680 <3> io_delay 413 00008605 C3 <3> .done: ret 414 <3> 415 <3> ; 416 <3> ; This initializes the protected-mode interrupt thunk set 417 <3> ; 418 <3> section .text16 419 <3> pm_init: 420 00008606 6631FF <3> xor edi,edi 421 00008609 BB[B820] <3> mov bx,IDT 422 0000860C BF[0000] <3> mov di,IRQStubs 423 <3> 424 0000860F 66B86A00EB7A <3> mov eax,7aeb006ah ; push byte .. jmp short .. 425 <3> 426 00008615 B90800 <3> mov cx,8 ; 8 groups of 32 IRQs 427 <3> .gloop: 428 00008618 51 <3> push cx 429 00008619 B92000 <3> mov cx,32 ; 32 entries per group 430 <3> .eloop: 431 0000861C 893F <3> mov [bx],di ; IDT offset [15:0] 432 0000861E C747022000 <3> mov word [bx+2],PM_CS32 ; IDT segment 433 00008623 66C74704008E0000 <3> mov dword [bx+4],08e00h ; IDT offset [31:16], 32-bit interrupt 434 <3> ; gate, CPL 0 (we don't have a TSS 435 <3> ; set up...) 436 0000862B 83C308 <3> add bx,8 437 <3> 438 0000862E 66AB <3> stosd 439 <3> ; Increment IRQ, decrement jmp short offset 440 00008630 6605000100FC <3> add eax,(-4 << 24)+(1 << 8) 441 <3> 442 00008636 E2E4 <3> loop .eloop 443 <3> 444 <3> ; At the end of each group, replace the EBxx with 445 <3> ; the final E9xxxxxxxx 446 00008638 83C703 <3> add di,3 447 0000863B C645FBE9 <3> mov byte [di-5],0E9h ; JMP NEAR 448 0000863F 66BA[87000000] <3> mov edx,pm_irq 449 00008645 6629FA <3> sub edx,edi 450 00008648 668955FC <3> mov [di-4],edx 451 <3> 452 0000864C 660500000080 <3> add eax,(0x80 << 24) ; Proper offset for the next one 453 00008652 59 <3> pop cx 454 00008653 E2C3 <3> loop .gloop 455 <3> 456 00008655 C3 <3> ret 457 <3> 458 <3> ; pm_init is called before bss clearing, so put these 459 <3> ; in .earlybss! 460 <3> section .earlybss 461 000030B4 <3> alignb 8 462 000030B8 <3> IDT: resq 256 463 <3> global RealModeSSSP 464 000038B8 <3> RealModeSSSP resd 1 ; Real-mode SS:SP 465 <3> 466 <3> section .gentextnr ; Autogenerated 32-bit code 467 00003B00 <3> IRQStubs: resb 4*256+3*8 468 <3> 469 <3> section .text16 470 <3> 471 <3> %include "callback.inc" ; Real-mode callbacks 1 <4> ;; ----------------------------------------------------------------------- 2 <4> ;; 3 <4> ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <4> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 <4> ;; 6 <4> ;; This program is free software; you can redistribute it and/or modify 7 <4> ;; it under the terms of the GNU General Public License as published by 8 <4> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <4> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <4> ;; (at your option) any later version; incorporated herein by reference. 11 <4> ;; 12 <4> ;; ----------------------------------------------------------------------- 13 <4> 14 <4> ;; 15 <4> ;; callback.inc 16 <4> ;; 17 <4> ;; Callbacks from 32-bit mode to 16-bit mode 18 <4> ;; 19 <4> 20 <4> ; 21 <4> ; 16-bit intcall/farcall handling code 22 <4> ; 23 <4> 24 <4> ; 25 <4> ; 32-bit support code 26 <4> ; 27 <4> bits 32 28 <4> section .text 29 <4> 30 <4> ; 31 <4> ; Intcall/farcall invocation. We manifest a structure on the real-mode stack, 32 <4> ; containing the com32sys_t structure from as well as 33 <4> ; the following entries (from low to high address): 34 <4> ; - Target offset 35 <4> ; - Target segment 36 <4> ; - Return offset 37 <4> ; - Return segment (== real mode cs == 0) 38 <4> ; - Return flags 39 <4> ; 40 <4> global core_farcall:function hidden 41 <4> core_farcall: 42 00100000 8B442404 <4> mov eax,[esp+1*4] ; CS:IP 43 00100004 EB0C <4> jmp core_syscall 44 <4> 45 <4> global core_intcall:function hidden 46 <4> core_intcall: 47 00100006 0FB6442404 <4> movzx eax,byte [esp+1*4] ; INT number 48 0010000B 8B048500000000 <4> mov eax,[eax*4] ; Get CS:IP from low memory 49 <4> 50 <4> core_syscall: 51 00100012 9C <4> pushfd ; Save IF among other things... 52 00100013 FF05[18020000] <4> inc dword [CallbackCtr] 53 00100019 53 <4> push ebx 54 0010001A 55 <4> push ebp 55 0010001B 56 <4> push esi 56 0010001C 57 <4> push edi 57 0010001D FF35[14020000] <4> push dword [CallbackSP] 58 <4> 59 00100023 FC <4> cld 60 <4> 61 00100024 670FB73E[B828] <4> movzx edi,word [word RealModeSSSP] 62 0010002A 670FB71E[BA28] <4> movzx ebx,word [word RealModeSSSP+2] 63 00100030 83EF36 <4> sub edi,54 ; Allocate 54 bytes 64 00100033 6667893E[B828] <4> mov [word RealModeSSSP],di 65 00100039 C1E304 <4> shl ebx,4 66 0010003C 01DF <4> add edi,ebx ; Create linear address 67 <4> 68 0010003E 8B742420 <4> mov esi,[esp+8*4] ; Source regs 69 00100042 31C9 <4> xor ecx,ecx 70 00100044 B10B <4> mov cl,11 ; 44 bytes to copy 71 00100046 F3A5 <4> rep movsd 72 <4> 73 <4> ; EAX is already set up to be CS:IP 74 00100048 AB <4> stosd ; Save in stack frame 75 00100049 B8[69020000] <4> mov eax,.rm_return ; Return seg:offs 76 0010004E AB <4> stosd ; Save in stack frame 77 0010004F 8B47F4 <4> mov eax,[edi-12] ; Return flags 78 00100052 25D70E2000 <4> and eax,0x200ed7 ; Mask (potentially) unsafe flags 79 00100057 8947F4 <4> mov [edi-12],eax ; Primary flags entry 80 0010005A 66AB <4> stosw ; Return flags 81 <4> 82 0010005C 66BB[5602] <4> mov bx,.rm 83 00100060 E9(78000000) <4> jmp enter_rm ; Go to real mode 84 <4> 85 <4> bits 16 86 <4> section .text16 87 <4> .rm: 88 00008656 89E0 <4> mov ax,sp 89 00008658 83C02C <4> add ax,9*4+4*2 90 0000865B A3[1402] <4> mov [CallbackSP],ax 91 0000865E 0FA9 <4> pop gs 92 00008660 0FA1 <4> pop fs 93 00008662 07 <4> pop es 94 00008663 1F <4> pop ds 95 00008664 6661 <4> popad 96 00008666 669D <4> popfd 97 00008668 CB <4> retf ; Invoke routine 98 <4> 99 <4> .rm_return: 100 <4> ; We clean up SP here because we don't know if the 101 <4> ; routine returned with RET, RETF or IRET 102 00008669 2E8B26[1402] <4> mov sp,[cs:CallbackSP] 103 0000866E 669C <4> pushfd 104 00008670 6660 <4> pushad 105 00008672 1E <4> push ds 106 00008673 06 <4> push es 107 00008674 0FA0 <4> push fs 108 00008676 0FA8 <4> push gs 109 00008678 66BB[65000000] <4> mov ebx,.pm_return 110 0000867E E927FE <4> jmp enter_pm 111 <4> 112 <4> ; On return, the 44-byte return structure is on the 113 <4> ; real-mode stack, plus the 10 additional bytes used 114 <4> ; by the target address (see above.) 115 <4> bits 32 116 <4> section .text 117 <4> .pm_return: 118 00100065 670FB736[B828] <4> movzx esi,word [word RealModeSSSP] 119 0010006B 670FB706[BA28] <4> movzx eax,word [word RealModeSSSP+2] 120 00100071 8B7C2424 <4> mov edi,[esp+9*4] ; Dest regs 121 00100075 C1E004 <4> shl eax,4 122 00100078 01C6 <4> add esi,eax ; Create linear address 123 0010007A 21FF <4> and edi,edi ; NULL pointer? 124 0010007C 7502 <4> jnz .do_copy 125 0010007E 89F7 <4> .no_copy: mov edi,esi ; Do a dummy copy-to-self 126 00100080 31C9 <4> .do_copy: xor ecx,ecx 127 00100082 B10B <4> mov cl,11 ; 44 bytes 128 00100084 F3A5 <4> rep movsd ; Copy register block 129 <4> 130 00100086 678306[B828]36 <4> add dword [word RealModeSSSP],54 131 <4> ; Remove from stack 132 <4> 133 0010008C 8F05[14020000] <4> pop dword [CallbackSP] 134 00100092 FF0D[18020000] <4> dec dword [CallbackCtr] 135 00100098 7506 <4> jnz .skip 136 0010009A FF15[44000000] <4> call [core_pm_hook] 137 <4> .skip: 138 001000A0 5F <4> pop edi 139 001000A1 5E <4> pop esi 140 001000A2 5D <4> pop ebp 141 001000A3 5B <4> pop ebx 142 001000A4 9D <4> popfd 143 001000A5 C3 <4> ret ; Return to 32-bit program 144 <4> 145 <4> ; 146 <4> ; Cfarcall invocation. We copy the stack frame to the real-mode stack, 147 <4> ; followed by the return CS:IP and the CS:IP of the target function. 148 <4> ; The value of IF is copied from the calling routine. 149 <4> ; 150 <4> global core_cfarcall:function hidden 151 <4> core_cfarcall: 152 001000A6 9C <4> pushfd ; Save IF among other things... 153 001000A7 FF05[18020000] <4> inc dword [CallbackCtr] 154 001000AD 53 <4> push ebx 155 001000AE 55 <4> push ebp 156 001000AF 56 <4> push esi 157 001000B0 57 <4> push edi 158 001000B1 FF35[14020000] <4> push dword [CallbackSP] 159 <4> 160 001000B7 FC <4> cld 161 001000B8 8B4C2424 <4> mov ecx,[esp+9*4] ; Size of stack frame 162 <4> 163 001000BC 670FB73E[B828] <4> movzx edi,word [word RealModeSSSP] 164 001000C2 670FB71E[BA28] <4> movzx ebx,word [word RealModeSSSP+2] 165 001000C8 6667893E[1402] <4> mov [word CallbackSP],di 166 001000CE 29CF <4> sub edi,ecx ; Allocate space for stack frame 167 001000D0 83E7FC <4> and edi,~3 ; Round 168 001000D3 83EF0C <4> sub edi,4*3 ; Return pointer, return value, EFLAGS 169 001000D6 6667893E[B828] <4> mov [word RealModeSSSP],di 170 001000DC C1E304 <4> shl ebx,4 171 001000DF 01DF <4> add edi,ebx ; Create linear address 172 <4> 173 001000E1 8B442414 <4> mov eax,[esp+5*4] ; EFLAGS from entry 174 001000E5 2502020000 <4> and eax,0x202 ; IF only 175 001000EA AB <4> stosd 176 001000EB 8B44241C <4> mov eax,[esp+7*4] ; CS:IP 177 001000EF AB <4> stosd ; Save to stack frame 178 001000F0 B8[84020000] <4> mov eax,.rm_return ; Return seg:off 179 001000F5 AB <4> stosd 180 001000F6 8B742420 <4> mov esi,[esp+8*4] ; Stack frame 181 001000FA 89C8 <4> mov eax,ecx ; Copy the stack frame 182 001000FC C1E902 <4> shr ecx,2 183 001000FF F3A5 <4> rep movsd 184 00100101 89C1 <4> mov ecx,eax 185 00100103 83E103 <4> and ecx,3 186 00100106 F3A4 <4> rep movsb 187 <4> 188 00100108 66BB[8102] <4> mov bx,.rm 189 0010010C E9(78000000) <4> jmp enter_rm 190 <4> 191 <4> bits 16 192 <4> section .text16 193 <4> .rm: 194 00008681 669D <4> popfd 195 00008683 CB <4> retf 196 <4> .rm_return: 197 00008684 2E8B26[1402] <4> mov sp,[cs:CallbackSP] 198 00008689 6689C6 <4> mov esi,eax 199 0000868C 66BB[11010000] <4> mov ebx,.pm_return 200 00008692 E913FE <4> jmp enter_pm 201 <4> 202 <4> bits 32 203 <4> section .text 204 <4> .pm_return: 205 00100111 89F0 <4> mov eax,esi 206 <4> ; EDX already set up to be the RM return value 207 00100113 8F05[14020000] <4> pop dword [CallbackSP] 208 00100119 FF0D[18020000] <4> dec dword [CallbackCtr] 209 0010011F 7506 <4> jnz .skip 210 00100121 FF15[44000000] <4> call [core_pm_hook] 211 <4> .skip: 212 00100127 5B <4> pop ebx 213 00100128 5D <4> pop ebp 214 00100129 5E <4> pop esi 215 0010012A 5F <4> pop edi 216 0010012B 9D <4> popfd 217 0010012C C3 <4> ret 218 <4> 219 <4> section .bss16 220 00003AD1 <4> alignb 4 221 <4> global core_pm_hook 222 00003AD4 <4> CallbackSP resd 1 ; SP saved during callback 223 00003AD8 <4> CallbackCtr resd 1 224 <4> 225 <4> bits 16 226 <4> section .text16 8 <2> %include "bcopy32.inc" ; 32-bit bcopy 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> ;; bcopy32.inc 16 <3> ;; 17 <3> ;; 32-bit bcopy routine for real mode 18 <3> ;; 19 <3> 20 <3> ; 21 <3> ; 32-bit bcopy routine for real mode 22 <3> ; 23 <3> ; We enter protected mode, set up a flat 32-bit environment, run rep movsd 24 <3> ; and then exit. IMPORTANT: This code assumes cs == 0. 25 <3> ; 26 <3> ; This code is probably excessively anal-retentive in its handling of 27 <3> ; segments, but this stuff is painful enough as it is without having to rely 28 <3> ; on everything happening "as it ought to." 29 <3> ; 30 <3> 31 <3> bits 16 32 <3> section .text16 33 <3> 34 <3> ; 35 <3> ; bcopy: 36 <3> ; 32-bit copy, overlap safe 37 <3> ; 38 <3> ; Inputs: 39 <3> ; ESI - source pointer (-1 means do bzero rather than bcopy) 40 <3> ; EDI - target pointer 41 <3> ; ECX - byte count 42 <3> ; 43 <3> ; Outputs: 44 <3> ; ESI - first byte after source (garbage if ESI == -1 on entry) 45 <3> ; EDI - first byte after target 46 <3> ; 47 00008695 67E30F <3> bcopy: jecxz .ret 48 <3> pm_call pm_bcopy 48 00008698 6668[00000000] <4> push dword %1 48 0000869E E8E2FD <4> call _pm_call 49 000086A1 6601CF <3> add edi,ecx 50 000086A4 6601CE <3> add esi,ecx 51 000086A7 C3 <3> .ret: ret 52 <3> 53 <3> ; 54 <3> ; shuffle_and_boot_raw: 55 <3> ; The new version of shuffle and boot. 56 <3> ; Inputs: 57 <3> ; ESI -> Pointer to list of (dst, src, len) pairs(*) 58 <3> ; EDI -> Pointer to safe area for list + shuffler 59 <3> ; (must not overlap this code nor the RM stack) 60 <3> ; ECX -> Byte count of list area (for initial copy) 61 <3> ; 62 <3> ; If src == -1: then the memory pointed to by (dst, len) is bzeroed; 63 <3> ; this is handled inside the bcopy routine. 64 <3> ; 65 <3> ; If len == 0: this marks the end of the list; dst indicates 66 <3> ; the entry point and src the mode (0 = pm, 1 = rm) 67 <3> ; 68 <3> ; (*) dst, src, and len are four bytes each 69 <3> ; 70 <3> shuffle_and_boot_raw: 71 000086A8 BB[BA00] <3> mov bx,pm_shuffle 72 000086AB E9FAFD <3> jmp enter_pm 73 <3> 74 <3> ; 75 <3> ; The 32-bit copy and shuffle code is "special", so it is in its own file 76 <3> ; 77 <3> %include "bcopyxx.inc" 1 <4> ;; ----------------------------------------------------------------------- 2 <4> ;; 3 <4> ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <4> ;; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin 5 <4> ;; 6 <4> ;; This program is free software; you can redistribute it and/or modify 7 <4> ;; it under the terms of the GNU General Public License as published by 8 <4> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <4> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <4> ;; (at your option) any later version; incorporated herein by reference. 11 <4> ;; 12 <4> ;; ----------------------------------------------------------------------- 13 <4> 14 <4> ;; 15 <4> ;; bcopy32xx.inc 16 <4> ;; 17 <4> 18 <4> 19 <4> ; 20 <4> ; 32-bit bcopy routine 21 <4> ; 22 <4> ; This is the actual 32-bit portion of the bcopy and shuffle and boot 23 <4> ; routines. ALL THIS CODE NEEDS TO BE POSITION-INDEPENDENT, with the 24 <4> ; sole exception being the actual relocation code at the beginning of 25 <4> ; pm_shuffle_boot. 26 <4> ; 27 <4> ; It also really needs to live all in a single segment, for the 28 <4> ; address calculcations to actually work. 29 <4> ; 30 <4> 31 <4> bits 32 32 <4> section .bcopyxx.text 33 <4> align 16 34 <4> ; 35 <4> ; pm_bcopy: 36 <4> ; 37 <4> ; This is the protected-mode core of the "bcopy" routine. 38 <4> ; Try to do aligned transfers; if the src and dst are relatively 39 <4> ; misaligned, align the dst. 40 <4> ; 41 <4> ; ECX is guaranteed to not be zero on entry. 42 <4> ; 43 <4> ; Clobbers ESI, EDI, ECX. 44 <4> ; 45 <4> 46 <4> pm_bcopy: 47 00008CA0 53 <4> push ebx 48 00008CA1 52 <4> push edx 49 00008CA2 50 <4> push eax 50 <4> 51 00008CA3 83FEFF <4> cmp esi,-1 52 00008CA6 747E <4> je .bzero 53 <4> 54 00008CA8 39FE <4> cmp esi,edi ; If source < destination, we might 55 00008CAA 722E <4> jb .reverse ; have to copy backwards 56 <4> 57 <4> .forward: 58 <4> ; Initial alignment 59 00008CAC 89FA <4> mov edx,edi 60 00008CAE D1EA <4> shr edx,1 61 00008CB0 7302 <4> jnc .faa1 62 00008CB2 A4 <4> movsb 63 00008CB3 49 <4> dec ecx 64 <4> .faa1: 65 00008CB4 88C8 <4> mov al,cl 66 00008CB6 83F902 <4> cmp ecx,2 67 00008CB9 7216 <4> jb .f_tiny 68 <4> 69 00008CBB D1EA <4> shr edx,1 70 00008CBD 7305 <4> jnc .faa2 71 00008CBF 66A5 <4> movsw 72 00008CC1 83E902 <4> sub ecx,2 73 <4> .faa2: 74 <4> 75 <4> ; Bulk transfer 76 00008CC4 88C8 <4> mov al,cl ; Save low bits 77 00008CC6 C1E902 <4> shr ecx,2 ; Convert to dwords 78 00008CC9 F3A5 <4> rep movsd ; Do our business 79 <4> ; At this point ecx == 0 80 <4> 81 00008CCB A802 <4> test al,2 82 00008CCD 7402 <4> jz .fab2 83 00008CCF 66A5 <4> movsw 84 <4> .fab2: 85 <4> .f_tiny: 86 00008CD1 A801 <4> test al,1 87 00008CD3 7401 <4> jz .fab1 88 00008CD5 A4 <4> movsb 89 <4> .fab1: 90 <4> .done: 91 00008CD6 58 <4> pop eax 92 00008CD7 5A <4> pop edx 93 00008CD8 5B <4> pop ebx 94 00008CD9 C3 <4> ret 95 <4> 96 <4> .reverse: 97 00008CDA 8D440EFF <4> lea eax,[esi+ecx-1] ; Point to final byte 98 00008CDE 39C7 <4> cmp edi,eax 99 00008CE0 77CA <4> ja .forward ; No overlap, do forward copy 100 <4> 101 00008CE2 FD <4> std ; Reverse copy 102 00008CE3 8D7C0FFF <4> lea edi,[edi+ecx-1] 103 00008CE7 89C6 <4> mov esi,eax 104 <4> 105 <4> ; Initial alignment 106 00008CE9 89FA <4> mov edx,edi 107 00008CEB D1EA <4> shr edx,1 108 00008CED 7202 <4> jc .raa1 109 00008CEF A4 <4> movsb 110 00008CF0 49 <4> dec ecx 111 <4> .raa1: 112 <4> 113 00008CF1 4E <4> dec esi 114 00008CF2 4F <4> dec edi 115 00008CF3 88C8 <4> mov al,cl 116 00008CF5 83F902 <4> cmp ecx,2 117 00008CF8 7222 <4> jb .r_tiny 118 00008CFA D1EA <4> shr edx,1 119 00008CFC 7205 <4> jc .raa2 120 00008CFE 66A5 <4> movsw 121 00008D00 83E902 <4> sub ecx,2 122 <4> .raa2: 123 <4> 124 <4> ; Bulk copy 125 00008D03 83EE02 <4> sub esi,2 126 00008D06 83EF02 <4> sub edi,2 127 00008D09 88C8 <4> mov al,cl ; Save low bits 128 00008D0B C1E902 <4> shr ecx,2 129 00008D0E F3A5 <4> rep movsd 130 <4> 131 <4> ; Final alignment 132 <4> .r_final: 133 00008D10 83C602 <4> add esi,2 134 00008D13 83C702 <4> add edi,2 135 00008D16 A802 <4> test al,2 136 00008D18 7402 <4> jz .rab2 137 00008D1A 66A5 <4> movsw 138 <4> .rab2: 139 <4> .r_tiny: 140 00008D1C 46 <4> inc esi 141 00008D1D 47 <4> inc edi 142 00008D1E A801 <4> test al,1 143 00008D20 7401 <4> jz .rab1 144 00008D22 A4 <4> movsb 145 <4> .rab1: 146 00008D23 FC <4> cld 147 00008D24 EBB0 <4> jmp short .done 148 <4> 149 <4> .bzero: 150 00008D26 31C0 <4> xor eax,eax 151 <4> 152 <4> ; Initial alignment 153 00008D28 89FA <4> mov edx,edi 154 00008D2A D1EA <4> shr edx,1 155 00008D2C 7302 <4> jnc .zaa1 156 00008D2E AA <4> stosb 157 00008D2F 49 <4> dec ecx 158 <4> .zaa1: 159 <4> 160 00008D30 88CB <4> mov bl,cl 161 00008D32 83F902 <4> cmp ecx,2 162 00008D35 7217 <4> jb .z_tiny 163 00008D37 D1EA <4> shr edx,1 164 00008D39 7305 <4> jnc .zaa2 165 00008D3B 66AB <4> stosw 166 00008D3D 83E902 <4> sub ecx,2 167 <4> .zaa2: 168 <4> 169 <4> ; Bulk 170 00008D40 88CB <4> mov bl,cl ; Save low bits 171 00008D42 C1E902 <4> shr ecx,2 172 00008D45 F3AB <4> rep stosd 173 <4> 174 00008D47 F6C302 <4> test bl,2 175 00008D4A 7402 <4> jz .zab2 176 00008D4C 66AB <4> stosw 177 <4> .zab2: 178 <4> .z_tiny: 179 00008D4E F6C301 <4> test bl,1 180 00008D51 7401 <4> jz .zab1 181 00008D53 AA <4> stosb 182 <4> .zab1: 183 00008D54 EB80 <4> jmp short .done 184 <4> 185 <4> ; 186 <4> ; shuffle_and_boot: 187 <4> ; 188 <4> ; This routine is used to shuffle memory around, followed by 189 <4> ; invoking an entry point somewhere in low memory. This routine 190 <4> ; can clobber any memory outside the bcopy special area. 191 <4> ; 192 <4> ; IMPORTANT: This routine does not set up any registers. 193 <4> ; It is the responsibility of the caller to generate an appropriate entry 194 <4> ; stub; *especially* when going to real mode. 195 <4> ; 196 <4> ; Inputs: 197 <4> ; ESI -> Pointer to list of (dst, src, len) pairs(*) 198 <4> ; EDI -> Pointer to safe area for list + shuffler 199 <4> ; (must not overlap this code nor the RM stack) 200 <4> ; ECX -> Byte count of list area (for initial copy) 201 <4> ; 202 <4> ; If src == -1: then the memory pointed to by (dst, len) is bzeroed; 203 <4> ; this is handled inside the bcopy routine. 204 <4> ; 205 <4> ; If len == 0: this marks the end of the list; dst indicates 206 <4> ; the entry point and src the mode (0 = pm, 1 = rm) 207 <4> ; 208 <4> ; (*) dst, src, and len are four bytes each 209 <4> ; 210 <4> ; do_raw_shuffle_and_boot is the same entry point, but with a C ABI: 211 <4> ; do_raw_shuffle_and_boot(safearea, descriptors, bytecount) 212 <4> ; 213 <4> global do_raw_shuffle_and_boot 214 <4> do_raw_shuffle_and_boot: 215 00008D56 89C7 <4> mov edi,eax 216 00008D58 89D6 <4> mov esi,edx 217 <4> 218 <4> pm_shuffle: 219 00008D5A FA <4> cli ; End interrupt service (for good) 220 00008D5B 89FB <4> mov ebx,edi ; EBX <- descriptor list 221 00008D5D 8D540F0F <4> lea edx,[edi+ecx+15] ; EDX <- where to relocate our code to 222 00008D61 83E2F0 <4> and edx,~15 ; Align 16 to benefit the GDT 223 00008D64 E837FFFFFF <4> call pm_bcopy 224 00008D69 BE[00000000] <4> mov esi,__bcopyxx_start ; Absolute source address 225 00008D6E 89D7 <4> mov edi,edx ; Absolute target address 226 00008D70 29F2 <4> sub edx,esi ; EDX <- address delta 227 00008D72 B9[00000000] <4> mov ecx,__bcopyxx_dwords 228 00008D77 8D82[E1000000] <4> lea eax,[edx+.safe] ; Resume point 229 <4> ; Relocate this code 230 00008D7D F3A5 <4> rep movsd 231 00008D7F FFE0 <4> jmp eax ; Jump to safe location 232 <4> .safe: 233 <4> ; Give ourselves a safe stack 234 00008D81 8DA2[80000000] <4> lea esp,[edx+bcopyxx_stack+__bcopyxx_end] 235 00008D87 81C2[00000000] <4> add edx,bcopy_gdt ; EDX <- new GDT 236 00008D8D 895202 <4> mov [edx+2],edx ; GDT self-pointer 237 00008D90 0F0112 <4> lgdt [edx] ; Switch to local GDT 238 <4> 239 <4> ; Now for the actual shuffling... 240 <4> .loop: 241 00008D93 8B3B <4> mov edi,[ebx] 242 00008D95 8B7304 <4> mov esi,[ebx+4] 243 00008D98 8B4B08 <4> mov ecx,[ebx+8] 244 00008D9B 83C30C <4> add ebx,12 245 00008D9E E307 <4> jecxz .done 246 00008DA0 E8FBFEFFFF <4> call pm_bcopy 247 00008DA5 EBEC <4> jmp .loop 248 <4> .done: 249 00008DA7 0F015A30 <4> lidt [edx+RM_IDT_ptr-bcopy_gdt] ; RM-like IDT 250 00008DAB 51 <4> push ecx ; == 0, for cleaning the flags register 251 00008DAC 21F6 <4> and esi,esi 252 00008DAE 7403 <4> jz pm_shuffle_16 253 00008DB0 9D <4> popfd ; Clean the flags 254 00008DB1 FFE7 <4> jmp edi ; Protected mode entry 255 <4> 256 <4> ; We have a 16-bit entry point, so we need to return 257 <4> ; to 16-bit mode. Note: EDX already points to the GDT. 258 <4> pm_shuffle_16: 259 00008DB3 89F8 <4> mov eax,edi 260 00008DB5 66894212 <4> mov [edx+PM_CS16+2],ax 261 00008DB9 6689421A <4> mov [edx+PM_DS16+2],ax 262 00008DBD C1E810 <4> shr eax,16 263 00008DC0 884214 <4> mov [edx+PM_CS16+4],al 264 00008DC3 886217 <4> mov [edx+PM_CS16+7],ah 265 00008DC6 88421C <4> mov [edx+PM_DS16+4],al 266 00008DC9 88621F <4> mov [edx+PM_DS16+7],ah 267 00008DCC 0F20C0 <4> mov eax,cr0 268 00008DCF 24FE <4> and al,~1 269 00008DD1 9D <4> popfd ; Clean the flags 270 <4> ; No flag-changing instructions below... 271 00008DD2 66BA1800 <4> mov dx,PM_DS16 272 00008DD6 8EDA <4> mov ds,edx 273 00008DD8 8EC2 <4> mov es,edx 274 00008DDA 8EE2 <4> mov fs,edx 275 00008DDC 8EEA <4> mov gs,edx 276 00008DDE 8ED2 <4> mov ss,edx 277 00008DE0 EA000000001000 <4> jmp PM_CS16:0 278 <4> 279 <4> section .bcopyxx.data 280 <4> 281 <4> alignz 16 282 <4> ; GDT descriptor entry 283 <4> %macro desc 1 284 <4> bcopy_gdt.%1: 285 <4> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 286 <4> %endmacro 287 <4> 288 <4> bcopy_gdt: 289 00008DF0 2F00 <4> dw bcopy_gdt_size-1 ; Null descriptor - contains GDT 290 00008DF2 [00000000] <4> dd bcopy_gdt ; pointer for LGDT instruction 291 00008DF6 0000 <4> dw 0 292 <4> 293 <4> ; TSS segment to keep Intel VT happy. Intel VT is 294 <4> ; unhappy about anything that doesn't smell like a 295 <4> ; full-blown 32-bit OS. 296 <4> desc TSS 296 <5> bcopy_gdt.%1: 296 <5> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 297 00008DF8 67008005 <4> dw 104-1, DummyTSS ; 08h 32-bit task state segment 298 00008DFC 00890000 <4> dd 00008900h ; present, dpl 0, 104 bytes @DummyTSS 299 <4> 300 <4> desc CS16 300 <5> bcopy_gdt.%1: 300 <5> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 301 00008E00 FFFF0000 <4> dd 0000ffffh ; 10h Code segment, use16, readable, 302 00008E04 009B0000 <4> dd 00009b00h ; present, dpl 0, cover 64K 303 <4> desc DS16 303 <5> bcopy_gdt.%1: 303 <5> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 304 00008E08 FFFF0000 <4> dd 0000ffffh ; 18h Data segment, use16, read/write, 305 00008E0C 00930000 <4> dd 00009300h ; present, dpl 0, cover 64K 306 <4> desc CS32 306 <5> bcopy_gdt.%1: 306 <5> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 307 00008E10 FFFF0000 <4> dd 0000ffffh ; 20h Code segment, use32, readable, 308 00008E14 009BCF00 <4> dd 00cf9b00h ; present, dpl 0, cover all 4G 309 <4> desc DS32 309 <5> bcopy_gdt.%1: 309 <5> PM_%1 equ bcopy_gdt.%1-bcopy_gdt 310 00008E18 FFFF0000 <4> dd 0000ffffh ; 28h Data segment, use32, read/write, 311 00008E1C 0093CF00 <4> dd 00cf9300h ; present, dpl 0, cover all 4G 312 <4> 313 <4> bcopy_gdt_size: equ $-bcopy_gdt 314 <4> ; 315 <4> ; Space for a dummy task state segment. It should never be actually 316 <4> ; accessed, but just in case it is, point to a chunk of memory that 317 <4> ; has a chance to not be used for anything real... 318 <4> ; 319 <4> DummyTSS equ 0x580 320 <4> 321 <4> align 4 322 00008E20 FFFF <4> RM_IDT_ptr: dw 0FFFFh ; Length (nonsense, but matches CPU) 323 00008E22 00000000 <4> dd 0 ; Offset 324 <4> 325 <4> bcopyxx_stack equ 128 ; We want this much stack 326 <4> 327 <4> section .rodata 328 <4> global __syslinux_shuffler_size 329 <4> extern __bcopyxx_len 330 <4> align 4 331 <4> __syslinux_shuffler_size: 332 00108908 [00000000] <4> dd __bcopyxx_len 333 <4> 334 <4> bits 16 335 <4> section .text16 9 <2> %include "strcpy.inc" ; strcpy() 1 <3> ; 2 <3> ; strcpy: Copy DS:SI -> ES:DI up to and including a null byte; 3 <3> ; on exit SI and DI point to the byte *after* the null byte 4 <3> ; 5 <3> section .text16 6 <3> 7 000086AE 50 <3> strcpy: push ax 8 000086AF AC <3> .loop: lodsb 9 000086B0 AA <3> stosb 10 000086B1 20C0 <3> and al,al 11 000086B3 75FA <3> jnz .loop 12 000086B5 58 <3> pop ax 13 000086B6 C3 <3> ret 10 <2> %include "adv.inc" ; Auxiliary Data Vector 1 <3> ;; ----------------------------------------------------------------------- 2 <3> ;; 3 <3> ;; Copyright 2007-2008 H. Peter Anvin - All Rights Reserved 4 <3> ;; 5 <3> ;; This program is free software; you can redistribute it and/or modify 6 <3> ;; it under the terms of the GNU General Public License as published by 7 <3> ;; the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 8 <3> ;; Boston MA 02110-1301, USA; either version 2 of the License, or 9 <3> ;; (at your option) any later version; incorporated herein by reference. 10 <3> ;; 11 <3> ;; ----------------------------------------------------------------------- 12 <3> 13 <3> ;; 14 <3> ;; adv.inc 15 <3> ;; 16 <3> ;; The auxiliary data vector and its routines 17 <3> ;; 18 <3> ;; The auxiliary data vector is a 512-byte aligned block that on the 19 <3> ;; disk-based derivatives can be part of the syslinux file itself. It 20 <3> ;; exists in two copies; when written, both copies are written (with a 21 <3> ;; sync in between, if from the operating system.) The first two 22 <3> ;; dwords are magic number and inverse checksum, then follows the data 23 <3> ;; area as a tagged array similar to BOOTP/DHCP, finally a tail 24 <3> ;; signature. 25 <3> ;; 26 <3> ;; Note that unlike BOOTP/DHCP, zero terminates the chain, and FF 27 <3> ;; has no special meaning. 28 <3> ;; 29 <3> 30 <3> ;; 31 <3> ;; List of ADV tags... 32 <3> ;; 33 <3> ADV_BOOTONCE equ 1 34 <3> 35 <3> ;; 36 <3> ;; Other ADV data... 37 <3> ;; 38 <3> ADV_MAGIC1 equ 0x5a2d2fa5 ; Head signature 39 <3> ADV_MAGIC2 equ 0xa3041767 ; Total checksum 40 <3> ADV_MAGIC3 equ 0xdd28bf64 ; Tail signature 41 <3> 42 <3> ADV_LEN equ 500 ; Data bytes 43 <3> 44 <3> adv_retries equ 6 ; Disk retries 45 <3> 46 <3> section .data 47 <3> global __syslinux_adv_ptr, __syslinux_adv_size 48 <3> __syslinux_adv_ptr: 49 0010EB60 [08000000] <3> dd adv0.data 50 <3> __syslinux_adv_size: 51 0010EB64 F4010000 <3> dd ADV_LEN 52 <3> 53 <3> section .adv 54 <3> ; Introduce the ADVs to valid but blank 55 <3> adv0: 56 00009000 <3> .head resd 1 57 00009004 <3> .csum resd 1 58 00009008 <3> .data resb ADV_LEN 59 000091FC <3> .tail resd 1 60 <3> .end equ $ 61 <3> adv1: 62 00009200 <3> .head resd 1 63 00009204 <3> .csum resd 1 64 00009208 <3> .data resb ADV_LEN 65 000093FC <3> .tail resd 1 66 <3> .end equ $ 67 <3> section .text16 68 <3> 69 <3> ; 70 <3> ; This is called after config file parsing, so we know 71 <3> ; the intended location of the ADV 72 <3> ; 73 <3> global adv_init 74 <3> adv_init: 75 000086B7 803E[7800]FF <3> cmp byte [ADVDrive],-1 76 000086BC 0F855901 <3> jne adv_read 77 <3> 78 <3> %if IS_SYSLINUX || IS_EXTLINUX 79 <3> cmp word [ADVSectors],2 ; Not present? 80 <3> jb adv_verify 81 <3> 82 <3> mov eax,[Hidden] 83 <3> mov edx,[Hidden+4] 84 <3> add [ADVSec0],eax 85 <3> adc [ADVSec0+4],edx 86 <3> add [ADVSec1],eax 87 <3> adc [ADVSec1+4],edx 88 <3> mov al,[DriveNumber] 89 <3> mov [ADVDrive],al 90 <3> jmp adv_read 91 <3> %endif 92 <3> 93 <3> ; 94 <3> ; Initialize the ADV data structure in memory 95 <3> ; 96 <3> adv_verify: 97 000086C0 803E[7800]FF <3> cmp byte [ADVDrive],-1 ; No ADV configured, still? 98 000086C5 7410 <3> je .reset ; Then unconditionally reset 99 <3> 100 000086C7 BE[0000] <3> mov si,adv0 101 000086CA E83900 <3> call .check_adv 102 000086CD 742C <3> jz .ok ; Primary ADV okay 103 000086CF BE[0002] <3> mov si,adv1 104 000086D2 E83100 <3> call .check_adv 105 000086D5 7425 <3> jz .adv1ok 106 <3> 107 <3> ; Neither ADV is usable; initialize to blank 108 <3> .reset: 109 000086D7 BF[0000] <3> mov di,adv0 110 000086DA 66B8A52F2D5A <3> mov eax,ADV_MAGIC1 111 000086E0 66AB <3> stosd 112 000086E2 66B8671704A3 <3> mov eax,ADV_MAGIC2 113 000086E8 66AB <3> stosd 114 000086EA 6631C0 <3> xor eax,eax 115 000086ED B97D00 <3> mov cx,ADV_LEN/4 116 000086F0 F366AB <3> rep stosd 117 000086F3 66B864BF28DD <3> mov eax,ADV_MAGIC3 118 000086F9 66AB <3> stosd 119 <3> 120 <3> .ok: 121 000086FB C3 <3> ret 122 <3> 123 <3> ; The primary ADV is bad, but the backup is OK 124 <3> .adv1ok: 125 000086FC BF[0000] <3> mov di,adv0 126 000086FF B98000 <3> mov cx,512/4 127 00008702 F366A5 <3> rep movsd 128 00008705 C3 <3> ret 129 <3> 130 <3> 131 <3> ; SI points to the putative ADV; unchanged by routine 132 <3> ; ZF=1 on return if good 133 <3> .check_adv: 134 00008706 56 <3> push si 135 00008707 66AD <3> lodsd 136 00008709 663DA52F2D5A <3> cmp eax,ADV_MAGIC1 137 0000870F 751E <3> jne .done ; ZF=0, i.e. bad 138 00008711 6631D2 <3> xor edx,edx 139 00008714 B97E00 <3> mov cx,ADV_LEN/4+1 ; Remaining dwords 140 <3> .csum: 141 00008717 66AD <3> lodsd 142 00008719 6601C2 <3> add edx,eax 143 0000871C E2F9 <3> loop .csum 144 0000871E 6681FA671704A3 <3> cmp edx,ADV_MAGIC2 145 00008725 7508 <3> jne .done 146 00008727 66AD <3> lodsd 147 00008729 663D64BF28DD <3> cmp eax,ADV_MAGIC3 148 <3> .done: 149 0000872F 5E <3> pop si 150 00008730 C3 <3> ret 151 <3> 152 <3> ; 153 <3> ; adv_get: find an ADV string if present 154 <3> ; 155 <3> ; Input: DL = ADV ID 156 <3> ; Output: CX = byte count (zero on not found) 157 <3> ; SI = pointer to data 158 <3> ; DL = unchanged 159 <3> ; 160 <3> ; Assumes CS == DS. 161 <3> ; 162 <3> 163 <3> adv_get: 164 00008731 50 <3> push ax 165 00008732 BE[0800] <3> mov si,adv0.data 166 00008735 31C0 <3> xor ax,ax ; Keep AH=0 at all times 167 <3> .loop: 168 00008737 AC <3> lodsb ; Read ID 169 00008738 38D0 <3> cmp al,dl 170 0000873A 740F <3> je .found 171 0000873C 20C0 <3> and al,al 172 0000873E 7415 <3> jz .end 173 00008740 AC <3> lodsb ; Read length 174 00008741 01C6 <3> add si,ax 175 00008743 81FE[FC01] <3> cmp si,adv0.tail 176 00008747 72EE <3> jb .loop 177 00008749 EB0A <3> jmp .end 178 <3> 179 <3> .found: 180 0000874B AC <3> lodsb 181 0000874C 89C1 <3> mov cx,ax 182 0000874E 01F0 <3> add ax,si ; Make sure it fits 183 00008750 3D[FC01] <3> cmp ax,adv0.tail 184 00008753 7602 <3> jbe .ok 185 <3> .end: 186 00008755 31C9 <3> xor cx,cx 187 <3> .ok: 188 00008757 58 <3> pop ax 189 00008758 C3 <3> ret 190 <3> 191 <3> ; 192 <3> ; adv_set: insert a string into the ADV in memory 193 <3> ; 194 <3> ; Input: DL = ADV ID 195 <3> ; FS:BX = input buffer 196 <3> ; CX = byte count (max = 255!) 197 <3> ; Output: CF=1 on error 198 <3> ; CX clobbered 199 <3> ; 200 <3> ; Assumes CS == DS == ES. 201 <3> ; 202 <3> adv_set: 203 00008759 50 <3> push ax 204 0000875A 56 <3> push si 205 0000875B 57 <3> push di 206 0000875C 20ED <3> and ch,ch 207 0000875E 7559 <3> jnz .overflow 208 <3> 209 00008760 51 <3> push cx 210 00008761 BE[0800] <3> mov si,adv0.data 211 00008764 31C0 <3> xor ax,ax 212 <3> .loop: 213 00008766 AC <3> lodsb 214 00008767 38D0 <3> cmp al,dl 215 00008769 740F <3> je .found 216 0000876B 20C0 <3> and al,al 217 0000876D 7423 <3> jz .endz 218 0000876F AC <3> lodsb 219 00008770 01C6 <3> add si,ax 220 00008772 81FE[FC01] <3> cmp si,adv0.tail 221 00008776 72EE <3> jb .loop 222 00008778 EB19 <3> jmp .end 223 <3> 224 <3> .found: ; Found, need to delete old copy 225 0000877A AC <3> lodsb 226 0000877B 8D7CFE <3> lea di,[si-2] 227 0000877E 57 <3> push di 228 0000877F 01C6 <3> add si,ax 229 00008781 B9[FC01] <3> mov cx,adv0.tail 230 00008784 29F1 <3> sub cx,si 231 00008786 7207 <3> jb .nukeit 232 00008788 F3A4 <3> rep movsb ; Remove the old one 233 0000878A 8825 <3> mov [di],ah ; Termination zero 234 0000878C 5E <3> pop si 235 0000878D EBD7 <3> jmp .loop 236 <3> .nukeit: 237 0000878F 5E <3> pop si 238 00008790 EB01 <3> jmp .end 239 <3> .endz: 240 00008792 4E <3> dec si 241 <3> .end: 242 <3> ; Now SI points to where we want to put our data 243 00008793 59 <3> pop cx 244 00008794 89F7 <3> mov di,si 245 00008796 E313 <3> jcxz .empty 246 00008798 01CE <3> add si,cx 247 0000879A 81FE[FA01] <3> cmp si,adv0.tail-2 248 0000879E 7319 <3> jae .overflow ; CF=0 249 <3> 250 000087A0 89DE <3> mov si,bx 251 000087A2 88D0 <3> mov al,dl 252 000087A4 AA <3> stosb 253 000087A5 88C8 <3> mov al,cl 254 000087A7 AA <3> stosb 255 000087A8 F364A4 <3> fs rep movsb 256 <3> 257 <3> .empty: 258 000087AB B9[FC01] <3> mov cx,adv0.tail 259 000087AE 29F9 <3> sub cx,di 260 000087B0 31C0 <3> xor ax,ax 261 000087B2 F3AA <3> rep stosb ; Zero-fill remainder 262 <3> 263 000087B4 F8 <3> clc 264 <3> .done: 265 000087B5 5F <3> pop di 266 000087B6 5E <3> pop si 267 000087B7 58 <3> pop ax 268 000087B8 C3 <3> ret 269 <3> .overflow: 270 000087B9 F9 <3> stc 271 000087BA EBF9 <3> jmp .done 272 <3> 273 <3> ; 274 <3> ; adv_cleanup: checksum adv0 and copy to adv1 275 <3> ; Assumes CS == DS == ES. 276 <3> ; 277 <3> adv_cleanup: 278 000087BC 6660 <3> pushad 279 000087BE BE[0800] <3> mov si,adv0.data 280 000087C1 B97D00 <3> mov cx,ADV_LEN/4 281 000087C4 6631D2 <3> xor edx,edx 282 <3> .loop: 283 000087C7 66AD <3> lodsd 284 000087C9 6601C2 <3> add edx,eax 285 000087CC E2F9 <3> loop .loop 286 000087CE 66B8671704A3 <3> mov eax,ADV_MAGIC2 287 000087D4 6629D0 <3> sub eax,edx 288 000087D7 8D7C04 <3> lea di,[si+4] ; adv1 289 000087DA BE[0000] <3> mov si,adv0 290 000087DD 66894404 <3> mov [si+4],eax ; Store checksum 291 000087E1 B98000 <3> mov cx,(ADV_LEN+12)/4 292 000087E4 F366A5 <3> rep movsd 293 000087E7 6661 <3> popad 294 000087E9 C3 <3> ret 295 <3> 296 <3> ; 297 <3> ; adv_write: write the ADV to disk. 298 <3> ; 299 <3> ; Location is in memory variables. 300 <3> ; Assumes CS == DS == ES. 301 <3> ; 302 <3> ; Returns CF=1 if the ADV cannot be written. 303 <3> ; 304 <3> global adv_write 305 <3> adv_write: 306 000087EA 6650 <3> push eax 307 000087EC 66A1[6800] <3> mov eax,[ADVSec0] 308 000087F0 660B06[6C00] <3> or eax,[ADVSec0+4] 309 000087F5 741E <3> je .bad 310 000087F7 66A1[7000] <3> mov eax,[ADVSec1] 311 000087FB 660B06[7400] <3> or eax,[ADVSec1+4] 312 00008800 7413 <3> je .bad 313 00008802 803E[7800]FF <3> cmp byte [ADVDrive],-1 314 00008807 740C <3> je .bad 315 <3> 316 00008809 E8B0FF <3> call adv_cleanup 317 0000880C B403 <3> mov ah,3 ; Write 318 0000880E E81300 <3> call adv_read_write 319 <3> 320 00008811 F8 <3> clc 321 00008812 6658 <3> pop eax 322 00008814 C3 <3> ret 323 <3> .bad: ; No location for ADV set 324 00008815 F9 <3> stc 325 00008816 6658 <3> pop eax 326 00008818 C3 <3> ret 327 <3> 328 <3> ; 329 <3> ; adv_read: read the ADV from disk 330 <3> ; 331 <3> ; Location is in memory variables. 332 <3> ; Assumes CS == DS == ES. 333 <3> ; 334 <3> adv_read: 335 00008819 50 <3> push ax 336 0000881A B402 <3> mov ah,2 ; Read 337 0000881C E80500 <3> call adv_read_write 338 0000881F E89EFE <3> call adv_verify 339 00008822 58 <3> pop ax 340 00008823 C3 <3> ret 341 <3> 342 <3> ; 343 <3> ; adv_read_write: disk I/O for the ADV 344 <3> ; 345 <3> ; On input, AH=2 for read, AH=3 for write. 346 <3> ; Assumes CS == DS == ES. 347 <3> ; 348 <3> adv_read_write: 349 00008824 8826[1C02] <3> mov [ADVOp],ah 350 00008828 6660 <3> pushad 351 <3> 352 <3> ; Check for EDD 353 0000882A BBAA55 <3> mov bx,55AAh 354 0000882D B441 <3> mov ah,41h ; EDD existence query 355 0000882F 8A16[7800] <3> mov dl,[ADVDrive] 356 00008833 CD13 <3> int 13h 357 00008835 BE[9C04] <3> mov si,.cbios 358 00008838 720E <3> jc .noedd 359 0000883A 81FB55AA <3> cmp bx,0AA55h 360 0000883E 7508 <3> jne .noedd 361 00008840 F6C101 <3> test cl,1 362 00008843 7403 <3> jz .noedd 363 00008845 BE[6C04] <3> mov si,.ebios 364 <3> .noedd: 365 <3> 366 00008848 66A1[6800] <3> mov eax,[ADVSec0] 367 0000884C 668B16[6C00] <3> mov edx,[ADVSec0+4] 368 00008851 BB[0000] <3> mov bx,adv0 369 00008854 E81200 <3> call .doone 370 <3> 371 00008857 66A1[7000] <3> mov eax,[ADVSec1] 372 0000885B 668B16[7400] <3> mov edx,[ADVSec1+4] 373 00008860 BB[0002] <3> mov bx,adv1 374 00008863 E80300 <3> call .doone 375 <3> 376 00008866 6661 <3> popad 377 00008868 C3 <3> ret 378 <3> 379 <3> .doone: 380 00008869 56 <3> push si 381 0000886A FFE6 <3> jmp si 382 <3> 383 <3> .ebios: 384 0000886C B90600 <3> mov cx,adv_retries 385 <3> .eb_retry: 386 <3> ; Form DAPA on stack 387 0000886F 6652 <3> push edx 388 00008871 6650 <3> push eax 389 00008873 06 <3> push es 390 00008874 53 <3> push bx 391 00008875 6A01 <3> push word 1 ; Sector count 392 00008877 6A10 <3> push word 16 ; DAPA size 393 00008879 89E6 <3> mov si,sp 394 0000887B 6660 <3> pushad 395 0000887D 8A16[7800] <3> mov dl,[ADVDrive] 396 00008881 B80040 <3> mov ax,4000h 397 00008884 0A26[1C02] <3> or ah,[ADVOp] 398 00008888 1E <3> push ds 399 00008889 16 <3> push ss 400 0000888A 1F <3> pop ds 401 0000888B CD13 <3> int 13h 402 0000888D 1F <3> pop ds 403 0000888E 6661 <3> popad 404 00008890 8D6410 <3> lea sp,[si+16] ; Remove DAPA 405 00008893 7202 <3> jc .eb_error 406 00008895 5E <3> pop si 407 00008896 C3 <3> ret 408 <3> .eb_error: 409 00008897 E2D6 <3> loop .eb_retry 410 00008899 F9 <3> stc 411 0000889A 5E <3> pop si 412 0000889B C3 <3> ret 413 <3> 414 <3> .cbios: 415 0000889C 6652 <3> push edx 416 0000889E 6650 <3> push eax 417 000088A0 55 <3> push bp 418 <3> 419 000088A1 6621D2 <3> and edx,edx ; > 2 TiB not possible 420 000088A4 7563 <3> jnz .cb_overflow 421 <3> 422 000088A6 8A16[7800] <3> mov dl,[ADVDrive] 423 000088AA 20D2 <3> and dl,dl 424 <3> ; Floppies: can't trust INT 13h 08h, we better know 425 <3> ; the geometry a priori, which means it better be our 426 <3> ; boot device... 427 000088AC 791B <3> jns .noparm ; Floppy drive... urk 428 <3> 429 000088AE B408 <3> mov ah,08h ; Get disk parameters 430 000088B0 CD13 <3> int 13h 431 000088B2 7215 <3> jc .noparm 432 000088B4 20E4 <3> and ah,ah 433 000088B6 7511 <3> jnz .noparm 434 000088B8 C1EA08 <3> shr dx,8 435 000088BB 42 <3> inc dx 436 000088BC 660FB7FA <3> movzx edi,dx ; EDI = heads 437 000088C0 83E13F <3> and cx,3fh 438 000088C3 660FB7F1 <3> movzx esi,cx ; ESI = sectors/track 439 000088C7 EB02 <3> jmp .parmok 440 <3> 441 <3> .noparm: 442 <3> ; No CHS info... this better be our boot drive, then 443 <3> %if IS_SYSLINUX || IS_EXTLINUX 444 <3> cmp dl,[DriveNumber] 445 <3> jne .cb_overflow ; Fatal error! 446 <3> movzx esi,word [bsSecPerTrack] 447 <3> movzx edi,word [bsHeads] 448 <3> %else 449 <3> ; Not a disk-based derivative... there is no hope 450 000088C9 EB3E <3> jmp .cb_overflow 451 <3> %endif 452 <3> 453 <3> .parmok: 454 <3> ; 455 <3> ; Dividing by sectors to get (track,sector): we may have 456 <3> ; up to 2^18 tracks, so we need to use 32-bit arithmetric. 457 <3> ; 458 000088CB 6631D2 <3> xor edx,edx 459 000088CE 66F7F6 <3> div esi 460 000088D1 31C9 <3> xor cx,cx 461 000088D3 87CA <3> xchg cx,dx ; CX <- sector index (0-based) 462 <3> ; EDX <- 0 463 <3> ; eax = track # 464 000088D5 66F7F7 <3> div edi ; Convert track to head/cyl 465 <3> 466 <3> ; Watch out for overflow, we might be writing! 467 000088D8 663DFF030000 <3> cmp eax,1023 468 000088DE 7729 <3> ja .cb_overflow 469 <3> 470 <3> ; 471 <3> ; Now we have AX = cyl, DX = head, CX = sector (0-based), 472 <3> ; BP = sectors to transfer, SI = bsSecPerTrack, 473 <3> ; ES:BX = data target 474 <3> ; 475 <3> 476 000088E0 C0E406 <3> shl ah,6 ; Because IBM was STOOPID 477 <3> ; and thought 8 bits were enough 478 <3> ; then thought 10 bits were enough... 479 000088E3 41 <3> inc cx ; Sector numbers are 1-based, sigh 480 000088E4 08E1 <3> or cl,ah 481 000088E6 88C5 <3> mov ch,al 482 000088E8 88D6 <3> mov dh,dl 483 000088EA 8A16[7800] <3> mov dl,[ADVDrive] 484 000088EE B001 <3> mov al,01h ; Transfer one sector 485 000088F0 8A26[1C02] <3> mov ah,[ADVOp] ; Operation 486 <3> 487 000088F4 BD0600 <3> mov bp,adv_retries 488 <3> .cb_retry: 489 000088F7 6660 <3> pushad 490 000088F9 CD13 <3> int 13h 491 000088FB 6661 <3> popad 492 000088FD 7207 <3> jc .cb_error 493 <3> 494 <3> .cb_done: 495 000088FF 5D <3> pop bp 496 00008900 6658 <3> pop eax 497 00008902 665A <3> pop edx 498 00008904 5E <3> pop si 499 00008905 C3 <3> ret 500 <3> 501 <3> .cb_error: 502 00008906 4D <3> dec bp 503 00008907 75EE <3> jnz .cb_retry 504 <3> .cb_overflow: 505 00008909 F9 <3> stc 506 0000890A EBF3 <3> jmp .cb_done 507 <3> 508 <3> section .data16 509 00008E97 00 <3> alignz 8 510 00008E98 0000000000000000 <3> ADVSec0 dq 0 ; Not specified 511 00008EA0 0000000000000000 <3> ADVSec1 dq 0 ; Not specified 512 00008EA8 FF <3> ADVDrive db -1 ; No ADV defined 513 00008EA9 FF <3> ADVCHSInfo db -1 ; We have CHS info for this drive 514 <3> 515 <3> section .bss16 516 00003ADC <3> ADVOp resb 1 517 <3> 518 <3> section .text16 11 <2> %include "timer.inc" ; Timer handling 1 <3> ;; ----------------------------------------------------------------------- 2 <3> ;; 3 <3> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 4 <3> ;; 5 <3> ;; This program is free software; you can redistribute it and/or modify 6 <3> ;; it under the terms of the GNU General Public License as published by 7 <3> ;; the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 8 <3> ;; Boston MA 02110-1301, USA; either version 2 of the License, or 9 <3> ;; (at your option) any later version; incorporated herein by reference. 10 <3> ;; 11 <3> ;; ----------------------------------------------------------------------- 12 <3> 13 <3> ;; 14 <3> ;; timer.inc 15 <3> ;; 16 <3> ;; Very simple counting timer 17 <3> ;; 18 <3> ;; This lets us have a simple incrementing variable without worrying 19 <3> ;; about the BIOS_timer variable wrapping around at "midnight" and other 20 <3> ;; weird things. 21 <3> ;; 22 <3> ;; This also maintains a timer variable calibrated in milliseconds 23 <3> ;; (wraparound time = 49.7 days!) 24 <3> ;; 25 <3> 26 <3> section .text16 27 <3> 28 <3> timer_init: 29 <3> ; Hook INT 1Ch 30 0000890C 66A17000 <3> mov eax,[BIOS_timer_hook] 31 00008910 66A3[3C05] <3> mov [BIOS_timer_next],eax 32 00008914 66C7067000- <3> mov dword [BIOS_timer_hook],timer_irq 32 00008919 [27050000] <3> 33 0000891D C3 <3> ret 34 <3> 35 <3> global bios_timer_cleanup:function hidden 36 <3> bios_timer_cleanup: 37 <3> ; Unhook INT 1Ch 38 0000891E 66A1[3C05] <3> mov eax,[BIOS_timer_next] 39 00008922 66A37000 <3> mov [BIOS_timer_hook],eax 40 00008926 C3 <3> ret 41 <3> 42 <3> ; 43 <3> ; The specified frequency is 14.31818 MHz/12/65536; this turns out 44 <3> ; to be a period of 54.92542 ms, or 0x36.ece8(187c) hexadecimal. 45 <3> ; 46 <3> global timer_irq:function hidden 47 <3> timer_irq: 48 00008927 2E66FF06[7C00] <3> inc dword [cs:__jiffies] 49 0000892D 2E8106[8400]E8EC <3> add word [cs:__ms_timer_adj],0xece8 50 00008934 2E668316[8000]36 <3> adc dword [cs:__ms_timer],0x36 51 0000893B EA00000000 <3> jmp 0:0 52 <3> global BIOS_timer_next:data hidden 53 <3> BIOS_timer_next equ $-4 54 <3> 55 <3> section .data16 56 00008EAA 00 <3> alignz 4 57 <3> global __jiffies:data hidden, __ms_timer 58 00008EAC 00000000 <3> __jiffies dd 0 ; Clock tick timer 59 00008EB0 00000000 <3> __ms_timer dd 0 ; Millisecond timer 60 00008EB4 0000 <3> __ms_timer_adj dw 0 ; Millisecond timer correction factor 12 <2> 13 <2> ; Note: the prefix section is included late, to avoid problems with some 14 <2> ; versions of NASM that had issues with forward references to EQU symbols. 15 <2> %include "prefix.inc" ; Prefix section for prepcore 1 <3> ; 2 <3> ; The prefix is a small structure that prefaces the actual code; 3 <3> ; it gives the compression program necessary information. 4 <3> ; 5 <3> 6 <3> section .prefix nowrite progbits align=16 7 00000000 [00000000] <3> pfx_start dd _start ; Start of raw chunk 8 00000004 [00000000] <3> pfx_compressed dd __pm_code_lma ; Start of compressed chunk 9 00000008 [06000000] <3> pfx_cdatalen dd lzo_data_size ; Pointer to compressed size field 10 <3> %if IS_ISOLINUX 11 0000000C [10000000] <3> pfx_checksum dd bi_length ; File length and checksum fields 12 <3> %else 13 <3> pfx_checksum dd 0 ; No checksum 14 <3> %endif 15 00000010 00000600 <3> pfx_maxlma dd MaxLMA ; Maximum size 16 <3> 17 <3> section .text16 1222 <1> 1223 <1> ; ----------------------------------------------------------------------------- 1224 <1> ; Begin data section 1225 <1> ; ----------------------------------------------------------------------------- 1226 <1> 1227 <1> section .data16 1228 00008EB6 43616E6E6F74206C6F- <1> err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0 1228 00008EBF 6164206469736B2069- <1> 1228 00008EC8 6D6167652028696E76- <1> 1228 00008ED1 616C69642066696C65- <1> 1228 00008EDA 293F0D0A00 <1> 1229 <1> 1230 <1> section .bss16 1231 <1> global OrigFDCTabPtr 1232 00003ADD <1> OrigFDCTabPtr resd 1 ; Keep bios_cleanup_hardware() honest