📄 ldlinux.asm
字号:
mov si,copyright_str call writestr;; Common initialization code;%include "cpuinit.inc";; Initialization that does not need to go into the any of the pre-load; areas; ; Now set up screen parameters call adjust_screen ; Wipe the F-key area mov al,NULLFILE mov di,FKeyName mov cx,10*(1 << FILENAME_MAX_LG2) rep stosb;; Now, everything is "up and running"... patch kaboom for more; verbosity and using the full screen system; ; E9 = JMP NEAR mov dword [kaboom.patch],0e9h+((kaboom2-(kaboom.patch+3)) << 8);; Compute some parameters that depend on cluster size; xor eax,eax cwd ; DX <- 0 inc dx ; DX:AX <- 64K div word [ClustSize] mov [ClustPerMoby],eax ; Clusters/64K;; Now we're all set to start with our *real* business. First load the; configuration file (if any) and parse it.;; In previous versions I avoided using 32-bit registers because of a; rumour some BIOSes clobbered the upper half of 32-bit registers at; random. I figure, though, that if there are any of those still left; they probably won't be trying to install Linux on them...;; The code is still ripe with 16-bitisms, though. Not worth the hassle; to take'm out. In fact, we may want to put them back if we're going; to boot ELKS at some point.; mov si,linuxauto_cmd ; Default command: "linux auto" mov di,default_cmd mov cx,linuxauto_len rep movsb mov di,KbdMap ; Default keymap 1:1 xor al,al inc ch ; CX <- 256mkkeymap: stosb inc al loop mkkeymap;; Load configuration file; mov di,syslinux_cfg call open jz no_config_file;; Now we have the config file open. Parse the config file and; run the user interface.;%include "ui.inc";; Linux kernel loading code is common.;%include "runkernel.inc";; COMBOOT-loading code;%include "comboot.inc"%include "com32.inc"%include "cmdline.inc";; Boot sector loading code;%include "bootsect.inc";; abort_check: let the user abort with <ESC> or <Ctrl-C>;abort_check: call pollchar jz ac_ret1 pusha call getchar cmp al,27 ; <ESC> je ac_kill cmp al,3 ; <Ctrl-C> jne ac_ret2ac_kill: mov si,aborted_msg;; abort_load: Called by various routines which wants to print a fatal; error message and return to the command prompt. Since this; may happen at just about any stage of the boot process, assume; our state is messed up, and just reset the segment registers; and the stack forcibly.;; SI = offset (in _text) of error message to print;abort_load: mov ax,cs ; Restore CS = DS = ES mov ds,ax mov es,ax cli mov sp,StackBuf-2*3 ; Reset stack mov ss,ax ; Just in case... sti call cwritestr ; Expects SI -> error msgal_ok: jmp enter_command ; Return to command prompt;; End of abort_check;ac_ret2: popaac_ret1: ret;; searchdir: Search the root directory for a pre-mangled filename in; DS:DI. This routine is similar to the one in the boot; sector, but is a little less Draconian when it comes to; error handling, plus it reads the root directory in; larger chunks than a sector at a time (which is probably; a waste of coding effort, but I like to do things right).;; FIXME: usually we can load the entire root dir in memory,; and files are usually at the beginning anyway. It probably; would be worthwhile to remember if we have the first chunk; in memory and skip the load if that (it would speed up online; help, mainly.);; NOTE: This file considers finding a zero-length file an; error. This is so we don't have to deal with that special; case elsewhere in the program (most loops have the test; at the end).;; If successful:; ZF clear; SI = cluster # for the first cluster; DX:AX = file length in bytes; If unsuccessful; ZF set;searchdir: push bp mov ax,[bsRootDirEnts] mov [DirScanCtr],ax mov ax,[RootDirSize] mov [DirBlocksLeft],ax mov eax,[RootDir]scan_group: movzx ebp,word [DirBlocksLeft] and bp,bp jz dir_return cmp bp,[BufSafeSec] jna load_last mov bp,[BufSafeSec]load_last: sub [DirBlocksLeft],bp push eax mov ax,[bsBytesPerSec] mul bp add ax,trackbuf-31 mov [EndofDirSec],ax ; End of loaded pop eax mov bx,trackbuf call getlinsecsr mov si,trackbufdir_test_name: cmp byte [si],0 ; Directory high water mark je dir_return ; Failed test byte [si+11],18h ; Check it really is a file jnz dir_not_this push di push si mov cx,11 ; Filename = 11 bytes repe cmpsb pop si pop di je dir_successdir_not_this: add si,byte 32 dec word [DirScanCtr] jz dir_return ; Out of it... cmp si,[EndofDirSec] jb dir_test_name add eax,ebp ; Increment linear sector number jmp short scan_groupdir_success: mov ax,[si+28] ; Length of file mov dx,[si+30] mov si,[si+26] ; Cluster pointer mov bx,ax or bx,dx ; Sets ZF iff DX:AX is zerodir_return: pop bp ret;; writechr: Write a single character in AL to the console without; mangling any registers; handle video pages correctly.;writechr: call write_serial ; write to serial port if needed pushfd pushad mov ah,0Eh mov bl,07h ; attribute mov bh,[cs:BIOS_page] ; current page int 10h popad popfd ret;;; kaboom2: once everything is loaded, replace the part of kaboom; starting with "kaboom.patch" with this partkaboom2: mov si,err_bootfailed call cwritestr call getchar call vgaclearmode int 19h ; And try once more to boot....norge: jmp short .norge ; If int 19h returned; this is the end;; mangle_name: Mangle a DOS filename pointed to by DS:SI into a buffer pointed; to by ES:DI; ends on encountering any whitespace;mangle_name: mov cx,11 ; # of bytes to writemn_loop: lodsb cmp al,' ' ; If control or space, end jna mn_end cmp al,'.' ; Period -> space-fill je mn_is_period cmp al,'a' jb mn_not_lower cmp al,'z' ja mn_not_uslower sub al,020h jmp short mn_not_lowermn_is_period: mov al,' ' ; We need to space-fillmn_period_loop: cmp cx,3 ; If <= 3 characters left jbe mn_loop ; Just ignore it stosb ; Otherwise, write a period loop mn_period_loop ; Dec CX and (always) jumpmn_not_uslower: cmp al,ucase_low jb mn_not_lower cmp al,ucase_high ja mn_not_lower mov bx,ucase_tab-ucase_low cs xlatbmn_not_lower: stosb loop mn_loop ; Don't continue if too longmn_end: mov al,' ' ; Space-fill name rep stosb ; Doesn't do anything if CX=0 ret ; Done;; Upper-case table for extended characters; this is technically code page 865,; but code page 437 users will probably not miss not being able to use the; cent sign in kernel images too much :-);; The table only covers the range 129 to 164; the rest we can deal with.;ucase_low equ 129ucase_high equ 164ucase_tab db 154, 144, 'A', 142, 'A', 143, 128, 'EEEIII' db 142, 143, 144, 146, 146, 'O', 153, 'OUUY', 153, 154 db 157, 156, 157, 158, 159, 'AIOU', 165;; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled; filename to the conventional representation. This is needed; for the BOOT_IMAGE= parameter for the kernel.; NOTE: A 13-byte buffer is mandatory, even if the string is; known to be shorter.;; DS:SI -> input mangled file name; ES:DI -> output buffer;; On return, DI points to the first byte after the output name,; which is set to a null byte.;unmangle_name: push si ; Save pointer to original name mov cx,8 mov bp,diun_copy_body: lodsb call lower_case stosb cmp al,' ' jbe un_cb_space mov bp,di ; Position of last nonblank+1un_cb_space: loop un_copy_body mov di,bp mov al,'.' ; Don't save stosb mov cx,3un_copy_ext: lodsb call lower_case stosb cmp al,' ' jbe un_ce_space mov bp,diun_ce_space: loop un_copy_ext mov di,bp mov byte [es:di], 0 pop si ret;; lower_case: Lower case a character in AL;lower_case: cmp al,'A' jb lc_ret cmp al,'Z' ja lc_1 or al,20h retlc_1: cmp al,lcase_low jb lc_ret cmp al,lcase_high ja lc_ret push bx mov bx,lcase_tab-lcase_low cs xlatb pop bxlc_ret: ret; -----------------------------------------------------------------------------; Common modules; -----------------------------------------------------------------------------%include "getc.inc" ; getc et al%include "conio.inc" ; Console I/O%include "writestr.inc" ; String output%include "parseconfig.inc" ; High-level config file handling%include "parsecmd.inc" ; Low-level config file handling%include "bcopy32.inc" ; 32-bit bcopy%include "loadhigh.inc" ; Load a file into high memory%include "font.inc" ; VGA font stuff%include "graphics.inc" ; VGA graphics%include "highmem.inc" ; High memory sizing; -----------------------------------------------------------------------------; Begin data section; -----------------------------------------------------------------------------CR equ 13 ; Carriage ReturnLF equ 10 ; Line FeedFF equ 12 ; Form FeedBS equ 8 ; Backspace;; Lower-case table for codepage 865;lcase_low equ 128lcase_high equ 165lcase_tab db 135, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138 db 139, 140, 141, 132, 134, 130, 145, 145, 147, 148, 149 db 150, 151, 152, 148, 129, 155, 156, 155, 158, 159, 160 db 161, 162, 163, 164, 164copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin' db CR, LF, 0boot_prompt db 'boot: ', 0wipe_char db BS, ' ', BS, 0err_notfound db 'Could not find kernel image: ',0err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0err_noram db 'It appears your computer has less than ' asciidec dosram_k db 'K of low ("DOS")' db CR, LF db 'RAM. Linux needs at least this amount to boot. If you get' db CR, LF db 'this message in error, hold down the Ctrl key while' db CR, LF db 'booting, and I will take your word for it.', CR, LF, 0err_badcfg db 'Unknown keyword in syslinux.cfg.', CR, LF, 0err_noparm db 'Missing parameter in syslinux.cfg.', CR, LF, 0err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0err_oldkernel db 'Cannot load a ramdisk with an old kernel image.' db CR, LF, 0err_notdos db ': attempted DOS system call', CR, LF, 0err_comlarge db 'COMBOOT image too large.', CR, LF, 0err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0err_bootfailed db CR, LF, 'Boot failed: please change disks and press ' db 'a key to continue.', CR, LF, 0ready_msg db 'Ready.', CR, LF, 0crlfloading_msg db CR, LFloading_msg db 'Loading ', 0dotdot_msg db '.'dot_msg db '.', 0aborted_msg db ' aborted.' ; Fall through to crlf_msg!crlf_msg db CR, LFnull_msg db 0crff_msg db CR, FF, 0syslinux_cfg db 'SYSLINUXCFG'%if IS_MDSLINUXmanifest db 'MANIFEST '%endif;; Command line options we'd like to take a look at;; mem= and vga= are handled as normal 32-bit integer valuesinitrd_cmd db 'initrd='initrd_cmd_len equ 7;; Config file keyword table;%include "keywords.inc";; Extensions to search for (in *forward* order).;exten_table: db 'CBT',0 ; COMBOOT (specific) db 'BSS',0 ; Boot Sector (add superblock) db 'BS ',0 ; Boot Sector db 'COM',0 ; COMBOOT (same as DOS) db 'C32',0 ; COM32exten_table_end: dd 0, 0 ; Need 8 null bytes here;; Misc initialized (data) variables;%ifdef debug ; This code for debugging onlydebug_magic dw 0D00Dh ; Debug code sentinel%endifAppendLen dw 0 ; Bytes in append= commandOntimeoutLen dw 0 ; Bytes in ontimeout commandOnerrorLen dw 0 ; Bytes in onerror commandKbdTimeOut dw 0 ; Keyboard timeout (if any)CmdLinePtr dw cmd_line_here ; Command line advancing pointerinitrd_flag equ $initrd_ptr dw 0 ; Initial ramdisk pointer/flagVKernelCtr dw 0 ; Number of registered vkernelsForcePrompt dw 0 ; Force promptAllowImplicit dw 1 ; Allow implicit kernelsAllowOptions dw 1 ; User-specified options allowedSerialPort dw 0 ; Serial port base (or 0 for no serial port)VGAFontSize dw 16 ; Defaults to 16 byte fontUserFont db 0 ; Using a user-specified fontScrollAttribute db 07h ; White on black (for text mode);; Stuff for the command line; we do some trickery here with equ to avoid; tons of zeros appended to our file and wasting space;linuxauto_cmd db 'linux auto',0linuxauto_len equ $-linuxauto_cmdboot_image db 'BOOT_IMAGE='boot_image_len equ $-boot_imageldlinux_end equ $ldlinux_len equ $-ldlinux_magic;; Put the getcbuf right after the code, aligned on a sector boundary;end_of_code equ (ldlinux_end-bootsec)+7C00hgetcbuf equ (end_of_code + 511) & 0FE00h; VGA font buffer at the end of memory (so loading a font works even; in graphics mode.)vgafontbuf equ 0E000h; This is a compile-time assert that we didn't run out of space%ifndef DEPEND%if (getcbuf+trackbufsize) > vgafontbuf%error "Out of memory, better reorganize something..."%endif%endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -