Chameleon

Chameleon Commit Details

Date:2011-10-30 10:40:05 (12 years 5 months ago)
Author:blackosx
Commit:1674
Parents: 1673
Message:Apply dmazar's changes to boot0md.s from http://forum.voodooprojects.org/index.php/topic,2091.msg10551.html#ms g10551 and http://forum.voodooprojects.org/index.php/topic,2091.msg10804.html#ms g10804.
Changes:
M/trunk/i386/boot0/boot0md.s

File differences

trunk/i386/boot0/boot0md.s
5454
5555
5656
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
5774
75
76
77
78
79
80
81
5882
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
59102
60103
61
104
105
106
62107
63108
64
109
110
65111
66
112
113
114
115
116
117
67118
68119
69120
......
116167
117168
118169
170
171
172
173
119174
120175
121176
......
175230
176231
177232
178
233
234
235
236
237
179238
180239
181240
182241
183242
184243
244
185245
186246
247
187248
188249
250
251
252
253
254
255
189256
190257
191258
......
229296
230297
231298
232
233
234
235
236
299
300
301
302
303
237304
238
305
239306
240
307
308
309
310
311
241312
242
243
244
245
246
247313
248314
249315
......
256322
257323
258324
259
325
260326
327
328
261329
262330
263331
......
265333
266334
267335
268
336
337
338
339
340
341
269342
270
343
271344
272
345
273346
274347
275
276
348
349
277350
278351
279
352
280353
281
354
282355
283356
357
358
284359
285360
286361
287362
288
363
289364
290365
291366
......
294369
295370
296371
297
372
298373
299374
300375
......
316391
317392
318393
319
320
321
322
323
324
325
326
327
394
328395
329396
330397
......
338405
339406
340407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
341422
342
343
423
424
425
426
427
344428
345
346
347
348
429
430
431
432
349433
350
351434
352
435
436
437
353438
354
355
356
439
440
441
357442
358
359
360443
361
362444
363445
364446
......
393475
394476
395477
396
478
479
397480
398
399481
400
401482
402483
403484
......
415496
416497
417498
499
500
418501
419
502
420503
421504
422505
......
447530
448531
449532
450
533
534
451535
452536
453537
......
457541
458542
459543
460
461544
462
463545
464546
465547
......
517599
518600
519601
602
603
520604
521605
522606
523
607
608
609
524610
525611
526612
527613
528614
529615
530
531616
532
533617
534618
535619
......
588672
589673
590674
591
592675
593676
594677
......
624707
625708
626709
627
628
629
630
631
632
633710
634711
635712
......
652729
653730
654731
655
656
657732
658733
659734
......
668743
669744
670745
671
746
747
748
672749
673750
674751
......
715792
716793
717794
795
718796
797
719798
720799
721800
......
732811
733812
734813
814
815
816
817
818
819
820
821
822
735823
736824
737825
......
770858
771859
772860
773
774
775
776
777
778
779
780
861
781862
863
864
865
866
782867
783868
784869
785
870
786871
787872
788
789873
790874
791875
876
792877
793878
794879
; - if not found, itarates over drives again and searches for active partition and
; loads from it
;
; dmazar: 19/7/2011
; Searching for bootable partition works in 3 passes now:
;
; - Pass1:
; - for the boot drive only:
; - searches MBR partition table for an active HSF+ bootable partition and boots it
; - if not found and disk is actually GPT, then searches for the first HFS+ bootable
; partition (or EFI with boot1f32) in the GPT array and boots it
; - if still not found, then continues with Pass2
;
; - Pass2:
; - iterates over all drives and for each drive:
; - searches MBR partition table for the first HSF+ bootable partition and boots it
; - if not found and disk is actually GPT, then searches for the first HFS+ bootable
; partition (or EFI with boot1f32) in the GPT array and boots it
; - if still not found, then continues with the next drive
; - if all drives are searched and nothing found, then continues with Pass3
; - Pass3:
; - iterates over all drives and for each drive:
; - searches MBR partition table for the first active bootable partition and boots it
; - if not found and disk is actually GPT, then searches for the first HFS+ bootable
; partition (or EFI with boot1f32) in the GPT and boots it
; - if still not found, then continues with the next drive
; - if all drives are searched and nothing found, finishes with "boot0: error"
;
; Bootable partition above means a partition with the boot sector signature (0xAA55)
; at the end of the partition boot sector.
; Booting partition means loading partition boot sector and passing control to partition
; boot loader (for example boot1h).
; Drives are searched in the order defined in the BIOS. Drive which is selected as the boot drive
; is searched first.
;
; If compiled with DEBUG=1 gives debug output:
; P - starting new pass
; D - starting disk scanning: MBR and then GPT
; p - checking MBR partition entry
; t - testing MBR partition
; l - MBR or GPT partition satisfies conditions - loading partition boot sector
; G - found GPT
; + - stage 1 booter loaded, press a key to continue
; E - error
;
;
; Set to 1 to enable obscure debug messages.
;
DEBUGEQU CONFIG_BOOT0_DEBUG
;DEBUGEQU CONFIG_BOOT0_DEBUG
DEBUGEQU 0
NOT_USEDEQU 0; exclude print_hex - no space for it
;
; Set to 1 to enable verbose mode
; Verbose - write boot0 messages
; No space for verbose and debug in the same time
;
VERBOSEEQU CONFIG_BOOT0_VERBOSE
;VERBOSEEQU CONFIG_BOOT0_VERBOSE
%if DEBUG
VERBOSEEQU 0
%else
VERBOSEEQU 1
%endif
;
; Various constants.
kDriveNumberEQU 0x80
%endif
kPass1EQU 3; Pass1
kPass2EQU 2; Pass2
kPass3EQU 1; Pass3
;
; Format of fdisk partition entry.
;
call print_char
%endmacro
%macro LogString 1
%macro DebugPauseMacro 0
call getc
%endmacro
%macro LogStringMacro 1
mov di, %1
call log_string
%endmacro
%if DEBUG
%define DebugChar(x) DebugCharMacro x
%define DebugPause DebugPauseMacro
%else
%define DebugChar(x)
%define DebugPause
%endif
%if VERBOSE
%define LogString(x) LogStringMacro x
%else
%define LogString(x)
%endif
;--------------------------------------------------------------------------
; Start of text segment.
;
start_reloc:
pushdx; save dl (boot drive) for second pass.
; will stay on stack if booter loaded in first pass.
; this should not be a problem
movbh, 1; BH = 1. two pass scanning (active or hfs partition).
; actuall use of it (scanning) is in find_boot
;
; BH is pass counter
; Pass1 BH=3, Pass2 BH=2, Pass3 BH=1
;
movbh, kPass1; BH = 3. Pass1
scan_drives:
pass_loop:
DebugChar('>')
DebugChar('P'); starting new pass
pushdx; save dl (boot drive) for next pass
.scan_drive:
%if DEBUG
mov al, dl
call print_hex
%endif
;
; Since this code may not always reside in the MBR, always start by
; loading the MBR to kMBRBuffer and LBA1 to kGPTBuffer.
mov bx, kMBRBuffer; MBR load address
call load
popbx; restore BH
jc .mbr_load_error; MBR load error - normally because we scanned all drives
jc .next_pass; MBR load error - normally because we scanned all drives
DebugChar('D'); starting disk scanning
;
; Look for the booter partition in the MBR partition table,
; which is at offset kMBRPartTable.
mov si, kMBRPartTable; pointer to partition table
call find_boot; will not return on success
; if returns - booter partition not found
; if returns - booter partition is not found
; skip scanning of all drives in Pass1
cmpbh, kPass1
je.next_pass
; try next drive
; if next drive does not exists - will break on above MBR load error
; if next drive does not exists - will break on the MBR load error above
incdl
jmpscan_drives
jmpshort .scan_drive
.mbr_load_error:
; all drives scanned - see if we need to run second pass
.next_pass:
; all drives scanned - move to next pass
popdx; restore orig boot drive
decbh; decrement scan pass counter
jzscan_drives; if zero - run seccond pass
jnzpass_loop; if not zero - exec next pass
; we ran two passes - nothing found - error
; we ran all passes - nothing found - error
error:
DebugChar('E')
DebugPause
LogString(boot_error_str)
hang:
hlt
jmp hang
jmp short hang
;--------------------------------------------------------------------------
; Arguments:
; DL = drive number (0x80 + unit number)
; SI = pointer to fdisk partition table.
; BH = pass counter (1=first pass, 0=second pass)
; BH = pass counter
;
; Clobber list:
; EAX, BX, EBP
.loop:
;
; First scan through the partition table looking for the active
; partition.
;
%if DEBUG
mov al, [si + part.type] ; print partition type
call print_hex
%endif
DebugChar('p'); checking partition entry
mov eax, [si + part.lba]; save starting LBA of current
mov [my_lba], eax; MBR partition entry for read_lba function
cmp BYTE [si + part.type], 0; unused partition?
mov bl, 1; Assume we can deal with GPT but try to scan
; later if not found any other bootable partitions.
;
; The following code between .testPass and .tryToBoot performs checking for 3 passes:
; Pass1 (BH=3) if (partition is HFS+ and active) then { DH=1; call loadBootSector}
; Pass2 (BH=2) if (partition is HFS+) then { DH=1; call loadBootSector}
; Pass3 (BH=1) if (partition is active) then { DH=0; call loadBootSector}
;
; BH is Pass counter
; DH is argument to loadBootSector
; = 0 - skip HFS+ partition signature check
; = 1 - check for HFS+ partition signature
;
; Code may be harder to read because I tried to optimized it for minimum size.
;
.testPass:
cmp bh, 1
jne .Pass2
DebugChar('t'); testing partition
xordh, dh ; DH=0 This will be used in Pass3 (partition is active, not HFS+).
cmp bh, kPass3; If this is Pass3 (BH=1)
je .checkActive; check for active flag only.
.Pass1:
cmp BYTE [si + part.type], kPartTypeHFS; In pass 1 we're going to find a HFS+ partition
; equipped with boot1h in its boot record
; regardless if it's active or not.
.checkHFS:
; We are in Pass1 (BH=3) or Pass2 (BH=2).
incdh ; DH=1
cmp BYTE [si + part.type], kPartTypeHFS; Check for a HFS+ partition.
jne .continue
movdh, 1 ; Argument for loadBootSector to check HFS+ partition signature.
jmp .tryToBoot
cmp bh, kPass2; It's HFS+. That's enough checking for Pass2,
je .tryToBoot; so try to boot (with DH=1)
; Pass1 needs active flag check also ...
.Pass2:
cmp BYTE [si + part.bootid], kPartActive; In pass 2 we are walking on the standard path
; by trying to hop on the active partition.
.checkActive:
; We are in Pass1 or Pass3
cmp BYTE [si + part.bootid], kPartActive; Check if partition is Active
jne .continue
xordh, dh ; Argument for loadBootSector to skip HFS+ partition
; signature check.
DebugChar('*')
;
; Found boot partition, read boot sector to memory.
;
initBootLoader:
DebugChar('J')
DebugChar('+')
DebugPause
%if VERBOSE
LogString(done_str)
%endif
jmp kBoot0LoadAddr
jne .exit; not found. Giving up.
cmp DWORD [di + 4], kGPTSignatureHigh ; looking for 'PART'
jne .exit; not found. Giving up indeed.
DebugChar('G'); found GPT
mov si, di
;
; Loading GUID Partition Table Array
;
call load; read GPT Array
pop si; SI = address of GPT Array
pop bx; BX = size of GUID Partition Array entry
jc error
;jc error
jc .exit; dmazar's change to continue disk scanning if encountering invalid LBA.
;
; Walk through GUID Partition Table Array
; otherwise skip to next partition.
;
%if VERBOSE
LogString(gpt_str)
%endif
.gpt_loop:
loadBootSector:
pusha
DebugChar('l'); loading partition boot sector
mov al, 3
mov bx, kBoot0LoadAddr
call load
jc error
;jc error
or dl, dl ; to set flag Z=0; dmazar's change to continue disk scanning if encountering invalid LBA.
jc .exit; dmazar's change to continue disk scanning if encountering invalid LBA.
ordh, dh
jz.checkBootSignature
.checkHFSSignature:
%if VERBOSE
;LogString(test_str); dmazar: removed to get space
%endif
;
; Looking for HFSPlus ('H+') or HFSPlus case-sensitive ('HX') signature.
pop cx
ret
;--------------------------------------------------------------------------
; read_lba - Read sectors from a partition using LBA addressing.
;
; It pushes 2 bytes with a smaller opcode than if WORD was used
push BYTE 16 ; offset 0-1, packet size
DebugChar('<')
%if DEBUG
mov eax, ecx
call print_hex
%endif
;
; INT13 Func 42 - Extended Read Sectors
;
jnc .exit
DebugChar('R') ; indicate INT13/F42 error
;
; Issue a disk reset on error.
; Should this be changed to Func 0xD to skip the diskette controller
popad
ret
%if VERBOSE
;--------------------------------------------------------------------------
; Write a string with 'boot0: ' prefix to the console.
;
.exit:
ret
%endif ;VERBOSE
%if DEBUG
;--------------------------------------------------------------------------
popa
ret
getc:
pusha
mov ah, 0
int 0x16
popa
ret
%endif ;DEBUG
%if NOT_USED
;--------------------------------------------------------------------------
; Write the 4-byte value to the console in hex.
call print_char
ret
getc:
pusha
mov ah, 0
int 0x16
popa
ret
%endif ;DEBUG
%endif ; NOT_USED
%if VERBOSE
;--------------------------------------------------------------------------
; NULL terminated strings.
;
log_title_strdb 10, 13, 'boot0: ', 0
log_title_strdb 10, 13, 'boot0:', 0
boot_error_str db 'error', 0
%if VERBOSE
gpt_strdb 'GPT', 0
;test_strdb 'test', 0
done_strdb 'done', 0
%endif
;--------------------------------------------------------------------------

Archive Download the corresponding diff file

Revision: 1674