📄 ldlinux.asm
字号:
; Linux wants the floppy motor shut off before starting the kernel,; at least bootsect.S seems to imply so;kill_motor: mov dx,03F2h xor al,al out dx,al;; Now we're as close to be done as we can be and still use our normal; routines, print a CRLF to end the row of dots; call abort_check ; Last chance!! mov si,crlf call writestr;; If we're debugging, wait for a keypress so we can read any debug messages;%ifdef debug xor ax,ax int 16h%endif;; Set up segment registers and the Linux real-mode stack; mov ax,real_mode_seg mov ds,ax mov es,ax mov fs,ax mov gs,ax cli mov ss,ax mov sp,linux_stack sti;; We're done... now RUN THAT KERNEL!!!!; jmp setup_seg:setup_entry;; cwritestr: write a null-terminated string to the console, saving; registers on entry (we can't use this in the boot sector,; since we haven't verified 386-ness yet);cwritestr: pushacwstr_1: lodsb and al,al jz cwstr_2 mov ah,0Eh ; Write to screen as TTY mov bx,0007h ; White on black, current page int 10h jmp short cwstr_1cwstr_2: popa ret;; Load RAM disk into high memory;loadinitrd: push es ; Save ES on entry mov ax,real_mode_seg mov es,ax mov si,[initrd_ptr] and si,si mov di,[InitRDat] ; initrd load address movzx eax,di shl eax,8 ; Convert to bytes mov [es:su_ramdiskat],eax ; Offset for ram disk push si mov si,InitRDCName ; Write ramdisk name call cwritestr mov si,dotdot_msg ; Write dots call cwritestrrd_load_loop: mov si,dot_msg ; Progress report call cwritestr pop si ; Restore cluster pointer call abort_check mov cx,[InitRDClust] cmp cx,[ClustPerMoby] jna rd_last_moby mov cx,[ClustPerMoby]rd_last_moby: sub [InitRDClust],cx xor bx,bx ; Load at offset 0 push word xfer_buf_seg ; Bounce buffer segment pop es call getfssec push si ; Save cluster pointer pushf ; Remember EOF mov si,prot_xfer_gdt xor bx,bx mov di,[InitRDat] mov cx,8000h ; Always transfer 64K call upload popf jc rd_load_done ; EOF? add word [InitRDat],100h ; Point to next 64K cmp word [InitRDClust],byte 0 ; Are we done? jne rd_load_loop ; Apparently notrd_load_done: pop si ; Clean up the stack mov si,crlf_msg call writestr mov si,loading_msg ; Write new "Loading " for call writestr ; the benefit of the kernel pop es ; Restore original ES ret;; upload: upload a chunk of data to high memory; es:bx = source address; di = linear target address (x 256); cx = count (words) - max 8000h for now;upload: pushad push es mov eax,09300000h ; Compute linear base [93h in field mov ax,es ; right beyond the 3-byte address shl eax,4 ; field! movzx ebx,bx add eax,ebx mov dword [px_src_low],eaxul_dl: push cs ; Set ES=CS (=DS) pop es mov [px_dst],di ; Save destination address push cx ; Save count xor eax,eax mov di,px_wipe_1 mov cx,4 stosd mov di,px_wipe_2 mov cx,4 stosd pop cx mov si,prot_xfer_gdt mov ah,87h int 15h jc ul_error pop es popad retul_error: pop ax ; Leave ES=CS (=DS) popad mov si,err_highload jmp abort_load;; download: same as upload, except si = linear source address (x 256); currently used only to recover the vkernels in case of an; aborted low-kernel load (don't you love corner cases?);download: pushad push es mov byte [px_src_low],0 mov [px_src],si jmp short ul_dl;; GDT for protected-mode transfers (int 15h AH=87h). Note that the low; 8 bits are set to zero in all transfers, so they never change in this; block.; align 4prot_xfer_gdt equ $px_wipe_1 times 16 db 0 ; Reserved dw 0FFFFh ; Limit: 64Kpx_src_low db 0 ; Low 8 bits of source addresspx_src dw 0 ; High 16 bits of source address db 93h ; Segment access flags dw 0 ; Reserved dw 0FFFFh ; Limit: 64Kpx_dst_low db 00h ; Low 8 bits of destination addresspx_dst dw 0 ; High 16 bits of destination address db 93h ; Segment access flags dw 0 ; Reservedpx_wipe_2 times 16 db 0 ; Reserved;; abort_check: let the user abort with <ESC> or <Ctrl-C>;abort_check: pushaac1: mov ah,1 ; Check for pending keystroke int 16h jz ac_ret ; If no pending keystroke xor ax,ax ; Load pending keystroke int 16h cmp al,27 ; <ESC> aborts (DOS geeks) je ac2 cmp al,3 ; So does Ctrl-C (UNIX geeks) jne ac1 ; Unknown key... try againac2: ; If we get here, ABORT! mov si,aborted_msg ; Fall through to abort_load;; 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 writestr ; Expects SI -> error msg cmp byte [VKernelsHigh],0 je al_ok mov si,1000h ; VKernels stashed high mov di,vk_seg ; Recover shr di,4 mov cx,8000h call download mov byte [VKernelsHigh],0al_ok: jmp enter_command ; Return to command prompt;; End of abort_check;ac_ret: popa 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).;; 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: mov ax,[bsRootDirEnts] mov [DirScanCtr],ax mov ax,[RootDirSize] mov [DirBlocksLeft],ax mov ax,[RootDir1] mov dx,[RootDir2]scan_group: mov bp,[DirBlocksLeft] and bp,bp jz dir_return cmp bp,[BufSafeSec] jna load_last mov bp,[BufSafeSec]load_last: sub [DirBlocksLeft],bp push ax push dx mov ax,[bsBytesPerSec] mul bp add ax,trackbuf-31 mov [EndofDirSec],ax ; End of loaded pop dx pop ax push bp ; Save number of sectors push ax ; Save present location push dx push di ; Save name mov bx,trackbuf call getlinsec pop di pop dx pop ax pop bp mov si,trackbufdir_test_name: cmp byte [si],0 ; Directory high water mark je dir_return ; Failed test byte [si+11],018h ; 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 ax,bp ; Increment linear sector number adc dx,byte 0 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: ret;; writechr: Write a single character in AL to the screen without; mangling any registers;writechr: pusha mov ah,0Eh mov bx,0007h ; white text on this page int 10h popa ret;; get_msg_file: Load a text file and write its contents to the screen,; interpreting color codes. Is called with SI and DX:AX; set by routine searchdir;get_msg_file: mov word [NextCharJump],msg_putchar ; State machine for color mov byte [TextAttribute],07h ; Default grey on white pusha mov bh,[TextPage] mov ah,03h ; Read cursor position int 10h mov [CursorDX],dx popaget_msg_chunk: push ax ; DX:AX = length of file push dx mov bx,trackbuf mov cx,[BufSafe] call getfssec pop dx pop ax push si ; Save current cluster mov si,trackbuf mov cx,[BufSafeBytes] ; No more than many bytesprint_msg_file: push cx push ax push dx lodsb cmp al,1Ah ; ASCII EOF? je msg_done_pop call [NextCharJump] ; Do what shall be done pop dx pop ax pop cx sub ax,byte 1 sbb dx,byte 0 mov bx,ax or bx,dx jz msg_done loop print_msg_file pop si jmp short get_msg_chunkmsg_done_pop: add sp,byte 6 ; Lose 3 words on the stackmsg_done: pop si retmsg_putchar: ; Normal character cmp al,0Fh ; ^O = color code follows je msg_ctrl_o cmp al,0Dh ; Ignore <CR> je msg_ignore cmp al,0Ah ; <LF> = newline je msg_newline cmp al,0Ch ; <FF> = clear screen je msg_formfeed mov bx,[TextAttrBX] mov ah,09h ; Write character/attribute mov cx,1 ; One character only int 10h ; Write to screen mov al,[CursorCol] inc ax cmp al,[VidCols] ja msg_newline mov [CursorCol],almsg_gotoxy: mov bh,[TextPage] mov dx,[CursorDX] mov ah,02h ; Set cursor position int 10hmsg_ignore: retmsg_ctrl_o: ; ^O = color code follows mov word [NextCharJump],msg_setbg retmsg_newline: ; Newline char or end of line mov byte [CursorCol],0 mov al,[CursorRow] inc ax cmp al,[VidRows] ja msg_scroll mov [CursorRow],al jmp short msg_gotoxymsg_scroll: xor cx,cx ; Upper left hand corner mov dx,[ScreenSize] mov [CursorRow],dh ; New cursor at the bottom mov bh,[TextAttribute] mov ax,0601h ; Scroll up one line int 10h jmp short msg_gotoxymsg_formfeed: ; Form feed character xor cx,cx mov [CursorDX],cx ; Upper lefthand corner mov dx,[ScreenSize] mov bh,[TextAttribute] mov ax,0600h ; Clear screen region int 10h jmp short msg_gotoxymsg_setbg: ; Color background character call unhexchar jc msg_color_bad shl al,4 mov [TextAttribute],al mov word [NextCharJump],msg_setfg retmsg_setfg: ; Color foreground character call unhexchar jc msg_color_bad or [TextAttribute],al ; setbg set foreground to 0 mov word [NextCharJump],msg_putchar retmsg_color_bad: mov byte [TextAttribute],07h ; Default attribute mov word [NextCharJump],msg_putchar ret;; open,getc: Load a file a character at a time for parsing in a manner; similar to the C library getc routine. Only one simultaneous; use is supported. Note: "open" trashes the trackbuf.;; open: Input: mangled filename in DS:DI; Output: ZF set on file not found or zero len
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -