📄 chain.s
字号:
; chain.S - LILO boot chainer ;; Copyright 1992-1998 Werner Almesberger.; Copyright 1999-2002 John Coffman.; All rights reserved.;; Licensed under the terms contained in the file 'COPYING' in the ; source directory.;; for debugging, set the EBDA size in Kilobytes; e.g., 64#define EBDA 0#define REVERSE_DL 1#if defined(LCF_SOLO_CHAIN) && !defined(DOS_D)#ifndef DOS_D#define DOS_D#endif#ifndef CHECK#define CHECK#endif#endif /* LCF_SOLO_CHAIN */#define LILO_ASM#include "lilo.h"#if VERSION_MINOR >= 50#define DEBUG#endif .text .globl _main .org 0_main: jmp start .org 6 .ascii "LILO" .word STAGE_CHAIN .word VERSIONoffset: .word 0drive: .byte 0 ! drive, 0x80, 0x81 .byte 0 ! head, always zerohint: .word drvmap ! pointer to drive mapptable: .blkw 0x20 ! partition table to preloadcmd: .word 0,0 ! command line to pass on; ES:DI contains a pointer to the command line passed from second-stagestart: xor bx,bx ! set SS:SP to 0:7C00 mov ss,bx mov sp,#BOOTSEG*16 ! #0x7C00 mov bp,sp ! address from BP#if EBDA push #0x40 pop ds mov word ptr [0x13],#640-EBDA ; simulate EBDA in Kilobytes#endif push cs pop ds#ifdef DEBUG push bx push bp push es pop ds mov si,di call say push cs pop ds mov si,#crlf call say pop bp pop bx#endif#if 1 mov al,#0x3D ! '=' sign mov cx,#-1 repne scasb ! scan for =srch: seg es mov al,(di) inc di cmp al,#0x20 ! test for space ja srch; real command line if AL==space, no command line if NUL or al,al jz nocmd mov [cmd],di mov [cmd+2],esnocmd:#endif;;; push cs;;; pop ds ! DS = SETUPSEG mov es,bx mov cx,#SECTOR_SIZE/2mtmp = SETUPSECS-1 ! broken math ... mov si,#mtmp*SECTOR_SIZE mov di,bp ! #0x7C00 rep movsw#ifdef DOS_D#ifdef CHECK mov si,#BOOTSEG*16+0x24 ; address of first byte to test cmp byte (bp+0x15),#0xf8 ; check media descriptor jne ck_failed seg es lodsb cmp al,#0x80 ; check range of device codes jb ck_failed cmp al,#0x8f ja ck_failed seg es lodsb or al,al ; check hi-byte is empty jnz ck_failed seg es lodsb cmp al,#0x29 ; I do not know what this byte means je ck_okay cmp al,#0x28 ; HPFS marker jne ck_failedck_okay: lea si,(si+4) ; address of vol label & fs type mov cx,#11 ; volume label (11)ck_next: seg es lodsb or al,al js ck_failed ; not alphabetic if >= 0x80 jz ck_loop ; NUL allowed for HPFS cmp al,#0x20 jb ck_failed ; not alphabetic if < SPACEck_loop: loop ck_next mov cx,#8 ; check Filesystem typeck_fstype: seg es lodsb or al,al ; not alphabetic if >= 0x80 js ck_failed cmp al,#0x20 ; not alphabetic if < SPACE jb ck_failed loop ck_fstype#endifdos4: call revmap1 mov (bp+0x24),dx ! fill in 0x24 and 0x25 mov si,offset#ifdef LCF_M386 mov edx,ptable+8(si) mov (bp+0x1C),edx#else mov dx,ptable+8(si) seg es mov BOOTSEG*16+0x1C,dx mov dx,ptable+10(si) seg es mov BOOTSEG*16+0x1E,dx#endif#ifdef DEBUG mov si,#update jmp ck_say ck_failed: mov si,#no_updateck_say: call say#elseck_failed:#endif#endif mov cx,#0x20 ! move partition table mov si,#ptable mov di,#PART_TABLE rep movsw ! mess with the partition table#if defined(LCF_REWRITE_TABLE) && !defined(LCF_READONLY) mov si,#prtmap ! get partition table change rulesprtclp: lodsw ! bios == 0 indicates end or al,al jz pmend ! at end -> quit cmp al,cache ! already in cache ? je incache ! yes -> no loading required push ax ! save table data call flush ! flush the cache pop ax push ax mov cache,al ! remember drive in cache#if 0 cmp al,drive ! boot drive ?#else call revmap1 cmp al,dl#endif jne noc ! no -> load into scratch area xor ax,ax ! load at 0000:0600 mov bx,#PARTS_LOAD jmp loaditpmend: call flush ! flush table br nopp ! and proceednoc: mov ax,ds mov bx,#PARTS_SCR ! scratch area 0000:0800loadit: mov es,ax ! set up pointers and remember them mov ces,ax mov cbx,bx mov ax,#0x201 ! load partition table, one sector mov dx,cache ! drive from cache (DH = 0) mov cx,#1#ifdef DEBUG pusha mov al,dl ! dump device code call bout mov si,#msg_load ! say loading call say popa#endif int 0x13 ! load it jc wrfail ! error -> abort pop ax ! get BIOS and offsetincache:les bx,cbx ! load pointer add bx,#PART_TABLE_OFFSET ! move to partition table add bl,ah ! offset is always in [0x1be,0x1fd] lodsw ! see what we need to do seg es ! match ? cmp byte ptr (bx),al jne nocng ! no -> do not change seg es ! change mov byte ptr (bx),ah mov byte ptr dirty,#1 ! mark as dirtynocng: br prtclp ! next oneflush: test byte ptr dirty,#1 ! dirty ? jz noflush ! no -> do not write mov ax,#0x301 ! write one sector mov dx,cache ! get the drive or dl,dl ! nothing cached ? jz noflush ! no -> do not flush les bx,cbx ! reload pointer#ifdef DEBUG pusha mov al,dl ! dump device code call bout mov si,#msg_write ! say writing call say popa#endif int 0x13 ! write ... jc wrfail ! arglnoflush:retwrfail: mov si,#failmsg ! complain call say mov ax,#FIRSTSEG ! try to restart LILO jmpi #GO,FIRSTSEGcache: .byte 0 ! drive, 0 means not cached .byte 0 ! head, always 0cbx: .blkw 1ces: .blkw 1dirty: .byte 0#endif; reverse drive mapping; uses AX; updates DL;revmap1: push si mov dx,drive ; get drive/head pair mov si,#drvmaprev0: lodsw ; get to, from pair or ax,ax ; test for end jz rev9 ; done cmp ah,dl ; booting from "to" jne rev0 ; loop if not mov dl,al ; substitute the "from"rev9: pop si ; restore SI retnopp: mov ax,drvmap ! need to install mapper ? or ax,ax jz noimap ! no -> go on call swap13noimap:#if REVERSE_DL call revmap1#else mov dx,drive ! initialize DX (drive and head)#endif mov si,offset ! DS:SI and ES:SI point to the partition add si,#PART_TABLE#ifdef DEBUG pusha mov cx,# 6000000>>16 mov dx,# 6000000 & 0xFFFF stc mov ah,# 0x86 int 0x15 ! Delay 6 seconds jnc delayed mov si,#msg_cont ! Hit any key ... call say xor ax,ax int 0x16 ! AH==0, get keydelayed: popa#endif xor ax,ax ! set DS and ES to zero mov ds,ax mov es,ax mov bx,#BOOTSEG*16 mov ss,ax ! on all processors since the 186 mov sp,bx ! these instructions are locked #ifdef LCF_COHERENT mov (si),dl ! yes, put it in the partition table#endif mov bp,si ! BP==SI flags hard disk boot push ax push bx#ifdef LCF_M386 seg ss cmp dword ptr (bx+6),#EX_MAG_HL#else seg ss cmp word ptr (bx+6),#EX_MAG_L jne gotoit seg ss cmp word ptr (bx+8),#EX_MAG_H#endif jne gotoit ! LILO signature required for command line#ifdef LCF_M386 seg cs cmp dword ptr [cmd],#0#else push ax seg cs mov ax,[cmd] seg cs or ax,[cmd+2] pop ax#endif je gotoit; pass on a command line seg cs les bx,[cmd] lea si,(bx-5)#ifdef LCF_M386 seg es mov dword ptr (si),#EX_MAG_HL#else seg es mov word ptr (si),#EX_MAG_L seg es mov word ptr (si+2),#EX_MAG_H#endif mov dl,#EX_DL_MAGgotoit: retf#ifdef XXXlilosig:.ascii "LILO"cmd: .ascii "98" .byte 0#endif#if defined(LCF_REWRITE_TABLE) || defined(DEBUG)! Display a NUL-terminated string on the consolesay: lodsb ! get byte or al,al ! NUL ? jz aret ! yes -> done mov ah,#14 ! display, tty-style xor bh,bh int 0x10 jmp say ! next onearet: ret ! donefailmsg:.ascii "Rewrite error." .byte 13,10,0#endif#ifdef DEBUGwout: push ax xchg ah,al call bout ! write hi-byte pop axbout: push ax ! save byte shr al,#4 ! display upper nibble call nout pop axnout: and al,#0x0F ! lower nible only daa ! smaller conversion routine add al,#0xF0 adc al,#0x40 ! AL is hex char [0..9A..F] push bx mov ah,#14 ! display, tty-style xor bh,bh int 0x10 pop bx retmsg_swap13: .ascii "Install drive Swapper" .byte 13,10,0msg_load: .ascii " - PT loaded" .byte 13,10,0msg_write: .ascii " - PT written" .byte 13,10,0no_update: .ascii "NO "update: .ascii "24-25 update has occurred"crlf: .byte 13,10,0msg_cont: .ascii "\r\nHit any key to continue ..." .byte 0#endifswap13: #ifdef DEBUG mov si,#msg_swap13 call say#endif seg es ! allocate 1 kB dec word ptr [0x413] int 0x12 ! get start segment shl ax,#6 ! we are running on a 386 cli ! disable interrupts xor bx,bx ! zero a few registers mov di,bx seg es ! change offset xchg bx,[4*0x13] ! 0x4c mov old13of,bx mov bx,ax ! change segment seg es xchg bx,[4*0x13+2] ! 0x4e mov old13sg,bx mov es,ax ! move drive swapper mov si,#new13 mov cx,#new13end-new13 rep movsb sti ! enable interrupts ret ! donenew13: push ax ! save AX (contains function code in AH) push bp ! need BP to mess with stack mov bp,sp jmp new13a ! make space for signature .org new13+6 .ascii "LILO" .word STAGE_DRIVE_MAP .word VERSION .word drvmap-new13 ! relative pointer to drive mapnew13a: ! Stack layout: ! ! +8 INT flags ! +6 INT CS ! +4 INT IP ! +2 AX ! BP+0 BP pushf ! push flags (to act like interrupt) push si mov si,#drvmap-new13mapfl: seg cs ! get next entry mov ax,(si) ! do not depend on DIRECTION flag lea si,(si+2) ! ** or ax,ax ! at end ? jz nomap ! yes -> do not map cmp dl,al ! match ? jne mapfl ! no -> continue mov dl,ah ! map drivenomap: pop si ! restore SI mov 8(bp),ax ! overwrite old flags (to remember mapping) mov ax,2(bp) ! restore AX mov bp,(bp) ! restore BP .byte 0x9a ! CALL FARold13of:.word 0old13sg:.word 0 push bp ! save BP again mov bp,sp ! New stack layout: ! ! +10 mapping (was flags) ! +8 INT CS ! +6 INT IP ! +4 AX ! +2 obsolete BP ! BP+0 BP xchg ax,4(bp) ! save AX and get command pushf ! fix driver number, if necessary cmp ah,#8 ! do not fix je done13 cmp ah,#0x15 ! do not fix je done13 mov ax,10(bp) ! no mapping ? or ax,ax jz done13 mov dl,al ! fix mappingdone13: mov ax,4(bp) ! restore AX pop 10(bp) ! restore flags pop bp ! get BP add sp,#4 ! fix SP iret ! donedrvmap: .blkw DRVMAP_SIZE+1new13end:#if defined(LCF_REWRITE_TABLE)prtmap: .blkw PRTMAP_SIZE*2+1 ! only first word of last entry is read#endiftheend:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -