📄 isolinux.asm
字号:
; -*- fundamental -*- (asm-mode sucks); $Id: isolinux.asm,v 1.95 2004/05/29 22:11:23 hpa Exp $; ****************************************************************************;; isolinux.asm;; A program to boot Linux kernels off a CD-ROM using the El Torito; boot standard in "no emulation" mode, making the entire filesystem; available. It is based on the SYSLINUX boot loader for MS-DOS; floppies.;; Copyright (C) 1994-2004 H. Peter Anvin;; This program is free software; you can redistribute it and/or modify; it under the terms of the GNU General Public License as published by; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,; USA; either version 2 of the License, or (at your option) any later; version; incorporated herein by reference.; ; ****************************************************************************%define IS_ISOLINUX 1%include "macros.inc"%include "config.inc"%include "kernel.inc"%include "bios.inc"%include "tracers.inc";; Some semi-configurable constants... change on your own risk.;my_id equ isolinux_idFILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null)FILENAME_MAX equ (1 << FILENAME_MAX_LG2)NULLFILE equ 0 ; Zero byte == null file nameretry_count equ 6 ; How patient are we with the BIOS?%assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the topMAX_OPEN_LG2 equ 6 ; log2(Max number of open files)MAX_OPEN equ (1 << MAX_OPEN_LG2)SECTORSIZE_LG2 equ 11 ; 2048 bytes/sector (El Torito requirement)SECTORSIZE equ (1 << SECTORSIZE_LG2);; This is what we need to do when idle;%macro RESET_IDLE 0 ; Nothing%endmacro%macro DO_IDLE 0 ; Nothing%endmacro;; The following structure is used for "virtual kernels"; i.e. LILO-style; option labels. The options we permit here are `kernel' and `append; Since there is no room in the bottom 64K for all of these, we; stick them at vk_seg:0000 and copy them down before we need them.;; Note: this structure can be added to, but it must ;%define vk_power 6 ; log2(max number of vkernels)%define max_vk (1 << vk_power) ; Maximum number of vkernels%define vk_shift (16-vk_power) ; Number of bits to shift%define vk_size (1 << vk_shift) ; Size of a vkernel buffer struc vkernelvk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!**vk_rname: resb FILENAME_MAX ; Real namevk_appendlen: resw 1 alignb 4vk_append: resb max_cmd_len+1 ; Command line alignb 4vk_end: equ $ ; Should be <= vk_size endstruc%ifndef DEPEND%if (vk_end > vk_size) || (vk_size*max_vk > 65536)%error "Too many vkernels defined, reduce vk_power"%endif%endif;; Segment assignments in the bottom 640K; 0000h - main code/data segment (and BIOS segment);real_mode_seg equ 3000hvk_seg equ 2000h ; Virtual kernelsxfer_buf_seg equ 1000h ; Bounce buffer for I/O to high memcomboot_seg equ real_mode_seg ; COMBOOT image loading zone;; File structure. This holds the information for each currently open file.; struc open_file_tfile_sector resd 1 ; Sector pointer (0 = structure free)file_left resd 1 ; Number of sectors left endstruc%ifndef DEPEND%if (open_file_t_size & (open_file_t_size-1))%error "open_file_t is not a power of 2"%endif%endif; ---------------------------------------------------------------------------; BEGIN CODE; ---------------------------------------------------------------------------;; Memory below this point is reserved for the BIOS and the MBR; absolute 1000htrackbuf resb 8192 ; Track buffer goes heretrackbufsize equ $-trackbuf; trackbuf ends at 3000h;; Constants for the xfer_buf_seg;; The xfer_buf_seg is also used to store message file buffers. We; need two trackbuffers (text and graphics), plus a work buffer; for the graphics decompressor.;xbs_textbuf equ 0 ; Also hard-coded, do not changexbs_vgabuf equ trackbufsizexbs_vgatmpbuf equ 2*trackbufsize struc dir_tdir_lba resd 1 ; Directory start (LBA)dir_len resd 1 ; Length in bytesdir_clust resd 1 ; Length in clusters endstruc absolute 5000h ; Here we keep our BSS stuffVKernelBuf: resb vk_size ; "Current" vkernel alignb 4AppendBuf resb max_cmd_len+1 ; append=Ontimeout resb max_cmd_len+1 ; ontimeoutOnerror resb max_cmd_len+1 ; onerrorKbdMap resb 256 ; Keyboard mapFKeyName resb 10*FILENAME_MAX ; File names for F-key helpNumBuf resb 15 ; Buffer to load numberNumBufEnd resb 1 ; Last byte in NumBufISOFileName resb 64 ; ISO filename canonicalization bufferISOFileNameEnd equ $ alignb 32KernelName resb FILENAME_MAX ; Mangled name for kernelKernelCName resb FILENAME_MAX ; Unmangled kernel nameInitRDCName resb FILENAME_MAX ; Unmangled initrd nameMNameBuf resb FILENAME_MAXInitRD resb FILENAME_MAXPartInfo resb 16 ; Partition table entryE820Buf resd 5 ; INT 15:E820 data bufferE820Mem resd 1 ; Memory detected by E820E820Max resd 1 ; Is E820 memory capped?HiLoadAddr resd 1 ; Address pointer for high load loopHighMemSize resd 1 ; End of memory pointer (bytes)RamdiskMax resd 1 ; Highest address for a ramdiskKernelSize resd 1 ; Size of kernel (bytes)SavedSSSP resd 1 ; Our SS:SP while running a COMBOOT imagePMESP resd 1 ; Protected-mode ESPRootDir resb dir_t_size ; Root directoryCurDir resb dir_t_size ; Current directoryKernelClust resd 1 ; Kernel size in clustersInitStack resd 1 ; Initial stack pointer (SS:SP)FirstSecSum resd 1 ; Checksum of bytes 64-2048ImageDwords resd 1 ; isolinux.bin size, dwordsFBytes equ $ ; Used by open/getcFBytes1 resw 1FBytes2 resw 1FClust resw 1 ; Number of clusters in open/getc fileFNextClust resw 1 ; Pointer to next cluster in d:oFPtr resw 1 ; Pointer to next char in bufferCmdOptPtr resw 1 ; Pointer to first option on cmd lineKernelCNameLen resw 1 ; Length of unmangled kernel nameInitRDCNameLen resw 1 ; Length of unmangled initrd nameNextCharJump resw 1 ; Routine to interpret next print charSetupSecs resw 1 ; Number of setup sectorsA20Test resw 1 ; Counter for testing status of A20A20Type resw 1 ; A20 typeCmdLineLen resw 1 ; Length of command line including nullGraphXSize resw 1 ; Width of splash screen fileVGAPos resw 1 ; Pointer into VGA memoryVGACluster resw 1 ; Cluster pointer for VGA image fileVGAFilePtr resw 1 ; Pointer into VGAFileBufCom32SysSP resw 1 ; SP saved during COM32 syscallConfigFile resw 1 ; Socket for config filePktTimeout resw 1 ; Timeout for current packetKernelExtPtr resw 1 ; During search, final null pointerLocalBootType resw 1 ; Local boot return codeImageSectors resw 1 ; isolinux.bin size, sectorsDiskSys resw 1 ; Last INT 13h callCursorDX equ $CursorCol resb 1 ; Cursor column for message fileCursorRow resb 1 ; Cursor row for message fileScreenSize equ $VidCols resb 1 ; Columns on screen-1VidRows resb 1 ; Rows on screen-1BaudDivisor resw 1 ; Baud rate divisorFlowControl equ $FlowOutput resb 1 ; Outputs to assert for serial flowFlowInput resb 1 ; Input bits for serial flowFlowIgnore resb 1 ; Ignore input unless these bits setTextAttribute resb 1 ; Text attribute for message fileRetryCount resb 1 ; Used for disk access retriesKbdFlags resb 1 ; Check for keyboard escapesLoadFlags resb 1 ; Loadflags from kernelA20Tries resb 1 ; Times until giving up on A20FuncFlag resb 1 ; == 1 if <Ctrl-F> pressedDisplayMask resb 1 ; Display modes maskISOFlags resb 1 ; Flags for ISO directory searchDiskError resb 1 ; Error code for disk I/ODriveNo resb 1 ; CD-ROM BIOS drive numberTextColorReg resb 17 ; VGA color registers for text modeVGAFileBuf resb FILENAME_MAX ; Unmangled VGA image nameVGAFileBufEnd equ $VGAFileMBuf resb FILENAME_MAX ; Mangled VGA image name alignb open_file_t_sizeFiles resb MAX_OPEN*open_file_t_size section .text org 7C00h;;;; Primary entry point. Because BIOSes are buggy, we only load the first;; CD-ROM sector (2K) of the file, so the number one priority is actually;; loading the rest.;;bootsec equ $StackBuf equ $-44_start: ; Far jump makes sure we canonicalize the address cli jmp 0:_start1 times 8-($-$$) nop ; Pad to file offset 8 ; This table gets filled in by mkisofs using the ; -boot-info-table optionbi_pvd: dd 0xdeadbeef ; LBA of primary volume descriptorbi_file: dd 0xdeadbeef ; LBA of boot filebi_length: dd 0xdeadbeef ; Length of boot filebi_csum: dd 0xdeadbeef ; Checksum of boot filebi_reserved: times 10 dd 0xdeadbeef ; Reserved_start1: mov [cs:InitStack],sp ; Save initial stack pointer mov [cs:InitStack+2],ss xor ax,ax mov ss,ax mov sp,StackBuf ; Set up stack mov ds,ax mov es,ax mov fs,ax mov gs,ax sti cld ; Show signs of life mov si,syslinux_banner call writestr%ifdef DEBUG_MESSAGES mov si,copyright_str call writestr%endif ; ; Before modifying any memory, get the checksum of bytes ; 64-2048 ;initial_csum: xor edi,edi mov si,_start1 mov cx,(SECTORSIZE-64) >> 2.loop: lodsd add edi,eax loop .loop mov [FirstSecSum],edi ; Set up boot file sizes mov eax,[bi_length] sub eax,SECTORSIZE-3 shr eax,2 ; bytes->dwords mov [ImageDwords],eax ; boot file dwords add eax,(2047 >> 2) shr eax,9 ; dwords->sectors mov [ImageSectors],ax ; boot file sectors mov [DriveNo],dl%ifdef DEBUG_MESSAGES mov si,startup_msg call writemsg mov al,dl call writehex2 call crlf%endif ; Now figure out what we're actually doing ; Note: use passed-in DL value rather than 7Fh because ; at least some BIOSes will get the wrong value otherwise mov ax,4B01h ; Get disk emulation status mov dl,[DriveNo] mov si,spec_packet int 13h jc award_hack ; changed for BrokenAwardHack mov dl,[DriveNo] cmp [sp_drive],dl ; Should contain the drive number jne spec_query_failed%ifdef DEBUG_MESSAGES mov si,spec_ok_msg call writemsg mov al,byte [sp_drive] call writehex2 call crlf%endiffound_drive: ; Some BIOSes apparently have limitations on the size ; that may be loaded (despite the El Torito spec being very ; clear on the fact that it must all be loaded.) Therefore, ; we load it ourselves, and *bleep* the BIOS. mov eax,[bi_file] ; Address of code to load inc eax ; Don't reload bootstrap code%ifdef DEBUG_MESSAGES mov si,offset_msg call writemsg call writehex8 call crlf%endif ; Just in case some BIOSes have problems with ; segment wraparound, use the normalized address mov bx,((7C00h+2048) >> 4) mov es,bx xor bx,bx mov bp,[ImageSectors]%ifdef DEBUG_MESSAGES push ax mov si,size_msg call writemsg mov ax,bp call writehex4 call crlf pop ax%endif call getlinsec push ds pop es%ifdef DEBUG_MESSAGES mov si,loaded_msg call writemsg%endif ; Verify the checksum on the loaded image.verify_image: mov si,7C00h+2048 mov bx,es mov ecx,[ImageDwords] mov edi,[FirstSecSum] ; First sector checksum.loop es lodsd add edi,eax dec ecx jz .done and si,si jnz .loop ; SI wrapped around, advance ES add bx,1000h mov es,bx jmp short .loop.done: mov ax,ds mov es,ax cmp [bi_csum],edi je integrity_ok mov si,checkerr_msg call writemsg jmp kaboomintegrity_ok:%ifdef DEBUG_MESSAGES mov si,allread_msg call writemsg%endif jmp all_read ; Jump to main code;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; There is a problem with certain versions of the AWARD BIOS ... ;; the boot sector will be loaded and executed correctly, but, because the;; int 13 vector points to the wrong code in the BIOS, every attempt to;; load the spec packet will fail. We scan for the equivalent of;;;; mov ax,0201h;; mov bx,7c00h;; mov cx,0006h;; mov dx,0180h;; pushf;; call <direct far>;;;; and use <direct far> as the new vector for int 13. The code above is;; used to load the boot code into ram, and there should be no reason;; for anybody to change it now or in the future. There are no opcodes;; that use encodings relativ to IP, so scanning is easy. If we find the;; code above in the BIOS code we can be pretty sure to run on a machine;; with an broken AWARD BIOS ... ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;%ifdef DEBUG_MESSAGES ;; ;;award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;;award_not_orig db "BAH: Original Int 13 vector : ",0 ;;award_not_new db "BAH: Int 13 vector changed to : ",0 ;;award_not_succ db "BAH: SUCCESS",CR,LF,0 ;;award_not_fail db "BAH: FAILURE" ;;award_not_crlf db CR,LF,0 ;; ;;%endif ;; ;;award_oldint13 dd 0 ;;award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;award_hack: mov si,spec_err_msg ; Moved to this place from call writemsg ; spec_query_faild ;%ifdef DEBUG_MESSAGES ; ; mov si,award_notice ; display our plan call writemsg ; mov si,award_not_orig ; display original int 13 call writemsg ; vector%endif ; mov eax,[13h*4] ; mov [award_oldint13],eax ; ;%ifdef DEBUG_MESSAGES ; ; call writehex8 ; mov si,award_not_crlf ; call writestr ;%endif ; push es ; save ES mov ax,0f000h ; ES = BIOS Seg mov es,ax ; cld ; xor di,di ; start at ES:DI = f000:0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -