加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

reactos操作系统实现(47)

发布时间:2020-12-15 05:01:35 所属栏目:百科 来源:网络整理
导读:当光盘变成记录数据以后,就开始使用光盘来分发操作系统了。毕竟光盘有着储存数据量大,成本便宜的优势。下面就来分析 Reactos 是怎么样通过光盘的格式来引导操作系统的。 现今的计算机 BIOS ,会在开机时根据 El Torito 规格,查找光盘上的开机代码。若该光

当光盘变成记录数据以后,就开始使用光盘来分发操作系统了。毕竟光盘有着储存数据量大,成本便宜的优势。下面就来分析Reactos是怎么样通过光盘的格式来引导操作系统的。

现今的计算机BIOS,会在开机时根据El Torito规格,查找光盘上的开机代码。若该光盘具有开机代码,则BIOS会指配一个磁盘驱动器代号给该光驱。磁盘驱动器代号通常为80(模拟硬盘)或是00(模拟软盘)等。借由模拟成硬盘或软盘,可让旧式的操作系统由光盘开机。

现今新式的操作系统则不需做模拟,只要有如ISOLINUX之类的开机引导程序(boot loader),即可由光盘开机。

#001 ; ****************************************************************************

#002 ;

#003 ; isolinux.asm

#004 ;

#005 ; A program to boot Linux kernels off a CD-ROM using the El Torito

#006 ; boot standard in "no emulation" mode,making the entire filesystem

#007 ; available. It is based on the SYSLINUX boot loader for MS-DOS

#008 ; floppies.

#009 ;

#010 ; Copyright (C) 1994-2001 H. Peter Anvin

#011 ;

#012 ; This program is free software; you can redistribute it and/or modify

#013 ; it under the terms of the GNU General Public License as published by

#014 ; the Free Software Foundation,Inc.,675 Mass Ave,Cambridge MA 02139,

#015 ; USA; either version 2 of the License,or (at your option) any later

#016 ; version; incorporated herein by reference.

#017 ;

#018 ; ****************************************************************************

#019 ;

#020 ; THIS FILE IS A MODIFIED VERSION OF ISOLINUX.ASM

#021 ; MODIFICATION DONE BY MICHAEL K TER LOUW

#022 ; LAST UPDATED 3-9-2002

#023 ; SEE "COPYING" FOR INFORMATION ABOUT THE LICENSE THAT APPLIES TO THIS RELEASE

#024 ;

#025 ; ****************************************************************************

#026 ;

#027 ; This file is a modified version of ISOLINUX.ASM.

#028 ; Modification done by Eric Kohl

#029 ; Last update 04-25-2002

#030 ;

#031 ; ****************************************************************************

#032

#033 ; Note: The Makefile builds one version with DEBUG_MESSAGES automatically.

#034 ;%define DEBUG_MESSAGES ; Uncomment to get debugging messages

#035

#036 %define WAIT_FOR_KEY

#037

#038

下面BIOS的数据区保留内存空间。

#039 ; ---------------------------------------------------------------------------

#040 ; BEGIN THE BIOS/CODE/DATA SEGMENT

#041 ; ---------------------------------------------------------------------------

#042

#043 absolute 0400h

#044 serial_base resw 4 ; Base addresses for 4 serial ports

#045 absolute 0413h

#046 BIOS_fbm resw 1 ; Free Base Memory (kilobytes)

#047 absolute 046Ch

#048 BIOS_timer resw 1 ; Timer ticks

#049 absolute 0472h

#050 BIOS_magic resw 1 ; BIOS reset magic

#051 absolute 0484h

#052 BIOS_vidrows resb 1 ; Number of screen rows

#053

#054 ;

#055 ; Memory below this point is reserved for the BIOS and the MBR

#056 ;

1000h以前都是BIOS的数据区,不能放置代码。

#057 absolute 1000h

#058 trackbuf resb 8192 ; Track buffer goes here

#059 trackbufsize equ $-trackbuf

#060 ; trackbuf ends at 3000h

#061

#062 struc open_file_t

#063 file_sector resd 1 ; Sector pointer (0 = structure free)

#064 file_left resd 1 ; Number of sectors left

#065 endstruc

#066

#067 struc dir_t

#068 dir_lba resd 1 ; Directory start (LBA)

#069 dir_len resd 1 ; Length in bytes

#070 dir_clust resd 1 ; Length in clusters

#071 endstruc

#072

#073

#074 MAX_OPEN_LG2 equ 2 ; log2(Max number of open files)

#075 MAX_OPEN equ (1 << MAX_OPEN_LG2)

#076 SECTORSIZE_LG2 equ 11 ; 2048 bytes/sector (El Torito requirement)

#077 SECTORSIZE equ (1 << SECTORSIZE_LG2)

#078 CR equ 13 ; Carriage Return

#079 LF equ 10 ; Line Feed

#080 retry_count equ 6 ; How patient are we with the BIOS?

#081

#082

#083

BSS段数据。

#084 absolute 5000h ; Here we keep our BSS stuff

#085

#086 DriveNo resb 1 ; CD-ROM BIOS drive number

#087 DiskError resb 1 ; Error code for disk I/O

#088 RetryCount resb 1 ; Used for disk access retries

#089 TimeoutCount resb 1 ; Timeout counter

#090 ISOFlags resb 1 ; Flags for ISO directory search

#091 RootDir resb dir_t_size ; Root directory

#092 CurDir resb dir_t_size ; Current directory

#093 ISOFileName resb 64 ; ISO filename canonicalization buffer

#094 ISOFileNameEnd equ $

#095

#096

#097 alignb open_file_t_size

#098 Files resb MAX_OPEN*open_file_t_size

#099

#100

#101

这里ISOBOOT有代码段开始,由于BIOS会读取光盘的引导区到内存 7000开始位置,跟硬盘和磁盘是一样的。

#102 section .text

#103 org 7000h

#104

#105 start:

#106 cli ; Disable interrupts

#107 xor ax,ax ; ax = segment zero

#108 mov ss,ax ; Initialize stack segment

#109 mov sp,start ; Set up stack

#110 mov ds,ax ; Initialize other segment registers

#111 mov es,ax

#112 mov fs,ax

#113 mov gs,ax

#114 sti ; Enable interrupts

#115 cld ; Increment pointers

#116

把引导代码从0000:7C00位置拷贝到0000:7000位置,然后再运行。

#117 mov cx,2048 >> 2 ; Copy the bootsector

#118 mov si,0x7C00 ; from 0000:7C00

#119 mov di,0x7000 ; to 0000:7000

#120 rep movsd ; copy the program

通过一个跳转,实现重定位代码位置。

#121 jmp 0:relocate ; jump into relocated code

#122

#123 relocate:

如果显示调度信息。

#124 ; Display the banner and copyright

#125 %ifdef DEBUG_MESSAGES

#126 mov si,isolinux_banner ; si points to hello message

#127 call writestr ; display the message

#128 mov si,copyright_str

#129 call writestr

#130 %endif

#131

#132

下面通过检查键盘输入来决定是否从光盘引导系统。

先清空键盘输入。

#133 ; Make sure the keyboard buffer is empty

#134 %ifdef WAIT_FOR_KEY

#135 .kbd_buffer_test:

#136 call pollchar

#137 jz .kbd_buffer_empty

#138 call getchar

#139 jmp .kbd_buffer_test

#140 .kbd_buffer_empty:

到这里已经把键盘缓冲区清空了。

检查硬盘的MBR是否可以引导。

#141

#142 ; Check for MBR on harddisk

#143 pusha

#144 mov ax,0201h

#145 mov dx,0080h

#146 mov cx,0001h

#147 mov bx,trackbuf

#148 int 13h

#149 popa

如果硬盘不是可引导的,就立即跳到光盘引导,不需要用户选择。

#150 jc .boot_cdrom ; could not read hdd

#151

判断硬盘是否有引导扇区。

#152 push ax

#153 mov ax,word [trackbuf]

#154 cmp ax,0

如果没有引导扇区,就立即跳到光盘引导。

#155 je .boot_cdrom ; no boot sector found (hopefully there are no weird bootsectors which begin with 0)

#156 pop ax

#157

开始显示用户选择光盘引导,还是磁盘引导,同时进行5秒钟计时,如果用户不按下任何按键,就会自动选择硬盘引导。

#158 ; Display the 'Press key' message and wait for a maximum of 5 seconds

输出换行回车。

#159 call crlf

输出按下任何键的提示字符串。

#160 mov si,presskey_msg ; si points to 'Press key' message

#161 call writestr ; display the message

#162

5秒钟倒计时。

#163 mov byte [TimeoutCount],5

#164 .next_second:

获取当前时钟计数到eax,并且相加19个计数。

#165 mov eax,[BIOS_timer] ; load current tick counter

#166 add eax,19 ;

#167

测试是否有键盘输入任何按键。

#168 .poll_again:

#169 call pollchar

如果有任何按键输入,就跳到光盘引导。

#170 jnz .boot_cdrom

#171

每次比较BIOS里的计数是否与EAX计数相同。

#172 mov ebx,[BIOS_timer]

#173 cmp eax,ebx

#174 jnz .poll_again

#175

如果经历过19个计数,说明已经过了1秒钟。接着开始在屏幕上打印一个点。

#176 mov si,dot_msg ; print '.'

#177 call writestr

如果超过5秒钟,就跳到硬盘引导。

#178 dec byte [TimeoutCount] ; decrement timeout counter

#179 jz .boot_harddisk

跳到下一秒计时。

#180 jmp .next_second

#181

硬盘引导的代码。

#182 .boot_harddisk:

#183 call crlf

#184

从第一个硬盘引导。

#185 ; Boot first harddisk (drive 0x80)

#186 mov ax,0201h

#187 mov dx,0080h

#188 mov cx,0001h

#189 mov bx,7C00h

#190 int 13h

#191 jnc .go_hd

#192 jmp kaboom

#193 .go_hd:

#194 mov ax,cs

#195 mov ds,ax

#196 mov es,ax

#197 mov fs,ax

#198 mov gs,ax

#199 mov dx,0080h

#200

#201 jmp 0:0x7C00

#202 %endif

#203

从光盘引导。

#204 .boot_cdrom:

#205 %ifdef WAIT_FOR_KEY

#206 call crlf

#207 call crlf

#208 %endif

#209

#210 ; Save and display the boot drive number

#211 mov [DriveNo],dl

#212 %ifdef DEBUG_MESSAGES

#213 mov si,startup_msg

#214 call writemsg

#215 mov al,dl

#216 call writehex2

#217 call crlf

#218 %endif

#219

获取光驱的模拟状态。

#220 ; Now figure out what we're actually doing

#221 ; Note: use passed-in DL value rather than 7Fh because

#222 ; at least some BIOSes will get the wrong value otherwise

#223 mov ax,4B01h ; Get disk emulation status

#224 mov dl,[DriveNo]

#225 mov si,spec_packet

#226 int 13h

#227 jc near spec_query_failed ; Shouldn't happen (BIOS bug)

#228 mov dl,[DriveNo]

#229 cmp [sp_drive],dl ; Should contain the drive number

#230 jne near spec_query_failed

#231

#232 %ifdef DEBUG_MESSAGES

#233 mov si,spec_ok_msg

#234 call writemsg

#235 mov al,byte [sp_drive]

#236 call writehex2

#237 call crlf

#238 %endif

#239

发现有驱动器可以使用。

#240 found_drive:

通过中断13 48H号功能读取驱动器信息。

#241 ; Get drive information

#242 mov ah,48h

#243 mov dl,[DriveNo]

#244 mov si,drive_params

#245 int 13h

#246 jnc params_ok

#247

#248 ; mov si,nosecsize_msg No use in reporting this

#249 ; call writemsg

#250

#251 params_ok:

#252 ; Check for the sector size (should be 2048,but

#253 ; some BIOSes apparently think we're 512-byte media)

#254 ;

#255 ; FIX: We need to check what the proper behaviour

#256 ; is for getlinsec when the BIOS thinks the sector

#257 ; size is 512!!! For that,we need such a BIOS,though...

#258 %ifdef DEBUG_MESSAGES

#259 mov si,secsize_msg

#260 call writemsg

#261 mov ax,[dp_secsize]

#262 call writehex4

#263 call crlf

#264 %endif

#265

#266

清空文件结构。

#267 ;

#268 ; Clear Files structures

#269 ;

#270 mov di,Files

#271 mov cx,(MAX_OPEN*open_file_t_size)/4

#272 xor eax,eax

#273 rep stosd

#274

#275 ;

#276 ; Now,we need to sniff out the actual filesystem data structures.

#277 ; mkisofs gave us a pointer to the primary volume descriptor

#278 ; (which will be at 16 only for a single-session disk!); from the PVD

#279 ; we should be able to find the rest of what we need to know.

#280 ;

获取一个扇区数据。

#281 get_fs_structures:

#282 mov eax,16 ; Primary Volume Descriptor (sector 16)

#283 mov bx,trackbuf

#284 call getonesec

#285

#286 mov eax,[trackbuf+156+2]

#287 mov [RootDir+dir_lba],eax

#288 mov [CurDir+dir_lba],eax

#289 %ifdef DEBUG_MESSAGES

#290 mov si,rootloc_msg

#291 call writemsg

#292 call writehex8

#293 call crlf

#294 %endif

#295

#296 mov eax,[trackbuf+156+10]

#297 mov [RootDir+dir_len],eax

#298 mov [CurDir+dir_len],eax

#299 %ifdef DEBUG_MESSAGES

#300 mov si,rootlen_msg

#301 call writemsg

#302 call writehex8

#303 call crlf

#304 %endif

#305 add eax,SECTORSIZE-1

#306 shr eax,SECTORSIZE_LG2

#307 mov [RootDir+dir_clust],eax

#308 mov [CurDir+dir_clust],eax

#309 %ifdef DEBUG_MESSAGES

#310 mov si,rootsect_msg

#311 call writemsg

#312 call writehex8

#313 call crlf

#314 %endif

#315

这里查找根目录里的目录名称“/LOADER”。

#316 ; Look for the "REACTOS" directory,and if found,

#317 ; make it the current directory instead of the root

#318 ; directory.

#319 mov di,isolinux_dir

#320 mov al,02h ; Search for a directory

#321 call searchdir_iso

#322 jnz .dir_found

#323 mov si,no_dir_msg

#324 call writemsg

#325 jmp kaboom

#326

#327 .dir_found:

#328 mov [CurDir+dir_len],eax

#329 mov eax,[si+file_left]

#330 mov [CurDir+dir_clust],eax

#331 xor eax,eax ; Free this file pointer entry

#332 xchg eax,[si+file_sector]

#333 mov [CurDir+dir_lba],eax

#334

#335

这里查找二级引导程序“SETUPLDR.SYS”文件。

#336 mov di,isolinux_bin ; di points to Isolinux filename

#337 call searchdir ; look for the file

#338 jnz .isolinux_opened ; got the file

#339 mov si,no_isolinux_msg ; si points to error message

#340 call writemsg ; display the message

#341 jmp kaboom ; fail boot

#342

#343 .isolinux_opened:

#344 mov di,si ; save file pointer

#345

#346 %ifdef DEBUG_MESSAGES

#347 mov si,filelen_msg

#348 call writemsg

#349 call writehex8

#350 call crlf

#351 %endif

#352

计算扇区的大小。

#353 mov ecx,eax ; calculate sector count

#354 shr ecx,11

#355 test eax,0x7FF

#356 jz .full_sector

#357 inc ecx

#358 .full_sector:

#359

#360 %ifdef DEBUG_MESSAGES

#361 mov eax,ecx

#362 mov si,filesect_msg

#363 call writemsg

#364 call writehex8

#365 call crlf

#366 %endif

#367

这里把二级引导程序加载到0x8000位置。

#368 mov bx,0x8000 ; bx = load address

#369 mov si,di ; restore file pointer

#370 mov cx,0xFFFF ; load the whole file

#371 call getfssec ; get the whole file

#372

#373 %ifdef DEBUG_MESSAGES

#374 mov si,startldr_msg

#375 call writemsg

#376 call crlf

#377 %endif

#378

#379 mov dl,[DriveNo] ; dl = boot drive

#380 mov dh,0 ; dh = boot partition

最后跳转到0x8000的位置运行二级引导程序,也就是运行SETUPLDR.SYS文件。

#381 jmp 0:0x8000 ; jump into OSLoader

#382

#383

#384

#385 ;

#386 ; searchdir:

#387 ;

#388 ; Open a file

#389 ;

#390 ; On entry:

#391 ; DS:DI = filename

#392 ; If successful:

#393 ; ZF clear

#394 ; SI = file pointer

#395 ; DX:AX or EAX = file length in bytes

#396 ; If unsuccessful

#397 ; ZF set

#398 ;

#399

#400 ;

#401 ; searchdir_iso is a special entry point for ISOLINUX only. In addition

#402 ; to the above,searchdir_iso passes a file flag mask in AL. This is useful

#403 ; for searching for directories.

#404 ;

#405 alloc_failure:

#406 xor ax,ax ; ZF <- 1

#407 ret

#408

#409 searchdir:

#410 xor al,al

#411 searchdir_iso:

#412 mov [ISOFlags],al

#413 call allocate_file ; Temporary file structure for directory

#414 jnz alloc_failure

#415 push es

#416 push ds

#417 pop es ; ES = DS

#418 mov si,CurDir

#419 cmp byte [di],'/' ; If filename begins with slash

#420 jne .not_rooted

#421 inc di ; Skip leading slash

#422 mov si,RootDir ; Reference root directory instead

#423 .not_rooted:

#424 mov eax,[si+dir_clust]

#425 mov [bx+file_left],eax

#426 mov eax,[si+dir_lba]

#427 mov [bx+file_sector],eax

#428 mov edx,[si+dir_len]

#429

#430 .look_for_slash:

#431 mov ax,di

#432 .scan:

#433 mov cl,[di]

#434 inc di

#435 and cl,cl

#436 jz .isfile

#437 cmp cl,'/'

#438 jne .scan

#439 mov [di-1],byte 0 ; Terminate at directory name

#440 mov cl,02h ; Search for directory

#441 xchg cl,[ISOFlags]

#442 push di

#443 push cx

#444 push word .resume ; Where to "return" to

#445 push es

#446 .isfile:

#447 xchg ax,di

#448

#449 .getsome:

#450 ; Get a chunk of the directory

#451 mov si,trackbuf

#452 pushad

#453 xchg bx,si

#454 mov cx,1 ; load one sector

#455 call getfssec

#456 popad

#457

#458 .compare:

#459 movzx eax,byte [si] ; Length of directory entry

#460 cmp al,33

#461 jb .next_sector

#462 mov cl,[si+25]

#463 xor cl,[ISOFlags]

#464 test cl,byte 8Eh ; Unwanted file attributes!

#465 jnz .not_file

#466 pusha

#467 movzx cx,byte [si+32] ; File identifier length

#468 add si,byte 33 ; File identifier offset

#469 call iso_compare_names

#470 popa

#471 je .success

#472 .not_file:

#473 sub edx,eax ; Decrease bytes left

#474 jbe .failure

#475 add si,ax ; Advance pointer

#476

#477 .check_overrun:

#478 ; Did we finish the buffer?

#479 cmp si,trackbuf+trackbufsize

#480 jb .compare ; No,keep going

#481

#482 jmp short .getsome ; Get some more directory

#483

#484 .next_sector:

#485 ; Advance to the beginning of next sector

#486 lea ax,[si+SECTORSIZE-1]

#487 and ax,~(SECTORSIZE-1)

#488 sub ax,si

#489 jmp short .not_file ; We still need to do length checks

#490

#491 .failure:

#492 %ifdef DEBUG_MESSAGES

#493 mov si,findfail_msg

#494 call writemsg

#495 call crlf

#496 %endif

#497 xor eax,eax ; ZF = 1

#498 mov [bx+file_sector],eax

#499 pop es

#500 ret

#501

#502 .success:

#503 mov eax,[si+2] ; Location of extent

#504 mov [bx+file_sector],eax

#505 mov eax,[si+10] ; Data length

#506 push eax

#507 add eax,SECTORSIZE-1

#508 shr eax,SECTORSIZE_LG2

#509 mov [bx+file_left],eax

#510 pop eax

#511 mov edx,eax

#512 shr edx,16

#513 and bx,bx ; ZF = 0

#514 mov si,bx

#515 pop es

#516 ret

#517

#518 .resume:

#519 ; We get here if we were only doing part of a lookup

#520 ; This relies on the fact that .success returns bx == si

#521 xchg edx,eax ; Directory length in edx

#522 pop cx ; Old ISOFlags

#523 pop di ; Next filename pointer

#524

#525 mov byte [di-1],'/' ; restore the backslash in the filename

#526

#527 mov [ISOFlags],cl ; Restore the flags

#528 jz .failure ; Did we fail? If so fail for real!

#529 jmp .look_for_slash ; Otherwise,next level

#530

#531 ;

#532 ; allocate_file: Allocate a file structure

#533 ;

#534 ; If successful:

#535 ; ZF set

#536 ; BX = file pointer

#537 ; In unsuccessful:

#538 ; ZF clear

#539 ;

#540 allocate_file:

#541 push cx

#542 mov bx,Files

#543 mov cx,MAX_OPEN

#544 .check:

#545 cmp dword [bx],byte 0

#546 je .found

#547 add bx,open_file_t_size ; ZF = 0

#548 loop .check

#549 ; ZF = 0 if we fell out of the loop

#550 .found:

#551 pop cx

#552 ret

#553

#554 ;

#555 ; iso_compare_names:

#556 ; Compare the names DS:SI and DS:DI and report if they are

#557 ; equal from an ISO 9660 perspective. SI is the name from

#558 ; the filesystem; CX indicates its length,and ';' terminates.

#559 ; DI is expected to end with a null.

#560 ;

#561 ; Note: clobbers AX,CX,SI,DI; assumes DS == ES == base segment

#562 ;

#563 iso_compare_names:

#564 ; First,terminate and canonicalize input filename

#565 push di

#566 mov di,ISOFileName

#567 .canon_loop:

#568 jcxz .canon_end

#569 lodsb

#570 dec cx

#571 cmp al,';'

#572 je .canon_end

#573 and al,al

#574 je .canon_end

#575 stosb

#576 cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun

#577 jb .canon_loop

#578 .canon_end:

#579 cmp di,ISOFileName

#580 jbe .canon_done

#581 cmp byte [di-1],'.' ; Remove terminal dots

#582 jne .canon_done

#583 dec di

#584 jmp short .canon_end

#585 .canon_done:

#586 mov [di],byte 0 ; Null-terminate string

#587 pop di

#588 mov si,ISOFileName

#589 .compare:

#590 lodsb

#591 mov ah,[di]

#592 inc di

#593 and ax,ax

#594 jz .success ; End of string for both

#595 and al,al ; Is either one end of string?

#596 jz .failure ; If so,failure

#597 and ah,ah

#598 jz .failure

#599 or ax,2020h ; Convert to lower case

#600 cmp al,ah

#601 je .compare

#602 .failure:

#603 and ax,ax ; ZF = 0 (at least one will be nonzero)

#604 .success:

#605 ret

#606

#607

#608

#609

#610

#611

#612

#613 ;

#614 ; getfssec: Get multiple clusters from a file,given the file pointer.

#615 ;

#616 ; On entry:

#617 ; ES:BX -> Buffer

#618 ; SI -> File pointer

#619 ; CX -> Cluster count; 0FFFFh = until end of file

#620 ; On exit:

#621 ; SI -> File pointer (or 0 on EOF)

#622 ; CF = 1 -> Hit EOF

#623 ;

#624 getfssec:

#625 cmp cx,[si+file_left]

#626 jna .ok_size

#627 mov cx,[si+file_left]

#628

#629 .ok_size:

#630 mov bp,cx

#631 push cx

#632 push si

#633 mov eax,[si+file_sector]

#634 call getlinsec

#635 xor ecx,ecx

#636 pop si

#637 pop cx

#638

#639 add [si+file_sector],ecx

#640 sub [si+file_left],ecx

#641 ja .not_eof ; CF = 0

#642

#643 xor ecx,ecx

#644 mov [si+file_sector],ecx ; Mark as unused

#645 xor si,si

#646 stc

#647

#648 .not_eof:

#649 ret

#650

#651

#652

#653 ; INT 13h,AX=4B01h,DL=<passed in value> failed.

#654 ; Try to scan the entire 80h-FFh from the end.

#655 spec_query_failed:

#656 mov si,spec_err_msg

#657 call writemsg

#658

#659 mov dl,0FFh

#660 .test_loop:

#661 pusha

#662 mov ax,4B01h

#663 mov si,spec_packet

#664 mov byte [si],13 ; Size of buffer

#665 int 13h

#666 popa

#667 jc .still_broken

#668

#669 mov si,maybe_msg

#670 call writemsg

#671 mov al,dl

#672 call writehex2

#673 call crlf

#674

#675 cmp byte [sp_drive],dl

#676 jne .maybe_broken

#677

#678 ; Okay,good enough...

#679 mov si,alright_msg

#680 call writemsg

#681 mov [DriveNo],dl

#682 .found_drive:

#683 jmp found_drive

#684

#685 ; Award BIOS 4.51 apparently passes garbage in sp_drive,

#686 ; but if this was the drive number originally passed in

#687 ; DL then consider it "good enough"

#688 .maybe_broken:

#689 cmp byte [DriveNo],dl

#690 je .found_drive

#691

#692 .still_broken:

#693 dec dx

#694 cmp dl,80h

#695 jnb .test_loop

#696

#697 fatal_error:

#698 mov si,nothing_msg

#699 call writemsg

#700

#701 .norge:

#702 jmp short .norge

#703

#704

#705

#706 ; Information message (DS:SI) output

#707 ; Prefix with "isolinux: "

#708 ;

#709 writemsg:

#710 push ax

#711 push si

#712 mov si,isolinux_str

#713 call writestr

#714 pop si

#715 call writestr

#716 pop ax

#717 ret

#718

#719 ;

#720 ; crlf: Print a newline

#721 ;

#722 crlf:

#723 mov si,crlf_msg

#724 ; Fall through

#725

#726 ;

#727 ; writestr: write a null-terminated string to the console,saving

#728 ; registers on entry.

#729 ;

#730 writestr:

#731 pushfd

#732 pushad

#733 .top:

#734 lodsb

#735 and al,al

#736 jz .end

#737 call writechr

#738 jmp short .top

#739 .end:

#740 popad

#741 popfd

#742 ret

#743

#744

#745 ;

#746 ; writehex[248]: Write a hex number in (AL,AX,EAX) to the console

#747 ;

#748 writehex2:

#749 pushfd

#750 pushad

#751 shl eax,24

#752 mov cx,2

#753 jmp short writehex_common

#754 writehex4:

#755 pushfd

#756 pushad

#757 shl eax,16

#758 mov cx,4

#759 jmp short writehex_common

#760 writehex8:

#761 pushfd

#762 pushad

#763 mov cx,8

#764 writehex_common:

#765 .loop:

#766 rol eax,4

#767 push eax

#768 and al,0Fh

#769 cmp al,10

#770 jae .high

#771 .low:

#772 add al,'0'

#773 jmp short .ischar

#774 .high:

#775 add al,'A'-10

#776 .ischar:

#777 call writechr

#778 pop eax

#779 loop .loop

#780 popad

#781 popfd

#782 ret

#783

#784 ;

#785 ; Write a character to the screen. There is a more "sophisticated"

#786 ; version of this in the subsequent code,so we patch the pointer

#787 ; when appropriate.

#788 ;

#789

#790 writechr:

#791 pushfd

#792 pushad

#793 mov ah,0Eh

#794 xor bx,bx

#795 int 10h

#796 popad

#797 popfd

#798 ret

#799

#800 ;

#801 ; Get one sector. Convenience entry point.

#802 ;

#803 getonesec:

#804 mov bp,1

#805 ; Fall through to getlinsec

#806

#807 ;

#808 ; Get linear sectors - EBIOS LBA addressing,2048-byte sectors.

#809 ;

#810 ; Note that we can't always do this as a single request,because at least

#811 ; Phoenix BIOSes has a 127-sector limit. To be on the safe side,stick

#812 ; to 32 sectors (64K) per request.

#813 ;

#814 ; Input:

#815 ; EAX - Linear sector number

#816 ; ES:BX - Target buffer

#817 ; BP - Sector count

#818 ;

#819 getlinsec:

#820 mov si,dapa ; Load up the DAPA

#821 mov [si+4],bx

#822 mov bx,es

#823 mov [si+6],bx

#824 mov [si+8],eax

#825 .loop2:

#826 push bp ; Sectors left

#827 cmp bp,[MaxTransfer]

#828 jbe .bp_ok

#829 mov bp,[MaxTransfer]

#830 .bp_ok:

#831 mov [si+2],bp

#832 push si

#833 mov dl,[DriveNo]

#834 mov ah,42h ; Extended Read

#835 call xint13

#836 pop si

#837 pop bp

#838 movzx eax,word [si+2] ; Sectors we read

#839 add [si+8],eax ; Advance sector pointer

#840 sub bp,ax ; Sectors left

#841 shl ax,SECTORSIZE_LG2-4 ; 2048-byte sectors -> segment

#842 add [si+6],ax ; Advance buffer pointer

#843 and bp,bp

#844 jnz .loop2

#845 mov eax,[si+8] ; Next sector

#846 ret

#847

#848 ; INT 13h with retry

#849 xint13:

#850 mov byte [RetryCount],retry_count

#851 .try:

#852 pushad

#853 int 13h

#854 jc .error

#855 add sp,byte 8*4 ; Clean up stack

#856 ret

#857 .error:

#858 mov [DiskError],ah ; Save error code

#859 popad

#860 dec byte [RetryCount]

#861 jz .real_error

#862 push ax

#863 mov al,[RetryCount]

#864 mov ah,[dapa+2] ; Sector transfer count

#865 cmp al,2 ; Only 2 attempts left

#866 ja .nodanger

#867 mov ah,1 ; Drop transfer size to 1

#868 jmp short .setsize

#869 .nodanger:

#870 cmp al,retry_count-2

#871 ja .again ; First time,just try again

#872 shr ah,1 ; Otherwise,try to reduce

#873 adc ah,0 ; the max transfer size,but not to 0

#874 .setsize:

#875 mov [MaxTransfer],ah

#876 mov [dapa+2],ah

#877 .again:

#878 pop ax

#879 jmp .try

#880

#881 .real_error:

#882 mov si,diskerr_msg

#883 call writemsg

#884 mov al,[DiskError]

#885 call writehex2

#886 mov si,ondrive_str

#887 call writestr

#888 mov al,dl

#889 call writehex2

#890 call crlf

#891 ; Fall through to kaboom

#892

#893 ;

#894 ; kaboom: write a message and bail out. Wait for a user keypress,

#895 ; then do a hard reboot.

#896 ;

#897 kaboom:

#898 mov ax,cs

#899 mov ds,ax

#900 mov es,ax

#901 mov fs,ax

#902 mov gs,ax

#903 sti

#904 mov si,err_bootfailed

#905 call writestr

#906 call getchar

#907 cli

#908 mov word [BIOS_magic],0 ; Cold reboot

#909 jmp 0F000h:0FFF0h ; Reset vector address

#910

#911 getchar:

#912 .again:

#913 mov ah,1 ; Poll keyboard

#914 int 16h

#915 jz .again

#916 .kbd:

#917 xor ax,ax ; Get keyboard input

#918 int 16h

#919 .func_key:

#920 ret

#921

#922

#923 ;

#924 ; pollchar: check if we have an input character pending (ZF = 0)

#925 ;

#926 pollchar:

#927 pushad

#928 mov ah,1 ; Poll keyboard

#929 int 16h

#930 popad

#931 ret

#932

#933

#934

#935 isolinux_banner db CR,LF,'Loading IsoBoot...',CR,0

#936 copyright_str db ' Copyright (C) 1994-2002 H. Peter Anvin',0

#937 presskey_msg db 'Press any key to boot from CD',0

#938 dot_msg db '.',0

#939

#940 %ifdef DEBUG_MESSAGES

#941 startup_msg: db 'Starting up,DL = ',0

#942 spec_ok_msg: db 'Loaded spec packet OK,drive = ',0

#943 secsize_msg: db 'Sector size appears to be ',0

#944 rootloc_msg: db 'Root directory location: ',0

#945 rootlen_msg: db 'Root directory length: ',0

#946 rootsect_msg: db 'Root directory length(sectors): ',0

#947 fileloc_msg: db 'SETUPLDR.SYS location: ',0

#948 filelen_msg: db 'SETUPLDR.SYS length: ',0

#949 filesect_msg: db 'SETUPLDR.SYS length(sectors): ',0

#950 findfail_msg: db 'Failed to find file!',0

#951 startldr_msg: db 'Starting SETUPLDR.SYS',0

#952 %endif

#953

#954 nosecsize_msg: db 'Failed to get sector size,assuming 0800',0

#955 spec_err_msg: db 'Loading spec packet failed,trying to wing it...',0

#956 maybe_msg: db 'Found something at drive = ',0

#957 alright_msg: db 'Looks like it might be right,continuing...',0

#958 nothing_msg: db 'Failed to locate CD-ROM device; boot failed.',0

#959 isolinux_str db 'IsoBoot: ',0

#960 crlf_msg db CR,0

#961 diskerr_msg: db 'Disk error ',0

#962 ondrive_str: db ',drive ',0

#963 err_bootfailed db CR,'Boot failed: press a key to retry...'

#964 isolinux_dir db '/LOADER',0

#965 no_dir_msg db 'Could not find the LOADER directory.',0

#966 isolinux_bin db 'SETUPLDR.SYS',0

#967 no_isolinux_msg db 'Could not find SETUPLDR.SYS.',0

#968

#969 ;

#970 ; El Torito spec packet

#971 ;

#972 align 8,db 0

#973 spec_packet: db 13h ; Size of packet

#974 sp_media: db 0 ; Media type

#975 sp_drive: db 0 ; Drive number

#976 sp_controller: db 0 ; Controller index

#977 sp_lba: dd 0 ; LBA for emulated disk image

#978 sp_devspec: dw 0 ; IDE/SCSI information

#979 sp_buffer: dw 0 ; User-provided buffer

#980 sp_loadseg: dw 0 ; Load segment

#981 sp_sectors: dw 0 ; Sector count

#982 sp_chs: db 0,0 ; Simulated CHS geometry

#983 sp_dummy: db 0 ; Scratch,safe to overwrite

#984

#985 ;

#986 ; EBIOS drive parameter packet

#987 ;

#988 align 8,db 0

#989 drive_params: dw 30 ; Buffer size

#990 dp_flags: dw 0 ; Information flags

#991 dp_cyl: dd 0 ; Physical cylinders

#992 dp_head: dd 0 ; Physical heads

#993 dp_sec: dd 0 ; Physical sectors/track

#994 dp_totalsec: dd 0,0 ; Total sectors

#995 dp_secsize: dw 0 ; Bytes per sector

#996 dp_dpte: dd 0 ; Device Parameter Table

#997 dp_dpi_key: dw 0 ; 0BEDDh if rest valid

#998 dp_dpi_len: db 0 ; DPI len

#999 db 0

#1000 dw 0

#1001 dp_bus: times 4 db 0 ; Host bus type

#1002 dp_interface: times 8 db 0 ; Interface type

#1003 db_i_path: dd 0,0 ; Interface path

#1004 db_d_path: dd 0,0 ; Device path

#1005 db 0

#1006 db_dpi_csum: db 0 ; Checksum for DPI info

#1007

#1008 ;

#1009 ; EBIOS disk address packet

#1010 ;

#1011 align 8,db 0

#1012 dapa: dw 16 ; Packet size

#1013 .count: dw 0 ; Block count

#1014 .off: dw 0 ; Offset of buffer

#1015 .seg: dw 0 ; Segment of buffer

#1016 .lba: dd 0 ; LBA (LSW)

#1017 dd 0 ; LBA (MSW)

#1018

#1019 alignb 4,db 0

#1020 MaxTransfer dw 2 ;32 ; Max sectors per transfer

#1021

#1022 times 2046-($-$$) db 0 ; Pad to file offset 2046

#1023 dw 0aa55h ; BootSector signature

#1024

上面分析了光盘引导程序,知道怎么跳转到二级引导程序工作。也就是加载SETUPLDR.SYS文件到内存,然后跳到相应位置运行。最后加载内核ntoskrnl.exe运行。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读