1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
|
; chain.S - LILO boot chainer
;
; Copyright 1992-1998 Werner Almesberger.
; Copyright 1999-2001 John Coffman.
; All rights reserved.
;
; Licensed under the terms contained in the file 'COPYING' in the
; source directory.
;
#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 VERSION
offset: .word 0
drive: .byte 0 ! drive, 0x80, 0x81
.byte 0 ! head, always zero
hint: .word drvmap ! pointer to drive map
ptable: .blkw 0x20 ! partition table to preload
start:
xor ax,ax ! set SS:SP to 0:7C00
mov ss,ax
mov sp,#BOOTSEG*16 ! #0x7C00
mov bp,sp ! address from BP
push cs
pop ds ! DS = SETUPSEG
mov es,ax
mov cx,#SECTOR_SIZE/2
mtmp = 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_failed
ck_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 < SPACE
ck_loop:
loop ck_next
mov cx,#8 ; check Filesystem type
ck_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
#endif
dos4:
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_update
ck_say:
call say
#else
ck_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 rules
prtclp: 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 loadit
pmend: call flush ! flush table
br nopp ! and proceed
noc: mov ax,ds
mov bx,#PARTS_SCR ! scratch area 0000:0800
loadit: 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 offset
incache: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 dirty
nocng: br prtclp ! next one
flush: 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 ! argl
noflush:ret
wrfail: mov si,#failmsg ! complain
call say
mov ax,#FIRSTSEG ! try to restart LILO
jmpi #GO,FIRSTSEG
cache: .byte 0 ! drive, 0 means not cached
.byte 0 ! head, always 0
cbx: .blkw 1
ces: .blkw 1
dirty: .byte 0
#endif
; reverse drive mapping
; uses AX, SI
; may update DL
;
revmap1: mov dx,drive ; get drive/head pair
revmap:
mov si,#drvmap
rev0: 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: ret
nopp:
mov ax,drvmap ! need to install mapper ?
or ax,ax
jz noimap ! no -> go on
call swap13
noimap:
#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 XXX
mov ax,ds
mov es,ax
mov si,#lilosig
mov bx,#cmd
mov dl,#0xfe
#else
xor ax,ax ! set DS and ES to zero
mov ds,ax
mov es,ax
#endif
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
retf
#ifdef XXX
lilosig:.ascii "LILO"
cmd: .ascii "98"
.byte 0
#endif
#if defined(LCF_REWRITE_TABLE) || defined(DEBUG)
! Display a NUL-terminated string on the console
say: 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 one
aret: ret ! done
failmsg:.ascii "Rewrite error."
.byte 13,10,0
#endif
#ifdef DEBUG
wout: push ax
xchg ah,al
call bout ! write hi-byte
pop ax
bout: push ax ! save byte
shr al,#4 ! display upper nibble
call nout
pop ax
nout: 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
ret
msg_swap13:
.ascii "Install drive Swapper"
.byte 13,10,0
msg_load:
.ascii " - PT loaded"
.byte 13,10,0
msg_write:
.ascii " - PT written"
.byte 13,10,0
no_update:
.ascii "NO "
update:
.ascii "24-25 update has occurred"
.byte 13,10,0
#endif
swap13:
#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 ! done
new13: 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 map
new13a:
! 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-new13
mapfl: 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 drive
nomap: 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 FAR
old13of:.word 0
old13sg:.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 mapping
done13: mov ax,4(bp) ! restore AX
pop 10(bp) ! restore flags
pop bp ! get BP
add sp,#4 ! fix SP
iret ! done
drvmap: .blkw DRVMAP_SIZE+1
new13end:
#if defined(LCF_REWRITE_TABLE)
prtmap: .blkw PRTMAP_SIZE*2+1 ! only first word of last entry is read
#endif
theend:
|