1 ; -*- fundamental -*- (asm-mode sucks) 2 ; **************************************************************************** 3 ; 4 ; ldlinux.asm 5 ; 6 ; A program to boot Linux kernels off an MS-DOS formatted floppy disk. This 7 ; functionality is good to have for installation floppies, where it may 8 ; be hard to find a functional Linux system to run LILO off. 9 ; 10 ; This program allows manipulation of the disk to take place entirely 11 ; from MS-LOSS, and can be especially useful in conjunction with the 12 ; umsdos filesystem. 13 ; 14 ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 15 ; Copyright 2009 Intel Corporation; author: H. Peter Anvin 16 ; 17 ; This program is free software; you can redistribute it and/or modify 18 ; it under the terms of the GNU General Public License as published by 19 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 20 ; Boston MA 02111-1307, USA; either version 2 of the License, or 21 ; (at your option) any later version; incorporated herein by reference. 22 ; 23 ; **************************************************************************** 24 25 %define IS_SYSLINUX 1 26 %include "head.inc" 1 <1> ; -*- fundamental -*- (asm-mode sucks) 2 <1> ; ----------------------------------------------------------------------- 3 <1> ; 4 <1> ; Copyright 2006-2008 H. Peter Anvin - All Rights Reserved 5 <1> ; 6 <1> ; This program is free software; you can redistribute it and/or modify 7 <1> ; it under the terms of the GNU General Public License as published by 8 <1> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <1> ; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <1> ; (at your option) any later version; incorporated herein by reference. 11 <1> ; 12 <1> ; ----------------------------------------------------------------------- 13 <1> 14 <1> ; 15 <1> ; head.inc 16 <1> ; 17 <1> ; Common header includes 18 <1> ; 19 <1> 20 <1> %ifndef _HEAD_INC 21 <1> %define _HEAD_INC 22 <1> 23 <1> %if __NASM_MAJOR__ < 2 || (__NASM_MAJOR__ == 2 && __NASM_MINOR__ < 3) 24 <1> %error "NASM 2.03 or later required to compile correctly" 25 <1> %elif __NASM_VERSION_ID__ == 0x020b0600 26 <1> %fatal "NASM 2.11.06 is known to miscompile Syslinux" 27 <1> %endif 28 <1> 29 <1> %include "macros.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <2> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 <2> ;; 6 <2> ;; This program is free software; you can redistribute it and/or modify 7 <2> ;; it under the terms of the GNU General Public License as published by 8 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <2> ;; (at your option) any later version; incorporated herein by reference. 11 <2> ;; 12 <2> ;; ----------------------------------------------------------------------- 13 <2> 14 <2> ;; 15 <2> ;; macros.inc 16 <2> ;; 17 <2> ;; Convenient macros 18 <2> ;; 19 <2> 20 <2> %ifndef _MACROS_INC 21 <2> %define _MACROS_INC 22 <2> 23 <2> ; 24 <2> ; Identify the module we're compiling; the "correct" should be defined 25 <2> ; in the module itself to 1 26 <2> ; 27 <2> %ifdef IS_SYSLINUX 28 <2> %define MY_NAME 'SYSLINUX' 29 <2> %else 30 <2> %define IS_SYSLINUX 0 31 <2> %endif 32 <2> %ifdef IS_PXELINUX 33 <2> %define MY_NAME 'PXELINUX' 34 <2> %if IS_LPXELINUX > 0 35 <2> %define MY_TYPE 'lwIP' 36 <2> %else 37 <2> %define MY_TYPE 'PXE' 38 <2> %endif 39 <2> %else 40 <2> %define IS_PXELINUX 0 41 <2> %endif 42 <2> %ifdef IS_ISOLINUX 43 <2> %define MY_NAME 'ISOLINUX' 44 <2> %else 45 <2> %define IS_ISOLINUX 0 46 <2> %endif 47 <2> %ifdef IS_EXTLINUX 48 <2> %define MY_NAME 'EXTLINUX' 49 <2> %else 50 <2> %define IS_EXTLINUX 0 51 <2> %endif 52 <2> 53 <2> ; 54 <2> ; Macros similar to res[bwd], but which works in the code segment (after 55 <2> ; section .text16) or the data segment (section .data16) 56 <2> ; 57 <2> %macro zb 1.nolist 58 <2> times %1 db 0 59 <2> %endmacro 60 <2> 61 <2> %macro zw 1.nolist 62 <2> times %1 dw 0 63 <2> %endmacro 64 <2> 65 <2> %macro zd 1.nolist 66 <2> times %1 dd 0 67 <2> %endmacro 68 <2> 69 <2> ; 70 <2> ; Align with zero bytes in a progbits segment 71 <2> ; 72 <2> %macro alignz 1.nolist 73 <2> times (((%1) - (($-$$) % (%1))) % (%1)) db 0 74 <2> %endmacro 75 <2> 76 <2> ; 77 <2> ; Macro to emit an unsigned decimal number as a string 78 <2> ; 79 <2> %macro asciidec 1.nolist 80 <2> %ifndef DEPEND ; Not safe for "depend" 81 <2> %push asciidec 82 <2> %assign %$v %1 83 <2> %if %$v == 0 84 <2> db '0' 85 <2> %else 86 <2> %assign %$dcount 0 87 <2> %assign %$n %$v 88 <2> %assign %$d 1 89 <2> %rep 20 90 <2> %if %$n != 0 91 <2> %assign %$dcount %$dcount + 1 92 <2> %assign %$n %$n / 10 93 <2> %assign %$d %$d * 10 94 <2> %endif 95 <2> %endrep 96 <2> %rep %$dcount 97 <2> %assign %$d %$d / 10 98 <2> db ((%$v / %$d) % 10) + '0' 99 <2> %endrep 100 <2> %endif 101 <2> %pop 102 <2> %endif 103 <2> %endmacro 104 <2> 105 <2> ; 106 <2> ; Macros for network byte order of constants 107 <2> ; 108 <2> %define htons(x) ( ( ((x) & 0FFh) << 8 ) + ( ((x) & 0FF00h) >> 8 ) ) 109 <2> %define ntohs(x) htons(x) 110 <2> %define htonl(x) ( ( ((x) & 0FFh) << 24) + ( ((x) & 0FF00h) << 8 ) + ( ((x) & 0FF0000h) >> 8 ) + ( ((x) & 0FF000000h) >> 24) ) 111 <2> %define ntohl(x) htonl(x) 112 <2> 113 <2> ; 114 <2> ; ASCII 115 <2> ; 116 <2> CR equ 13 ; Carriage Return 117 <2> LF equ 10 ; Line Feed 118 <2> FF equ 12 ; Form Feed 119 <2> BS equ 8 ; Backspace 120 <2> 121 <2> %endif ; _MACROS_INC 30 <1> %include "config.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 2002-2009 H. Peter Anvin - All Rights Reserved 4 <2> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 <2> ;; 6 <2> ;; This program is free software; you can redistribute it and/or modify 7 <2> ;; it under the terms of the GNU General Public License as published by 8 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <2> ;; (at your option) any later version; incorporated herein by reference. 11 <2> ;; 12 <2> ;; ----------------------------------------------------------------------- 13 <2> 14 <2> ;; 15 <2> ;; config.inc 16 <2> ;; 17 <2> ;; Common configuration options. Some of these are imposed by the kernel. 18 <2> ;; 19 <2> 20 <2> %ifndef _CONFIG_INC 21 <2> %define _CONFIG_INC 22 <2> 23 <2> max_cmd_len equ 2047 ; Must be &3; 2047 is the kernel limit 24 <2> HIGHMEM_MAX equ 037FFFFFFh ; DEFAULT highest address for an initrd 25 <2> DEFAULT_BAUD equ 9600 ; Default baud rate for serial port 26 <2> BAUD_DIVISOR equ 115200 ; Serial port parameter 27 <2> MAX_FKEYS equ 12 ; Number of F-key help files 28 <2> 29 <2> ; 30 <2> ; log2(Max filename size Including final null) 31 <2> ; 32 <2> FILENAME_MAX_LG2 equ 8 33 <2> FILENAME_MAX equ (1 << FILENAME_MAX_LG2) ; Max mangled filename size 34 <2> 35 <2> ; 36 <2> ; Version number definitinons 37 <2> ; 38 <2> %include "../version.gen" 1 <3> %define VERSION 6.04 2 <3> %define VERSION_STR "6.04" 3 <3> %define VERSION_MAJOR 6 4 <3> %define VERSION_MINOR 4 5 <3> %define YEAR 2015 6 <3> %define YEAR_STR "2015" 39 <2> 40 <2> %endif ; _CONFIG_INC 31 <1> %include "layout.inc" 1 <2> ; ----------------------------------------------------------------------- 2 <2> ; 3 <2> ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <2> ; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin 5 <2> ; 6 <2> ; This program is free software; you can redistribute it and/or modify 7 <2> ; it under the terms of the GNU General Public License as published by 8 <2> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ; Bostom MA 02111-1307, USA; either version 2 of the License, or 10 <2> ; (at your option) any later version; incorporated herein by reference. 11 <2> ; 12 <2> ; ----------------------------------------------------------------------- 13 <2> 14 <2> ; 15 <2> ; layout.inc 16 <2> ; 17 <2> ; Memory layout of segments 18 <2> ; 19 <2> 20 <2> ; Default to 16-bit code 21 <2> bits 16 22 <2> 23 <2> ; Memory below 0800h is reserved for the BIOS and the MBR. 24 <2> BSS_START equ 0800h 25 <2> 26 <2> ; Text starts at the load address of 07C00h. 27 <2> TEXT_START equ 7C00h 28 <2> 29 <2> ; 30 <2> ; 16-bit stack layout 31 <2> ; 32 <2> ; PXELINUX: There are apparently some AMI BIOSes in the field which 33 <2> ; put their BEV stack somewhere below 7C00h (and therefore don't 34 <2> ; handle localboot properly), so avoid that immediate memory region. 35 <2> ; The range that is known to be bad is approximately 75E8..7C00; the 36 <2> ; lower bound is tight. 37 <2> ; 38 <2> global STACK_LEN, STACK_TOP, STACK_BASE 39 <2> STACK_LEN equ 4096 40 <2> %if IS_PXELINUX 41 <2> STACK_TOP equ 7000h 42 <2> %else 43 <2> STACK_TOP equ 7c00h 44 <2> %endif 45 <2> STACK_BASE equ STACK_TOP - STACK_LEN 46 <2> 47 <2> ; The secondary BSS section, above the text; we really wish we could 48 <2> ; just make it follow .bcopy32 or hang off the end, 49 <2> ; but it doesn't seem to work that way. 50 <2> LATEBSS_START equ 0B800h 51 <2> 52 <2> ; 53 <2> ; 32-bit stack layout 54 <2> ; 55 <2> STACK32_LEN equ 64*1024 56 <2> 57 <2> section .stack nobits write align=4096 58 0031F000 <2> resb STACK32_LEN 59 <2> 60 <2> ; 61 <2> ; The various sections and their relationship 62 <2> ; 63 <2> ; Use .earlybss for things that MUST be in low memory. 64 <2> section .earlybss nobits write 65 <2> section .config write progbits align=4 66 <2> section .replacestub exec write progbits align=16 67 <2> section .gentextnr exec write nobits align=16 68 <2> section .stack16 write nobits align=16 69 <2> 70 <2> ; Use .bss16 for things that doesn't have to be in low memory; 71 <2> ; .earlybss should be used for things that absolutely have 72 <2> ; to be below 0x7c00. 73 <2> section .bss16 write nobits align=16 74 <2> 75 <2> %if 0 ; IS_PXELINUX 76 <2> ; Warning here: RBFG build 22 randomly overwrites 77 <2> ; memory location [0x5680,0x576c), possibly more. It 78 <2> ; seems that it gets confused and screws up the 79 <2> ; pointer to its own internal packet buffer and starts 80 <2> ; writing a received ARP packet into low memory. 81 <2> section .rbfg write nobits 82 <2> RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet... 83 <2> %endif 84 <2> 85 <2> section .init exec write progbits align=1 86 <2> section .text16 exec write progbits align=1 87 <2> section .textnr exec nowrite progbits align=1 88 <2> section .bcopyxx.text exec nowrite progbits align=16 89 <2> section .bcopyxx.data noexec write progbits align=16 90 <2> section .data16 noexec write progbits align=16 91 <2> 92 <2> section .adv write nobits align=512 93 <2> 94 <2> ; .uibss contains bss data which is guaranteed to be 95 <2> ; safe to clobber during the loading of the image. This 96 <2> ; is because while loading the primary image we will clobber 97 <2> ; the spillover from the last fractional sector load. 98 <2> section .uibss write nobits align=16 99 <2> 100 <2> section .savedata write nobits align=16 101 <2> 102 <2> ; Symbols from linker script 103 <2> %macro SECINFO 1 104 <2> extern __%1_start, __%1_end 105 <2> extern __%1_len, __%1_dwords 106 <2> %endmacro 107 <2> 108 <2> SECINFO bss16 108 <3> extern __%1_start, __%1_end 108 <3> extern __%1_len, __%1_dwords 109 <2> SECINFO uibss 109 <3> extern __%1_start, __%1_end 109 <3> extern __%1_len, __%1_dwords 110 <2> SECINFO config 110 <3> extern __%1_start, __%1_end 110 <3> extern __%1_len, __%1_dwords 111 <2> SECINFO replacestub 111 <3> extern __%1_start, __%1_end 111 <3> extern __%1_len, __%1_dwords 112 <2> SECINFO bcopyxx 112 <3> extern __%1_start, __%1_end 112 <3> extern __%1_len, __%1_dwords 113 <2> 114 <2> SECINFO pm_code 114 <3> extern __%1_start, __%1_end 114 <3> extern __%1_len, __%1_dwords 115 <2> SECINFO high_clear 115 <3> extern __%1_start, __%1_end 115 <3> extern __%1_len, __%1_dwords 116 <2> extern __pm_code_lma 117 <2> 118 <2> SECINFO bss 118 <3> extern __%1_start, __%1_end 118 <3> extern __%1_len, __%1_dwords 119 <2> 120 <2> extern free_high_memory 121 <2> 122 <2> global _start 123 <2> 124 <2> section .text16 125 <2> 126 <2> ; 127 <2> ; Segment assignments in the bottom 640K 128 <2> ; Keep the low-memory footprint as small as possible... overrun is a hard 129 <2> ; failure! 130 <2> ; 131 <2> 132 <2> serial_buf_size equ 4096 ; Should be a power of 2 133 <2> 134 <2> ; 135 <2> ; Transfer buffer segment: guaranteed to be aligned 64K, used for disk I/O 136 <2> ; One symbol for the segment number, one for the absolute address 137 <2> ; 138 <2> extern xfer_buf_seg 139 <2> section .xfer_buf write nobits align=65536 140 <2> global core_xfer_buf:data hidden 141 00010000 <2> core_xfer_buf resb 65536 142 <2> 143 <2> ; 144 <2> ; At the very end, the lowmem heap 145 <2> ; 146 <2> extern __lowmem_heap 147 <2> min_lowmem_heap equ 65536 148 <2> 149 <2> section .text16 32 <1> %include "pmcall.inc" 1 <2> ;; 2 <2> ;; pmcall.inc 3 <2> ;; 4 <2> ;; Macros for the stack frame set up by pm_call, assuming ebp is left 5 <2> ;; as the RM frame pointer. 6 <2> ;; 7 <2> 8 <2> %ifndef PMCALL_INC 9 <2> %define PMCALL_INC 10 <2> 11 <2> %define RM_GS word [ebp] 12 <2> %define RM_FS word [ebp+2] 13 <2> %define RM_ES word [ebp+4] 14 <2> %define RM_DS word [ebp+6] 15 <2> 16 <2> %define RM_EDI dword [ebp+8] 17 <2> %define RM_DI word [ebp+8] 18 <2> %define RM_HDI word [ebp+10] 19 <2> %define RM_DIL byte [ebp+8] 20 <2> %define RM_DIH byte [ebp+9] 21 <2> 22 <2> %define RM_ESI dword [ebp+12] 23 <2> %define RM_SI word [ebp+12] 24 <2> %define RM_HSI word [ebp+14] 25 <2> %define RM_SIL byte [ebp+12] 26 <2> %define RM_SIH byte [ebp+13] 27 <2> 28 <2> %define RM_EBP dword [ebp+16] 29 <2> %define RM_BP word [ebp+16] 30 <2> %define RM_HBP word [ebp+18] 31 <2> %define RM_BPL byte [ebp+16] 32 <2> %define RM_BPH byte [ebp+17] 33 <2> 34 <2> %define RM_EBX dword [ebp+24] 35 <2> %define RM_BX word [ebp+24] 36 <2> %define RM_HBX word [ebp+26] 37 <2> %define RM_BL byte [ebp+24] 38 <2> %define RM_BH byte [ebp+25] 39 <2> 40 <2> %define RM_EDX dword [ebp+28] 41 <2> %define RM_DX word [ebp+28] 42 <2> %define RM_HDX word [ebp+30] 43 <2> %define RM_DL byte [ebp+28] 44 <2> %define RM_DH byte [ebp+29] 45 <2> 46 <2> %define RM_ECX dword [ebp+32] 47 <2> %define RM_CX word [ebp+32] 48 <2> %define RM_HCX word [ebp+34] 49 <2> %define RM_CL byte [ebp+32] 50 <2> %define RM_CH byte [ebp+33] 51 <2> 52 <2> %define RM_EAX dword [ebp+36] 53 <2> %define RM_AX word [ebp+36] 54 <2> %define RM_HAX word [ebp+38] 55 <2> %define RM_AL byte [ebp+36] 56 <2> %define RM_AH byte [ebp+37] 57 <2> 58 <2> %define RM_EFLAGS dword [ebp+40] 59 <2> %define RM_FLAGS word [ebp+40] 60 <2> %define RM_HFLAGS word [ebp+42] 61 <2> %define RM_FLAGSL byte [ebp+40] 62 <2> %define RM_FLAGSH byte [ebp+41] 63 <2> 64 <2> ; Convenience macro to call a PM function 65 <2> %macro pm_call 1 66 <2> push dword %1 67 <2> call _pm_call 68 <2> %endmacro 69 <2> 70 <2> %endif ; PMCALL_INC 33 <1> %include "extern.inc" 1 <2> ; 2 <2> ; extern.inc 3 <2> ; 4 <2> ; Prototypes for external functions 5 <2> 6 <2> %ifndef EXTERN_INC 7 <2> %define EXTERN_INC 8 <2> 9 <2> ; rllpack.c 10 <2> extern rllpack, rllunpack 11 <2> 12 <2> ; hello.c 13 <2> extern hello 14 <2> 15 <2> ; elflink/load_env32.c 16 <2> extern load_env32, pm_env32_run 17 <2> 18 <2> extern mp1, mp2, mp3, mp4, mp5 19 <2> 20 <2> extern hexdump 21 <2> 22 <2> extern mem_init 23 <2> 24 <2> ; fs.c 25 <2> extern pm_fs_init 26 <2> extern SectorSize, SectorShift 27 <2> 28 <2> ; chdir.c 29 <2> extern pm_realpath 30 <2> 31 <2> ; readdir.c 32 <2> extern opendir, readdir, closedir 33 <2> 34 <2> ; idle.c 35 <2> extern __idle 36 <2> 37 <2> %ifdef DEBUG 38 <2> ; debug.c 39 <2> extern pm_debug_msg 40 <2> 41 <2> %macro dprint 1+ 42 <2> push ax 43 <2> call %%fwd 44 <2> db %1 45 <2> db 0 46 <2> %%fwd: pop ax 47 <2> pm_call pm_debug_msg 48 <2> pop ax 49 <2> %endmacro 50 <2> %else 51 <2> %macro dprint 1+ 52 <2> %endmacro 53 <2> %endif 54 <2> 55 <2> %if IS_PXELINUX 56 <2> ; pxe.c 57 <2> extern unload_pxe, reset_pxe 58 <2> %endif 59 <2> 60 <2> ; plaincon.c 61 <2> extern pm_writechr 62 <2> 63 <2> ; cleanup.c 64 <2> extern cleanup_hardware 65 <2> 66 <2> ; writestr.c 67 <2> extern pm_writestr, crlf 68 <2> 69 <2> ; writehex.c 70 <2> extern pm_writehex2, pm_writehex4, pm_writehex8 71 <2> 72 <2> ; graphics.c 73 <2> extern syslinux_force_text_mode, vgashowcursor, vgahidecursor, pm_using_vga 74 <2> 75 <2> ; conio.c 76 <2> extern pm_pollchar, pm_write_serial, pm_serialcfg 77 <2> 78 <2> ; font.c 79 <2> extern pm_getchar, pm_adjust_screen, pm_userfont 80 <2> 81 <2> %endif ; EXTERN_INC 34 <1> %include "kernel.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <2> ;; 5 <2> ;; This program is free software; you can redistribute it and/or modify 6 <2> ;; it under the terms of the GNU General Public License as published by 7 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 9 <2> ;; (at your option) any later version; incorporated herein by reference. 10 <2> ;; 11 <2> ;; ----------------------------------------------------------------------- 12 <2> 13 <2> ;; 14 <2> ;; kernel.inc 15 <2> ;; 16 <2> ;; Header file for the kernel interface definitions 17 <2> ;; 18 <2> 19 <2> %ifndef _KERNEL_INC 20 <2> %define _KERNEL_INC 21 <2> 22 <2> ;; 23 <2> ;; Structure of the real_mode_seg 24 <2> ;; 25 <2> 26 <2> struc real_mode_seg_t 27 00000000 <2> resb 20h-($-$$) ; org 20h 28 00000020 <2> kern_cmd_magic resw 1 ; 0020 Magic # for command line 29 00000022 <2> kern_cmd_offset resw 1 ; 0022 Offset for kernel command line 30 00000024 <2> resb 497-($-$$) ; org 497d 31 000001F1 <2> bs_setupsecs resb 1 ; 01F1 Sectors for setup code (0 -> 4) 32 000001F2 <2> bs_rootflags resw 1 ; 01F2 Root readonly flag 33 000001F4 <2> bs_syssize resw 1 ; 01F4 34 000001F6 <2> bs_swapdev resw 1 ; 01F6 Swap device (obsolete) 35 000001F8 <2> bs_ramsize resw 1 ; 01F8 Ramdisk flags, formerly ramdisk size 36 000001FA <2> bs_vidmode resw 1 ; 01FA Video mode 37 000001FC <2> bs_rootdev resw 1 ; 01FC Root device 38 000001FE <2> bs_bootsign resw 1 ; 01FE Boot sector signature (0AA55h) 39 00000200 <2> su_jump resb 1 ; 0200 0EBh 40 00000201 <2> su_jump2 resb 1 ; 0201 Size of following header 41 00000202 <2> su_header resd 1 ; 0202 New setup code: header 42 00000206 <2> su_version resw 1 ; 0206 See linux/arch/i386/boot/setup.S 43 00000208 <2> su_switch resw 1 ; 0208 44 0000020A <2> su_setupseg resw 1 ; 020A 45 0000020C <2> su_startsys resw 1 ; 020C 46 0000020E <2> su_kver resw 1 ; 020E Kernel version pointer 47 00000210 <2> su_loader resb 1 ; 0210 Loader ID 48 00000211 <2> su_loadflags resb 1 ; 0211 Load high flag 49 00000212 <2> su_movesize resw 1 ; 0212 50 00000214 <2> su_code32start resd 1 ; 0214 Start of code loaded high 51 00000218 <2> su_ramdiskat resd 1 ; 0218 Start of initial ramdisk 52 0000021C <2> su_ramdisklen resd 1 ; 021C Length of initial ramdisk 53 00000220 <2> su_bsklugeoffs resw 1 ; 0220 54 00000222 <2> su_bsklugeseg resw 1 ; 0222 55 00000224 <2> su_heapend resw 1 ; 0224 56 00000226 <2> su_pad1 resw 1 ; 0226 57 00000228 <2> su_cmd_line_ptr resd 1 ; 0228 58 0000022C <2> su_ramdisk_max resd 1 ; 022C 59 00000230 <2> resb (0f800h-12)-($-$$) 60 <2> linux_stack equ $ ; F7F4 61 0000F7F4 <2> linux_fdctab resb 12 62 <2> cmd_line_here equ $ ; F800 Should be out of the way 63 <2> endstruc 64 <2> 65 <2> ; 66 <2> ; Old kernel command line signature 67 <2> ; 68 <2> CMD_MAGIC equ 0A33Fh ; Command line magic 69 <2> 70 <2> ; 71 <2> ; If we're loading the command line old-style, we need a smaller 72 <2> ; heap. 73 <2> ; 74 <2> old_cmd_line_here equ 9800h 75 <2> old_max_cmd_len equ 2047 76 <2> old_linux_fdctab equ old_cmd_line_here-12 77 <2> old_linux_stack equ old_linux_fdctab 78 <2> 79 <2> ; 80 <2> ; Magic number of su_header field 81 <2> ; 82 <2> HEADER_ID equ 'HdrS' ; HdrS (in littleendian hex) 83 <2> 84 <2> ; 85 <2> ; Flags for the su_loadflags field 86 <2> ; 87 <2> LOAD_HIGH equ 01h ; Large kernel, load high 88 <2> QUIET_FLAG equ 20h ; Quiet the kernel 89 <2> KEEP_SEGMENTS equ 40h ; Don't reload segments 90 <2> CAN_USE_HEAP equ 80h ; Boot loader reports heap size 91 <2> 92 <2> ; 93 <2> ; ID codes for various modules 94 <2> ; 95 <2> syslinux_id equ 031h ; 3 = SYSLINUX family; 1 = SYSLINUX 96 <2> pxelinux_id equ 032h ; 3 = SYSLINUX family; 2 = PXELINUX 97 <2> isolinux_id equ 033h ; 3 = SYSLINUX family; 3 = ISOLINUX 98 <2> extlinux_id equ 034h ; 3 = SYSLINUX family; 4 = EXTLINUX 99 <2> 100 <2> ; 101 <2> ; Types of vkernels 102 <2> ; 103 <2> VK_LOCALBOOT equ -1 ; localboot (no actual kernel loaded) 104 <2> VK_KERNEL equ 0 ; Choose by filename 105 <2> VK_LINUX equ 1 ; Linux kernel image 106 <2> VK_BOOT equ 2 ; Boot sector 107 <2> VK_BSS equ 3 ; BSS boot sector 108 <2> VK_PXE equ 4 ; PXE NBP 109 <2> VK_FDIMAGE equ 5 ; Floppy disk image 110 <2> VK_COMBOOT equ 6 ; COMBOOT image 111 <2> VK_COM32 equ 7 ; COM32 image 112 <2> VK_CONFIG equ 8 ; Configuration file 113 <2> VK_TYPES equ 9 ; Number of VK types 114 <2> 115 <2> %endif ; _KERNEL_INC 35 <1> %include "bios.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <2> ;; 5 <2> ;; This program is free software; you can redistribute it and/or modify 6 <2> ;; it under the terms of the GNU General Public License as published by 7 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 9 <2> ;; (at your option) any later version; incorporated herein by reference. 10 <2> ;; 11 <2> ;; ----------------------------------------------------------------------- 12 <2> 13 <2> ;; 14 <2> ;; bios.inc 15 <2> ;; 16 <2> ;; Header file for the BIOS data structures etc. 17 <2> ;; 18 <2> 19 <2> %ifndef _BIOS_INC 20 <2> %define _BIOS_INC 21 <2> 22 <2> ; Interrupt vectors 23 <2> absolute 4*1Ch 24 00000070 <2> BIOS_timer_hook resd 1 25 <2> 26 <2> absolute 4*1Eh 27 <2> fdctab equ $ 28 00000078 <2> fdctab1 resw 1 29 0000007A <2> fdctab2 resw 1 30 <2> 31 <2> absolute 0400h 32 00000400 <2> serial_base resw 4 ; Base addresses for 4 serial ports 33 <2> absolute 0413h 34 00000413 <2> BIOS_fbm resw 1 ; Free Base Memory (kilobytes) 35 <2> absolute 0462h 36 00000462 <2> BIOS_page resb 1 ; Current video page 37 <2> absolute 046Ch 38 0000046C <2> BIOS_timer resw 1 ; Timer ticks 39 <2> absolute 0472h 40 00000472 <2> BIOS_magic resw 1 ; BIOS reset magic 41 <2> absolute 0484h 42 00000484 <2> BIOS_vidrows resb 1 ; Number of screen rows 43 <2> 44 <2> %endif ; _BIOS_INC 36 <1> %include "tracers.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved 4 <2> ;; 5 <2> ;; This program is free software; you can redistribute it and/or modify 6 <2> ;; it under the terms of the GNU General Public License as published by 7 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 9 <2> ;; (at your option) any later version; incorporated herein by reference. 10 <2> ;; 11 <2> ;; ----------------------------------------------------------------------- 12 <2> 13 <2> ;; 14 <2> ;; tracers.inc 15 <2> ;; 16 <2> ;; Debugging tracers 17 <2> ;; 18 <2> 19 <2> %ifndef _TRACERS_INC 20 <2> %define _TRACERS_INC 21 <2> 22 <2> ; Note: The Makefile builds one version with DEBUG_MESSAGES automatically. 23 <2> ; %define DEBUG_TRACERS 1 ; Uncomment to get debugging tracers 24 <2> ; %define DEBUG_MESSAGES ; Uncomment to get debugging messages 25 <2> 26 <2> %ifdef DEBUG_TRACERS 27 <2> 28 <2> %macro TRACER 1 29 <2> call debug_tracer 30 <2> db %1 31 <2> %endmacro 32 <2> 33 <2> %else ; DEBUG_TRACERS 34 <2> 35 <2> %macro TRACER 1 36 <2> %endmacro 37 <2> 38 <2> %endif ; DEBUG_TRACERS 39 <2> 40 <2> %endif ; _TRACERS_INC 37 <1> %include "stack.inc" 1 <2> ; ----------------------------------------------------------------------- 2 <2> ; 3 <2> ; Copyright 2005-2008 H. Peter Anvin - All Rights Reserved 4 <2> ; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin 5 <2> ; 6 <2> ; This program is free software; you can redistribute it and/or modify 7 <2> ; it under the terms of the GNU General Public License as published by 8 <2> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <2> ; (at your option) any later version; incorporated herein by reference. 11 <2> ; 12 <2> ; ----------------------------------------------------------------------- 13 <2> 14 <2> ; 15 <2> ; stack.inc 16 <2> ; 17 <2> ; How to reset the stack pointer 18 <2> ; 19 <2> 20 <2> %ifndef _STACK_INC 21 <2> %define _STACK_INC 22 <2> 23 <2> ; 24 <2> ; This macro resets the stack pointer (including SS), and sets 25 <2> ; DS == ES == 0, interrupts on, DF = 0. 26 <2> ; 27 <2> ; It takes a 16-bit register that can be safely clobbered as parameter. 28 <2> ; 29 <2> %macro RESET_STACK_AND_SEGS 1 30 <2> xor %1,%1 31 <2> mov ds,%1 32 <2> mov es,%1 33 <2> lss esp,[BaseStack] 34 <2> mov dword [PMESP],__stack_end ; Reset PM stack 35 <2> sti 36 <2> cld 37 <2> %endmacro 38 <2> 39 <2> section .data16 40 <2> alignz 4 41 <2> global BaseStack:data hidden 42 00009440 607B0000 <2> BaseStack dd StackHome ; ESP of the "home" stack pointer 43 00009444 0000 <2> dw 0 ; SS of the "home" stack pointer 44 <2> 45 <2> section .text16 46 <2> 47 <2> %endif ; _STACK_INC 38 <1> %include "io.inc" 1 <2> ;; ----------------------------------------------------------------------- 2 <2> ;; 3 <2> ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <2> ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin 5 <2> ;; 6 <2> ;; This program is free software; you can redistribute it and/or modify 7 <2> ;; it under the terms of the GNU General Public License as published by 8 <2> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 <2> ;; Boston MA 02111-1307, USA; either version 2 of the License, or 10 <2> ;; (at your option) any later version; incorporated herein by reference. 11 <2> ;; 12 <2> ;; ----------------------------------------------------------------------- 13 <2> 14 <2> ;; 15 <2> ;; io.inc 16 <2> ;; 17 <2> ;; I/O related macros 18 <2> ;; 19 <2> 20 <2> %ifndef _IO_INC 21 <2> %define _IO_INC 22 <2> 23 <2> %define IO_DELAY_PORT 80h ; Invalid port (we hope!) 24 <2> 25 <2> %macro io_delay 0.nolist 26 <2> out IO_DELAY_PORT,al 27 <2> out IO_DELAY_PORT,al 28 <2> %endmacro 29 <2> 30 <2> %macro slow_out 2.nolist 31 <2> out %1,%2 32 <2> io_delay 33 <2> %endmacro 34 <2> 35 <2> %endif ; _IO_INC 39 <1> 40 <1> %endif ; _HEAD_INC 27 28 ; 29 ; Some semi-configurable constants... change on your own risk. 30 ; 31 my_id equ syslinux_id 32 33 section .rodata 34 alignz 4 35 ROOT_FS_OPS: 36 extern vfat_fs_ops 37 00110320 [00000000] dd vfat_fs_ops 38 extern ext2_fs_ops 39 00110324 [00000000] dd ext2_fs_ops 40 extern ntfs_fs_ops 41 00110328 [00000000] dd ntfs_fs_ops 42 extern xfs_fs_ops 43 0011032C [00000000] dd xfs_fs_ops 44 extern btrfs_fs_ops 45 00110330 [00000000] dd btrfs_fs_ops 46 extern ufs_fs_ops 47 00110334 [00000000] dd ufs_fs_ops 48 00110338 00000000 dd 0 49 50 %include "diskfs.inc" 1 <1> ; -*- fundamental -*- (asm-mode sucks) 2 <1> ; ----------------------------------------------------------------------- 3 <1> ; 4 <1> ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 5 <1> ; Copyright 2009-2011 Intel Corporation; author: H. Peter Anvin 6 <1> ; 7 <1> ; This program is free software; you can redistribute it and/or modify 8 <1> ; it under the terms of the GNU General Public License as published by 9 <1> ; the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 10 <1> ; Boston MA 02110-1301, USA; either version 2 of the License, or 11 <1> ; (at your option) any later version; incorporated herein by reference. 12 <1> ; 13 <1> ; ----------------------------------------------------------------------- 14 <1> 15 <1> ; 16 <1> ; diskfs.inc 17 <1> ; 18 <1> ; Common code for conventional disk-based filesystems 19 <1> ; 20 <1> 21 <1> ; 22 <1> ; Some semi-configurable constants... change on your own risk. 23 <1> ; 24 <1> NULLFILE equ 0 ; Null character == empty filename 25 <1> NULLOFFSET equ 0 ; Position in which to look 26 <1> retry_count equ 16 ; How patient are we with the disk? 27 <1> %assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top 28 <1> LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with 29 <1> 30 <1> ; This indicates the general format of the last few bytes in the boot sector 31 <1> BS_MAGIC_VER equ 0x1b << 9 32 <1> 33 <1> MIN_SECTOR_SHIFT equ 9 34 <1> MIN_SECTOR_SIZE equ (1 << MIN_SECTOR_SHIFT) 35 <1> 36 <1> ; --------------------------------------------------------------------------- 37 <1> ; BEGIN CODE 38 <1> ; --------------------------------------------------------------------------- 39 <1> 40 <1> ; 41 <1> ; Memory below this point is reserved for the BIOS and the MBR 42 <1> ; 43 <1> section .earlybss 44 <1> global trackbuf:data hidden 45 <1> trackbufsize equ 8192 46 00001000 <1> trackbuf resb trackbufsize ; Track buffer goes here 47 <1> ; ends at 2800h 48 <1> 49 <1> ; 50 <1> ; Common bootstrap code for disk-based derivatives 51 <1> ; 52 <1> %include "diskstart.inc" 1 <2> ; ----------------------------------------------------------------------- 2 <2> ; 3 <2> ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <2> ; Copyright 2009-2011 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., 51 Franklin St, Fifth Floor, 9 <2> ; Boston MA 02110-1301, 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> ; diskstart.inc 16 <2> ; 17 <2> ; Common early-bootstrap code for harddisk-based Syslinux derivatives. 18 <2> ; 19 <2> 20 <2> Sect1Ptr0_VAL equ 0xdeadbeef 21 <2> Sect1Ptr1_VAL equ 0xfeedface 22 <2> 23 <2> %include "diskboot.inc" 1 <3> ; ----------------------------------------------------------------------- 2 <3> ; 3 <3> ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved 4 <3> ; Copyright 2009-2011 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., 51 Franklin St, Fifth Floor, 9 <3> ; Boston MA 02110-1301, 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> ; diskboot.inc 16 <3> ; 17 <3> ; Common boot sector code for harddisk-based Syslinux derivatives. 18 <3> ; 19 <3> ; Requires macros z[bwd], labels ldlinux_ent, ldlinux_magic, ldlinux_sys 20 <3> ; and constants BS_MAGIC_VER, LDLINUX_MAGIC, retry_count, Sect1Ptr[01]_VAL, 21 <3> ; STACK_TOP 22 <3> ; 23 <3> 24 <3> section .init 25 <3> ; 26 <3> ; Some of the things that have to be saved very early are saved 27 <3> ; "close" to the initial stack pointer offset, in order to 28 <3> ; reduce the code size... 29 <3> ; 30 <3> 31 <3> global StackBuf, PartInfo, Hidden, OrigESDI, DriveNumber 32 <3> global OrigFDCTabPtr 33 <3> StackBuf equ STACK_TOP-44-92 ; Start the stack here (grow down - 4K) 34 <3> PartInfo equ StackBuf 35 <3> .mbr equ PartInfo 36 <3> .gptlen equ PartInfo+16 37 <3> .gpt equ PartInfo+20 38 <3> FloppyTable equ PartInfo+76 39 <3> ; Total size of PartInfo + FloppyTable == 76+16 = 92 bytes 40 <3> Hidden equ StackBuf-24 ; Partition offset (qword) 41 <3> OrigFDCTabPtr equ StackBuf-16 ; Original FDC table 42 <3> OrigDSSI equ StackBuf-12 ; DS:SI -> partinfo 43 <3> OrigESDI equ StackBuf-8 ; ES:DI -> $PnP structure 44 <3> DriveNumber equ StackBuf-4 ; Drive number 45 <3> StackHome equ Hidden ; The start of the canonical stack 46 <3> 47 <3> ; 48 <3> ; Primary entry point. Tempting as though it may be, we can't put the 49 <3> ; initial "cli" here; the jmp opcode in the first byte is part of the 50 <3> ; "magic number" (using the term very loosely) for the DOS superblock. 51 <3> ; 52 <3> bootsec equ $ 53 00007C00 EB58 <3> _start: jmp short start ; 2 bytes 54 00007C02 90 <3> nop ; 1 byte 55 <3> ; 56 <3> ; "Superblock" follows -- it's in the boot sector, so it's already 57 <3> ; loaded and ready for us 58 <3> ; 59 00007C03 5359534C494E5558 <3> bsOemName db MY_NAME ; The SYS command sets this, so... 60 <3> zb 8-($-bsOemName) 61 <3> 62 <3> ; 63 <3> ; These are the fields we actually care about. We end up expanding them 64 <3> ; all to dword size early in the code, so generate labels for both 65 <3> ; the expanded and unexpanded versions. 66 <3> ; 67 <3> %macro superb 1 68 <3> bx %+ %1 equ SuperInfo+($-superblock)*8+4 69 <3> bs %+ %1 equ $ 70 <3> zb 1 71 <3> %endmacro 72 <3> %macro superw 1 73 <3> bx %+ %1 equ SuperInfo+($-superblock)*8 74 <3> bs %+ %1 equ $ 75 <3> zw 1 76 <3> %endmacro 77 <3> %macro superd 1 78 <3> bx %+ %1 equ $ ; no expansion for dwords 79 <3> bs %+ %1 equ $ 80 <3> zd 1 81 <3> %endmacro 82 <3> superblock equ $ 83 <3> superw BytesPerSec 83 <4> bx %+ %1 equ SuperInfo+($-superblock)*8 83 <4> bs %+ %1 equ $ 83 00007C0B 0000 <4> zw 1 84 <3> superb SecPerClust 84 <4> bx %+ %1 equ SuperInfo+($-superblock)*8+4 84 <4> bs %+ %1 equ $ 84 00007C0D 00 <4> zb 1 85 <3> superw ResSectors 85 <4> bx %+ %1 equ SuperInfo+($-superblock)*8 85 <4> bs %+ %1 equ $ 85 00007C0E 0000 <4> zw 1 86 <3> superb FATs 86 <4> bx %+ %1 equ SuperInfo+($-superblock)*8+4 86 <4> bs %+ %1 equ $ 86 00007C10 00 <4> zb 1 87 <3> superw RootDirEnts 87 <4> bx %+ %1 equ SuperInfo+($-superblock)*8 87 <4> bs %+ %1 equ $ 87 00007C11 0000 <4> zw 1 88 <3> superw Sectors 88 <4> bx %+ %1 equ SuperInfo+($-superblock)*8 88 <4> bs %+ %1 equ $ 88 00007C13 0000 <4> zw 1 89 <3> superb Media 89 <4> bx %+ %1 equ SuperInfo+($-superblock)*8+4 89 <4> bs %+ %1 equ $ 89 00007C15 00 <4> zb 1 90 <3> superw FATsecs 90 <4> bx %+ %1 equ SuperInfo+($-superblock)*8 90 <4> bs %+ %1 equ $ 90 00007C16 0000 <4> zw 1 91 <3> superw SecPerTrack 91 <4> bx %+ %1 equ SuperInfo+($-superblock)*8 91 <4> bs %+ %1 equ $ 91 00007C18 0000 <4> zw 1 92 <3> superw Heads 92 <4> bx %+ %1 equ SuperInfo+($-superblock)*8 92 <4> bs %+ %1 equ $ 92 00007C1A 0000 <4> zw 1 93 <3> superinfo_size equ ($-superblock)-1 ; How much to expand 94 <3> superd Hidden 94 <4> bx %+ %1 equ $ 94 <4> bs %+ %1 equ $ 94 00007C1C 00000000 <4> zd 1 95 <3> superd HugeSectors 95 <4> bx %+ %1 equ $ 95 <4> bs %+ %1 equ $ 95 00007C20 00000000 <4> zd 1 96 <3> ; 97 <3> ; This is as far as FAT12/16 and FAT32 are consistent 98 <3> ; 99 <3> ; FAT12/16 need 26 more bytes, 100 <3> ; FAT32 need 54 more bytes 101 <3> ; 102 <3> superblock_len_fat16 equ $-superblock+26 103 <3> superblock_len_fat32 equ $-superblock+54 104 00007C24 00 <3> zb 54 ; Maximum needed size 105 <3> superblock_max equ $-superblock 106 <3> 107 <3> SecPerClust equ bxSecPerClust 108 <3> 109 <3> ; 110 <3> ; Note we don't check the constraints above now; we did that at install 111 <3> ; time (we hope!) 112 <3> ; 113 <3> start: 114 00007C5A FA <3> cli ; No interrupts yet, please 115 00007C5B FC <3> cld ; Copy upwards 116 <3> ; 117 <3> ; Set up the stack 118 <3> ; 119 00007C5C 31C9 <3> xor cx,cx 120 00007C5E 8ED1 <3> mov ss,cx 121 00007C60 BC767B <3> mov sp,StackBuf-2 ; Just below BSS (-2 for alignment) 122 00007C63 52 <3> push dx ; Save drive number (in DL) 123 00007C64 06 <3> push es ; Save initial ES:DI -> $PnP pointer 124 00007C65 57 <3> push di 125 00007C66 1E <3> push ds ; Save original DS:SI -> partinfo 126 00007C67 56 <3> push si 127 00007C68 8EC1 <3> mov es,cx 128 <3> 129 <3> ; 130 <3> ; DS:SI may contain a partition table entry and possibly a GPT entry. 131 <3> ; Preserve it for us. This saves 56 bytes of the GPT entry, which is 132 <3> ; currently the maximum we care about. Total is 76 bytes. 133 <3> ; 134 00007C6A B126 <3> mov cl,(16+4+56)/2 ; Save partition info 135 00007C6C BF787B <3> mov di,PartInfo 136 00007C6F F3A5 <3> rep movsw ; This puts CX back to zero 137 <3> 138 00007C71 8ED9 <3> mov ds,cx ; Now we can initialize DS... 139 <3> 140 <3> ; 141 <3> ; Now sautee the BIOS floppy info block to that it will support decent- 142 <3> ; size transfers; the floppy block is 11 bytes and is stored in the 143 <3> ; INT 1Eh vector (brilliant waste of resources, eh?) 144 <3> ; 145 <3> ; Of course, if BIOSes had been properly programmed, we wouldn't have 146 <3> ; had to waste precious space with this code. 147 <3> ; 148 00007C73 BB7800 <3> mov bx,fdctab 149 00007C76 0FB437 <3> lfs si,[bx] ; FS:SI -> original fdctab 150 00007C79 0FA0 <3> push fs ; Save on stack in case we need to bail 151 00007C7B 56 <3> push si 152 <3> 153 <3> ; Save the old fdctab even if hard disk so the stack layout 154 <3> ; is the same. The instructions above do not change the flags 155 00007C7C 20D2 <3> and dl,dl ; If floppy disk (00-7F), assume no 156 <3> ; partition table 157 00007C7E 781B <3> js harddisk 158 <3> 159 <3> floppy: 160 00007C80 31C0 <3> xor ax,ax 161 00007C82 B106 <3> mov cl,6 ; 12 bytes (CX == 0) 162 <3> ; es:di -> FloppyTable already 163 <3> ; This should be safe to do now, interrupts are off... 164 00007C84 893F <3> mov [bx],di ; FloppyTable 165 00007C86 894702 <3> mov [bx+2],ax ; Segment 0 166 00007C89 F364A5 <3> fs rep movsw ; Faster to move words 167 00007C8C 8A0E[1800] <3> mov cl,[bsSecPerTrack] ; Patch the sector count 168 00007C90 884DF8 <3> mov [di-12+4],cl 169 <3> 170 00007C93 50 <3> push ax ; Partition offset == 0 171 00007C94 50 <3> push ax 172 00007C95 50 <3> push ax 173 00007C96 50 <3> push ax 174 <3> 175 00007C97 CD13 <3> int 13h ; Some BIOSes need this 176 <3> ; Using xint13 costs +1B 177 00007C99 EB62 <3> jmp short not_harddisk 178 <3> ; 179 <3> ; The drive number and possibly partition information was passed to us 180 <3> ; by the BIOS or previous boot loader (MBR). Current "best practice" is to 181 <3> ; trust that rather than what the superblock contains. 182 <3> ; 183 <3> ; Note: di points to beyond the end of PartInfo 184 <3> ; Note: false negatives might slip through the handover area's sanity checks, 185 <3> ; if the region is very close (less than a paragraph) to 186 <3> ; PartInfo ; no false positives are possible though 187 <3> ; 188 <3> harddisk: 189 00007C9B 8B55AA <3> mov dx,[di-76-10] ; Original DS 190 00007C9E 8B75A8 <3> mov si,[di-76-12] ; Original SI 191 00007CA1 C1EE04 <3> shr si,4 192 00007CA4 01F2 <3> add dx,si 193 00007CA6 83FA4F <3> cmp dx,4fh ; DS:SI < 50h:0 (BDA or IVT) ? 194 00007CA9 7631 <3> jbe .no_partition 195 00007CAB 81FAB207 <3> cmp dx,(PartInfo-75)>>4 ; DS:SI in overwritten memory? 196 00007CAF 732B <3> jae .no_partition 197 00007CB1 F645B47F <3> test byte [di-76],7Fh ; Sanity check: "active flag" should 198 00007CB5 7525 <3> jnz .no_partition ; be 00 or 80 199 00007CB7 384DB8 <3> cmp [di-76+4],cl ; Sanity check: partition type != 0 200 00007CBA 7420 <3> je .no_partition 201 00007CBC 663D21475054 <3> cmp eax,'!GPT' ; !GPT signature? 202 00007CC2 7510 <3> jne .mbr 203 00007CC4 807DB8ED <3> cmp byte [di-76+4],0EDh ; Synthetic GPT partition entry? 204 00007CC8 750A <3> jne .mbr 205 <3> .gpt: ; GPT-style partition info 206 00007CCA 66FF75EC <3> push dword [di-76+20+36] 207 00007CCE 66FF75E8 <3> push dword [di-76+20+32] 208 00007CD2 EB0F <3> jmp .gotoffs 209 <3> .mbr: ; MBR-style partition info 210 00007CD4 51 <3> push cx ; Upper half partition offset == 0 211 00007CD5 51 <3> push cx 212 00007CD6 66FF75BC <3> push dword [di-76+8] ; Partition offset (dword) 213 00007CDA EB07 <3> jmp .gotoffs 214 <3> .no_partition: 215 <3> ; 216 <3> ; No partition table given... assume that the Hidden field in the boot sector 217 <3> ; tells the truth (in particular, is zero if this is an unpartitioned disk.) 218 <3> ; 219 00007CDC 51 <3> push cx 220 00007CDD 51 <3> push cx 221 00007CDE 66FF36[1C00] <3> push dword [bsHidden] 222 <3> .gotoffs: 223 <3> ; 224 <3> ; Get disk drive parameters (don't trust the superblock.) Don't do this for 225 <3> ; floppy drives -- INT 13:08 on floppy drives will (may?) return info about 226 <3> ; what the *drive* supports, not about the *media*. Fortunately floppy disks 227 <3> ; tend to have a fixed, well-defined geometry which is stored in the superblock. 228 <3> ; 229 <3> ; DL == drive # still 230 00007CE3 B408 <3> mov ah,08h 231 00007CE5 E8E900 <3> call xint13 232 00007CE8 7213 <3> jc no_driveparm 233 00007CEA 20E4 <3> and ah,ah 234 00007CEC 750F <3> jnz no_driveparm 235 00007CEE C1EA08 <3> shr dx,8 236 00007CF1 42 <3> inc dx ; Contains # of heads - 1 237 00007CF2 8916[1A00] <3> mov [bsHeads],dx 238 00007CF6 83E13F <3> and cx,3fh 239 00007CF9 890E[1800] <3> mov [bsSecPerTrack],cx 240 <3> no_driveparm: 241 <3> not_harddisk: 242 <3> ; 243 <3> ; Ready to enable interrupts, captain 244 <3> ; 245 00007CFD FB <3> sti 246 <3> 247 <3> ; 248 <3> ; Do we have EBIOS (EDD)? 249 <3> ; 250 <3> eddcheck: 251 00007CFE BBAA55 <3> mov bx,55AAh 252 00007D01 B441 <3> mov ah,41h ; EDD existence query 253 00007D03 E8CB00 <3> call xint13 254 00007D06 7210 <3> jc .noedd 255 00007D08 81FB55AA <3> cmp bx,0AA55h 256 00007D0C 750A <3> jne .noedd 257 00007D0E F6C101 <3> test cl,1 ; Extended disk access functionality set 258 00007D11 7405 <3> jz .noedd 259 <3> ; 260 <3> ; We have EDD support... 261 <3> ; 262 00007D13 C606[4601]00 <3> mov byte [getonesec.jmp+1],(getonesec_ebios-(getonesec.jmp+2)) 263 <3> .noedd: 264 <3> 265 <3> ; 266 <3> ; Load the first sector of LDLINUX.SYS; this used to be all proper 267 <3> ; with parsing the superblock and root directory; it doesn't fit 268 <3> ; together with EBIOS support, unfortunately. 269 <3> ; 270 <3> Sect1Load: 271 00007D18 66B8EFBEADDE <3> mov eax,strict dword Sect1Ptr0_VAL ; 0xdeadbeef 272 <3> Sect1Ptr0 equ $-4 273 00007D1E 66BACEFAEDFE <3> mov edx,strict dword Sect1Ptr1_VAL ; 0xfeedface 274 <3> Sect1Ptr1 equ $-4 275 00007D24 BB[0004] <3> mov bx,ldlinux_sys ; Where to load it 276 00007D27 E80E00 <3> call getonesec 277 <3> 278 <3> ; Some modicum of integrity checking 279 00007D2A 66813E[1C04]5A8C3A- <3> cmp dword [ldlinux_magic+4],LDLINUX_MAGIC^HEXDATE 279 00007D32 62 <3> 280 00007D33 7574 <3> jne kaboom 281 <3> 282 <3> ; Go for it! 283 00007D35 E9F802 <3> jmp ldlinux_ent 284 <3> 285 <3> ; 286 <3> ; getonesec: load a single disk linear sector EDX:EAX into the buffer 287 <3> ; at ES:BX. 288 <3> ; 289 <3> ; This routine assumes CS == DS == SS, and trashes most registers. 290 <3> ; 291 <3> ; Stylistic note: use "xchg" instead of "mov" when the source is a register 292 <3> ; that is dead from that point; this saves space. However, please keep 293 <3> ; the order to dst,src to keep things sane. 294 <3> ; 295 <3> getonesec: 296 00007D38 660306607B <3> add eax,[Hidden] ; Add partition offset 297 00007D3D 661316647B <3> adc edx,[Hidden+4] 298 00007D42 B91000 <3> mov cx,retry_count 299 00007D45 EB2B <3> .jmp: jmp strict short getonesec_cbios 300 <3> 301 <3> ; 302 <3> ; getonesec_ebios: 303 <3> ; 304 <3> ; getonesec implementation for EBIOS (EDD) 305 <3> ; 306 <3> getonesec_ebios: 307 <3> .retry: 308 <3> ; Form DAPA on stack 309 00007D47 6652 <3> push edx 310 00007D49 6650 <3> push eax 311 00007D4B 06 <3> push es 312 00007D4C 53 <3> push bx 313 00007D4D 6A01 <3> push word 1 314 00007D4F 6A10 <3> push word 16 315 00007D51 89E6 <3> mov si,sp 316 00007D53 6660 <3> pushad 317 00007D55 B442 <3> mov ah,42h ; Extended Read 318 00007D57 E87700 <3> call xint13 319 00007D5A 6661 <3> popad 320 00007D5C 8D6410 <3> lea sp,[si+16] ; Remove DAPA 321 00007D5F 7201 <3> jc .error 322 00007D61 C3 <3> ret 323 <3> 324 <3> .error: 325 <3> ; Some systems seem to get "stuck" in an error state when 326 <3> ; using EBIOS. Doesn't happen when using CBIOS, which is 327 <3> ; good, since some other systems get timeout failures 328 <3> ; waiting for the floppy disk to spin up. 329 <3> 330 00007D62 6660 <3> pushad ; Try resetting the device 331 00007D64 31C0 <3> xor ax,ax 332 00007D66 E86800 <3> call xint13 333 00007D69 6661 <3> popad 334 00007D6B E2DA <3> loop .retry ; CX-- and jump if not zero 335 <3> 336 <3> ; Total failure. Try falling back to CBIOS. 337 00007D6D C606[4601]2B <3> mov byte [getonesec.jmp+1],(getonesec_cbios-(getonesec.jmp+2)) 338 <3> 339 <3> ; 340 <3> ; getonesec_cbios: 341 <3> ; 342 <3> ; getlinsec implementation for legacy CBIOS 343 <3> ; 344 <3> getonesec_cbios: 345 <3> .retry: 346 00007D72 6660 <3> pushad 347 <3> 348 00007D74 660FB736[1800] <3> movzx esi,word [bsSecPerTrack] 349 00007D7A 660FB73E[1A00] <3> movzx edi,word [bsHeads] 350 <3> ; 351 <3> ; Dividing by sectors to get (track,sector): we may have 352 <3> ; up to 2^18 tracks, so we need to use 32-bit arithmetric. 353 <3> ; 354 00007D80 66F7F6 <3> div esi 355 00007D83 31C9 <3> xor cx,cx 356 00007D85 87CA <3> xchg cx,dx ; CX <- sector index (0-based) 357 <3> ; EDX <- 0 358 <3> ; eax = track # 359 00007D87 66F7F7 <3> div edi ; Convert track to head/cyl 360 <3> 361 00007D8A 663DFF030000 <3> cmp eax,1023 ; Outside the CHS range? 362 00007D90 7717 <3> ja kaboom 363 <3> 364 <3> ; 365 <3> ; Now we have AX = cyl, DX = head, CX = sector (0-based), 366 <3> ; SI = bsSecPerTrack, ES:BX = data target 367 <3> ; 368 00007D92 C0E406 <3> shl ah,6 ; Because IBM was STOOPID 369 <3> ; and thought 8 bits were enough 370 <3> ; then thought 10 bits were enough... 371 00007D95 41 <3> inc cx ; Sector numbers are 1-based, sigh 372 00007D96 08E1 <3> or cl,ah 373 00007D98 88C5 <3> mov ch,al 374 00007D9A 88D6 <3> mov dh,dl 375 00007D9C B80102 <3> mov ax,0201h ; Read one sector 376 00007D9F E82F00 <3> call xint13 377 00007DA2 6661 <3> popad 378 00007DA4 7201 <3> jc .error 379 00007DA6 C3 <3> ret 380 <3> 381 <3> .error: 382 00007DA7 E2C9 <3> loop .retry 383 <3> ; Fall through to disk_error 384 <3> 385 <3> ; 386 <3> ; kaboom: write a message and bail out. 387 <3> ; 388 <3> %ifdef BINFMT 389 <3> global kaboom 390 <3> %else 391 <3> global kaboom:function hidden 392 <3> %endif 393 <3> disk_error: 394 <3> kaboom: 395 00007DA9 31F6 <3> xor si,si 396 00007DAB 8ED6 <3> mov ss,si 397 00007DAD BC687B <3> mov sp,OrigFDCTabPtr ; Reset stack 398 00007DB0 8EDE <3> mov ds,si ; Reset data segment 399 00007DB2 668F067800 <3> pop dword [fdctab] ; Restore FDC table 400 <3> .patch: ; When we have full code, intercept here 401 00007DB7 BE[DA01] <3> mov si,bailmsg 402 00007DBA AC <3> .loop: lodsb 403 00007DBB 20C0 <3> and al,al 404 00007DBD 7409 <3> jz .done 405 00007DBF B40E <3> mov ah,0Eh ; Write to screen as TTY 406 00007DC1 BB0700 <3> mov bx,0007h ; Attribute 407 00007DC4 CD10 <3> int 10h 408 00007DC6 EBF2 <3> jmp short .loop 409 <3> 410 <3> .done: 411 00007DC8 31C0 <3> xor ax,ax 412 00007DCA CD16 <3> .again: int 16h ; Wait for keypress 413 <3> ; NB: replaced by int 18h if 414 <3> ; chosen at install time.. 415 00007DCC CD19 <3> int 19h ; And try once more to boot... 416 00007DCE F4 <3> .norge: hlt ; If int 19h returned; this is the end 417 00007DCF EBFD <3> jmp short .norge 418 <3> 419 <3> ; 420 <3> ; INT 13h wrapper function 421 <3> ; 422 <3> xint13: 423 00007DD1 8A16747B <3> mov dl,[DriveNumber] 424 00007DD5 06 <3> push es ; ES destroyed by INT 13h AH 08h 425 00007DD6 CD13 <3> int 13h 426 00007DD8 07 <3> pop es 427 00007DD9 C3 <3> ret 428 <3> 429 <3> ; 430 <3> ; Error message on failure 431 <3> ; 432 00007DDA 426F6F74206572726F- <3> bailmsg: db 'Boot error', 0Dh, 0Ah, 0 432 00007DE3 720D0A00 <3> 433 <3> 434 <3> ; This fails if the boot sector overflows 435 00007DE7 00 <3> zb 1F8h-($-$$) 436 <3> 437 00007DF8 FE02B23E <3> bs_magic dd LDLINUX_MAGIC 438 00007DFC 1837 <3> bs_link dw (Sect1Load - bootsec) | BS_MAGIC_VER 439 00007DFE 55AA <3> bootsignature dw 0xAA55 440 <3> 441 <3> ; 442 <3> ; =========================================================================== 443 <3> ; End of boot sector 444 <3> ; =========================================================================== 24 <2> 25 <2> ; =========================================================================== 26 <2> ; Padding after the (minimum) 512-byte boot sector so that the rest of 27 <2> ; the file has aligned sectors, even if they are larger than 512 bytes. 28 <2> ; =========================================================================== 29 <2> 30 <2> section .init 31 00007E00 00 <2> align_pad zb 512 32 <2> 33 <2> ; =========================================================================== 34 <2> ; Start of LDLINUX.SYS 35 <2> ; =========================================================================== 36 <2> 37 <2> LDLINUX_SYS equ ($-$$)+TEXT_START 38 <2> ldlinux_sys: 39 <2> 40 00008000 0D0A5359534C494E55- <2> early_banner db CR, LF, MY_NAME, ' ', VERSION_STR, ' ', 0 40 00008009 5820362E30342000 <2> 41 00008011 0D0A1A <2> db CR, LF, 1Ah ; EOF if we "type" this in DOS 42 <2> 43 00008014 00 <2> alignz 8 44 00008018 FE02B23E <2> ldlinux_magic dd LDLINUX_MAGIC 45 0000801C 5A8C3A62 <2> dd LDLINUX_MAGIC^HEXDATE 46 <2> 47 <2> ; 48 <2> ; This area is patched by the installer. It is found by looking for 49 <2> ; LDLINUX_MAGIC, plus 8 bytes. 50 <2> ; 51 <2> SUBVOL_MAX equ 256 52 <2> CURRENTDIR_MAX equ FILENAME_MAX 53 <2> 54 <2> patch_area: 55 00008020 0000 <2> DataSectors dw 0 ; Number of sectors (not including bootsec) 56 00008022 0000 <2> ADVSectors dw 0 ; Additional sectors for ADVs 57 00008024 00000000 <2> LDLDwords dd 0 ; Total dwords starting at ldlinux_sys, 58 00008028 00000000 <2> CheckSum dd 0 ; Checksum starting at ldlinux_sys 59 <2> ; value = LDLINUX_MAGIC - [sum of dwords] 60 0000802C 7F00 <2> MaxTransfer dw 127 ; Max sectors to transfer 61 0000802E [0680] <2> EPAPtr dw EPA - LDLINUX_SYS ; Pointer to the extended patch area 62 <2> 63 <2> ; 64 <2> ; Extended patch area -- this is in .data16 so it doesn't occupy space in 65 <2> ; the first sector. Use this structure for anything that isn't used by 66 <2> ; the first sector itself. 67 <2> ; 68 <2> section .data16 69 <2> alignz 2 70 <2> EPA: 71 00009446 [9882] <2> ADVSecPtr dw ADVSec0 - LDLINUX_SYS 72 00009448 [1C80] <2> CurrentDirPtr dw CurrentDirName-LDLINUX_SYS ; Current directory name string 73 0000944A 0001 <2> CurrentDirLen dw CURRENTDIR_MAX 74 0000944C [1C81] <2> SubvolPtr dw SubvolName-LDLINUX_SYS 75 0000944E 0001 <2> SubvolLen dw SUBVOL_MAX 76 00009450 [EE85] <2> SecPtrOffset dw SectorPtrs-LDLINUX_SYS 77 00009452 C000 <2> SecPtrCnt dw (SectorPtrsEnd - SectorPtrs)/10 78 <2> 79 <2> ; 80 <2> ; Boot sector patch pointers 81 <2> ; 82 00009454 1A01 <2> Sect1Ptr0Ptr dw Sect1Ptr0 - bootsec ; Pointers to Sector 1 location 83 00009456 2001 <2> Sect1Ptr1Ptr dw Sect1Ptr1 - bootsec 84 00009458 CA01 <2> RAIDPatchPtr dw kaboom.again - bootsec ; Patch to INT 18h in RAID mode 85 <2> 86 <2> ; 87 <2> ; Pointer to the Syslinux banner 88 <2> ; 89 0000945A [2082] <2> BannerPtr dw syslinux_banner - LDLINUX_SYS 90 <2> 91 <2> ; 92 <2> ; Base directory name and subvolume, if applicable. 93 <2> ; 94 <2> %define HAVE_CURRENTDIRNAME 95 <2> global CurrentDirName:data hidden, SubvolName:data hidden 96 0000945C 00 <2> CurrentDirName times CURRENTDIR_MAX db 0 97 0000955C 00 <2> SubvolName times SUBVOL_MAX db 0 98 <2> 99 <2> section .init 100 <2> ldlinux_ent: 101 <2> ; 102 <2> ; Note that some BIOSes are buggy and run the boot sector at 07C0:0000 103 <2> ; instead of 0000:7C00 and the like. We don't want to add anything 104 <2> ; more to the boot sector, so it is written to not assume a fixed 105 <2> ; value in CS, but we don't want to deal with that anymore from now 106 <2> ; on. 107 <2> ; 108 00008030 EA[3504]0000 <2> jmp 0:.next ; Normalize CS:IP 109 00008035 FB <2> .next: sti ; In case of broken INT 13h BIOSes 110 <2> 111 <2> ; 112 <2> ; Tell the user we got this far 113 <2> ; 114 00008036 BE[0004] <2> mov si,early_banner 115 00008039 E88801 <2> call writestr_early 116 <2> 117 <2> ; 118 <2> ; Checksum data thus far 119 <2> ; 120 0000803C BE[0004] <2> mov si,ldlinux_sys 121 0000803F 8B0E[0B00] <2> mov cx,[bsBytesPerSec] 122 00008043 C1E902 <2> shr cx,2 123 00008046 66BA02FD4DC1 <2> mov edx,-LDLINUX_MAGIC 124 <2> .checksum: 125 0000804C 66AD <2> lodsd 126 0000804E 6601C2 <2> add edx,eax 127 00008051 E2F9 <2> loop .checksum 128 00008053 668916[2804] <2> mov [CheckSum],edx ; Save intermediate result 129 00008058 660FB7DE <2> movzx ebx,si ; Start of the next sector 130 <2> 131 <2> ; 132 <2> ; Tell the user if we're using EBIOS or CBIOS 133 <2> ; 134 <2> print_bios: 135 0000805C BE[E605] <2> mov si,cbios_name 136 0000805F 803E[4601]00 <2> cmp byte [getonesec.jmp+1],(getonesec_ebios-(getonesec.jmp+2)) 137 00008064 7508 <2> jne .cbios 138 00008066 BE[EA05] <2> mov si,ebios_name 139 00008069 C606[F504]00 <2> mov byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2)) 140 <2> .cbios: 141 0000806E 8936[0020] <2> mov [BIOSName],si 142 00008072 E84F01 <2> call writestr_early 143 <2> 144 <2> section .earlybss 145 <2> global BIOSName 146 <2> alignb 2 147 <2> %define HAVE_BIOSNAME 1 148 00003000 <2> BIOSName resw 1 149 <2> 150 <2> section .init 151 <2> ; 152 <2> ; Now we read the rest of LDLINUX.SYS. 153 <2> ; 154 <2> load_rest: 155 00008075 53 <2> push bx ; LSW of load address 156 <2> 157 00008076 668D36[EE05] <2> lea esi,[SectorPtrs] 158 0000807B 8B0E[2004] <2> mov cx,[DataSectors] 159 0000807F 49 <2> dec cx ; Minus this sector 160 <2> 161 <2> .get_chunk: 162 00008080 E32A <2> jcxz .done 163 00008082 668B04 <2> mov eax,[si] 164 00008085 668B5404 <2> mov edx,[si+4] 165 00008089 660FB76C08 <2> movzx ebp,word [si+8] 166 0000808E 29E9 <2> sub cx,bp 167 00008090 6653 <2> push ebx 168 00008092 66C1EB04 <2> shr ebx,4 ; Convert to a segment 169 00008096 8EC3 <2> mov es,bx 170 00008098 31DB <2> xor bx,bx 171 0000809A E84B00 <2> call getlinsec 172 0000809D 665B <2> pop ebx 173 0000809F 0FAF2E[0B00] <2> imul bp,[bsBytesPerSec] ; Will be < 64K 174 000080A4 6601EB <2> add ebx,ebp 175 000080A7 83C60A <2> add si,10 176 000080AA EBD4 <2> jmp .get_chunk 177 <2> 178 <2> .done: 179 <2> 180 <2> ; 181 <2> ; All loaded up, verify that we got what we needed. 182 <2> ; Note: the checksum field is embedded in the checksum region, so 183 <2> ; by the time we get to the end it should all cancel out. 184 <2> ; 185 <2> verify_checksum: 186 000080AC 5E <2> pop si ; LSW of load address 187 000080AD 660FB706[0B00] <2> movzx eax,word [bsBytesPerSec] 188 000080B3 C1E802 <2> shr ax,2 189 000080B6 668B0E[2404] <2> mov ecx,[LDLDwords] ; Total dwords 190 000080BB 6629C1 <2> sub ecx,eax ; ... minus one sector 191 000080BE 66A1[2804] <2> mov eax,[CheckSum] 192 <2> .checksum: 193 000080C2 660304 <2> add eax,[si] 194 000080C5 83C604 <2> add si,4 195 000080C8 7508 <2> jnz .nowrap 196 <2> ; Handle segment wrap 197 000080CA 8CDA <2> mov dx,ds 198 000080CC 81C20010 <2> add dx,1000h 199 000080D0 8EDA <2> mov ds,dx 200 <2> .nowrap: 201 000080D2 6649 <2> dec ecx 202 000080D4 75EC <2> jnz .checksum 203 <2> 204 000080D6 8ED9 <2> mov ds,cx 205 <2> 206 000080D8 6621C0 <2> and eax,eax ; Should be zero 207 000080DB 0F84(0000) <2> jz all_read ; We're cool, go for it! 208 <2> 209 <2> ; 210 <2> ; Uh-oh, something went bad... 211 <2> ; 212 000080DF BE[D705] <2> mov si,checksumerr_msg 213 000080E2 E8DF00 <2> call writestr_early 214 000080E5 E9C1FC <2> jmp kaboom 215 <2> 216 <2> ; 217 <2> ; ----------------------------------------------------------------------------- 218 <2> ; Subroutines that have to be in the first sector 219 <2> ; ----------------------------------------------------------------------------- 220 <2> 221 <2> 222 <2> 223 <2> ; 224 <2> ; getlinsec: load a sequence of BP floppy sector given by the linear sector 225 <2> ; number in EAX into the buffer at ES:BX. We try to optimize 226 <2> ; by loading up to a whole track at a time, but the user 227 <2> ; is responsible for not crossing a 64K boundary. 228 <2> ; (Yes, BP is weird for a count, but it was available...) 229 <2> ; 230 <2> ; On return, BX points to the first byte after the transferred 231 <2> ; block. 232 <2> ; 233 <2> ; This routine assumes CS == DS. 234 <2> ; 235 <2> global getlinsec:function hidden 236 <2> getlinsec: 237 000080E8 6660 <2> pushad 238 000080EA 660306607B <2> add eax,[Hidden] ; Add partition offset 239 000080EF 661316647B <2> adc edx,[Hidden+4] 240 000080F4 EB51 <2> .jmp: jmp strict short getlinsec_cbios 241 <2> 242 <2> ; 243 <2> ; getlinsec_ebios: 244 <2> ; 245 <2> ; getlinsec implementation for EBIOS (EDD) 246 <2> ; 247 <2> getlinsec_ebios: 248 <2> .loop: 249 000080F6 55 <2> push bp ; Sectors left 250 <2> .retry2: 251 000080F7 E8BF00 <2> call maxtrans ; Enforce maximum transfer size 252 000080FA 660FB7FD <2> movzx edi,bp ; Sectors we are about to read 253 000080FE B91000 <2> mov cx,retry_count 254 <2> .retry: 255 <2> 256 <2> ; Form DAPA on stack 257 00008101 6652 <2> push edx 258 00008103 6650 <2> push eax 259 00008105 06 <2> push es 260 00008106 53 <2> push bx 261 00008107 57 <2> push di 262 00008108 6A10 <2> push word 16 263 0000810A 89E6 <2> mov si,sp 264 0000810C 6660 <2> pushad 265 0000810E B442 <2> mov ah,42h ; Extended Read 266 00008110 1E <2> push ds 267 00008111 16 <2> push ss 268 00008112 1F <2> pop ds 269 00008113 E8BBFC <2> call xint13 270 00008116 1F <2> pop ds 271 00008117 6661 <2> popad 272 00008119 8D6410 <2> lea sp,[si+16] ; Remove DAPA 273 0000811C 7218 <2> jc .error 274 0000811E 5D <2> pop bp 275 0000811F 6601F8 <2> add eax,edi ; Advance sector pointer 276 00008122 6683D200 <2> adc edx,0 277 00008126 29FD <2> sub bp,di ; Sectors left 278 00008128 0FAF3E[0B00] <2> imul di,[bsBytesPerSec] 279 0000812D 01FB <2> add bx,di ; Advance buffer pointer 280 0000812F 21ED <2> and bp,bp 281 00008131 75C3 <2> jnz .loop 282 <2> 283 00008133 6661 <2> popad 284 00008135 C3 <2> ret 285 <2> 286 <2> .error: 287 <2> ; Some systems seem to get "stuck" in an error state when 288 <2> ; using EBIOS. Doesn't happen when using CBIOS, which is 289 <2> ; good, since some other systems get timeout failures 290 <2> ; waiting for the floppy disk to spin up. 291 <2> 292 00008136 6660 <2> pushad ; Try resetting the device 293 00008138 31C0 <2> xor ax,ax 294 0000813A E894FC <2> call xint13 295 0000813D 6661 <2> popad 296 0000813F E2C0 <2> loop .retry ; CX-- and jump if not zero 297 <2> 298 <2> ;shr word [MaxTransfer],1 ; Reduce the transfer size 299 <2> ;jnz .retry2 300 <2> 301 <2> ; Total failure. Try falling back to CBIOS. 302 00008141 C606[F504]51 <2> mov byte [getlinsec.jmp+1],(getlinsec_cbios-(getlinsec.jmp+2)) 303 <2> ;mov byte [MaxTransfer],63 ; Max possibe CBIOS transfer 304 <2> 305 00008146 5D <2> pop bp 306 <2> ; ... fall through ... 307 <2> 308 <2> ; 309 <2> ; getlinsec_cbios: 310 <2> ; 311 <2> ; getlinsec implementation for legacy CBIOS 312 <2> ; 313 <2> getlinsec_cbios: 314 <2> .loop: 315 00008147 6652 <2> push edx 316 00008149 6650 <2> push eax 317 0000814B 55 <2> push bp 318 0000814C 53 <2> push bx 319 <2> 320 0000814D 660FB736[1800] <2> movzx esi,word [bsSecPerTrack] 321 00008153 660FB73E[1A00] <2> movzx edi,word [bsHeads] 322 <2> ; 323 <2> ; Dividing by sectors to get (track,sector): we may have 324 <2> ; up to 2^18 tracks, so we need to use 32-bit arithmetric. 325 <2> ; 326 00008159 66F7F6 <2> div esi 327 0000815C 31C9 <2> xor cx,cx 328 0000815E 87CA <2> xchg cx,dx ; CX <- sector index (0-based) 329 <2> ; EDX <- 0 330 <2> ; eax = track # 331 00008160 66F7F7 <2> div edi ; Convert track to head/cyl 332 <2> 333 00008163 663DFF030000 <2> cmp eax,1023 ; Outside the CHS range? 334 00008169 0F873CFC <2> ja kaboom 335 <2> 336 <2> ; 337 <2> ; Now we have AX = cyl, DX = head, CX = sector (0-based), 338 <2> ; BP = sectors to transfer, SI = bsSecPerTrack, 339 <2> ; ES:BX = data target 340 <2> ; 341 <2> 342 0000816D E84900 <2> call maxtrans ; Enforce maximum transfer size 343 <2> 344 <2> ; Must not cross track boundaries, so BP <= SI-CX 345 00008170 29CE <2> sub si,cx 346 00008172 39F5 <2> cmp bp,si 347 00008174 7602 <2> jna .bp_ok 348 00008176 89F5 <2> mov bp,si 349 <2> .bp_ok: 350 <2> 351 00008178 C0E406 <2> shl ah,6 ; Because IBM was STOOPID 352 <2> ; and thought 8 bits were enough 353 <2> ; then thought 10 bits were enough... 354 0000817B 41 <2> inc cx ; Sector numbers are 1-based, sigh 355 0000817C 08E1 <2> or cl,ah 356 0000817E 88C5 <2> mov ch,al 357 00008180 88D6 <2> mov dh,dl 358 00008182 95 <2> xchg ax,bp ; Sector to transfer count 359 00008183 B402 <2> mov ah,02h ; Read sectors 360 00008185 BD1000 <2> mov bp,retry_count 361 <2> .retry: 362 00008188 6660 <2> pushad 363 0000818A E844FC <2> call xint13 364 0000818D 6661 <2> popad 365 0000818F 721B <2> jc .error 366 <2> .resume: 367 00008191 660FB6C8 <2> movzx ecx,al ; ECX <- sectors transferred 368 00008195 0FAF06[0B00] <2> imul ax,[bsBytesPerSec] ; Convert sectors in AL to bytes in AX 369 0000819A 5B <2> pop bx 370 0000819B 01C3 <2> add bx,ax 371 0000819D 5D <2> pop bp 372 0000819E 6658 <2> pop eax 373 000081A0 665A <2> pop edx 374 000081A2 6601C8 <2> add eax,ecx 375 000081A5 29CD <2> sub bp,cx 376 000081A7 759E <2> jnz .loop 377 000081A9 6661 <2> popad 378 000081AB C3 <2> ret 379 <2> 380 <2> .error: 381 000081AC 4D <2> dec bp 382 000081AD 75D9 <2> jnz .retry 383 <2> 384 000081AF 95 <2> xchg ax,bp ; Sectors transferred <- 0 385 000081B0 D12E[2C04] <2> shr word [MaxTransfer],1 386 000081B4 75DB <2> jnz .resume 387 000081B6 E9F0FB <2> jmp kaboom 388 <2> 389 <2> maxtrans: 390 000081B9 3B2E[2C04] <2> cmp bp,[MaxTransfer] 391 000081BD 7604 <2> jna .ok 392 000081BF 8B2E[2C04] <2> mov bp,[MaxTransfer] 393 000081C3 C3 <2> .ok: ret 394 <2> 395 <2> ; 396 <2> ; 397 <2> ; writestr_early: write a null-terminated string to the console 398 <2> ; This assumes we're on page 0. This is only used for early 399 <2> ; messages, so it should be OK. 400 <2> ; 401 <2> writestr_early: 402 000081C4 6660 <2> pushad 403 000081C6 AC <2> .loop: lodsb 404 000081C7 20C0 <2> and al,al 405 000081C9 7409 <2> jz .return 406 000081CB B40E <2> mov ah,0Eh ; Write to screen as TTY 407 000081CD BB0700 <2> mov bx,0007h ; Attribute 408 000081D0 CD10 <2> int 10h 409 000081D2 EBF2 <2> jmp short .loop 410 000081D4 6661 <2> .return: popad 411 000081D6 C3 <2> ret 412 <2> 413 <2> ; 414 <2> ; Checksum error message 415 <2> ; 416 000081D7 204C6F616420657272- <2> checksumerr_msg db ' Load error - ', 0 ; Boot failed appended 416 000081E0 6F72202D2000 <2> 417 <2> 418 <2> ; 419 <2> ; BIOS type string 420 <2> ; 421 000081E6 43485300 <2> cbios_name db 'CHS', 0 ; CHS/CBIOS 422 000081EA 45444400 <2> ebios_name db 'EDD', 0 ; EDD/EBIOS 423 <2> 424 <2> ; 425 <2> ; Debug routine 426 <2> ; 427 <2> %ifdef debug 428 <2> safedumpregs: 429 <2> cmp word [Debug_Magic],0D00Dh 430 <2> jnz nc_return 431 <2> jmp dumpregs 432 <2> %endif 433 <2> 434 <2> rl_checkpt equ $ ; Must be <= 8000h 435 <2> 436 <2> rl_checkpt_off equ $-ldlinux_sys 437 <2> %ifndef DEPEND 438 <2> %if rl_checkpt_off > 512-10 ; Need minimum one extent 439 <2> %assign rl_checkpt_overflow rl_checkpt_off - (512-10) 440 <2> %error Sector 1 overflow by rl_checkpt_overflow bytes 441 <2> %endif 442 <2> %endif 443 <2> 444 <2> ; 445 <2> ; Extent pointers... each extent contains an 8-byte LBA and an 2-byte 446 <2> ; sector count. In most cases, we will only ever need a handful of 447 <2> ; extents, but we have to assume a maximally fragmented system where each 448 <2> ; extent contains only one sector. 449 <2> ; 450 <2> alignz 2 451 <2> MaxInitDataSize equ 96 << 10 452 <2> MaxLMA equ LDLINUX_SYS+MaxInitDataSize 453 000081EE 00 <2> SectorPtrs zb 10*(MaxInitDataSize >> MIN_SECTOR_SHIFT) 454 <2> SectorPtrsEnd equ $ 455 <2> 456 <2> ; ---------------------------------------------------------------------------- 457 <2> ; End of code and data that have to be in the first sector 458 <2> ; ---------------------------------------------------------------------------- 459 <2> 460 <2> section .text16 461 <2> all_read: 462 <2> ; We enter here with ES scrambled... 463 00008970 31C0 <2> xor ax,ax 464 00008972 8EC0 <2> mov es,ax 465 <2> ; 466 <2> ; Let the user (and programmer!) know we got this far. This used to be 467 <2> ; in Sector 1, but makes a lot more sense here. 468 <2> ; 469 00008974 BE[2F02] <2> mov si,late_banner 470 00008977 E8(C405) <2> call writestr_early 471 <2> 472 0000897A BE[B602] <2> mov si,copyright_str 473 0000897D E8(C405) <2> call writestr_early 474 <2> 475 <2> 476 <2> ; 477 <2> ; Insane hack to expand the DOS superblock to dwords 478 <2> ; 479 <2> expand_super: 480 00008980 6631C0 <2> xor eax,eax 481 00008983 BE[0B00] <2> mov si,superblock 482 00008986 BF[0000] <2> mov di,SuperInfo 483 00008989 B91000 <2> mov cx,superinfo_size 484 <2> .loop: 485 0000898C AD <2> lodsw 486 0000898D 4E <2> dec si 487 0000898E 66AB <2> stosd ; Store expanded word 488 00008990 30E4 <2> xor ah,ah 489 00008992 66AB <2> stosd ; Store expanded byte 490 00008994 E2F6 <2> loop .loop 491 <2> 492 <2> 493 <2> ; 494 <2> ; Common initialization code 495 <2> ; 496 <2> %include "init.inc" 1 <3> ; -*- fundamental -*- 2 <3> ; ----------------------------------------------------------------------- 3 <3> ; 4 <3> ; Copyright 2004-2008 H. Peter Anvin - All Rights Reserved 5 <3> ; Copyright 2009 Intel Corporation; author: H. Peter Anvin 6 <3> ; 7 <3> ; This program is free software; you can redistribute it and/or modify 8 <3> ; it under the terms of the GNU General Public License as published by 9 <3> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330, 10 <3> ; Boston MA 02111-1307, USA; either version 2 of the License, or 11 <3> ; (at your option) any later version; incorporated herein by reference. 12 <3> ; 13 <3> ; ----------------------------------------------------------------------- 14 <3> 15 <3> ; 16 <3> ; init.inc 17 <3> ; 18 <3> ; Common initialization code (inline) 19 <3> ; 20 <3> 21 <3> section .text16 22 <3> common_init: 23 <3> ; Initialize PM invocation framework 24 00008996 E83302 <3> call pm_init 25 <3> 26 <3> %if IS_PXELINUX 27 <3> ; Save derivative-specific data 28 <3> pm_call pm_save_data 29 <3> %endif 30 <3> 31 <3> ; Decompress PM code to its target location 32 <3> pm_call pm_decompress 32 00008999 6668[00000000] <4> push dword %1 32 0000899F E8A700 <4> call _pm_call 33 000089A2 663D[00000000] <3> cmp eax,__pm_code_len 34 000089A8 0F85(A901) <3> jne kaboom 35 <3> 36 <3> extern syslinux_register_bios, init 37 <3> 38 <3> pm_call syslinux_register_bios 38 000089AC 6668[00000000] <4> push dword %1 38 000089B2 E89400 <4> call _pm_call 39 <3> pm_call init 39 000089B5 6668[00000000] <4> push dword %1 39 000089BB E88B00 <4> call _pm_call 40 <3> 41 <3> ; 42 <3> ; The code to decompress the PM code and initialize other segments. 43 <3> ; 44 <3> extern _lzo1x_decompress_asm_fast_safe 45 <3> 46 <3> section .textnr 47 <3> bits 32 48 <3> pm_decompress: 49 00008F50 68[10000000] <3> push __pm_code_len + 16 ; Space for decompressed size 50 00008F55 54 <3> push esp ; Pointer to previous word 51 00008F56 68[00000000] <3> push __pm_code_start ; Target address 52 00008F5B FF35[1C020000] <3> push dword [lzo_data_size] ; Compressed size 53 00008F61 68[00000000] <3> push dword __pm_code_lma 54 00008F66 E8(00000000) <3> call _lzo1x_decompress_asm_fast_safe 55 00008F6B 83C410 <3> add esp,16 56 00008F6E 8F4524 <3> pop RM_EAX ; Decompressed size 57 <3> 58 <3> ; Zero bss sections (but not .earlybss, since it may 59 <3> ; contain already-live data.) 60 00008F71 31C0 <3> xor eax,eax 61 00008F73 BF[00000000] <3> mov edi,__bss_start 62 00008F78 B9[00000000] <3> mov ecx,__bss_dwords 63 00008F7D F3AB <3> rep stosd 64 00008F7F BF[00000000] <3> mov edi,__bss16_start 65 00008F84 B9[00000000] <3> mov ecx,__bss16_dwords 66 00008F89 F3AB <3> rep stosd 67 00008F8B BF[00000000] <3> mov edi,__high_clear_start ; .uibss, .lowmem 68 00008F90 B9[00000000] <3> mov ecx,__high_clear_dwords 69 00008F95 F3AB <3> rep stosd 70 <3> 71 00008F97 C3 <3> ret 72 <3> 73 <3> section .data16 74 0000965C 00000000 <3> lzo_data_size dd 0 ; filled in by compressor 75 <3> 76 <3> section .text16 77 <3> bits 16 497 <2> 498 000089BE 6660 <2> pushad 499 000089C0 66B8[00000000] <2> mov eax,ROOT_FS_OPS 500 000089C6 0FB616747B <2> movzx dx,byte [DriveNumber] 501 <2> ; DH = 0: we are boot from disk not CDROM 502 000089CB 668B0E607B <2> mov ecx,[Hidden] 503 000089D0 668B1E647B <2> mov ebx,[Hidden+4] 504 000089D5 8B36[1A00] <2> mov si,[bsHeads] 505 000089D9 8B3E[1800] <2> mov di,[bsSecPerTrack] 506 000089DD 660FB72E[2C04] <2> movzx ebp,word [MaxTransfer] 507 <2> pm_call pm_fs_init 507 000089E3 6668[00000000] <3> push dword %1 507 000089E9 E85D00 <3> call _pm_call 508 <2> pm_call load_env32 508 000089EC 6668[00000000] <3> push dword %1 508 000089F2 E85400 <3> call _pm_call 509 000089F5 6661 <2> popad 510 <2> 511 <2> section .bss16 512 00003810 <2> SuperInfo resq 16 ; The first 16 bytes expanded 8 times 513 <2> 514 <2> ; 515 <2> ; Banner information not needed in sector 1 516 <2> ; 517 <2> section .data16 518 <2> global syslinux_banner 519 00009660 0D0A5359534C494E55- <2> syslinux_banner db CR, LF, MY_NAME, ' ', VERSION_STR 519 00009669 5820362E3034 <2> 520 0000966F 20362E30342D707265- <2> late_banner db ' ', DATE_STR, 0 520 00009678 322A00 <2> 521 <2> 522 <2> section .text16 53 <1> 54 <1> ; 55 <1> ; Now, everything is "up and running"... patch kaboom for more 56 <1> ; verbosity and using the full screen system 57 <1> ; 58 <1> ; E9 = JMP NEAR 59 000089F7 BF[B701] <1> mov di,kaboom.patch 60 000089FA B0E9 <1> mov al,0e9h 61 000089FC AA <1> stosb 62 000089FD B8[A100] <1> mov ax,kaboom2-2 63 00008A00 29F8 <1> sub ax,di 64 00008A02 AB <1> stosw 65 <1> 66 <1> ; 67 <1> ; If we get to this point ldlinux.c32 failed to run. There's nothing 68 <1> ; left to do but inform that user that something went wrong. 69 <1> ; 70 <1> enter_command: 71 <1> auto_boot: 72 00008A03 E9(A901) <1> jmp kaboom 73 <1> 74 <1> section .bss16 75 <1> alignb 4 76 00003890 <1> ThisKbdTo resd 1 ; Temporary holder for KbdTimeout 77 00003894 <1> ThisTotalTo resd 1 ; Temporary holder for TotalTimeout 78 00003898 <1> KernelExtPtr resw 1 ; During search, final null pointer 79 0000389A <1> FuncFlag resb 1 ; Escape sequences received from keyboard 80 0000389B <1> KernelType resb 1 ; Kernel type, from vkernel, if known 81 <1> global KernelName 82 0000389C <1> KernelName resb FILENAME_MAX ; Mangled name for kernel 83 <1> 84 <1> section .text16 85 <1> ; 86 <1> ; COM32 vestigial data structure 87 <1> ; 88 <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 0000967B 00 <2> alignz 4 43 <2> __entry_esp: 44 0000967C 00000000 <2> dd 0 ; Dummy to avoid _exit issues 45 <2> __com32: 46 00009680 09000000 <2> dd 9 ; Argument count 47 00009684 00000000 <2> dd 0 ; No command line 48 00009688 [06000000] <2> dd core_intcall ; Intcall entry point 49 0000968C 00000000 <2> dd 0 ; Bounce buffer address 50 00009690 00000000 <2> dd 0 ; 64K bounce buffer 51 00009694 [00000000] <2> dd core_farcall ; Farcall entry point 52 00009698 [A6000000] <2> dd core_cfarcall ; Cfarcall entry point 53 0000969C 00000000 <2> HighMemSize dd 0 ; End of memory pointer (bytes) 54 000096A0 00000000 <2> dd 0 ; No module name 55 000096A4 [00000000] <2> dd pm_api_vector ; Protected mode functions 56 <2> 57 <2> section .uibss 58 00009C00 <2> Com32Name resb FILENAME_MAX 59 <2> 60 <2> section .bss16 61 <2> %ifndef HAVE_CURRENTDIRNAME 62 <2> global CurrentDirName:data hidden 63 <2> CurrentDirName resb FILENAME_MAX 64 <2> %endif 65 <2> 66 <2> section .text16 89 <1> 90 <1> ; 91 <1> ; Common local boot code 92 <1> ; 93 <1> %include "localboot.inc" 1 <2> section .text16 2 <2> global local_boot16:function hidden 3 <2> local_boot16: 4 00008A06 B90000 <2> mov cx,0 5 00008A09 8ED1 <2> mov ss,cx 6 00008A0B BC007C <2> mov sp,7C00h 7 00008A0E EA007C0000 <2> jmp 0:07C00h 94 <1> 95 <1> ; 96 <1> ; kaboom2: once everything is loaded, replace the part of kaboom 97 <1> ; starting with "kaboom.patch" with this part 98 <1> 99 <1> kaboom2: 100 00008A13 BE[E602] <1> mov si,err_bootfailed 101 <1> pm_call pm_writestr 101 00008A16 6668[00000000] <2> push dword %1 101 00008A1C E82A00 <2> call _pm_call 102 00008A1F 803E[CB01]18 <1> cmp byte [kaboom.again+1],18h ; INT 18h version? 103 00008A24 7416 <1> je .int18 104 <1> pm_call pm_getchar 104 00008A26 6668[00000000] <2> push dword %1 104 00008A2C E81A00 <2> call _pm_call 105 <1> pm_call syslinux_force_text_mode 105 00008A2F 6668[00000000] <2> push dword %1 105 00008A35 E81100 <2> call _pm_call 106 00008A38 CD19 <1> int 19h ; And try once more to boot... 107 00008A3A EBFE <1> .norge: jmp short .norge ; If int 19h returned; this is the end 108 <1> .int18: 109 <1> pm_call syslinux_force_text_mode 109 00008A3C 6668[00000000] <2> push dword %1 109 00008A42 E80400 <2> call _pm_call 110 00008A45 CD18 <1> int 18h 111 00008A47 EBFE <1> .noreg: jmp short .noreg ; Nynorsk 112 <1> 113 <1> ; ----------------------------------------------------------------------------- 114 <1> ; Common modules 115 <1> ; ----------------------------------------------------------------------------- 116 <1> 117 <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 00008A49 669C <3> pushfd 40 00008A4B 6660 <3> pushad 41 00008A4D 1E <3> push ds 42 00008A4E 06 <3> push es 43 00008A4F 0FA0 <3> push fs 44 00008A51 0FA8 <3> push gs 45 00008A53 89E5 <3> mov bp,sp 46 00008A55 8CC8 <3> mov ax,cs 47 00008A57 66BB[48000000] <3> mov ebx,.pm 48 00008A5D 8ED8 <3> mov ds,ax 49 00008A5F 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 00008F98 F6452902 <3> test RM_FLAGSH,02h ; RM EFLAGS.IF 56 00008F9C 7401 <3> jz .no_sti 57 00008F9E FB <3> sti 58 <3> .no_sti: 59 00008F9F FF552E <3> call [ebp+4*2+9*4+2] ; Entrypoint on RM stack 60 00008FA2 66BB[F100] <3> mov bx,.rm 61 00008FA6 EB20 <3> jmp enter_rm 62 <3> 63 <3> bits 16 64 <3> section .text16 65 <3> .rm: 66 00008A61 0FA9 <3> pop gs 67 00008A63 0FA1 <3> pop fs 68 00008A65 07 <3> pop es 69 00008A66 1F <3> pop ds 70 00008A67 6661 <3> popad 71 00008A69 669D <3> popfd 72 00008A6B 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 00008A6E FA <3> cli 89 00008A6F 6631C0 <3> xor eax,eax 90 00008A72 8ED8 <3> mov ds,ax 91 00008A74 8CD0 <3> mov ax,ss 92 00008A76 8926[0828] <3> mov [RealModeSSSP],sp 93 00008A7A A3[0A28] <3> mov [RealModeSSSP+2],ax 94 00008A7D 660FB7EC <3> movzx ebp,sp 95 00008A81 66C1E004 <3> shl eax,4 96 00008A85 6601C5 <3> add ebp,eax ; EBP -> top of real-mode stack 97 00008A88 FC <3> cld 98 00008A89 E86400 <3> call enable_a20 99 <3> 100 <3> .a20ok: 101 00008A8C C606[0D00]89 <3> mov byte [bcopy_gdt.TSS+5],89h ; Mark TSS unbusy 102 <3> 103 00008A91 0F0116[0000] <3> lgdt [bcopy_gdt] ; We can use the same GDT just fine 104 00008A96 0F011E[6C02] <3> lidt [PM_IDT_ptr] ; Set up the IDT 105 00008A9B 0F20C0 <3> mov eax,cr0 106 00008A9E 0C01 <3> or al,1 107 00008AA0 0F22C0 <3> mov cr0,eax ; Enter protected mode 108 00008AA3 EA[5800]2000 <3> jmp PM_CS32:.in_pm 109 <3> 110 <3> bits 32 111 <3> section .textnr 112 <3> .in_pm: 113 00008FA8 31C0 <3> xor eax,eax ; Available for future use... 114 00008FAA 8EE0 <3> mov fs,eax 115 00008FAC 8EE8 <3> mov gs,eax 116 00008FAE 0F00D0 <3> lldt ax 117 <3> 118 00008FB1 B028 <3> mov al,PM_DS32 ; Set up data segments 119 00008FB3 8EC0 <3> mov es,eax 120 00008FB5 8ED8 <3> mov ds,eax 121 00008FB7 8ED0 <3> mov ss,eax 122 <3> 123 00008FB9 B008 <3> mov al,PM_TSS ; Be nice to Intel's VT by 124 00008FBB 0F00D8 <3> ltr ax ; giving it a valid TR 125 <3> 126 00008FBE 8B25[68020000] <3> mov esp,[PMESP] ; Load protmode %esp 127 00008FC4 89E8 <3> mov eax,ebp ; EAX -> top of real-mode stack 128 00008FC6 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 00008FC8 FA <3> cli 145 00008FC9 FC <3> cld 146 00008FCA 8925[68020000] <3> mov [PMESP],esp ; Save exit %esp 147 00008FD0 EA[38010000]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 00008AA8 B81800 <3> mov ax,PM_DS16 ; Real-mode-like segment 153 00008AAB 8EC0 <3> mov es,ax 154 00008AAD 8ED8 <3> mov ds,ax 155 00008AAF 8ED0 <3> mov ss,ax 156 00008AB1 8EE0 <3> mov fs,ax 157 00008AB3 8EE8 <3> mov gs,ax 158 <3> 159 00008AB5 0F011E[3000] <3> lidt [RM_IDT_ptr] ; Real-mode IDT (rm needs no GDT) 160 00008ABA 31D2 <3> xor dx,dx 161 00008ABC 0F20C0 <3> mov eax,cr0 162 00008ABF 24FE <3> and al,~1 163 00008AC1 0F22C0 <3> mov cr0,eax 164 00008AC4 EA[5901]0000 <3> jmp 0:.in_rm 165 <3> 166 <3> .in_rm: ; Back in real mode 167 00008AC9 2E0FB226[0828] <3> lss sp,[cs:RealModeSSSP] ; Restore stack 168 00008ACF 660FB7E4 <3> movzx esp,sp ; Make sure the high bits are zero 169 00008AD3 8EDA <3> mov ds,dx ; Set up sane segments 170 00008AD5 8EC2 <3> mov es,dx 171 00008AD7 8EE2 <3> mov fs,dx 172 00008AD9 8EEA <3> mov gs,dx 173 00008ADB 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 000096A8 [00000000] <3> PMESP dd __stack_end ; Protected-mode ESP 180 <3> 181 000096AC FF07 <3> PM_IDT_ptr: dw 8*256-1 ; Length 182 000096AE [08200000] <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 00008FD7 60 <3> pushad 196 00008FD8 0FB6742420 <3> movzx esi,byte [esp+8*4] ; Interrupt number 197 00008FDD FF05[98010000] <3> inc dword [CallbackCtr] 198 00008FE3 BB[6D010000] <3> mov ebx,.rm 199 00008FE8 EBDE <3> jmp enter_rm ; Go to real mode 200 <3> 201 <3> bits 16 202 <3> section .text16 203 <3> .rm: 204 00008ADD 9C <3> pushf ; Flags on stack 205 00008ADE 2E67FF1CB500000000 <3> call far [cs:esi*4] ; Call IVT entry 206 00008AE7 66BB[9A000000] <3> mov ebx,.pm 207 00008AED E97EFF <3> jmp enter_pm ; Go back to PM 208 <3> 209 <3> bits 32 210 <3> section .textnr 211 <3> .pm: 212 00008FEA FF0D[98010000] <3> dec dword [CallbackCtr] 213 00008FF0 7506 <3> jnz .skip 214 00008FF2 FF15[74020000] <3> call [core_pm_hook] 215 <3> .skip: 216 00008FF8 61 <3> popad 217 00008FF9 83C404 <3> add esp,4 ; Drop interrupt number 218 00008FFC 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 00008FFD C3 <3> ret 228 <3> 229 <3> section .data16 230 000096B2 00 <3> alignz 4 231 <3> global core_pm_hook 232 000096B4 [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 000096B8 [9201] <3> A20Ptr dw a20_dunno 247 <3> 248 <3> section .bss16 249 <3> alignb 4 250 0000399C <3> A20Test resd 1 ; Counter for testing A20 status 251 000039A0 <3> A20Tries resb 1 ; Times until giving up on A20 252 <3> 253 <3> section .text16 254 <3> enable_a20: 255 00008AF0 6660 <3> pushad 256 00008AF2 2EC606[9001]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 00008AF8 E87C00 <3> call a20_test 266 00008AFB 7577 <3> jnz a20_done 267 <3> ; Otherwise, see if we had something memorized... 268 00008AFD 2EFF26[7802] <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 00008B02 2EC706[7802][9201] <3> mov word [cs:A20Ptr], a20_bios 276 00008B09 B80124 <3> mov ax,2401h 277 00008B0C 9C <3> pushf ; Some BIOSes muck with IF 278 00008B0D CD15 <3> int 15h 279 00008B0F 9D <3> popf 280 <3> 281 00008B10 E86400 <3> call a20_test 282 00008B13 755F <3> jnz a20_done 283 <3> 284 <3> ; 285 <3> ; Enable the keyboard controller A20 gate 286 <3> ; 287 <3> a20_kbc: 288 00008B15 B201 <3> mov dl, 1 ; Allow early exit 289 00008B17 E88E00 <3> call empty_8042 290 00008B1A 7558 <3> jnz a20_done ; A20 live, no need to use KBC 291 <3> 292 00008B1C 2EC706[7802][A501] <3> mov word [cs:A20Ptr], a20_kbc ; Starting KBC command sequence 293 <3> 294 00008B23 B0D1 <3> mov al,0D1h ; Write output port 295 00008B25 E664 <3> out 064h, al 296 00008B27 E87C00 <3> call empty_8042_uncond 297 <3> 298 00008B2A B0DF <3> mov al,0DFh ; A20 on 299 00008B2C E660 <3> out 060h, al 300 00008B2E 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 00008B31 B0FF <3> mov al,0FFh ; Null command 306 00008B33 E664 <3> out 064h, al 307 00008B35 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 00008B38 51 <3> .kbc_wait: push cx 316 00008B39 31C9 <3> xor cx,cx 317 <3> .kbc_wait_loop: 318 00008B3B E83900 <3> call a20_test 319 00008B3E 7533 <3> jnz a20_done_pop 320 00008B40 E2F9 <3> loop .kbc_wait_loop 321 <3> 322 00008B42 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 00008B43 2EC706[7802][D301] <3> mov word [cs:A20Ptr], a20_fast 328 00008B4A E492 <3> in al, 092h 329 00008B4C 0C02 <3> or al,02h 330 00008B4E 24FE <3> and al,~01h ; Don't accidentally reset the machine! 331 00008B50 E692 <3> out 092h, al 332 <3> 333 00008B52 51 <3> .fast_wait: push cx 334 00008B53 31C9 <3> xor cx,cx 335 <3> .fast_wait_loop: 336 00008B55 E81F00 <3> call a20_test 337 00008B58 7519 <3> jnz a20_done_pop 338 00008B5A E2F9 <3> loop .fast_wait_loop 339 <3> 340 00008B5C 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 00008B5D 2EFE0E[9001] <3> dec byte [cs:A20Tries] 347 00008B62 759E <3> jnz a20_dunno ; Did we get the wrong type? 348 <3> 349 00008B64 BE[7A02] <3> mov si, err_a20 350 <3> pm_call pm_writestr 350 00008B67 6668[00000000] <4> push dword %1 350 00008B6D E8D9FE <4> call _pm_call 351 00008B70 E9(A901) <3> jmp kaboom 352 <3> 353 <3> section .data16 354 000096BA 0D0A41323020676174- <3> err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0 354 000096C3 65206E6F7420726573- <3> 354 000096CC 706F6E64696E67210D- <3> 354 000096D5 0A00 <3> 355 <3> section .text16 356 <3> 357 <3> ; 358 <3> ; A20 unmasked, proceed... 359 <3> ; 360 00008B73 59 <3> a20_done_pop: pop cx 361 00008B74 6661 <3> a20_done: popad 362 00008B76 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 00008B77 06 <3> push es 373 00008B78 51 <3> push cx 374 00008B79 6650 <3> push eax 375 00008B7B B9FFFF <3> mov cx,0FFFFh ; HMA = segment 0FFFFh 376 00008B7E 8EC1 <3> mov es,cx 377 00008B80 2E66A1[8C01] <3> mov eax,[cs:A20Test] 378 00008B85 B92000 <3> mov cx,32 ; Loop count 379 00008B88 EB0F <3> jmp .test ; First iteration = early out 380 00008B8A 660541EA0A43 <3> .wait: add eax,0x430aea41 ; A large prime number 381 00008B90 2E66A3[8C01] <3> mov [cs:A20Test],eax 382 00008B95 E680E680 <3> io_delay ; Serialize, and fix delay 383 00008B99 26663B06[9C01] <3> .test: cmp eax,[es:A20Test+10h] 384 00008B9F E1E9 <3> loopz .wait 385 00008BA1 6658 <3> .done: pop eax 386 00008BA3 59 <3> pop cx 387 00008BA4 07 <3> pop es 388 00008BA5 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 00008BA6 30D2 <3> xor dl,dl 397 <3> empty_8042: 398 00008BA8 E8CCFF <3> call a20_test 399 00008BAB 7404 <3> jz .a20_on 400 00008BAD 20D2 <3> and dl,dl 401 00008BAF 751A <3> jnz .done 402 00008BB1 E680E680 <3> .a20_on: io_delay 403 00008BB5 E464 <3> in al, 064h ; Status port 404 00008BB7 A801 <3> test al,1 405 00008BB9 7408 <3> jz .no_output 406 00008BBB E680E680 <3> io_delay 407 00008BBF E460 <3> in al, 060h ; Read input 408 00008BC1 EBE5 <3> jmp short empty_8042 409 <3> .no_output: 410 00008BC3 A802 <3> test al,2 411 00008BC5 75E1 <3> jnz empty_8042 412 00008BC7 E680E680 <3> io_delay 413 00008BCB 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 00008BCC 6631FF <3> xor edi,edi 421 00008BCF BB[0820] <3> mov bx,IDT 422 00008BD2 BF[0000] <3> mov di,IRQStubs 423 <3> 424 00008BD5 66B86A00EB7A <3> mov eax,7aeb006ah ; push byte .. jmp short .. 425 <3> 426 00008BDB B90800 <3> mov cx,8 ; 8 groups of 32 IRQs 427 <3> .gloop: 428 00008BDE 51 <3> push cx 429 00008BDF B92000 <3> mov cx,32 ; 32 entries per group 430 <3> .eloop: 431 00008BE2 893F <3> mov [bx],di ; IDT offset [15:0] 432 00008BE4 C747022000 <3> mov word [bx+2],PM_CS32 ; IDT segment 433 00008BE9 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 00008BF1 83C308 <3> add bx,8 437 <3> 438 00008BF4 66AB <3> stosd 439 <3> ; Increment IRQ, decrement jmp short offset 440 00008BF6 6605000100FC <3> add eax,(-4 << 24)+(1 << 8) 441 <3> 442 00008BFC E2E4 <3> loop .eloop 443 <3> 444 <3> ; At the end of each group, replace the EBxx with 445 <3> ; the final E9xxxxxxxx 446 00008BFE 83C703 <3> add di,3 447 00008C01 C645FBE9 <3> mov byte [di-5],0E9h ; JMP NEAR 448 00008C05 66BA[87000000] <3> mov edx,pm_irq 449 00008C0B 6629FA <3> sub edx,edi 450 00008C0E 668955FC <3> mov [di-4],edx 451 <3> 452 00008C12 660500000080 <3> add eax,(0x80 << 24) ; Proper offset for the next one 453 00008C18 59 <3> pop cx 454 00008C19 E2C3 <3> loop .gloop 455 <3> 456 00008C1B 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 00003002 <3> alignb 8 462 00003008 <3> IDT: resq 256 463 <3> global RealModeSSSP 464 00003808 <3> RealModeSSSP resd 1 ; Real-mode SS:SP 465 <3> 466 <3> section .gentextnr ; Autogenerated 32-bit code 467 00003A00 <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[98010000] <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[94010000] <4> push dword [CallbackSP] 58 <4> 59 00100023 FC <4> cld 60 <4> 61 00100024 670FB73E[0828] <4> movzx edi,word [word RealModeSSSP] 62 0010002A 670FB71E[0A28] <4> movzx ebx,word [word RealModeSSSP+2] 63 00100030 83EF36 <4> sub edi,54 ; Allocate 54 bytes 64 00100033 6667893E[0828] <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[BF020000] <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[AC02] <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 00008C1C 89E0 <4> mov ax,sp 89 00008C1E 83C02C <4> add ax,9*4+4*2 90 00008C21 A3[9401] <4> mov [CallbackSP],ax 91 00008C24 0FA9 <4> pop gs 92 00008C26 0FA1 <4> pop fs 93 00008C28 07 <4> pop es 94 00008C29 1F <4> pop ds 95 00008C2A 6661 <4> popad 96 00008C2C 669D <4> popfd 97 00008C2E 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 00008C2F 2E8B26[9401] <4> mov sp,[cs:CallbackSP] 103 00008C34 669C <4> pushfd 104 00008C36 6660 <4> pushad 105 00008C38 1E <4> push ds 106 00008C39 06 <4> push es 107 00008C3A 0FA0 <4> push fs 108 00008C3C 0FA8 <4> push gs 109 00008C3E 66BB[65000000] <4> mov ebx,.pm_return 110 00008C44 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[0828] <4> movzx esi,word [word RealModeSSSP] 119 0010006B 670FB706[0A28] <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[0828]36 <4> add dword [word RealModeSSSP],54 131 <4> ; Remove from stack 132 <4> 133 0010008C 8F05[94010000] <4> pop dword [CallbackSP] 134 00100092 FF0D[98010000] <4> dec dword [CallbackCtr] 135 00100098 7506 <4> jnz .skip 136 0010009A FF15[74020000] <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[98010000] <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[94010000] <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[0828] <4> movzx edi,word [word RealModeSSSP] 164 001000C2 670FB71E[0A28] <4> movzx ebx,word [word RealModeSSSP+2] 165 001000C8 6667893E[9401] <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[0828] <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[DA020000] <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[D702] <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 00008C47 669D <4> popfd 195 00008C49 CB <4> retf 196 <4> .rm_return: 197 00008C4A 2E8B26[9401] <4> mov sp,[cs:CallbackSP] 198 00008C4F 6689C6 <4> mov esi,eax 199 00008C52 66BB[11010000] <4> mov ebx,.pm_return 200 00008C58 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[94010000] <4> pop dword [CallbackSP] 208 00100119 FF0D[98010000] <4> dec dword [CallbackCtr] 209 0010011F 7506 <4> jnz .skip 210 00100121 FF15[74020000] <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 000039A1 <4> alignb 4 221 <4> global core_pm_hook 222 000039A4 <4> CallbackSP resd 1 ; SP saved during callback 223 000039A8 <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 00008C5B 67E30F <3> bcopy: jecxz .ret 48 <3> pm_call pm_bcopy 48 00008C5E 6668[00000000] <4> push dword %1 48 00008C64 E8E2FD <4> call _pm_call 49 00008C67 6601CF <3> add edi,ecx 50 00008C6A 6601CE <3> add esi,ecx 51 00008C6D 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 00008C6E BB[BA00] <3> mov bx,pm_shuffle 72 00008C71 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 000092B0 53 <4> push ebx 48 000092B1 52 <4> push edx 49 000092B2 50 <4> push eax 50 <4> 51 000092B3 83FEFF <4> cmp esi,-1 52 000092B6 747E <4> je .bzero 53 <4> 54 000092B8 39FE <4> cmp esi,edi ; If source < destination, we might 55 000092BA 722E <4> jb .reverse ; have to copy backwards 56 <4> 57 <4> .forward: 58 <4> ; Initial alignment 59 000092BC 89FA <4> mov edx,edi 60 000092BE D1EA <4> shr edx,1 61 000092C0 7302 <4> jnc .faa1 62 000092C2 A4 <4> movsb 63 000092C3 49 <4> dec ecx 64 <4> .faa1: 65 000092C4 88C8 <4> mov al,cl 66 000092C6 83F902 <4> cmp ecx,2 67 000092C9 7216 <4> jb .f_tiny 68 <4> 69 000092CB D1EA <4> shr edx,1 70 000092CD 7305 <4> jnc .faa2 71 000092CF 66A5 <4> movsw 72 000092D1 83E902 <4> sub ecx,2 73 <4> .faa2: 74 <4> 75 <4> ; Bulk transfer 76 000092D4 88C8 <4> mov al,cl ; Save low bits 77 000092D6 C1E902 <4> shr ecx,2 ; Convert to dwords 78 000092D9 F3A5 <4> rep movsd ; Do our business 79 <4> ; At this point ecx == 0 80 <4> 81 000092DB A802 <4> test al,2 82 000092DD 7402 <4> jz .fab2 83 000092DF 66A5 <4> movsw 84 <4> .fab2: 85 <4> .f_tiny: 86 000092E1 A801 <4> test al,1 87 000092E3 7401 <4> jz .fab1 88 000092E5 A4 <4> movsb 89 <4> .fab1: 90 <4> .done: 91 000092E6 58 <4> pop eax 92 000092E7 5A <4> pop edx 93 000092E8 5B <4> pop ebx 94 000092E9 C3 <4> ret 95 <4> 96 <4> .reverse: 97 000092EA 8D440EFF <4> lea eax,[esi+ecx-1] ; Point to final byte 98 000092EE 39C7 <4> cmp edi,eax 99 000092F0 77CA <4> ja .forward ; No overlap, do forward copy 100 <4> 101 000092F2 FD <4> std ; Reverse copy 102 000092F3 8D7C0FFF <4> lea edi,[edi+ecx-1] 103 000092F7 89C6 <4> mov esi,eax 104 <4> 105 <4> ; Initial alignment 106 000092F9 89FA <4> mov edx,edi 107 000092FB D1EA <4> shr edx,1 108 000092FD 7202 <4> jc .raa1 109 000092FF A4 <4> movsb 110 00009300 49 <4> dec ecx 111 <4> .raa1: 112 <4> 113 00009301 4E <4> dec esi 114 00009302 4F <4> dec edi 115 00009303 88C8 <4> mov al,cl 116 00009305 83F902 <4> cmp ecx,2 117 00009308 7222 <4> jb .r_tiny 118 0000930A D1EA <4> shr edx,1 119 0000930C 7205 <4> jc .raa2 120 0000930E 66A5 <4> movsw 121 00009310 83E902 <4> sub ecx,2 122 <4> .raa2: 123 <4> 124 <4> ; Bulk copy 125 00009313 83EE02 <4> sub esi,2 126 00009316 83EF02 <4> sub edi,2 127 00009319 88C8 <4> mov al,cl ; Save low bits 128 0000931B C1E902 <4> shr ecx,2 129 0000931E F3A5 <4> rep movsd 130 <4> 131 <4> ; Final alignment 132 <4> .r_final: 133 00009320 83C602 <4> add esi,2 134 00009323 83C702 <4> add edi,2 135 00009326 A802 <4> test al,2 136 00009328 7402 <4> jz .rab2 137 0000932A 66A5 <4> movsw 138 <4> .rab2: 139 <4> .r_tiny: 140 0000932C 46 <4> inc esi 141 0000932D 47 <4> inc edi 142 0000932E A801 <4> test al,1 143 00009330 7401 <4> jz .rab1 144 00009332 A4 <4> movsb 145 <4> .rab1: 146 00009333 FC <4> cld 147 00009334 EBB0 <4> jmp short .done 148 <4> 149 <4> .bzero: 150 00009336 31C0 <4> xor eax,eax 151 <4> 152 <4> ; Initial alignment 153 00009338 89FA <4> mov edx,edi 154 0000933A D1EA <4> shr edx,1 155 0000933C 7302 <4> jnc .zaa1 156 0000933E AA <4> stosb 157 0000933F 49 <4> dec ecx 158 <4> .zaa1: 159 <4> 160 00009340 88CB <4> mov bl,cl 161 00009342 83F902 <4> cmp ecx,2 162 00009345 7217 <4> jb .z_tiny 163 00009347 D1EA <4> shr edx,1 164 00009349 7305 <4> jnc .zaa2 165 0000934B 66AB <4> stosw 166 0000934D 83E902 <4> sub ecx,2 167 <4> .zaa2: 168 <4> 169 <4> ; Bulk 170 00009350 88CB <4> mov bl,cl ; Save low bits 171 00009352 C1E902 <4> shr ecx,2 172 00009355 F3AB <4> rep stosd 173 <4> 174 00009357 F6C302 <4> test bl,2 175 0000935A 7402 <4> jz .zab2 176 0000935C 66AB <4> stosw 177 <4> .zab2: 178 <4> .z_tiny: 179 0000935E F6C301 <4> test bl,1 180 00009361 7401 <4> jz .zab1 181 00009363 AA <4> stosb 182 <4> .zab1: 183 00009364 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 00009366 89C7 <4> mov edi,eax 216 00009368 89D6 <4> mov esi,edx 217 <4> 218 <4> pm_shuffle: 219 0000936A FA <4> cli ; End interrupt service (for good) 220 0000936B 89FB <4> mov ebx,edi ; EBX <- descriptor list 221 0000936D 8D540F0F <4> lea edx,[edi+ecx+15] ; EDX <- where to relocate our code to 222 00009371 83E2F0 <4> and edx,~15 ; Align 16 to benefit the GDT 223 00009374 E837FFFFFF <4> call pm_bcopy 224 00009379 BE[00000000] <4> mov esi,__bcopyxx_start ; Absolute source address 225 0000937E 89D7 <4> mov edi,edx ; Absolute target address 226 00009380 29F2 <4> sub edx,esi ; EDX <- address delta 227 00009382 B9[00000000] <4> mov ecx,__bcopyxx_dwords 228 00009387 8D82[E1000000] <4> lea eax,[edx+.safe] ; Resume point 229 <4> ; Relocate this code 230 0000938D F3A5 <4> rep movsd 231 0000938F FFE0 <4> jmp eax ; Jump to safe location 232 <4> .safe: 233 <4> ; Give ourselves a safe stack 234 00009391 8DA2[80000000] <4> lea esp,[edx+bcopyxx_stack+__bcopyxx_end] 235 00009397 81C2[00000000] <4> add edx,bcopy_gdt ; EDX <- new GDT 236 0000939D 895202 <4> mov [edx+2],edx ; GDT self-pointer 237 000093A0 0F0112 <4> lgdt [edx] ; Switch to local GDT 238 <4> 239 <4> ; Now for the actual shuffling... 240 <4> .loop: 241 000093A3 8B3B <4> mov edi,[ebx] 242 000093A5 8B7304 <4> mov esi,[ebx+4] 243 000093A8 8B4B08 <4> mov ecx,[ebx+8] 244 000093AB 83C30C <4> add ebx,12 245 000093AE E307 <4> jecxz .done 246 000093B0 E8FBFEFFFF <4> call pm_bcopy 247 000093B5 EBEC <4> jmp .loop 248 <4> .done: 249 000093B7 0F015A30 <4> lidt [edx+RM_IDT_ptr-bcopy_gdt] ; RM-like IDT 250 000093BB 51 <4> push ecx ; == 0, for cleaning the flags register 251 000093BC 21F6 <4> and esi,esi 252 000093BE 7403 <4> jz pm_shuffle_16 253 000093C0 9D <4> popfd ; Clean the flags 254 000093C1 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 000093C3 89F8 <4> mov eax,edi 260 000093C5 66894212 <4> mov [edx+PM_CS16+2],ax 261 000093C9 6689421A <4> mov [edx+PM_DS16+2],ax 262 000093CD C1E810 <4> shr eax,16 263 000093D0 884214 <4> mov [edx+PM_CS16+4],al 264 000093D3 886217 <4> mov [edx+PM_CS16+7],ah 265 000093D6 88421C <4> mov [edx+PM_DS16+4],al 266 000093D9 88621F <4> mov [edx+PM_DS16+7],ah 267 000093DC 0F20C0 <4> mov eax,cr0 268 000093DF 24FE <4> and al,~1 269 000093E1 9D <4> popfd ; Clean the flags 270 <4> ; No flag-changing instructions below... 271 000093E2 66BA1800 <4> mov dx,PM_DS16 272 000093E6 8EDA <4> mov ds,edx 273 000093E8 8EC2 <4> mov es,edx 274 000093EA 8EE2 <4> mov fs,edx 275 000093EC 8EEA <4> mov gs,edx 276 000093EE 8ED2 <4> mov ss,edx 277 000093F0 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 00009400 2F00 <4> dw bcopy_gdt_size-1 ; Null descriptor - contains GDT 290 00009402 [00000000] <4> dd bcopy_gdt ; pointer for LGDT instruction 291 00009406 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 00009408 67008005 <4> dw 104-1, DummyTSS ; 08h 32-bit task state segment 298 0000940C 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 00009410 FFFF0000 <4> dd 0000ffffh ; 10h Code segment, use16, readable, 302 00009414 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 00009418 FFFF0000 <4> dd 0000ffffh ; 18h Data segment, use16, read/write, 305 0000941C 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 00009420 FFFF0000 <4> dd 0000ffffh ; 20h Code segment, use32, readable, 308 00009424 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 00009428 FFFF0000 <4> dd 0000ffffh ; 28h Data segment, use32, read/write, 311 0000942C 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 00009430 FFFF <4> RM_IDT_ptr: dw 0FFFFh ; Length (nonsense, but matches CPU) 323 00009432 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 0011033C [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 00008C74 50 <3> strcpy: push ax 8 00008C75 AC <3> .loop: lodsb 9 00008C76 AA <3> stosb 10 00008C77 20C0 <3> and al,al 11 00008C79 75FA <3> jnz .loop 12 00008C7B 58 <3> pop ax 13 00008C7C 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 001191E0 [08000000] <3> dd adv0.data 50 <3> __syslinux_adv_size: 51 001191E4 F4010000 <3> dd ADV_LEN 52 <3> 53 <3> section .adv 54 <3> ; Introduce the ADVs to valid but blank 55 <3> adv0: 56 00009800 <3> .head resd 1 57 00009804 <3> .csum resd 1 58 00009808 <3> .data resb ADV_LEN 59 000099FC <3> .tail resd 1 60 <3> .end equ $ 61 <3> adv1: 62 00009A00 <3> .head resd 1 63 00009A04 <3> .csum resd 1 64 00009A08 <3> .data resb ADV_LEN 65 00009BFC <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 00008C7D 803E[A802]FF <3> cmp byte [ADVDrive],-1 76 00008C82 0F858601 <3> jne adv_read 77 <3> 78 <3> %if IS_SYSLINUX || IS_EXTLINUX 79 00008C86 833E[2204]02 <3> cmp word [ADVSectors],2 ; Not present? 80 00008C8B 7226 <3> jb adv_verify 81 <3> 82 00008C8D 66A1607B <3> mov eax,[Hidden] 83 00008C91 668B16647B <3> mov edx,[Hidden+4] 84 00008C96 660106[9802] <3> add [ADVSec0],eax 85 00008C9B 661116[9C02] <3> adc [ADVSec0+4],edx 86 00008CA0 660106[A002] <3> add [ADVSec1],eax 87 00008CA5 661116[A402] <3> adc [ADVSec1+4],edx 88 00008CAA A0747B <3> mov al,[DriveNumber] 89 00008CAD A2[A802] <3> mov [ADVDrive],al 90 00008CB0 E95901 <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 00008CB3 803E[A802]FF <3> cmp byte [ADVDrive],-1 ; No ADV configured, still? 98 00008CB8 7410 <3> je .reset ; Then unconditionally reset 99 <3> 100 00008CBA BE[0000] <3> mov si,adv0 101 00008CBD E83900 <3> call .check_adv 102 00008CC0 742C <3> jz .ok ; Primary ADV okay 103 00008CC2 BE[0002] <3> mov si,adv1 104 00008CC5 E83100 <3> call .check_adv 105 00008CC8 7425 <3> jz .adv1ok 106 <3> 107 <3> ; Neither ADV is usable; initialize to blank 108 <3> .reset: 109 00008CCA BF[0000] <3> mov di,adv0 110 00008CCD 66B8A52F2D5A <3> mov eax,ADV_MAGIC1 111 00008CD3 66AB <3> stosd 112 00008CD5 66B8671704A3 <3> mov eax,ADV_MAGIC2 113 00008CDB 66AB <3> stosd 114 00008CDD 6631C0 <3> xor eax,eax 115 00008CE0 B97D00 <3> mov cx,ADV_LEN/4 116 00008CE3 F366AB <3> rep stosd 117 00008CE6 66B864BF28DD <3> mov eax,ADV_MAGIC3 118 00008CEC 66AB <3> stosd 119 <3> 120 <3> .ok: 121 00008CEE C3 <3> ret 122 <3> 123 <3> ; The primary ADV is bad, but the backup is OK 124 <3> .adv1ok: 125 00008CEF BF[0000] <3> mov di,adv0 126 00008CF2 B98000 <3> mov cx,512/4 127 00008CF5 F366A5 <3> rep movsd 128 00008CF8 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 00008CF9 56 <3> push si 135 00008CFA 66AD <3> lodsd 136 00008CFC 663DA52F2D5A <3> cmp eax,ADV_MAGIC1 137 00008D02 751E <3> jne .done ; ZF=0, i.e. bad 138 00008D04 6631D2 <3> xor edx,edx 139 00008D07 B97E00 <3> mov cx,ADV_LEN/4+1 ; Remaining dwords 140 <3> .csum: 141 00008D0A 66AD <3> lodsd 142 00008D0C 6601C2 <3> add edx,eax 143 00008D0F E2F9 <3> loop .csum 144 00008D11 6681FA671704A3 <3> cmp edx,ADV_MAGIC2 145 00008D18 7508 <3> jne .done 146 00008D1A 66AD <3> lodsd 147 00008D1C 663D64BF28DD <3> cmp eax,ADV_MAGIC3 148 <3> .done: 149 00008D22 5E <3> pop si 150 00008D23 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 00008D24 50 <3> push ax 165 00008D25 BE[0800] <3> mov si,adv0.data 166 00008D28 31C0 <3> xor ax,ax ; Keep AH=0 at all times 167 <3> .loop: 168 00008D2A AC <3> lodsb ; Read ID 169 00008D2B 38D0 <3> cmp al,dl 170 00008D2D 740F <3> je .found 171 00008D2F 20C0 <3> and al,al 172 00008D31 7415 <3> jz .end 173 00008D33 AC <3> lodsb ; Read length 174 00008D34 01C6 <3> add si,ax 175 00008D36 81FE[FC01] <3> cmp si,adv0.tail 176 00008D3A 72EE <3> jb .loop 177 00008D3C EB0A <3> jmp .end 178 <3> 179 <3> .found: 180 00008D3E AC <3> lodsb 181 00008D3F 89C1 <3> mov cx,ax 182 00008D41 01F0 <3> add ax,si ; Make sure it fits 183 00008D43 3D[FC01] <3> cmp ax,adv0.tail 184 00008D46 7602 <3> jbe .ok 185 <3> .end: 186 00008D48 31C9 <3> xor cx,cx 187 <3> .ok: 188 00008D4A 58 <3> pop ax 189 00008D4B 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 00008D4C 50 <3> push ax 204 00008D4D 56 <3> push si 205 00008D4E 57 <3> push di 206 00008D4F 20ED <3> and ch,ch 207 00008D51 7559 <3> jnz .overflow 208 <3> 209 00008D53 51 <3> push cx 210 00008D54 BE[0800] <3> mov si,adv0.data 211 00008D57 31C0 <3> xor ax,ax 212 <3> .loop: 213 00008D59 AC <3> lodsb 214 00008D5A 38D0 <3> cmp al,dl 215 00008D5C 740F <3> je .found 216 00008D5E 20C0 <3> and al,al 217 00008D60 7423 <3> jz .endz 218 00008D62 AC <3> lodsb 219 00008D63 01C6 <3> add si,ax 220 00008D65 81FE[FC01] <3> cmp si,adv0.tail 221 00008D69 72EE <3> jb .loop 222 00008D6B EB19 <3> jmp .end 223 <3> 224 <3> .found: ; Found, need to delete old copy 225 00008D6D AC <3> lodsb 226 00008D6E 8D7CFE <3> lea di,[si-2] 227 00008D71 57 <3> push di 228 00008D72 01C6 <3> add si,ax 229 00008D74 B9[FC01] <3> mov cx,adv0.tail 230 00008D77 29F1 <3> sub cx,si 231 00008D79 7207 <3> jb .nukeit 232 00008D7B F3A4 <3> rep movsb ; Remove the old one 233 00008D7D 8825 <3> mov [di],ah ; Termination zero 234 00008D7F 5E <3> pop si 235 00008D80 EBD7 <3> jmp .loop 236 <3> .nukeit: 237 00008D82 5E <3> pop si 238 00008D83 EB01 <3> jmp .end 239 <3> .endz: 240 00008D85 4E <3> dec si 241 <3> .end: 242 <3> ; Now SI points to where we want to put our data 243 00008D86 59 <3> pop cx 244 00008D87 89F7 <3> mov di,si 245 00008D89 E313 <3> jcxz .empty 246 00008D8B 01CE <3> add si,cx 247 00008D8D 81FE[FA01] <3> cmp si,adv0.tail-2 248 00008D91 7319 <3> jae .overflow ; CF=0 249 <3> 250 00008D93 89DE <3> mov si,bx 251 00008D95 88D0 <3> mov al,dl 252 00008D97 AA <3> stosb 253 00008D98 88C8 <3> mov al,cl 254 00008D9A AA <3> stosb 255 00008D9B F364A4 <3> fs rep movsb 256 <3> 257 <3> .empty: 258 00008D9E B9[FC01] <3> mov cx,adv0.tail 259 00008DA1 29F9 <3> sub cx,di 260 00008DA3 31C0 <3> xor ax,ax 261 00008DA5 F3AA <3> rep stosb ; Zero-fill remainder 262 <3> 263 00008DA7 F8 <3> clc 264 <3> .done: 265 00008DA8 5F <3> pop di 266 00008DA9 5E <3> pop si 267 00008DAA 58 <3> pop ax 268 00008DAB C3 <3> ret 269 <3> .overflow: 270 00008DAC F9 <3> stc 271 00008DAD 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 00008DAF 6660 <3> pushad 279 00008DB1 BE[0800] <3> mov si,adv0.data 280 00008DB4 B97D00 <3> mov cx,ADV_LEN/4 281 00008DB7 6631D2 <3> xor edx,edx 282 <3> .loop: 283 00008DBA 66AD <3> lodsd 284 00008DBC 6601C2 <3> add edx,eax 285 00008DBF E2F9 <3> loop .loop 286 00008DC1 66B8671704A3 <3> mov eax,ADV_MAGIC2 287 00008DC7 6629D0 <3> sub eax,edx 288 00008DCA 8D7C04 <3> lea di,[si+4] ; adv1 289 00008DCD BE[0000] <3> mov si,adv0 290 00008DD0 66894404 <3> mov [si+4],eax ; Store checksum 291 00008DD4 B98000 <3> mov cx,(ADV_LEN+12)/4 292 00008DD7 F366A5 <3> rep movsd 293 00008DDA 6661 <3> popad 294 00008DDC 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 00008DDD 6650 <3> push eax 307 00008DDF 66A1[9802] <3> mov eax,[ADVSec0] 308 00008DE3 660B06[9C02] <3> or eax,[ADVSec0+4] 309 00008DE8 741E <3> je .bad 310 00008DEA 66A1[A002] <3> mov eax,[ADVSec1] 311 00008DEE 660B06[A402] <3> or eax,[ADVSec1+4] 312 00008DF3 7413 <3> je .bad 313 00008DF5 803E[A802]FF <3> cmp byte [ADVDrive],-1 314 00008DFA 740C <3> je .bad 315 <3> 316 00008DFC E8B0FF <3> call adv_cleanup 317 00008DFF B403 <3> mov ah,3 ; Write 318 00008E01 E81300 <3> call adv_read_write 319 <3> 320 00008E04 F8 <3> clc 321 00008E05 6658 <3> pop eax 322 00008E07 C3 <3> ret 323 <3> .bad: ; No location for ADV set 324 00008E08 F9 <3> stc 325 00008E09 6658 <3> pop eax 326 00008E0B 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 00008E0C 50 <3> push ax 336 00008E0D B402 <3> mov ah,2 ; Read 337 00008E0F E80500 <3> call adv_read_write 338 00008E12 E89EFE <3> call adv_verify 339 00008E15 58 <3> pop ax 340 00008E16 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 00008E17 8826[9C01] <3> mov [ADVOp],ah 350 00008E1B 6660 <3> pushad 351 <3> 352 <3> ; Check for EDD 353 00008E1D BBAA55 <3> mov bx,55AAh 354 00008E20 B441 <3> mov ah,41h ; EDD existence query 355 00008E22 8A16[A802] <3> mov dl,[ADVDrive] 356 00008E26 CD13 <3> int 13h 357 00008E28 BE[1F05] <3> mov si,.cbios 358 00008E2B 720E <3> jc .noedd 359 00008E2D 81FB55AA <3> cmp bx,0AA55h 360 00008E31 7508 <3> jne .noedd 361 00008E33 F6C101 <3> test cl,1 362 00008E36 7403 <3> jz .noedd 363 00008E38 BE[EF04] <3> mov si,.ebios 364 <3> .noedd: 365 <3> 366 00008E3B 66A1[9802] <3> mov eax,[ADVSec0] 367 00008E3F 668B16[9C02] <3> mov edx,[ADVSec0+4] 368 00008E44 BB[0000] <3> mov bx,adv0 369 00008E47 E81200 <3> call .doone 370 <3> 371 00008E4A 66A1[A002] <3> mov eax,[ADVSec1] 372 00008E4E 668B16[A402] <3> mov edx,[ADVSec1+4] 373 00008E53 BB[0002] <3> mov bx,adv1 374 00008E56 E80300 <3> call .doone 375 <3> 376 00008E59 6661 <3> popad 377 00008E5B C3 <3> ret 378 <3> 379 <3> .doone: 380 00008E5C 56 <3> push si 381 00008E5D FFE6 <3> jmp si 382 <3> 383 <3> .ebios: 384 00008E5F B90600 <3> mov cx,adv_retries 385 <3> .eb_retry: 386 <3> ; Form DAPA on stack 387 00008E62 6652 <3> push edx 388 00008E64 6650 <3> push eax 389 00008E66 06 <3> push es 390 00008E67 53 <3> push bx 391 00008E68 6A01 <3> push word 1 ; Sector count 392 00008E6A 6A10 <3> push word 16 ; DAPA size 393 00008E6C 89E6 <3> mov si,sp 394 00008E6E 6660 <3> pushad 395 00008E70 8A16[A802] <3> mov dl,[ADVDrive] 396 00008E74 B80040 <3> mov ax,4000h 397 00008E77 0A26[9C01] <3> or ah,[ADVOp] 398 00008E7B 1E <3> push ds 399 00008E7C 16 <3> push ss 400 00008E7D 1F <3> pop ds 401 00008E7E CD13 <3> int 13h 402 00008E80 1F <3> pop ds 403 00008E81 6661 <3> popad 404 00008E83 8D6410 <3> lea sp,[si+16] ; Remove DAPA 405 00008E86 7202 <3> jc .eb_error 406 00008E88 5E <3> pop si 407 00008E89 C3 <3> ret 408 <3> .eb_error: 409 00008E8A E2D6 <3> loop .eb_retry 410 00008E8C F9 <3> stc 411 00008E8D 5E <3> pop si 412 00008E8E C3 <3> ret 413 <3> 414 <3> .cbios: 415 00008E8F 6652 <3> push edx 416 00008E91 6650 <3> push eax 417 00008E93 55 <3> push bp 418 <3> 419 00008E94 6621D2 <3> and edx,edx ; > 2 TiB not possible 420 00008E97 7573 <3> jnz .cb_overflow 421 <3> 422 00008E99 8A16[A802] <3> mov dl,[ADVDrive] 423 00008E9D 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 00008E9F 791B <3> jns .noparm ; Floppy drive... urk 428 <3> 429 00008EA1 B408 <3> mov ah,08h ; Get disk parameters 430 00008EA3 CD13 <3> int 13h 431 00008EA5 7215 <3> jc .noparm 432 00008EA7 20E4 <3> and ah,ah 433 00008EA9 7511 <3> jnz .noparm 434 00008EAB C1EA08 <3> shr dx,8 435 00008EAE 42 <3> inc dx 436 00008EAF 660FB7FA <3> movzx edi,dx ; EDI = heads 437 00008EB3 83E13F <3> and cx,3fh 438 00008EB6 660FB7F1 <3> movzx esi,cx ; ESI = sectors/track 439 00008EBA EB12 <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 00008EBC 3A16747B <3> cmp dl,[DriveNumber] 445 00008EC0 754A <3> jne .cb_overflow ; Fatal error! 446 00008EC2 660FB736[1800] <3> movzx esi,word [bsSecPerTrack] 447 00008EC8 660FB73E[1A00] <3> movzx edi,word [bsHeads] 448 <3> %else 449 <3> ; Not a disk-based derivative... there is no hope 450 <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 00008ECE 6631D2 <3> xor edx,edx 459 00008ED1 66F7F6 <3> div esi 460 00008ED4 31C9 <3> xor cx,cx 461 00008ED6 87CA <3> xchg cx,dx ; CX <- sector index (0-based) 462 <3> ; EDX <- 0 463 <3> ; eax = track # 464 00008ED8 66F7F7 <3> div edi ; Convert track to head/cyl 465 <3> 466 <3> ; Watch out for overflow, we might be writing! 467 00008EDB 663DFF030000 <3> cmp eax,1023 468 00008EE1 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 00008EE3 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 00008EE6 41 <3> inc cx ; Sector numbers are 1-based, sigh 480 00008EE7 08E1 <3> or cl,ah 481 00008EE9 88C5 <3> mov ch,al 482 00008EEB 88D6 <3> mov dh,dl 483 00008EED 8A16[A802] <3> mov dl,[ADVDrive] 484 00008EF1 B001 <3> mov al,01h ; Transfer one sector 485 00008EF3 8A26[9C01] <3> mov ah,[ADVOp] ; Operation 486 <3> 487 00008EF7 BD0600 <3> mov bp,adv_retries 488 <3> .cb_retry: 489 00008EFA 6660 <3> pushad 490 00008EFC CD13 <3> int 13h 491 00008EFE 6661 <3> popad 492 00008F00 7207 <3> jc .cb_error 493 <3> 494 <3> .cb_done: 495 00008F02 5D <3> pop bp 496 00008F03 6658 <3> pop eax 497 00008F05 665A <3> pop edx 498 00008F07 5E <3> pop si 499 00008F08 C3 <3> ret 500 <3> 501 <3> .cb_error: 502 00008F09 4D <3> dec bp 503 00008F0A 75EE <3> jnz .cb_retry 504 <3> .cb_overflow: 505 00008F0C F9 <3> stc 506 00008F0D EBF3 <3> jmp .cb_done 507 <3> 508 <3> section .data16 509 000096D7 00 <3> alignz 8 510 000096D8 0000000000000000 <3> ADVSec0 dq 0 ; Not specified 511 000096E0 0000000000000000 <3> ADVSec1 dq 0 ; Not specified 512 000096E8 FF <3> ADVDrive db -1 ; No ADV defined 513 000096E9 FF <3> ADVCHSInfo db -1 ; We have CHS info for this drive 514 <3> 515 <3> section .bss16 516 000039AC <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 00008F0F 66A17000 <3> mov eax,[BIOS_timer_hook] 31 00008F13 66A3[CF05] <3> mov [BIOS_timer_next],eax 32 00008F17 66C7067000- <3> mov dword [BIOS_timer_hook],timer_irq 32 00008F1C [BA050000] <3> 33 00008F20 C3 <3> ret 34 <3> 35 <3> global bios_timer_cleanup:function hidden 36 <3> bios_timer_cleanup: 37 <3> ; Unhook INT 1Ch 38 00008F21 66A1[CF05] <3> mov eax,[BIOS_timer_next] 39 00008F25 66A37000 <3> mov [BIOS_timer_hook],eax 40 00008F29 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 00008F2A 2E66FF06[AC02] <3> inc dword [cs:__jiffies] 49 00008F30 2E8106[B402]E8EC <3> add word [cs:__ms_timer_adj],0xece8 50 00008F37 2E668316[B002]36 <3> adc dword [cs:__ms_timer],0x36 51 00008F3E 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 000096EA 00 <3> alignz 4 57 <3> global __jiffies:data hidden, __ms_timer 58 000096EC 00000000 <3> __jiffies dd 0 ; Clock tick timer 59 000096F0 00000000 <3> __ms_timer dd 0 ; Millisecond timer 60 000096F4 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 [1C020000] <3> pfx_cdatalen dd lzo_data_size ; Pointer to compressed size field 10 <3> %if IS_ISOLINUX 11 <3> pfx_checksum dd bi_length ; File length and checksum fields 12 <3> %else 13 0000000C 00000000 <3> pfx_checksum dd 0 ; No checksum 14 <3> %endif 15 00000010 00000200 <3> pfx_maxlma dd MaxLMA ; Maximum size 16 <3> 17 <3> section .text16 118 <1> 119 <1> ; ----------------------------------------------------------------------------- 120 <1> ; Begin data section 121 <1> ; ----------------------------------------------------------------------------- 122 <1> 123 <1> section .data16 124 <1> global copyright_str 125 000096F6 20436F707972696768- <1> copyright_str db ' Copyright (C) 1994-' 125 000096FF 742028432920313939- <1> 125 00009708 342D <1> 126 0000970A 32303135 <1> asciidec YEAR 127 0000970E 20482E205065746572- <1> db ' H. Peter Anvin et al', CR, LF, 0 127 00009717 20416E76696E206574- <1> 127 00009720 20616C0D0A00 <1> 128 00009726 0D0A426F6F74206661- <1> err_bootfailed db CR, LF, 'Boot failed: please change disks and press ' 128 0000972F 696C65643A20706C65- <1> 128 00009738 617365206368616E67- <1> 128 00009741 65206469736B732061- <1> 128 0000974A 6E6420707265737320 <1> 129 00009753 61206B657920746F20- <1> db 'a key to continue.', CR, LF, 0 129 0000975C 636F6E74696E75652E- <1> 129 00009765 0D0A00 <1> 130 <1> 131 <1> ; 132 <1> ; Misc initialized (data) variables 133 <1> ; 134 <1> %ifdef debug ; This code for debugging only 135 <1> debug_magic dw 0D00Dh ; Debug code sentinel 136 <1> %endif