📄 ldlinux.asm
字号:
mov cl,[ClustShift] mov dx,[gs:si+20] ; High cluster word shl edx,16 mov dx,[gs:si+26] ; Low cluster word sub edx,2 shl edx,cl add edx,[DataArea] mov [bx],edx ; Starting sector mov eax,[gs:si+28] ; File length again mov dx,[gs:si+30] ; 16-bitism, sigh mov si,bx and eax,eax ; ZF <- 0 pop es pop gs pop cx pop bx 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 test byte [cs:DisplayCon], 01h jz .nothing pushad mov ah,0Eh mov bl,07h ; attribute mov bh,[cs:BIOS_page] ; current page int 10h popad.nothing: 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;; getfssec_edx: Get multiple sectors from a file;; This routine makes sure the subtransfers do not cross a 64K boundary,; and will correct the situation if it does, UNLESS *sectors* cross; 64K boundaries.;; ES:BX -> Buffer; EDX -> Current sector number; CX -> Sector count (0FFFFh = until end of file); Must not exceed the ES segment; Returns EDX=0, CF=1 on EOF (not necessarily error); All arguments are advanced to reflect data read.;getfssec_edx: push ebp push eax.getfragment: xor ebp,ebp ; Fragment sector count push edx ; Starting sector pointer.getseccnt: inc bp dec cx jz .do_read xor eax,eax mov ax,es shl ax,4 add ax,bx ; Now AX = how far into 64K block we are not ax ; Bytes left in 64K block inc eax shr eax,SECTOR_SHIFT ; Sectors left in 64K block cmp bp,ax jnb .do_read ; Unless there is at least 1 more sector room... mov eax,edx ; Current sector inc edx ; Predict it's the linearly next sector call nextsector jc .do_read cmp edx,eax ; Did it match? jz .getseccnt.do_read: pop eax ; Starting sector pointer call getlinsecsr lea eax,[eax+ebp-1] ; This is the last sector actually read shl bp,9 add bx,bp ; Adjust buffer pointer call nextsector jc .eof mov edx,eax and cx,cx jnz .getfragment.done: pop eax pop ebp ret.eof: xor edx,edx stc jmp .done;; getfssec: Get multiple sectors from a file;; Same as above, except SI is a pointer to a open_file_t;; ES:BX -> Buffer; DS:SI -> Pointer to open_file_t; CX -> Sector count (0FFFFh = until end of file); Must not exceed the ES segment; Returns CF=1 on EOF (not necessarily error); All arguments are advanced to reflect data read.;getfssec: push edx movzx edx,cx cmp edx,[si+4] jbe .sizeok mov edx,[si+4] mov cx,dx.sizeok: sub [si+4],edx mov edx,[si] call getfssec_edx mov [si],edx pop edx ret;; nextcluster: Advance a cluster pointer in EDI to the next cluster; pointed at in the FAT tables. CF=0 on return if end of file.;nextcluster: jmp strict short nextcluster_fat28 ; This gets patchednextcluster_fat12: push eax push edx push bx push cx push si mov edx,edi shr edi,1 pushf ; Save the shifted-out LSB (=CF) add edx,edi mov eax,edx shr eax,9 call getfatsector mov bx,dx and bx,1FFh mov cl,[gs:si+bx] inc edx mov eax,edx shr eax,9 call getfatsector mov bx,dx and bx,1FFh mov ch,[gs:si+bx] popf jnc .even shr cx,4.even: and cx,0FFFh movzx edi,cx cmp di,0FF0h pop si pop cx pop bx pop edx pop eax ret;; FAT16 decoding routine.;nextcluster_fat16: push eax push si push bx mov eax,edi shr eax,SECTOR_SHIFT-1 call getfatsector mov bx,di add bx,bx and bx,1FEh movzx edi,word [gs:si+bx] cmp di,0FFF0h pop bx pop si pop eax ret;; FAT28 ("FAT32") decoding routine.;nextcluster_fat28: push eax push si push bx mov eax,edi shr eax,SECTOR_SHIFT-2 call getfatsector mov bx,di add bx,bx add bx,bx and bx,1FCh mov edi,dword [gs:si+bx] and edi,0FFFFFFFh ; 28 bits only cmp edi,0FFFFFF0h pop bx pop si pop eax ret;; nextsector: Given a sector in EAX on input, return the next sector; of the same filesystem object, which may be the root; directory or a cluster chain. Returns EOF.;; Assumes CS == DS.;nextsector: push edi push edx mov edx,[DataArea] mov edi,eax sub edi,edx jae .isdata ; Root directory inc eax cmp eax,edx cmc jmp .done.isdata: not edi test edi,[ClustMask] jz .endcluster ; It's not the final sector in a cluster inc eax jmp .done.endcluster: push gs ; nextcluster trashes gs push cx not edi mov cl,[ClustShift] shr edi,cl add edi,2 ; Now EDI contains the cluster number call nextcluster cmc jc .exit ; There isn't anything else... ; New cluster number now in EDI sub edi,2 shl edi,cl ; CF <- 0, unless something is very wrong lea eax,[edi+edx].exit: pop cx pop gs.done: pop edx pop edi ret;; getfatsector: Check for a particular sector (in EAX) in the FAT cache,; and return a pointer in GS:SI, loading it if needed.;; Assumes CS == DS.;getfatsector: add eax,[FAT] ; FAT starting address jmp getcachesector; -----------------------------------------------------------------------------; 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%include "strcpy.inc" ; strcpy()%include "cache.inc" ; Metadata disk cache; -----------------------------------------------------------------------------; Begin data section; ----------------------------------------------------------------------------- section .data;; 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' ; Mangled formConfigName db 'syslinux.cfg',0 ; Unmangled form%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%endif alignb 4, db 0BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbufBufSafeSec dw trackbufsize/SECTOR_SIZE ; = how many sectors?BufSafeBytes dw trackbufsize ; = how many bytes?EndOfGetCBuf dw getcbuf+trackbufsize ; = getcbuf+BufSafeBytes%ifndef DEPEND%if ( trackbufsize % SECTOR_SIZE ) != 0%error trackbufsize must be a multiple of SECTOR_SIZE%endif%endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -