Chameleon

Chameleon Commit Details

Date:2011-10-07 21:03:12 (12 years 6 months ago)
Author:blackosx
Commit:1619
Parents: 1618
Message:Replace boot0md with dmaazar's changes to effectively become boot0workV2 - see here for more details http://forum.voodooprojects.org/index.php/topic,2091.msg10804.html#ms g10804 .The add detection for it in CheckDiskMicrocode script.
Changes:
A/branches/blackosx/i386/boot0/boot0md_original.s
M/branches/blackosx/i386/boot0/boot0md.s
M/branches/blackosx/package/Scripts/Sub/CheckDiskMicrocode.sh

File differences

branches/blackosx/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
;
; 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
jc .exit
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
;--------------------------------------------------------------------------
branches/blackosx/i386/boot0/boot0md_original.s
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
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
; Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
;
; @APPLE_LICENSE_HEADER_START@
;
; Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
; Reserved. This file contains Original Code and/or Modifications of
; Original Code as defined in and that are subject to the Apple Public
; Source License Version 2.0 (the "License"). You may not use this file
; except in compliance with the License. Please obtain a copy of the
; License at http://www.apple.com/publicsource and read it before using
; this file.
;
; The Original Code and all software distributed under the License are
; distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
; License for the specific language governing rights and limitations
; under the License.
;
; @APPLE_LICENSE_HEADER_END@
;
; Boot Loader: boot0
;
; A small boot sector program written in x86 assembly whose only
; responsibility is to locate the active partition, load the
; partition booter into memory, and jump to the booter's entry point.
; It leaves the boot drive in DL and a pointer to the partition entry in SI.
;
; This boot loader must be placed in the Master Boot Record.
;
; In order to coexist with a fdisk partition table (64 bytes), and
; leave room for a two byte signature (0xAA55) in the end, boot0 is
; restricted to 446 bytes (512 - 64 - 2). If boot0 did not have to
; live in the MBR, then we would have 510 bytes to work with.
;
; boot0 is always loaded by the BIOS or another booter to 0:7C00h.
;
; This code is written for the NASM assembler.
; nasm boot0.s -o boot0
;
; This version of boot0 implements hybrid GUID/MBR partition scheme support
;
;
; Turbo added EFI System Partition boot support
;
; Added KillerJK's switchPass2 modifications
;
; dmazar: 10/7/2011 added scanning of all BIOS accessible drives:
; - iterates over all drives and searches for HSF bootable partition (with boot1h)
; and loads from it
; - if not found, itarates over drives again and searches for active partition and
; loads from it
;
;
; Set to 1 to enable obscure debug messages.
;
DEBUGEQU CONFIG_BOOT0_DEBUG
;
; Set to 1 to enable verbose mode
;
VERBOSEEQU CONFIG_BOOT0_VERBOSE
;
; Various constants.
;
kBoot0SegmentEQU 0x0000
kBoot0StackEQU 0xFFF0; boot0 stack pointer
kBoot0LoadAddrEQU 0x7C00; boot0 load address
kBoot0RelocAddrEQU 0xE000; boot0 relocated address
kMBRBufferEQU 0x1000; MBR buffer address
kLBA1BufferEQU 0x1200; LBA1 - GPT Partition Table Header buffer address
kGPTABufferEQU 0x1400; GUID Partition Entry Array buffer address
kPartTableOffsetEQU 0x1be
kMBRPartTableEQU kMBRBuffer + kPartTableOffset
kSectorBytesEQU 512; sector size in bytes
kBootSignatureEQU 0xAA55; boot sector signature
kHFSPSignatureEQU 'H+'; HFS+ volume signature
kHFSPCaseSignatureEQU 'HX'; HFS+ volume case-sensitive signature
kFAT32BootCodeOffset EQU 0x5a; offset of boot code in FAT32 boot sector
kBoot1FAT32MagicEQU 'BO'; Magic string to detect our boot1f32 code
kGPTSignatureLowEQU 'EFI '; GUID Partition Table Header Signature
kGPTSignatureHighEQU 'PART'
kGUIDLastDwordOffsEQU 12; last 4 byte offset of a GUID
kPartCountEQU 4; number of paritions per table
kPartTypeHFSEQU 0xaf; HFS+ Filesystem type
kPartTypePMBREQU 0xee; On all GUID Partition Table disks a Protective MBR (PMBR)
; in LBA 0 (that is, the first block) precedes the
; GUID Partition Table Header to maintain compatibility
; with existing tools that do not understand GPT partition structures.
; The Protective MBR has the same format as a legacy MBR
; and contains one partition entry with an OSType set to 0xEE
; reserving the entire space used on the disk by the GPT partitions,
; including all headers.
kPartActive EQU 0x80; active flag enabled
kPartInactive EQU 0x00; active flag disabled
kHFSGUID EQU 0x48465300; first 4 bytes of Apple HFS Partition Type GUID.
kAppleGUIDEQU 0xACEC4365; last 4 bytes of Apple type GUIDs.
kEFISystemGUIDEQU 0x3BC93EC9; last 4 bytes of EFI System Partition Type GUID:
; C12A7328-F81F-11D2-BA4B-00A0C93EC93B
%ifdef FLOPPY
kDriveNumberEQU 0x00
%else
kDriveNumberEQU 0x80
%endif
;
; Format of fdisk partition entry.
;
; The symbol 'part_size' is automatically defined as an `EQU'
; giving the size of the structure.
;
struc part
.bootid resb 1 ; bootable or not
.head resb 1 ; starting head, sector, cylinder
.sect resb 1 ;
.cyl resb 1 ;
.type resb 1 ; partition type
.endhead resb 1 ; ending head, sector, cylinder
.endsect resb 1 ;
.endcyl resb 1 ;
.lba resd 1 ; starting lba
.sectors resd 1 ; size in sectors
endstruc
;
; Format of GPT Partition Table Header
;
strucgpth
.Signature resb8
.Revision resb4
.HeaderSizeresb4
.HeaderCRC32resb4
.Reservedresb4
.MyLBAresb8
.AlternateLBAresb8
.FirstUsableLBAresb8
.LastUsableLBAresb8
.DiskGUIDresb16
.PartitionEntryLBAresb8
.NumberOfPartitionEntriesresb4
.SizeOfPartitionEntryresb4
.PartitionEntryArrayCRC32resb4
endstruc
;
; Format of GUID Partition Entry Array
;
strucgpta
.PartitionTypeGUIDresb16
.UniquePartitionGUIDresb16
.StartingLBAresb8
.EndingLBAresb8
.Attributesresb8
.PartitionNameresb72
endstruc
;
; Macros.
;
%macro DebugCharMacro 1
mov al, %1
call print_char
%endmacro
%macro LogString 1
mov di, %1
call log_string
%endmacro
%if DEBUG
%define DebugChar(x) DebugCharMacro x
%else
%define DebugChar(x)
%endif
;--------------------------------------------------------------------------
; Start of text segment.
SEGMENT .text
ORG kBoot0RelocAddr
;--------------------------------------------------------------------------
; Boot code is loaded at 0:7C00h.
;
start:
;
; Set up the stack to grow down from kBoot0Segment:kBoot0Stack.
; Interrupts should be off while the stack is being manipulated.
;
cli ; interrupts off
xor ax, ax ; zero ax
mov ss, ax ; ss <- 0
mov sp, kBoot0Stack ; sp <- top of stack
sti ; reenable interrupts
mov es, ax ; es <- 0
mov ds, ax ; ds <- 0
;
; Relocate boot0 code.
;
mov si, kBoot0LoadAddr ; si <- source
mov di, kBoot0RelocAddr ; di <- destination
cld ; auto-increment SI and/or DI registers
mov cx, kSectorBytes/2 ; copy 256 words
repnz movsw ; repeat string move (word) operation
;
; Code relocated, jump to start_reloc in relocated location.
;
jmp kBoot0Segment:start_reloc
;--------------------------------------------------------------------------
; Start execution from the relocated location.
;
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
scan_drives:
DebugChar('>')
%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.
;
pushbx; save BH (scan pass counter)
xor eax, eax
mov [my_lba], eax; store LBA sector 0 for read_lba function
mov al, 2; load two sectors: MBR and LBA1
mov bx, kMBRBuffer; MBR load address
call load
popbx; restore BH
jc .mbr_load_error; MBR load error - normally because we scanned all drives
;
; 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
; try next drive
; if next drive does not exists - will break on above MBR load error
incdl
jmpscan_drives
.mbr_load_error:
; all drives scanned - see if we need to run second pass
popdx; restore orig boot drive
decbh; decrement scan pass counter
jzscan_drives; if zero - run seccond pass
; we ran two passes - nothing found - error
error:
LogString(boot_error_str)
hang:
hlt
jmp hang
;--------------------------------------------------------------------------
; Find the active (boot) partition and load the booter from the partition.
;
; Arguments:
; DL = drive number (0x80 + unit number)
; SI = pointer to fdisk partition table.
; BH = pass counter (1=first pass, 0=second pass)
;
; Clobber list:
; EAX, BX, EBP
;
find_boot:
;
; Check for boot block signature 0xAA55 following the 4 partition
; entries.
;
cmp WORD [si + part_size * kPartCount], kBootSignature
jne .exit ; boot signature not found.
xor bl, bl; BL will be set to 1 later in case of
; Protective MBR has been found
.start_scan:
mov cx, kPartCount ; number of partition entries per table
.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
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?
je .continue ; skip to next entry
cmp BYTE [si + part.type], kPartTypePMBR; check for Protective MBR
jne .testPass
mov BYTE [si + part.bootid], kPartInactive; found Protective MBR
; clear active flag to make sure this protective
; partition won't be used as a bootable partition.
mov bl, 1; Assume we can deal with GPT but try to scan
; later if not found any other bootable partitions.
.testPass:
cmp bh, 1
jne .Pass2
.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.
jne .continue
movdh, 1 ; Argument for loadBootSector to check HFS+ partition signature.
jmp .tryToBoot
.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.
jne .continue
xordh, dh ; Argument for loadBootSector to skip HFS+ partition
; signature check.
DebugChar('*')
;
; Found boot partition, read boot sector to memory.
;
.tryToBoot:
call loadBootSector
jne .continue
jmp SHORT initBootLoader
.continue:
add si, BYTE part_size ; advance SI to next partition entry
loop .loop ; loop through all partition entries
;
; Scanned all partitions but not found any with active flag enabled
; Anyway if we found a protective MBR before we still have a chance
; for a possible GPT Header at LBA 1
;
dec bl
jnz .exit; didn't find Protective MBR before
call checkGPT
.exit:
ret; Giving up.
;
; Jump to partition booter. The drive number is already in register DL.
; SI is pointing to the modified partition entry.
;
initBootLoader:
DebugChar('J')
%if VERBOSE
LogString(done_str)
%endif
jmp kBoot0LoadAddr
;
; Found Protective MBR Partition Type: 0xEE
; Check for 'EFI PART' string at the beginning
; of LBA1 for possible GPT Table Header
;
checkGPT:
push bx
mov di, kLBA1Buffer; address of GUID Partition Table Header
cmp DWORD [di], kGPTSignatureLow; looking for 'EFI '
jne .exit; not found. Giving up.
cmp DWORD [di + 4], kGPTSignatureHigh ; looking for 'PART'
jne .exit; not found. Giving up indeed.
mov si, di
;
; Loading GUID Partition Table Array
;
mov eax, [si + gpth.PartitionEntryLBA] ; starting LBA of GPT Array
mov [my_lba], eax; save starting LBA for read_lba function
mov cx, [si + gpth.NumberOfPartitionEntries]; number of GUID Partition Array entries
mov bx, [si + gpth.SizeOfPartitionEntry]; size of GUID Partition Array entry
push bx; push size of GUID Partition entry
;
; Calculating number of sectors we need to read for loading a GPT Array
;
; push dx; preserve DX (DL = BIOS drive unit number)
; mov ax, cx; AX * BX = number of entries * size of one entry
; mul bx; AX = total byte size of GPT Array
; pop dx; restore DX
; shr ax, 9; convert to sectors
;
; ... or:
; Current GPT Arrays uses 128 partition entries each 128 bytes long
; 128 entries * 128 bytes long GPT Array entries / 512 bytes per sector = 32 sectors
;
moval, 32; maximum sector size of GPT Array (hardcoded method)
mov bx, kGPTABuffer
push bx; push address of GPT Array
call load; read GPT Array
pop si; SI = address of GPT Array
pop bx; BX = size of GUID Partition Array entry
jc error
;
; Walk through GUID Partition Table Array
; and load boot record from first available HFS+ partition.
;
; If it has boot signature (0xAA55) then jump to it
; otherwise skip to next partition.
;
%if VERBOSE
LogString(gpt_str)
%endif
.gpt_loop:
mov eax, [si + gpta.PartitionTypeGUID + kGUIDLastDwordOffs]
cmpeax, kAppleGUID; check current GUID Partition for Apple's GUID type
je.gpt_ok
;
; Turbo - also try EFI System Partition
;
cmpeax, kEFISystemGUID; check current GUID Partition for EFI System Partition GUID type
jne.gpt_continue
.gpt_ok:
;
; Found HFS Partition
;
mov eax, [si + gpta.StartingLBA]; load boot sector from StartingLBA
mov [my_lba], eax
movdh, 1; Argument for loadBootSector to check HFS+ partition signature.
call loadBootSector
jne .gpt_continue; no boot loader signature
mov si, kMBRPartTable; fake the current GUID Partition
mov [si + part.lba], eax; as MBR style partition for boot1h
mov BYTE [si + part.type], kPartTypeHFS; with HFS+ filesystem type (0xAF)
jmp SHORT initBootLoader
.gpt_continue:
add si, bx; advance SI to next partition entry
loop .gpt_loop; loop through all partition entries
.exit:
pop bx
ret; no more GUID partitions. Giving up.
;--------------------------------------------------------------------------
; loadBootSector - Load boot sector
;
; Arguments:
; DL = drive number (0x80 + unit number)
; DH = 0 skip HFS+ partition signature checking
; 1 enable HFS+ partition signature checking
; [my_lba] = starting LBA.
;
; Returns:
; ZF = 0 if boot sector hasn't kBootSignature
; 1 if boot sector has kBootSignature
;
loadBootSector:
pusha
mov al, 3
mov bx, kBoot0LoadAddr
call load
jc error
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.
;
movax, [kBoot0LoadAddr + 2 * kSectorBytes]
cmp ax, kHFSPSignature; 'H+'
je.checkBootSignature
cmpax, kHFSPCaseSignature; 'HX'
je.checkBootSignature
;
; Looking for boot1f32 magic string.
;
movax, [kBoot0LoadAddr + kFAT32BootCodeOffset]
cmpax, kBoot1FAT32Magic
jne .exit
.checkBootSignature:
;
; Check for boot block signature 0xAA55
;
mov di, bx
cmp WORD [di + kSectorBytes - 2], kBootSignature
.exit:
popa
ret
;--------------------------------------------------------------------------
; load - Load one or more sectors from a partition.
;
; Arguments:
; AL = number of 512-byte sectors to read.
; ES:BX = pointer to where the sectors should be stored.
; DL = drive number (0x80 + unit number)
; [my_lba] = starting LBA.
;
; Returns:
; CF = 0 success
; 1 error
;
load:
push cx
.ebios:
mov cx, 5 ; load retry count
.ebios_loop:
call read_lba ; use INT13/F42
jnc .exit
loop .ebios_loop
.exit:
pop cx
ret
;--------------------------------------------------------------------------
; read_lba - Read sectors from a partition using LBA addressing.
;
; Arguments:
; AL = number of 512-byte sectors to read (valid from 1-127).
; ES:BX = pointer to where the sectors should be stored.
; DL = drive number (0x80 + unit number)
; [my_lba] = starting LBA.
;
; Returns:
; CF = 0 success
; 1 error
;
read_lba:
pushad ; save all registers
mov bp, sp ; save current SP
;
; Create the Disk Address Packet structure for the
; INT13/F42 (Extended Read Sectors) on the stack.
;
; push DWORD 0 ; offset 12, upper 32-bit LBA
push ds ; For sake of saving memory,
push ds ; push DS register, which is 0.
mov ecx, [my_lba] ; offset 8, lower 32-bit LBA
push ecx
push es ; offset 6, memory segment
push bx ; offset 4, memory offset
xor ah, ah ; offset 3, must be 0
push ax ; offset 2, number of sectors
; 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
;
; Arguments:
; AH = 0x42
; DL = drive number (80h + drive unit)
; DS:SI = pointer to Disk Address Packet
;
; Returns:
; AH = return status (sucess is 0)
; carry = 0 success
; 1 error
;
; Packet offset 2 indicates the number of sectors read
; successfully.
;
mov si, sp
mov ah, 0x42
int 0x13
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
; reset?
;
xor ax, ax ; Func 0
int 0x13 ; INT 13
stc ; set carry to indicate error
.exit:
mov sp, bp ; restore SP
popad
ret
;--------------------------------------------------------------------------
; Write a string with 'boot0: ' prefix to the console.
;
; Arguments:
; ES:DI pointer to a NULL terminated string.
;
; Clobber list:
; DI
;
log_string:
pusha
pushdi
movsi, log_title_str
callprint_string
popsi
callprint_string
popa
ret
;--------------------------------------------------------------------------
; Write a string to the console.
;
; Arguments:
; DS:SI pointer to a NULL terminated string.
;
; Clobber list:
; AX, BX, SI
;
print_string:
mov bx, 1 ; BH=0, BL=1 (blue)
cld ; increment SI after each lodsb call
.loop:
lodsb ; load a byte from DS:SI into AL
cmp al, 0 ; Is it a NULL?
je .exit ; yes, all done
mov ah, 0xE ; INT10 Func 0xE
int 0x10 ; display byte in tty mode
jmp short .loop
.exit:
ret
%if DEBUG
;--------------------------------------------------------------------------
; Write a ASCII character to the console.
;
; Arguments:
; AL = ASCII character.
;
print_char:
pusha
mov bx, 1 ; BH=0, BL=1 (blue)
mov ah, 0x0e ; bios INT 10, Function 0xE
int 0x10 ; display byte in tty mode
popa
ret
;--------------------------------------------------------------------------
; Write the 4-byte value to the console in hex.
;
; Arguments:
; EAX = Value to be displayed in hex.
;
print_hex:
pushad
mov cx, WORD 4
bswap eax
.loop:
push ax
ror al, 4
call print_nibble ; display upper nibble
pop ax
call print_nibble ; display lower nibble
ror eax, 8
loop .loop
mov al, 10 ; carriage return
call print_char
mov al, 13
call print_char
popad
ret
print_nibble:
and al, 0x0f
add al, '0'
cmp al, '9'
jna .print_ascii
add al, 'A' - '9' - 1
.print_ascii:
call print_char
ret
getc:
pusha
mov ah, 0
int 0x16
popa
ret
%endif ;DEBUG
;--------------------------------------------------------------------------
; NULL terminated strings.
;
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
;--------------------------------------------------------------------------
; Pad the rest of the 512 byte sized booter with zeroes. The last
; two bytes is the mandatory boot sector signature.
;
; If the booter code becomes too large, then nasm will complain
; that the 'times' argument is negative.
;
; According to EFI specification, maximum boot code size is 440 bytes
;
pad_boot:
times 440-($-$$) db 0
pad_table_and_sig:
times 510-($-$$) db 0
dw kBootSignature
ABSOLUTE 0xE400
;
; In memory variables.
;
my_lbaresd1; Starting LBA for read_lba function
; END
branches/blackosx/package/Scripts/Sub/CheckDiskMicrocode.sh
8787
8888
8989
90
91
92
93
94
95
96
9097
91
98
9299
93100
94101
"$scriptDir"InstallLog.sh "${targetVolume}" "Target disk already has existing Chameleon stage 0 loader - boot0md."
exit 1
fi
if [ "${stage0type}" == "742b80" ]; then
#echo "DEBUG: Found existing Chameleon stage 0 loader - Boot0workV2"
#echo "DEBUG: And will leave Boot0workV2 installed."
"$scriptDir"InstallLog.sh "${targetVolume}" "Target disk already has existing Chameleon stage 0 loader - Boot0workV2."
exit 1
fi
if [ "${stage0type}" != "0b807c" ] && [ "${stage0type}" != "0a803c" ] && [ "${stage0type}" != "ee7505" ] && [ "${windowsloader}" != "33c08ed0" ] ; then
if [ "${stage0type}" != "0b807c" ] && [ "${stage0type}" != "0a803c" ] && [ "${stage0type}" != "ee7505" ] && [ "${stage0type}" != "742b80" ] && [ "${windowsloader}" != "33c08ed0" ] ; then
#echo "DEBUG: Something other than Chameleon or a Windows bootloader was found"
test=$(echo "${mbr437}" | awk -F0 '{print NF-1}' )
#echo "DEBUG: Disk microcode found: ${test} - Preserving."

Archive Download the corresponding diff file

Revision: 1619