📄 ldlinux.asm
字号:
; say how to check for a 186/188, so I *hope* it falls out as a 8086; or 286 in this test.;; Also, provide an escape route in case it doesn't work.;check_escapes: mov ah,02h ; Check keyboard flags int 16h mov [KbdFlags],al ; Save for boot prompt check test al,04h ; Ctrl->skip 386 check jnz skip_checkstest_8086: pushf ; Get flags pop ax and ax,0FFFh ; Clear top 4 bits push ax ; Load into FLAGS popf pushf ; And load back pop ax and ax,0F000h ; Get top 4 bits cmp ax,0F000h ; If set -> 8086/8088 je not_386test_286: pushf ; Get flags pop ax or ax,0F000h ; Set top 4 bits push ax popf pushf pop ax and ax,0F000h ; Get top 4 bits jnz is_386 ; If not clear -> 386not_386: mov si,err_not386 call writestr jmp kaboomis_386: .386 ; Now we know it's a 386;; Now check that there is at least 608K of low (DOS) memory; (608K = 9800h segments); int 12h cmp ax,608 jae enough_ram mov si,err_noram call writestr jmp kaboomenough_ram:skip_checks:;; Initialization that does not need to go into the any of the pre-load; areas; mov al,[BIOS_vidrows] and al,al jnz vidrows_is_ok mov al,25 ; No vidrows in BIOS, assume 25vidrows_is_ok: mov [VidRows],al mov ah,0fh int 10h ; Read video state mov [TextPage],bh dec ah ; Store count-1 (same as rows) mov [VidCols],ah;; 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.; mov si,linuxauto_cmd ; Default command: "linux auto" mov di,default_cmd mov cx,linuxauto_len rep movsb;; Load configuration file; mov di,syslinux_cfg call open jz near no_config_fileparse_config: call getkeyword jc near end_config_file ; Config file loaded cmp ax,'de' ; DEfault je pc_default cmp ax,'ap' ; APpend je pc_append cmp ax,'ti' ; TImeout je near pc_timeout cmp ax,'pr' ; PRompt je near pc_prompt cmp ax,'di' ; DIsplay je near pc_display cmp ax,'la' ; LAbel je near pc_label cmp ax,'ke' ; KErnel je pc_kernel cmp ax,'im' ; IMplicit je near pc_implicit cmp al,'f' ; F-key jne parse_config jmp pc_fkeypc_default: mov di,default_cmd ; "default" command call getline mov si,auto_cmd ; add "auto"+null mov cx,auto_len rep movsb jmp short parse_configpc_append: cmp word [VKernelCtr],byte 0 ; "append" command ja pc_append_vk mov di,AppendBuf call getline sub di,AppendBufpc_app1: mov [AppendLen],di jmp short parse_configpc_append_vk: mov di,VKernelBuf+vk_append ; "append" command (vkernel) call getline sub di,VKernelBuf+vk_append cmp di,byte 2 jne pc_app2 cmp byte [VKernelBuf+vk_append],'-' jne pc_app2 mov di,0 ; If "append -" -> null stringpc_app2: mov [VKernelBuf+vk_appendlen],di jmp short parse_config_2 pc_kernel: cmp word [VKernelCtr],byte 0 ; "kernel" command je near parse_config ; (vkernel only) mov di,trackbuf push di call getline pop si mov di,VKernelBuf+vk_rname call mangle_name jmp short parse_config_2pc_timeout: call getint ; "timeout" command jc parse_config_2 mov ax,0D215h ; There are approx 1.D215h mul bx ; clock ticks per 1/10 s add bx,dx mov [KbdTimeOut],bx jmp short parse_config_2pc_display: mov di,trackbuf push di call getline ; Get filename to display pop si mov di,MNameBuf ; Mangled name buffer push di call mangle_name ; Mangle file name pop di call searchdir ; Search for file jz parse_config_2 ; File not found? call get_msg_file ; Load and display fileparse_config_2: jmp parse_configpc_prompt: call getint ; "prompt" command jc parse_config_2 mov [ForcePrompt],bx jmp short parse_config_2pc_implicit: call getint ; "implicit" command jc parse_config_2 mov [AllowImplicit],bx jmp short parse_config_2pc_fkey: sub ah,'1' jnb pc_fkey1 mov ah,9 ; F10pc_fkey1: xor cx,cx mov cl,ah push cx mov ax,1 shl ax,cl or [FKeyMap], ax ; Mark that we have this loaded mov di,trackbuf push di call getline ; Get filename to display pop si pop di shl di,4 ; Multiply number by 16 add di,FKeyName call mangle_name ; Mangle file name jmp short parse_config_2pc_label: call commit_vk ; Commit any current vkernel mov di,trackbuf ; Get virtual filename push di call getline pop si mov di,VKernelBuf+vk_vname call mangle_name ; Mangle virtual name inc word [VKernelCtr] ; One more vkernel mov si,VKernelBuf+vk_vname ; By default, rname == vname mov di,VKernelBuf+vk_rname mov cx,11 rep movsb mov si,AppendBuf ; Default append==global append mov di,VKernelBuf+vk_append mov cx,[AppendLen] mov [VKernelBuf+vk_appendlen],cx rep movsb jmp short parse_config_2;; commit_vk: Store the current VKernelBuf into buffer segment;commit_vk: cmp word [VKernelCtr],byte 0 je cvk_ret ; No VKernel = return cmp word [VKernelCtr],byte 16 ; Above limit? ja cvk_overflow mov di,[VKernelCtr] dec di shl di,12 ; 4K/buffer mov si,VKernelBuf mov cx,1024 ; = 4K bytes push es push word vk_seg pop es rep movsd ; Copy to buffer segment pop escvk_ret: retcvk_overflow: mov word [VKernelCtr],16 ; No more than 16, please ret;; End of configuration file;end_config_file: call commit_vk ; Commit any current vkernelno_config_file:;; Check whether or not we are supposed to display the boot prompt.;check_for_key: cmp word [ForcePrompt],byte 0 ; Force prompt? jnz enter_command test byte [KbdFlags],5Bh ; Caps, Scroll, Shift, Alt jz near auto_boot ; If neither, default bootenter_command: mov si,boot_prompt call writestr mov di,command_line;; get the very first character -- we can either time; out, or receive a character press at this time. Some dorky BIOSes stuff; a return in the buffer on bootup, so wipe the keyboard buffer first.;clear_buffer: mov ah,1 ; Check for pending char int 16h jz get_char_time xor ax,ax ; Get char int 16h jmp short clear_bufferget_char_time: mov cx,[KbdTimeOut] and cx,cx jz get_char ; Timeout == 0 -> no timeout inc cx ; The first loop will happen ; immediately as we don't ; know the appropriate DX valuetime_loop: push cxtick_loop: push dx mov ah,1 ; Check for pending keystroke int 16h jnz get_char_pop xor ax,ax int 1Ah ; Get time "of day" pop ax cmp dx,ax ; Has the timer advanced? je tick_loop pop cx loop time_loop ; If so, decrement counter jmp command_done ; Timeout!get_char_pop: pop eax ; Clear the stackget_char: xor ax,ax ; Get char int 16h and al,al jz func_key cmp al,' ' ; ASCII? jb not_ascii ja enter_char cmp di,command_line ; Space must not be first je get_charenter_char: cmp di,max_cmd_len+command_line ; Check there's space jnb get_char stosb ; Save it call writechr ; Echo to screen jmp short get_charnot_ascii: cmp al,0Dh ; Enter je command_done cmp al,08h ; Backspace jne get_char cmp di,command_line ; Make sure there is anything je get_char ; to erase dec di ; Unstore one character mov si,wipe_char ; and erase it from the screen call writestr jmp short get_charfunc_key: push di cmp ah,68 ; F10 ja get_char sub ah,59 ; F1 jb get_char mov cl,ah shr ax,4 ; Convert to x16 mov bx,1 shl bx,cl and bx,[FKeyMap] jz get_char ; Undefined F-key mov di,ax add di,FKeyName call searchdir jz fk_nofile call get_msg_file jmp short fk_wrcmdfk_nofile: mov si,crlf call writestrfk_wrcmd: mov si,boot_prompt call writestr pop di ; Command line write pointer push di mov byte [di],0 ; Null-terminate command line mov si,command_line call writestr ; Write command line so far pop di jmp short get_charauto_boot: mov si,default_cmd mov di,command_line mov cx,(max_cmd_len+4) >> 2 rep movsd jmp short load_kernelcommand_done: mov si,crlf call writestr cmp di,command_line ; Did we just hit return? je auto_boot xor al,al ; Store a final null stosbload_kernel: ; Load the kernel now;; First we need to mangle the kernel name the way DOS would...; mov si,command_line mov di,KernelName push si push di call mangle_name pop di pop si;; Fast-forward to first option (we start over from the beginning, since; mangle_name doesn't necessarily return a consistent ending state.);clin_non_wsp: lodsb cmp al,' ' ja clin_non_wspclin_is_wsp: and al,al jz clin_opt_ptr lodsb cmp al,' ' jbe clin_is_wspclin_opt_ptr: dec si ; Point to first nonblank mov [CmdOptPtr],si ; Save ptr to first option;; Now check if it is a "virtual kernel"; mov cx,[VKernelCtr] push ds push word vk_seg pop ds cmp cx,byte 0 je not_vk xor si,si ; Point to first vkernelvk_check: pusha mov cx,11 repe cmpsb ; Is this it? je vk_found popa add si,4096 ; 4K per vkernel structure loop vk_checknot_vk: pop ds;; Not a "virtual kernel" - check that's OK and construct the command line; cmp word [AllowImplicit],byte 0 je bad_implicit push es push si push di mov di,real_mode_seg mov es,di mov si,AppendBuf mov di,cmd_line_here mov cx,[AppendLen] rep movsb mov [CmdLinePtr],di pop di pop si pop es;; Find the kernel on disk;get_kernel: mov si,KernelName mov di,KernelCName call unmangle_name ; Get human form sub di,KernelCName mov [KernelCNameLen],di mov di,KernelName ; Search on disk call searchdir jnz kernel_goodbad_kernel: mov si,err_notfound ; Complain about missing kernel call writestr mov si,KernelCName call writestr mov si,crlf jmp abort_load ; Ask user for clue;; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0";bad_implicit: mov si,KernelName ; For the error message mov di,KernelCName call unmangle_name jmp short bad_kernel;; vk_found: We *are* using a "virtual kernel";vk_found: popa push di mov di,VKernelBuf mov cx,vk_size >> 2 rep movsd push es ; Restore old DS pop ds push es push word real_mode_seg pop es mov di,cmd_line_here mov si,VKernelBuf+vk_append mov cx,[VKernelBuf+vk_appendlen] rep movsb
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -