📄 second.s
字号:
#if 0/* second.S - LILO second stage boot loader */Copyright 1992-1998 Werner Almesberger.Copyright 1999-2005 John Coffman.All rights reserved.Licensed under the terms contained in the file 'COPYING' in the source directory.#endif/*#define DEBUG*/#define REG_DUMP 1/*#define DELL_DIRTY_HACK*/#define PIXADDRESS#define MEMORY_CHECK#define RETAIN#define DNAME 1#define LILO_ASM#include "lilo.h"get common.s /* as86 "include" will bypass the CPP */#define MAP Map#define MAP2 Map2#define DFLCMD Dflcmd#define DESCR Descr#define KEYTABLE Keytable#define PARMLINE Parmline#define DEBUG_INITRD 0#ifdef DEBUG#define DEBUG_NEW 1#else#if VERSION_MINOR<50#define DEBUG_NEW 0#else#define DEBUG_NEW 1#ifndef MEMORY_CHECK#define MEMORY_CHECK#endif#endif /* VERSION_MINOR */#endif /* DEBUG *//* The following is set to 1 to enable map file writing */#if DEBUG_NEW# define WR_ENABLE 2# if VERSION_MINOR>=90# undef WR_ENABLE# define WR_ENABLE 1# endif#else# define WR_ENABLE 1#endif#if DEBUG_NEW==0 && !(WR_ENABLE&1)#error "Retail version should have WR_ENABLE=1"#endif/* if compiling READONLY, then WR_ENABLE should never be used */#ifdef LCF_READONLY# undef WR_ENABLE#endif#define BEG_FS#define SEG_FS seg fs#define END_FS/* get rid of the following to revert to old int 0x15/fn 0x88 mem scheme */#define HIGHMEM_MAX 0x38000000LOADSEG = SYSSEG ! max kernel = 1024 sectors#define UI_MAGIC 0xff /* take input from keyboard */#ifdef MENUSTAGE_MENU = STAGE_FLAG_MENUX=MENU#elseSTAGE_MENU = 0#endif#ifdef BITMAPSTAGE_BITMAP = STAGE_FLAG_BMP4X=BITMAP#elseSTAGE_BITMAP = 0#endif#ifdef LCF_NOSERIALSTAGE_SERIAL = 0#elseSTAGE_SERIAL = STAGE_FLAG_SERIAL#endif#ifdef TEXTX=TEXT#endif .text .globl _main .org 0_main: jmp start .org 6! Boot device parameters. They are set by the installer.sig: .ascii "LILO"version: .word VERSIONmapstamp: .long 0stage: .word STAGE_SECOND|STAGE_SERIAL|STAGE_MENU|STAGE_BITMAPport: .byte 0 ! COM port (0 = unused, 1 = COM1, etc.)sparam: .byte 0 ! serial port parameters (0 = unused)timout: .word 0 ! input timeoutdelay: .word 0 ! boot delayms_len: .word 0 ! initial greeting messagekt_cx: .word 0 ! keyboard translation tablekt_dx: .word 0kt_al: .byte 0flag2: .byte 0 ! second stage specific flags! GDT for "high" loading .align 16gdt: ! space for BIOS .blkb 0x10 ! source .word 0xffff ! no limits .byte 0 .word LOADSEG>>4 ! start: 0x10000 .byte 0x93 ! permissions .word 0 ! padding for 80286 mode :-( ! destination .word 0xffff ! no limits .word 0 ! start - filled in by user .byte 0 .byte 0x93 ! permissions .word 0 ! padding for 80286 mode :-( ! space for BIOS .blkb 0x10start: cld ! only CLD in the code; there is no STD push ds pop fs ! address parameters from here seg cs mov [init_dx],dx ! save DX passed in from first.S int 0x12 ! get memory available#if EBDA_EXTRA sub ax,#EBDA_EXTRA ! allocate extra EBDA#endif shl ax,#6 ! convert to paragraphs sub ax,#Dataend/16 mov es,ax ! destination address push cs pop ds xor si,si xor di,di xor ax,ax mov cx,#max_secondary/2 ! count of words to move rep movsw add di,#BSSstart-max_secondary mov cx,#BSSsize/2 rep stosw push es push #continue retf ! branch to continue addresscontinue:#ifdef DELL_DIRTY_HACK;;; push dx ! preserve DX (already saved) mov ax,#0x1200 ! enable video (VGA) mov bl,#0x36 ! (probably a nop on EGA or MDA) int 0x10 ! video call;;; pop dx ! restore DX on Dell geforce nVidia card#endif#ifndef LCF_NOSERIAL call serial_setup ! set up the COM port, if any#endif#ifndef LCF_NODRAIN mov cx,#32 ! drain type-ahead buffer ?drkbd: mov ah,#1 ! is a key pressed ? int 0x16 jz comcom ! no -> done xor ah,ah ! get the key int 0x16 loop drkbd#endifcomcom: mov al,#0x4c ! display an 'L' call display push #0 ! get pointer to disk parameter table in DS:SI pop ds lds si,[0x78] ! 0x78 = 4*0x1E#ifndef LCF_XL_SECS cmp byte ptr (si+4),#9 ! okay ? ja dskok ! yes -> do not patch#endif push cs ! get pointer to new area in ES:DI pop es mov di,#dskprm mov cx,#6 ! copy 12 bytes rep movsw seg es ! patch number of sectors#ifndef LCF_XL_SECS mov byte ptr (di-8),#18#else mov byte ptr (di-8),#LCF_XL_SECS#endif push #0 pop ds cli ! paranoia mov [0x78],#dskprm mov [0x7a],es stidskok:#ifndef LCF_NOSERIAL seg cs ! clear the break flag mov byte ptr break,#0#endif call instto ! get timer interrupt;;; jmp restrt ! get going! Restart here after a boot errorrestrt: mov bx,cs ! adjust segment registers mov ds,bx mov es,bx sub bx,#MAX_SETUPSECS*0x20+0x20 ! segment for setup code & ! bootsect mov cx,#INITSEG cmp bx,cx jbe restrt1 mov bx,cx ! BX is the smaller segment #restrt1: mov word ptr [map],#MAP mov [initseg],bx ! set up INITSEG (was 0x9000) lea cx,(bx+0x20) mov [setupseg],cx ! set up SETUPSEG (was 0x9020) mov cx,cs sub cx,bx ! subtract [initseg] shl cx,#4 ! get stack size mov ss,bx ! must lock with move to SP below mov sp,cx ! data on the stack)#if DEBUG_NEW pusha mov bx,#msg_where call say mov ax,[initseg] call wout mov ax,[setupseg] call swout mov ax,cs call swout mov ax,ss call swout mov al,#0x3A ; colon call display mov ax,sp call wout mov al,#32 ; space call display BEG_FS SEG_FS ! external parameters ? mov ax,[EX_OFF+6] ; DH:DL as passed to first.S END_FS call swout mov ax,[init_dx] ; DX into second Stage call swout call crlf#if REG_DUMP call frd0 .ascii "Registers at startup of first stage loader:\n" .ascii " AX BX CX DX SI DI BP DS ES\n" .byte 0frd0: pop bx call say BEG_FS SEG_FS ! external parameters ? mov ax,[EX_OFF-2-4] ; AX call wout SEG_FS ! external parameters ? mov ax,[EX_OFF-8-4] ; BX call swout SEG_FS ! external parameters ? mov ax,[EX_OFF-4-4] ; CX call swout SEG_FS ! external parameters ? mov ax,[EX_OFF-6-4] ; DX call swout SEG_FS ! external parameters ? mov ax,[EX_OFF-14-4] ; SI call swout SEG_FS ! external parameters ? mov ax,[EX_OFF-16-4] ; DI call swout SEG_FS ! external parameters ? mov ax,[EX_OFF-12-4] ; BP call swout SEG_FS ! external parameters ? mov ax,[EX_OFF-18+16] ; DS call swout SEG_FS ! external parameters ? mov ax,[EX_OFF-20+16] ; ES call swout END_FS call crlf#endif popa#endif cmp dword [sig],#EX_MAG_HL ! "LILO" jne crshbrn2 cmp dword [mcmdbeg+6],#0x4547414d ; "MAGE" from BOOT_IMAGE jne crshbrn2 cmp BYTE [stage],#STAGE_SECOND#if 1 jne crshbrn cmp WORD [version],#VERSION#endifcrshbrn2: jne crshbrn mov [cmdbeg],#acmdbeg ! probably unattended boot mov di,#devmap ; place to store the device map#ifdef LCF_FIRST6 mov ah,[init_dx] ! AH is physical device BEG_FS SEG_FS mov al,[par1_secondary+0+SSDIFF] ; map device logical END_FS#else mov ax,[init_dx] ! AH is flags & device, AL is physical device xchg ah,al and ax,#DEV_MASK_asm<<8 | DEV_MASK_asm ! mask to pure device codes#endif cmp ah,al je end_tt#if DEBUG_NEW pusha call wout ! TT entry, maybe call crlf popa#endif stosw ; set up the translation from map -> bootend_tt: xor ax,ax stoswldsc: BEG_FS SEG_FS mov eax,[par1_mapstamp] END_FS cmp eax,[par2_mapstamp] jne timeerr call kt_read ! read the KEYTABLE call build_vol_tab mov bx,#DESCR mov si,#KEYTABLE+256+mt_descrdescr_more: lodsw xchg cx,ax lodsw xchg dx,ax lodsb call cread jc near fdnok ! error -> retry add bh,#2 ! increment address cmp si,#KEYTABLE+256+mt_descr+sa_size*MAX_DESCR_SECS_asm jb descr_more mov si,#DESCR ! compute a checksum of the descriptor table mov di,#SECTOR_SIZE*MAX_DESCR_SECS-4 push dword #CRC_POLY1 call crc32 add di,si cmp eax,dword (di) jz nochkerr! Timestamp errortimeerr: mov bx,#msg_time jmp zz! Checksum errorchkerr: mov bx,#msg_chkerr jmp zz ! go waitcrshbrn: mov bx,#msg_sigerr ! signature not foundzz: call sayzzz: hlt ! wait for interrupt jmp zzz ! sit here forevernochkerr:#ifdef DEBUG pusha mov bx,#nochker_msg call say popa jmp nochkerr1nochker_msg: .ascii "Descriptor checksum okay\n" .byte 0nochkerr1:#endif#ifdef LCF_VIRTUAL; remove those items that have "vmdisable", if virtual boot call vmtest jnc virtual_done mov di,#DESCR0 ; point at first descriptorvir_loop: test byte ptr [id_name](di),#0xFF ; test for NUL name jz virtual_done test word ptr [id_flags](di),#FLAG_VMDISABLE jz vir_skip push di lea si,[id_size](di)vir_loop1: mov cx,#id_size rep movsb test byte ptr [id_name](di),#0xFF jnz vir_loop1 pop di jmp vir_loopvir_skip: add di,#id_size jmp vir_loopvirtual_done:#endif#if defined(MENU) || defined(BITMAP) xor bx,bx ! defaults are all zero mov [dimage],bx ! set default image to boot mov [abs_cx],bx ! upper left of scroll area ! means screen is not cleared#endif mov bx,#KEYTABLE+256 mov al,(bx+mt_flag) BEG_FS SEG_FS ! get possible FLAG_NOBD or byte ptr [par1_prompt+SSDIFF],al END_FS#ifdef MENU call title_stuff#endif mov bx,#DFLCMD;BEG_FS;SEG_FS mov cx,mt_dflcmd+KEYTABLE+256 ;DFCMD_OFF;SEG_FS mov dx,mt_dflcmd+2+KEYTABLE+256;SEG_FS mov al,mt_dflcmd+4+KEYTABLE+256;END_FS call cread jc fdnok ! error -> retry mov bx,#DFLCMD cmp word ptr (bx),#DC_MAGIC ! okay ? jne bdcmag ! no -> do not write#ifndef LCF_READONLY mov word ptr (bx),#DC_MGOFF ! erase the magic number call cmd_write ! write out the command line#if 0; 22.6.2 -- removed, because this is worse that the first; command lock bug mov si,#DESCR0 lea di,(bx+2) mov cx,#16 rep movsb; 22.6.2#endif#endif jmp dokay ! continuebdcmag: mov byte ptr (bx+2),#0 ! disable the command line jmp dokay ! go onfdnok: #if 0 xor ax,ax ! reset FDC mov dl,al int 0x13#endif br ldsc ! retry! List all known boot imageslist: mov byte ptr (bx),#0 ! set EOL marker call crlf#ifdef MENU inc word [suppress] ! suppress console output#endif mov si,#DESCR0 ! list all images mov cx,#IMAGES xor dl,dl ! DL counts the imageslloop: testb (si),#0xff ! done ? jz ldone ! yes mov bx,si ! display the name call say add si,#MAX_IMAGE_NAME+4 inc dl ! count the image test dl,#3 ! inside line -> go on jnz fill call crlf jmp imgdne ! next imagefill: push bx ! fill with spaces mov al,#0x20 call display pop bx inc bx cmp bx,si jbe fillimgdne: add si,#id_size-MAX_IMAGE_NAME-4 loop lloop ! next imageldone: test dl,#3 ! already at BOL ? jz atbol ! yes -> no CRLF call crlfatbol: #ifdef MENU dec word [suppress]#endif br iloop ! done! Ready to process user inputdokay: mov bx,#ospc ! display 'O ' call say/* ifdef HIGHMEM_MAX */ xor eax,eax mov dword ptr [hma],eax/* #endif */ mov ospc,al ! disable the message mov word ptr vgaovr,#VGA_NOCOVR ! disable VGA override;; BEG_FS;; SEG_FS xchg ax,par2_delay ;DSC_OFF-8+SSDIFF;; END_FS or old_del,ax ! remember delay mov nodfl,#iloop ! interactive prompt if falling through BEG_FS SEG_FS ! enter boot prompt ? test byte ptr par1_prompt+SSDIFF,#FLAG_PROMPT ;DSC_OFF+15+SSDIFF,#0 END_FS jnz extp ! yes -> check for external parameters mov nodfl,#bfirst ! boot first image if falling through call waitsh ! wait for a shifting key jc iloop ! key pressed -> enter interactive mode! Check for external parametersextp: BEG_FS SEG_FS ! external parameters ? cmp byte ptr EX_OFF+6,#EX_DL_MAG END_FS jne noex ! no -> go on BEG_FS SEG_FS mov bl,EX_OFF+7 ! get drive SEG_FS ! clear flag mov byte ptr EX_OFF+6,bl ! clear flag SEG_FS ! load the signature pointer les bx,EX_OFF END_FS seg es cmp dword ptr (bx),#EX_MAG_HL ! "LILO" jne noex ! no -> go on BEG_FS SEG_FS mov si,EX_OFF+4 ! pointer to the command line END_FS seg es cmp byte ptr (si),#0 ! empty ? je iloop ! yes -> enter interactive mode jmp niloop ! enter non-interactive mode! No external parameters after timeout -> boot first imagenoex: push cs ! restore ES pop es mov si,#DFLCMD+2 ! default command line ? cmp byte ptr (si),#0 jne niloop ! yes -> use it mov ax,nodfl ! no idea how to tell as86 to do jmp (addr) :-( jmp ax ! fall through! Command input processoriloop:#if defined(MENU) || defined(BITMAP) call menu_setup#endif#ifndef BITMAP;; BEG_FS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -