Lilo的实现

书承上文:http://www.cnblogs.com/long123king/p/3549267.html

我们找一份Lilo的源码来看一下

http://freecode.com/projects/lilo

ftp://metalab.unc.edu/pub/Linux/system/boot/lilo/lilo-22.8.src.tar.gz

first.S就是写到MBR中的,我们刚刚分析了一部分的汇编代码文件

   1: #if 0
   2: ;  first.S  -  LILO first stage boot loader with LBA32 support */
   3: Copyright 1992-1998 Werner Almesberger.
   4: Copyright 1999-2005 John Coffman.
   5: All rights reserved.
   6:  
   7: Licensed under the terms contained in the file 'COPYING' in the 
   8: source directory.
   9:  
  10: #endif
  11: #define LILO_ASM
  12: #include "lilo.h"
  13: get common.s        /* as86 "include" will bypass the CPP */
  14:  
  15: #define DEBUG 0
  16:  
  17: #if VERSION_MINOR>=50
  18: # define DEBUG_NEW
  19:  
  20: # undef VIDEO_ENABLE
  21: # define VIDEO_ENABLE 3
  22:  
  23: # define VALIDATE !DEBUG    /* adds 0Dh bytes */
  24: # define SECOND_CHECK !DEBUG    /* adds  5h bytes */
  25: # define CYL1023 DEBUG        /* subs  8h bytes */
  26: # define GEOMETRIC !DEBUG    /* adds  1h byte  */
  27:  
  28: # if DEBUG
  29: #  define DEBUG_LARGE
  30: # endif
  31: #else
  32:  
  33: # define VALIDATE 1        /* adds 0Dh bytes */
  34: # define SECOND_CHECK 1        /* adds  5h bytes */
  35: # define CYL1023 0        /* subs  8h bytes */
  36: # define GEOMETRIC 1        /* adds  1h byte  */
  37: #endif
  38:  
  39:  
  40: !  VIDEO_ENABLE    for those systems that disable the video on boot
  41: !    = 0        first stage does not enable video
  42: !    = 1        use get vid mode/set vid mode to enable
  43: !    = 2        use VGA enable call to enable video
  44: !            (cannot use, as code gets too big)
  45: !    = 3        use direct mode set (mode 3, CGA, EGA, VGA)
  46: !    = 7        use direct mode set (mode 7, MDA)
  47: !
  48: #ifndef VIDEO_ENABLE
  49: # if VALIDATE==0
  50: #  define VIDEO_ENABLE 2
  51: # else
  52: #  define VIDEO_ENABLE 2
  53: # endif
  54: #endif
  55:  
  56: ! do not change the following -- it must correspond to the code in bsect.c
  57: #define RELOCATABLE -1
  58:  
  59:  
  60:     .text
  61:  
  62:     .globl    _main
  63:  
  64:     .org    0
  65:  
  66: zero:
  67: _main:    cli            ! NT 4 blows up if this is missing
  68:     jmp    start
  69:  
  70: stage:    .byte    STAGE_FIRST
  71:     .org    4
  72: reloc:
  73: #if RELOCATABLE
  74:     .word    theend-zero    ! size of the code & params
  75: #else
  76:     .word    0        ! no size indication
  77: #endif
  78:     .org    6
  79:  
  80: ! Boot device parameters. They are set by the installer.
  81:  
  82: sig:    .ascii    "LILO"
  83: vers:    .word    VERSION
  84: mapstamp: .long 0        ! map timestamp
  85:  
  86: length    =  *-sig        ! for the stage 1 vs stage 2 comparison
  87:  
  88: raid:    .long    0        ! raid sector offset
  89: tstamp:    .long    0        ! timestamp
  90: map_serial_no:    .long    0    ! volume S/N containing map file
  91: prompt:    .word    0        ! indicates whether to always enter prompt
  92:                 ! contains many other flags, too
  93:  
  94: d_dev:    .byte    0x80        ! map file device code
  95: d_flag:    .byte    0        ! disk addressing flags
  96: d_addr:    .long    0        ! disk addr of second stage index sector
  97:  
  98:  
  99: edd_packet    =  0
 100: ;;;    .word    16        ! size of packet
 101: ;;;    .word    1        ! count of bytes to read
 102:  
 103: edd_addr    =  4
 104: ;;;    .word    map2        ! where to read
 105: ;;;    .word    *-*        ! segment where to read
 106:  
 107: edd_d_addr    =  8
 108: ;;;    .long    1        ! low address or CX,DX (geometric)
 109:                 ! start at sector 1 for search in geo mode
 110:  
 111: ;;;    .long    0        ! hi address
 112:  
 113: #if 0
 114: !  These locations are referenced as EX_OFF 
 115: !                    (they used to be at CODE_START_1)
 116: ext_si:    .word    0        ! external interface
 117: ext_es:    .word    0        ! these locations are referenced in second.S
 118: ext_bx:    .word    0        ! do not disturb the ordering
 119: ext_dl:    .byte    0        ! second.S will check this magic number
 120: ext_dh:    .byte    0        ! not referenced, but must align stack
 121: ext_stack:
 122: #endif
 123:     
 124: /***************************************************/
 125: !    The following instruction MUST be
 126: !    first instruction after the CLI/JMP short
 127: !    at the start of the file; otherwise
 128: !    the boot sector relocation fails.
 129: !
 130: start:
 131:     mov    ax,#BOOTSEG    ! use DS,ES,SS = 0x07C0
 132: /***************************************************/
 133:  
 134:     mov    ss,ax
 135:     mov    sp,#SETUP_STACKSIZE    ! set the stack for First Stage
 136:     sti            ! now it is safe
 137:  
 138:     push    dx        ! set ext_dl (and ext_dh, which is not used)
 139:     push    bx        ! WATCH the order of pushes
 140:     push    es        ! set ext_es
 141:     push    si        ! set ext_si
 142:  
 143: #ifdef DEBUG_NEW
 144:     push    ds
 145:     push    es    ! just not enough space with debug turned on
 146: #endif
 147:  
 148: #define JRC_DS_EQ_SS
 149:  
 150:     cld            ! do not forget to do this !!!
 151:     mov    ds,ax        ! address data area
 152:     xor    bp,bp        ! shorted addressing
 153:  
 154: #if VIDEO_ENABLE
 155: ! a BIOS has been found where the video interrupt (0x10) trashes DX
 156: !   so, we had better be very paranoid about DX
 157: !
 158: # if VIDEO_ENABLE==2
 159:     pusha            ! protect DX
 160: # endif
 161: # if VIDEO_ENABLE > 2
 162:     mov    ax,#VIDEO_ENABLE    ! set video mode 3 or 7
 163: # elif VIDEO_ENABLE==1
 164:     mov    ah,#15        ! get video mode
 165:     int    0x10
 166:     cbw
 167: # else  /* VIDEO_ENABLE==2 */
 168:     mov    ax,#0x1200    ! enable video (VGA)
 169:     mov    bl,#0x36    ! (probably a nop on EGA or MDA)
 170: # endif
 171:     int    0x10        ! video call
 172: # if VIDEO_ENABLE==2
 173:     popa            ! restore DX
 174: # endif
 175: #endif
 176:  
 177: #if (VIDEO_ENABLE&1) == 0
 178:     mov    al,#0x0d    ! gimme a CR ...
 179:     call    display
 180: ; the suspect call for trashing DX on one BIOS:
 181:     mov    al,#0x0a    ! ... an LF ...
 182:     call    display
 183: #endif
 184:  
 185: #if defined(DEBUG_NEW)
 186:     mov    ah,dl
 187:     call    bout        ! code in AH
 188: #endif
 189:     mov    al,#0x4c    ! ... an 'L' ...
 190:     call    display
 191:  
 192: lagain:
 193:     pusha            ! preserve all the registers for restart
 194:  
 195:     push    ds
 196:     pop    es        ! use buffer at end of boot sector
 197:  
 198:     cmp    dl,#EX_DL_MAG    ! possible boot command line (chain.S)
 199:     jne    boot_in_dl
 200:     mov    dl,dh        ! code passed in DH instead
 201: boot_in_dl:
 202:  
 203:     mov    bx,#map2    ! buffer for volume search
 204:     mov    dh,[d_dev](bp)  ! map device to DH
 205:  
 206: #if VALIDATE
 207:     mov    ax,dx        ! copy device code to AL
 208:     and    ah,#0x80    ! AH = 00 or 80
 209:     xor    al,ah        ! hi-bits must be the same
 210:     js    use_installed
 211:     cmp    al,#MAX_BIOS_DEVICES    ! limit the device code
 212:     jae    use_installed    ! jump if DL is not valid
 213: #endif
 214:  
 215: ! map is on boot device for RAID1, and if so marked; viz.,
 216:  
 217:     test    byte ptr [prompt](bp),#FLAG_MAP_ON_BOOT
 218:     jnz    use_boot    ! as passed in from BIOS or MBR loader
 219:  
 220: use_installed:
 221:     mov    dl,dh        ! device code to DL
 222:     mov    esi,[map_serial_no](bp)    ! to search for
 223:     or    esi,esi
 224:     jz    done_search
 225:  
 226:     push    dx        ! save flags
 227:  
 228:     mov    ah,#8        ! get number of hard disks
 229:     mov    dl,#0x80
 230:     push    bx        ! paranoia
 231:     int    0x13
 232:     pop    bx
 233:     jc    error
 234:  
 235:     movzx    cx,dl        ! extend to word in CX
 236:  
 237: #if GEOMETRIC
 238:     mov    dx,#0x80-1    ! device 80, flags=0
 239: #else
 240:     mov    dx,#LBA32_FLAG*256+0x80-1    ! device 80, flags=LBA32
 241: #endif
 242:  
 243: vagain:
 244:     inc    dx
 245:     xor    eax,eax
 246: #if GEOMETRIC
 247:     inc    ax        ! geometric addressing
 248: #endif
 249:     call    disk_read    ! read 
 250:  
 251:     cmp    esi,[PART_TABLE_OFFSET-6](bx)
 252:     je    vol_found
 253:     loop    vagain
 254:  
 255:     pop    dx        ! restore specified BIOS code
 256:                 ! AX and DX are identical at this point
 257:  
 258: vol_found:
 259:         ! uses value in DX, stack may have extra value
 260:  
 261: done_search:    
 262: use_boot:
 263:     push    bx        ! save map2 for later
 264:  
 265:     mov    dh,[d_flag](bp)    ! get device flags to DH
 266:     mov    si,#d_addr
 267:     call    pread        ! increments BX
 268:  
 269:     mov    ah,#0x99    ! possible error code
 270:     cmp    dword (bx-4),#EX_MAG_HL    ! "LILO"
 271:     jne    error
 272:  
 273:     pop    si        ! point at #map2
 274:  
 275: #if 1
 276:     push    #SETUP_STACKSIZE/16 + BOOTSEG + SECTOR_SIZE/16*2
 277:     pop    es
 278: #else
 279:     mov    ax,ds        ! get segment
 280:     add    ax,#SETUP_STACKSIZE/16    !   + SECTOR_SIZE/16*2
 281:     mov    es,ax
 282: #endif
 283:     xor    bx,bx
 284:  
 285: sload:
 286:     call    pread        ! read using map at DS:SI
 287:     jnz    sload        ! into memory at ES:BX (auto increment)
 288:  
 289: ! Verify second stage loader signature
 290:     
 291:     mov    si,#sig        ! pointer to signature area
 292:     mov    di,si
 293:     mov    cx,#length    ! number of bytes to compare
 294:     mov    ah,#0x9A    ! possible error code
 295:     repe
 296:       cmpsb            ! check Signature 1 & 2
 297:     jne    error    ! check Signature 2
 298:  
 299: #if SECOND_CHECK
 300: /* it would be nice to re-incorporate this check */
 301:     mov    al,#STAGE_SECOND    ! do not touch AH (error code)
 302:     scasb
 303:     jne    error
 304: #endif
 305:  
 306: ! Start the second stage loader     DS=location of Params
 307:  
 308:     push    es        ! segment of second stage
 309:     push    bp        ! BP==0
 310:  
 311:     mov    al,#0x49    ! display an 'I'
 312:     call    display
 313:  
 314:     retf            ! Jump to ES:BP
 315:  
 316:  
 317:  
 318:  
 319: disk_error2:
 320:     mov    ah,#0x40    ; signal seek error
 321:  
 322: ! no return from error
 323: error:
 324:  
 325: #ifndef LCF_NO1STDIAG
 326:         mov    al,#32          ! display a space
 327:     call    display0
 328:  
 329:     call    bout
 330: #endif
 331:  
 332: #ifndef DEBUG_LARGE
 333:     dec    byte [zero](bp)        !  CLI == 0xFA == 250
 334:     jz    zzz
 335:  
 336: #ifndef DEBUG_NEW
 337:     mov    sp,#SETUP_STACKSIZE-4*2-8*2    ! set the stack for First Stage
 338: #else
 339:     mov    sp,#SETUP_STACKSIZE-4*2-2*2-8*2    ! set the stack for First Stage
 340: #endif
 341:     popa                ! restore registers for restart
 342:     jmp    near lagain        ! redo from start
 343: #endif
 344:  
 345:  
 346: zzz:
 347: #ifndef DEBUG_NEW
 348:     hlt
 349: #endif
 350:     jmp    zzz        ! spin; wait for Ctrl-Alt-Del
 351:  
 352:  
 353:  
 354:  
 355: ! packet read routine
 356:  
 357: disk_read:
 358: #ifndef JRC_DS_EQ_SS
 359:     push    ds
 360: #endif
 361:     pusha
 362:  
 363: #ifndef JRC_DS_EQ_SS
 364:     push    ss
 365:     pop    ds
 366: #endif
 367:  
 368:     push    bp        ! BP==0
 369:     push    bp        ! BP==0
 370:  
 371:     push    eax        ! low order disk address
 372: #ifdef DEBUG_LARGE
 373:     xchg    ax,dx
 374:     call    wout
 375:     xchg    ax,dx
 376:     call    dout        ! print out disk address
 377: #endif
 378:     push    es        ! memory segment ES
 379:     push    bx        ! memory offset BX
 380:     push    #1        ! sector count
 381:     push    #16        ! size of packet = 16 bytes
 382:     mov    si,sp        ! address of packet  DS:SI
 383:  
 384:     push    bx
 385:  
 386:     test    dh,#LINEAR_FLAG|LBA32_FLAG
 387:     jz    disk_geometric
 388:     
 389:     test    dh,#LBA32_FLAG
 390:     jz    disk_convert    ; it must be LINEAR
 391:  
 392:     mov    bx,#0x55AA    ;magic number
 393:     mov    ah,#0x41
 394:     int    0x13
 395:     jc    disk_convert
 396:     cmp    bx,#0xAA55    ;changed?
 397:     jne    disk_convert
 398:     test    cl,#EDD_PACKET    ;EDD packet calls supported
 399:     jnz    disk_edd
 400:  
 401: disk_convert:
 402:     push    dx
 403:     push    es        ! protect on floppies
 404:     mov    ah,#8        ! get geometry
 405:     int    0x13
 406:     pop    es
 407: disk_error3:            ! transfer through on CF=1
 408:     jc    error        ! disk_error12
 409:  
 410: #if !CYL1023
 411:     push    cx
 412:     shr    cl,#6        ;;;;
 413:     xchg    cl,ch       ;CX is max cylinder number
 414:     mov    di,cx       ;DI saves it
 415:     pop    cx
 416: #endif
 417:     shr    dx,#8
 418:     xchg    ax,dx        ;AX <- DX
 419:     inc    ax        ;AX is number of heads (256 allowed)
 420:  
 421: ; compensate for Davide BIOS bug
 422:     dec    cx        ; 1..63 -> 0..62;  0->63
 423:     and    cx,#0x003f    ;CX is number of sectors
 424:     inc    cx        ; allow Sectors==0 to mean 64
 425:  
 426:     mul    cx        ; kills DX also
 427:     xchg    ax,bx           ;save in BX
 428:  
 429:     mov    ax,[edd_d_addr](si)    ;low part of address
 430:     mov    dx,[edd_d_addr+2](si)    ;hi part of address
 431:  
 432:     cmp    dx,bx
 433:     jae    disk_error2    ;prevent division error
 434:  
 435:     div    bx        ;AX is cyl, DX is head/sect
 436: #if CYL1023
 437:     cmp    ax,#1023
 438: #else
 439:     cmp    ax,di
 440: #endif
 441:     ja    disk_error2    ;cyl is too big
 442:  
 443:     shl    ah,#6        ; save hi 2 bits
 444:     xchg    al,ah
 445:     xchg    ax,dx
 446:     div    cl        ;AH = sec-1, AL = head
 447:     or    dl,ah       ;form Cyl/Sec
 448:     mov    cx,dx
 449:     inc    cx        ; sector is 1 based
 450:  
 451:     pop    dx        ! restore device code
 452:     mov    dh,al        ! set head#
 453:     jmp    disk_read2
 454:  
 455:  
 456:  
 457: disk_edd:
 458:     mov    ah,#0x42
 459: disk_int13:
 460:     pop    bx
 461:  
 462:     mov    bp,#5
 463: disk_retry:
 464:     pusha
 465:     int    0x13
 466: #if 0
 467:     stc
 468:     mov    ah,#0x9C
 469: #endif
 470:     jnc    disk_okay
 471:  
 472:     dec    bp        ! does not alter CF, already 0
 473:     jz    disk_error3    ! go to "jc" with CF=1 & ZF=1
 474:  
 475:     xor    ax,ax        ! reset the disk controller
 476:     int    0x13
 477:     popa            ! reset AX,BX,CX,DX,SI
 478:     dec    bp        ! fix up BP count
 479:     jmp    disk_retry
 480:  
 481:  
 482: disk_geometric:
 483:     push    eax
 484:     pop    cx
 485:     pop    ax
 486:     mov    dh,ah
 487:  
 488: disk_read2:
 489:     mov    ax,#0x201    ;read, count of 1
 490:     jmp    disk_int13
 491:  
 492:  
 493: disk_okay:
 494: ; the pusha block is implicitly removed below
 495: ;;;    mov    (si+2*16-1),ah    ! set error code
 496: ;   the error code is never checked
 497:     lea    sp,(si+16)    ! do not touch carry; 
 498:     popa
 499: #ifndef JRC_DS_EQ_SS
 500:     pop    ds
 501: #endif
 502:     ret
 503:  
 504:  
 505:  
 506: ! Pointer Read -- read using pointer in DS:SI
 507:  
 508: pread:
 509:     lodsd            ! get address
 510:     or    eax,eax
 511:     jz    done
 512:     add    eax,[raid](bp)    ! reloc is 0 on non-raid
 513:     call    disk_read    
 514:  
 515:     add    bh,#SECTOR_SIZE/256        ! next sector
 516: done:
 517:     ret
 518:  
 519:  
 520:  
 521:  
 522: #if !defined(LCF_NO1STDIAG) || defined(DEBUG_NEW)
 523: bout:    rol     ax,#4        ! bring hi-nibble to position
 524:     call    nout
 525:     rol     ax,#4        ! bring lo-nibble to position
 526: nout:    and    al,#0x0F    ! display one nibble
 527:     daa            ! shorter conversion routine
 528:     add    al,#0xF0
 529:     adc    al,#0x40    ! is now a hex char 0..9A..F
 530: #endif
 531: ; display - write byte in AL to console
 532: ;    preserves all register contents
 533: ; 
 534: display0:
 535: #ifndef LCF_NOVGA
 536: display:
 537: #endif
 538:     pusha        ! make sure no register is changed
 539:     mov    bx,#7        !  BH=0, BL=07
 540:     mov    ah,#14
 541:     int    0x10
 542:     popa        ! restore all the registers
 543: #ifdef LCF_NOVGA
 544: display:
 545: #endif
 546:     ret
 547:  
 548: #ifdef DEBUG_LARGE
 549:  
 550: dout:    pushad
 551:     ror    eax,#16
 552:     call    wout
 553:     ror    eax,#16
 554:     call    wout
 555:     mov    al,#0x20    ! space
 556:     call    display
 557:     popad
 558:     ret
 559:  
 560: wout:    push    ax
 561:     call    bout    ! put out AH
 562:     pop    ax
 563:     push    ax
 564:     xchg    al,ah
 565:     call    bout    ! put out AL (now in AH)
 566:     pop    ax
 567:     ret
 568: #endif
 569:  
 570: theend:
 571:  
 572: !
 573: !   If 'first' loads as the MBR, then there must be space for the partition
 574: !   table.  If 'first' loads as the boot record of some partition, then
 575: !   the space reserved below is not used.  But we must reserve the area
 576: !   as a hedge against the first case.
 577: !
 578: !
 579:     .org    MAX_BOOT_SIZE    !
 580:     .word    0,0,0,0        ! space for NT, DRDOS, and LiLO volume S/N
 581:  
 582: !    .org    0x1be        ! spot for the partition table
 583: p_table:
 584:     .blkb    16
 585:     .blkb    16
 586:     .blkb    16
 587:     .blkb    16
 588: #ifdef FIRST
 589:     .org    *-2
 590:     .long    FIRST        ! boot block check
 591: #else
 592:     .word    0xAA55        ! boot block signature
 593: #endif
 594:  
 595: ! Better be exactly 0x200
 596:  
 597: map2    equ    *        ! addressed as ES:[map2]

    .text

    .globl    _main

    .org    0

zero:
_main:    cli            ! NT 4 blows up if this is missing
    jmp    start

#if (VIDEO_ENABLE&1) == 0
    mov    al,#0x0d    ! gimme a CR ...
    call    display
; the suspect call for trashing DX on one BIOS:
    mov    al,#0x0a    ! ... an LF ...
    call    display
#endif

#if defined(DEBUG_NEW)
    mov    ah,dl
    call    bout        ! code in AH
#endif
    mov    al,#0x4c    ! ... an 'L' ...
    call    display

second.S是主要的加载文件

我们找到下面代码:

jmpi    0,SETUPSEG        ; segment part is a variable

SYSSEG    =  0x1000    ; DEF_SYSSEG
SETUPSEG = 0x9020    ; DEF_SETUPSEG

因此:

   1: lb 0x90200
   2: c

因此,对于调试Linux内核来说,只要在0x90200处设置断点,即可以直接进入到Setup程序部分,而不需要考虑Lilo的具体实现。

原文地址:https://www.cnblogs.com/long123king/p/3549649.html