· 6 years ago · Dec 06, 2019, 02:32 PM
1.8086
2.186
3.model tiny, stdcall
4
5
6BOOT_FLAG_INACTIVE_PARTITION = 00h
7BOOT_FLAG_ACTIVE_PARTITION = 080h
8
9;
10; Head/Sector/Cylinder - Disk Address
11;
12
13Disk_HSC struct
14
15 Head db 00h
16 Sector db 00h
17 Cylinder db 00h
18
19Disk_HSC ends
20
21
22
23;
24; Master Boot Record - Partition Table Entry
25;
26
27MBR_PartitionTableEntry struct
28
29 IsActive db 00h
30 StartHSC Disk_HSC {}
31 FileSystemId db 00h
32 EndHSC Disk_HSC {}
33 StartSector dd 000000000h
34 SectorsTotal dd 000000000h
35
36MBR_PartitionTableEntry ends
37
38
39
40;
41; Master Boot Record - Partition Table
42;
43
44MBR_PartitionTable struct
45
46 PrimaryPartition MBR_PartitionTableEntry 4 dup({})
47
48MBR_PartitionTable ends
49
50
51;;;;;;;CONFIG_S1_TEXT_ATTRIBUTE = (cga_normal OR bg_black OR light_green)
52
53;;;;;;;S1_MBR_BOOTCODE_SEGMENT = 0000h
54S1_MBR_LOAD_ADDRESS = 07c00h
55S1_MBR_RELOCATION_ADDR = 00600h
56
57;;;;;;;;CONFIG_S1_READ_SECTOR_RETRY = 3
58
59;-;S1_CODE_LENGTH textequ <(end_of_master_boot_record - master_boot_record)>
60
61;;;;;;;;;;;;S1_CODE_LENGTH_DYN textequ <(end_of_virtual_dynamic_data_sector - master_boot_record)>
62
63
64; --------------------------------------------------------------
65; --------------------------------------------------------------
66; MBR - Bootsector
67; --------------------------------------------------------------
68; --------------------------------------------------------------
69
70
71RELOCATION_SEGMENT SEGMENT AT 0000h
72
73 org S1_MBR_RELOCATION_ADDR
74
75
76 relocated_bootcode LABEL FAR
77
78RELOCATION_SEGMENT ENDS
79
80
81
82BOOTSEGMENT SEGMENT
83
84
85
86; ------------------------------------------------------------
87; --------------- Wizard Boot MBR (x86/cv) ---------------------
88; ------------------------------------------------------------
89
90
91;-; --- Machine State ---
92;-;
93;-; cs:ip 0000:07c00
94;-;
95;-; dl = Boot Drive
96;-;
97;-; ---------------------
98
99
100;ORG 0600h
101org S1_MBR_RELOCATION_ADDR
102
103
104master_boot_record:
105
106 ; WARNING: ALL CODE BEFORE RELOCATION IS COMPLETE,
107 ; HAS TO BE RELOCATABLE
108
109
110;-; VM_INT3
111 xor ax, ax ; ax = 0
112 mov ds, ax ; Copy bootcode from codesegment 0000h
113 mov si, 07c00h ; Copy bootcode from offset 07c00h
114
115
116 cli
117
118 xor cx, cx ; cx = 0
119 mov ss, cx ; ss = 0
120
121 mov sp, si ; Original load address 0000:7c00 becomes start of stack
122
123 sti
124
125 ;;; WARNING: STACK IS VALID ONLY FROM THIS POINT ON
126 ;;; WARNING: DO NOT USE STACK BEFORE THIS LINE
127
128
129 ; Use Stack to store data to pass on to S2 VBR
130 ;
131 ; CS:IP 0000:7c00
132 ;
133 ; dx: dh = ? (IBM), dl = Boot Drive
134 ; es:di --> "$PnP" (just to be sure S2 should not rely on this data)
135 ; ds:si --> Active/Bootable Partition Table Entry at S1_MBR_RELOCATION_ADDR + (n * 10h)
136 ; ds:bp --> same as ds:si
137 ;
138 ; ==> PUSHA --> AX, CX, DX, BX, SP, BP, SI, DI
139;-; ; PUSH CS
140;-; ; PUSH DS
141 ; PUSH ES
142 ;
143 ; Note: There is no need to store cs, ds
144 ;
145 ; ss:7c00 : code
146 ; ss:sp - 02h : ax = 0
147 ; ss:sp - 04h : cx = 0
148 ; ss:sp - 06h : dx: dh = ?, dl = Boot Drive
149 ; ss:sp - 08h : bx = ?
150 ; ss:sp - 0ah : sp = 0x7c00 (sp before pusha)
151 ; ss:sp - 0ch : bp = 0x7c00 - 12h = 0x7bee
152 ; ss:sp - 0eh : si = 0x7c00
153 ; ss:sp - 10h : di --> offset "$PnP"
154 ; ss:sp - 12h : es --> segment "$PnP"
155
156;-; mov bp, sp ; 2:
157;-; sub bp, 12h ; 3:
158;-; mov bp, 07beeh ; 3:
159
160 mov bp, 07beeh ; 3:
161
162 pusha
163;-; push cs
164;-; push ds
165 push es
166
167
168 ; This copies the bootcode from its original load adress to S1_MBR_RELOCATION_ADDR
169 ;
170 ; ds:si 0000:7c00 ==COPY==> es:di 0000:0600
171 ;
172 ; Note: Only 512 bytes, 256 words respectively will be copied including the
173 ; 0xAA55 signature of the MBR.
174
175 mov es, cx ; Copy bootcode to segment 0000h
176 mov di, S1_MBR_RELOCATION_ADDR ; Copy bootcode to offset 'S1_MBR_RELOCATION_ADDR'
177
178 inc ch ; 2 Bytes: cx = 0; inc ch ==> cx = 0100h (256 words, 512 bytes)
179;-; mov cx, 0100h ; 3 Bytes: mov cx, 0100h ==> cx = 0100h (256 words, 512 bytes)
180
181 cld ; Copy bootcode ascending
182
183 ; Move ==> Copy cx words from [ds;si] to [es:di]
184 ; Move cx = 0100h = 256 words or 512 bytes as words
185 rep movsw
186
187
188
189 ; NOTE: RELOCATION IS COMPLETE
190 ; CODE DOES NOT NEED TO BE RELOCATABLE
191 ; AFTER COMPLETION OF
192 ; 'jmp 0000:S1_MBR_RELOCATION_ADDR + relocated_bootcode_start'
193
194
195;-; ; Absolute far jump, simulated via 'pushw, pushw, retf' sequence
196;-; ; es = segment 0
197;-; ; offset = Next instruction after this one offsetwise from the beginning of
198;-; ; the bootcode at label 'master_boot_record' in the copied bootcode at
199;-; ; S1_MBR_RELOCATION_ADDR (0600h) + instruction offset.
200;-; ; Length: 5 Bytes
201;-; retfar es <lowword(S1_MBR_RELOCATION_ADDR + (relocated_bootcode_start - master_boot_record))>
202
203;-; VM_INT3
204
205 ; Relative jump into same segment
206 ; E9 <ADDR>
207 ; Length: 3 Bytes
208 db 0E9h
209 dw (S1_MBR_RELOCATION_ADDR - S1_MBR_LOAD_ADDRESS) ; Address relative to the start of the E9 opcode
210
211
212; ---------------------------------------------------------------------------------------
213; ---------------------------------- End of Relocatable Code ---------------------------------
214; ---------------------------------------------------------------------------------------
215
216
217; ---------------------------------------------------------------------------------------
218; --------------------------------- Absolute Code Starts Here -------------------------------
219; ---------------------------------------------------------------------------------------
220
221
222;-; --- Machine State ---
223;-;
224;-; cs:ip 0000:relocated_bootcode_start
225;-;
226;-;
227;-; cs = ds = es = ss = 0
228;-;
229;-; ax = 0
230;-; bx = ?
231;-; cx = 0
232;-; dx: dh = ?, dl = Boot Drive
233;-;
234;-; si = 0x7e00
235;-; di = 0x800
236;-; sp = 0x7bee
237;-; bp = 0x7bee
238;-;
239;-; df = 0
240;-;
241;-; [ds:si] ==> 0000:7e00 0x????
242;-; [es:di] ==> 0000:0800 0x????
243;-;
244;-; ---------------------
245;-; VM_INT3
246;-; ---------------------
247
248
249
250; Execution is transfered to the copied code by the E9 relative jump and resumes here.
251
252relocated_bootcode_start:
253
254
255; Zero Generator
256;
257; Pushes 0xff (256) Zero-Words on the stack, thus whenever
258; needed, one can pop zero word wide zeroes.
259
260 inc ch ; 2 Bytes: cx = 0x0100 as cx was 0000h before
261
262ZeroGenerator255:
263
264 push es ; es = 0000h
265 ; Push a word at a time, thus 256 words containing 0000h will
266 ; end up on the stack with ss:sp ==> 0000:7a00 in the end
267
268 loop ZeroGenerator255 ; Dec cx, until cx == 0 (256 times)
269
270
271; A word on the ZeroGenerator
272;
273; The ZeroGenerator, works as outlined in the following. Everytime, a constant
274; zero is needed as either word or byte size, we assume that as a general rule
275; thumb, a mov rx, 0009h is three bytes long, while more efficient methods require
276; still about two bytes, eg. xor rl, rl; xor rx, rx; xor si, si; mov si, rx;
277; mov es, rx.
278;
279; The ZeroGenerator is 5 bytes in opcodes, and the general push/pop operations for
280; rl, rh, rx, si, es, .... are about one byte length as opcodes. Thatfor, if we
281; use an amount of at least 5 generated zeroes from the stack, we will save one byte
282; for every further use of stack zeroes. It may be slower than the average mov and xor,
283; but we gain decrease in size. Sure we could have generated more zeroes on the stack
284; easily, but we didn't want to overwrite the whole segment, would we?
285;
286; Final Note: Using the stack this way, redefines 'balanced stack' to whenever the
287; top-most element currently referenced by sp on the stack is a zero
288; word, which has been generated by our ZeroGenerator. So, we want to
289; balance the stack before we draw zeroes. This means that we will only
290; draw zeroes at strategicly favorable times, else we would cause more
291; trouble than what we could gain from it.
292;
293; Zero Generator : 5 Bytes
294; Zeroes : 1 Bytes
295; Break Even Point : -10 Bytes
296; ==============================
297; Bytes Saved : -4 Bytes
298;
299
300
301;-; --- Machine State ---
302;-;
303;-; cs = ds = es = ss = 0
304;-;
305;-; ax = 0
306;-; bx = ??
307;-; cx = 0
308;-; dx: dh = ?, dl = Boot Drive
309;-;
310;-; si = 0x7e00
311;-; di = 0x800
312;-; sp = 0x79ee
313;-; bp = 0x7bee
314;-;
315;-; df = 0
316;-;
317;-; [ds:si] ==> 0000:7e00 0x????
318;-; [es:di] ==> 0000:0800 0x????
319;-;
320;-; ZeroGenerator: *512/512 ; Max/Min in bytes (*=balanced, !=unbalanced)
321;-;
322;-; ---------------------
323;-; VM_INT3
324;-; ---------------------
325
326
327
328; Print Welcome Message
329;-; push ax ; 1: Push 0 ==> No Reset after Print
330push 1
331 call PAR_WelcomeMsg ; We use an implied Zero from the Zero Generator ==> sp + 2
332 ; cx == 0
333
334
335
336;-; --- Machine State ---
337;-;
338;-; cs = ds = es = ss = 0
339;-;
340;-; ax = 0
341;-; bx = ??
342;-; cx = 0
343;-; dx: dh = ?, dl = Boot Drive
344;-;
345;-; si = 0x7e00
346;-; di = 0x800
347;-; sp = 0x79f0
348;-; bp = 0x7bee
349;-;
350;-; df = 0
351;-;
352;-; [ds:si] ==> 0000:7e00 0x????
353;-; [es:di] ==> 0000:0800 0x????
354;-;
355;-; ZeroGenerator: *510/510 ; Max/Min in bytes (*=balanced, !=unbalanced)
356;-;
357;-; ---------------------
358;-; VM_INT3
359;-; ---------------------
360
361
362
363Reset_Disk_System:
364
365; Disk - Reset Disk System
366;
367; Reset the disk system, just in case and atm it's only 4 bytes
368;
369; parameters
370; ah = 00h (function)
371; dl = drive
372;
373; returns
374; cf = clear if successful/set on error
375; ah = status, 0x00 for success, everything else for error
376; if needed, evaluate values as specified by table
377; http://www.ctyme.com/intr/rb-0606.htm (int 13h, f=01h)
378;
379; Note: ax is already 0000h
380; stc is set or cleared by the function call, so no need to explicitly set it
381
382;-; stc ; Set carry-flag
383;-; pop ax ; Draw 0000h from the ZeroGenerator
384
385 int 13h ; Reset Disk System
386
387; jc PAR_Fail_Reset_Disk_System
388
389
390;-; --- Machine State ---
391;-;
392;-; cs = ds = es = ss = 0
393;-;
394;-; ax = 0?
395;-; bx = ???
396;-; cx = 0
397;-; dx: dh = ?, dl = Boot Drive
398;-;
399;-; si = 0x7e00
400;-; di = 0x800
401;-; sp = 0x79ee
402;-; bp = 0x7bee
403;-;
404;-; cf = 0
405;-; df = 0
406;-;
407;-; [ds:si] ==> 0000:7e00 0x????
408;-; [es:di] ==> 0000:0800 0x????
409;-;
410;-; ZeroGenerator: *512/512 ; Max/Min in bytes (*=balanced, !=unbalanced)
411;-;
412;-; ---------------------
413;-; VM_INT3
414;-; ---------------------
415
416
417
418; Find Active Partition
419;
420; Find the active partion in the partition table and save it in dh
421;
422
423 mov bx, S1_MBR_RELOCATION_ADDR + 001aeh
424 ; Start of partition table at ds:S1_MBR_RELOCATION_ADDR + 01beh - 10h
425 ; Warning: ds still points to the initial cs segment
426
427Check_Partition_Table_Next_Entry:
428
429 pop ax ; Reset ax to 0000h from the ZeroGenerator
430
431 add bx, 10h ; Calculate offset for the next partition table entry
432 ; Next entry in the partition table is 16 bytes from the
433 ; current one.
434
435;-; add al, ds:[bx] ; Generates DS prefix
436 add al, [bx] ; Loads the n-th partition table entry's first byte
437 ; from address [ds:01beh + (n * 010h)]; where n = 0..4
438 ; containing the active/bootable marker in bit 7
439 ;
440 ; Note: n = 4 returns 0x55 as end of table marker
441
442 jz Check_Partition_Table_Next_Entry ; If al was zero, "these are not the droids,
443 ; which you're looking for" (check next entry)
444
445 cmp al, 55h
446 jz Check_Partition_Table_End
447; jz No_Active_Partition_Found ; Exit loop when encountering the end of table marker 0x55
448 ; Loop runs until EOT is encountered or an active partition
449 ; has been found, and if exited here then no active partition
450 ; could have been found.
451
452 shl al, 1 ; Check if bit 7 marks this partition as active
453
454 jnc Check_Partition_Table_Next_Entry
455
456Check_Partition_Table_End:
457
458 mov [bp + 06h], bx ; Save offset of Active/Bootable Partition Table Entry on the stack
459
460
461;-; --- Machine State ---
462;-;
463;-; cs = ds = es = ss = 0
464;-;
465;-; ax = ?
466;-; bx --> offset Active/Bootable Partion Table Entry
467;-; cx = 0
468;-; dx: dh = ?, dl = Boot Drive
469;-;
470;-; si = 0x7e00
471;-; di = 0x800
472;-; sp = 0x79f0 - 0x79f6
473;-; bp = 0x7bee
474;-;
475;-; cf = 0
476;-; df = 0
477;-;
478;-; [ds:si] ==> 0000:7e00 0x????
479;-; [es:di] ==> 0000:0800 0x????
480;-;
481;-; ZeroGenerator: *510/504 ; Max/Min in bytes (*=balanced, !=unbalanced)
482;-;
483;-; ---------------------
484;-; VM_INT3
485;-; ---------------------
486
487
488
489Prepare_Boot_Process:
490
491Check_Int13_Extensions:
492
493; IBM/MS Int 13h Extensions - Installation Check
494;
495; Check, if drive supports the IBM/MS Int 13h Extensions
496;
497; parameters
498; ah = 41h (function)
499; bx = 55aah
500; dl = drive (hard disks only)
501;
502; returns
503; cf = set on error (extensions not supported)
504;
505; ah = 01h (invalid function)
506;
507;
508; cf = clear on success
509;
510; bx = aa55h
511; ah = major extension version
512; 01h = 1.x
513; 20h = 2.0/EDD-1.0
514; 21h = 2.1/EDD-1.1
515; 30h = EDD-3.0
516; al = internal use
517; cx = API subset support bitmap (http://www.ctyme.com/intr/rb-0706.htm)
518; Bit 0 - extended disk access functions (42-44h, 47h, 48h)
519; Bit 1 - removable drive controller functions (45h, 46h, 48h, 49h, Int 15h/52h)
520; Bit 2 - EDD - enhanced disk drive functions (48h, 4eh)
521; Bits 3-15 reserved (0)
522; dh = extension version (v2.0+ ??? -- not present in 1.x)
523;
524
525;-; stc ; Set carry-flag
526
527;-; mov dl, drive ; dl already contains the drive
528
529 mov bx, 055aah ; Needed for Int 13h, Function 41h
530 mov ah, 41h ; Int 13h, Function 41h
531
532 int 13h
533
534 jc Check_Int13_Extensions_Not_Installed
535
536 cmp bx, word ptr ds:[si] ; The ds is intrinsic to cmp, but was
537 ; added for readability reasons, the
538 ; generated code is the same, as the
539 ; prefix as long as it is in ds will not
540 ; be generated.
541 jne Check_Int13_Extensions_Not_Installed
542
543 shr cx, 1 ; Shift the LSBit of CX into the carry flag, for the 42h and 48h functions
544 ; are all we need.
545
546 ; cf is now bit 0 of cx, telling us, if the functions 42h and 48h are valid,
547 ; thus we generate cf at bit position 6 in bp ==> bp = 0000h (cf=0) or 0040h (cf=1)
548;wrong al rcl bp, 7 ; rol cf to bit position 6 in bp, which atm is 0000h
549 rcl bp, 15 ; rol cf to bit position 14 in bp, which atm is 0000h
550
551
552Check_Int13_Extensions_Not_Installed:
553
554 ; if a jump was taken to this destination
555 ; bp = 0000h
556 ; else
557 ; bp = 0400h
558
559 ; if jump was taken to this destination
560 ; cf = 1
561 ; ah = 01h
562 ; bx = 055aah
563 ; else
564 ; cf = 0
565 ; ah = major extension version
566 ; bx = 0aa55h
567
568
569;-; --- Machine State ---
570;-;
571;-; cs = ds = es = ss = 0
572;-;
573;-; ax = ?
574;-; bx --> offset Active/Bootable Partion Table Entry
575;-; cx = 0
576;-; dx: dh = ?, dl = Boot Drive
577;-;
578;-; si = 0x7e00
579;-; di = 0x800
580;-; sp = 0x79f0 - 0x79f6
581;-; bp = 0x7bee
582;-;
583;-; cf = 0
584;-; df = 0
585;-;
586;-; [ds:si] ==> 0000:7e00 0x????
587;-; [es:di] ==> 0000:0800 0x????
588;-;
589;-; ZeroGenerator: *510/504 ; Max/Min in bytes (*=balanced, !=unbalanced)
590;-;
591;-; ---------------------
592;-; VM_INT3
593;-; ---------------------
594
595;VM_INT3
596
597; ah = major version of extensions / 01h for error
598; al = ? unkonw globbered
599; bx = aa55h for success/55aah on error
600; cx = API subset support bitmap shr by one, thus lsb lost (actually in bp bit 6)
601; dh = extension version on success/ still undefined on error
602; dl = BootDrive (unchanged)
603
604; cs = 0
605; ds = initial cs
606; es = 0
607; ss = 0
608; sp = 07a08h (+2h pop bp)
609; stack = 253 (Stack Zero Words) balanced
610; bp = 0 <== pop 0000h; on success has changed to 00400h
611
612; si = 07dfeh (points to the word value 0xaa55, or byte array (0x55, 0xaa))
613; di = 07feh
614
615; cf = 0 (in bp bit position 6 now, cf = bit 10 of bp)
616; df = 0
617
618 mov ah, 08h ; Preload functions (08h, 48h)
619 or ax, bp ; Adjust function to be eihter one of (08h, 48h)
620
621 ; (04h) [es:di] = 0000:0000h for function (08h)
622; pop es ; (08h) es is already zero
623 pop di ; (08h) Draw 0000h from ZeroGenerator
624
625 ; (048h) [ds:si]
626; pop ds ; (048h) ds contains the last reference to the original cs
627 ; and we do not really need to change that atm, so we don't
628 ; use segment zero.
629 not si ; (048h) si contains 07dfeh, binary inversion becomes 08201h
630 ; and all we care about is, that it's outside of the ranges
631 ; 07c00h-07e00h and 00600h-00800h, so 8201h will be fine.
632 ; Plus, if needed we could revert it back and forth.
633
634 ; Init drive parameter buffer at [es:di]
635 mov [si], 0001ah ; (048h) Length of buffer (Version 1.x == 0001ah)
636; mov [si + 2], es ; (048h) Phoenix Bios Fix, (es == 0000h)
637
638 push dx ; We backup dh and dl which contains the drive number, that we
639 ; originally booted from, since 08h globbers it.
640
641 int 13h ; Either function 08h or 048h will be called now
642
643; Pre int13h, f=08h,048h call
644;
645; ah = 08h or 048h
646; al = ? unkonw globbered
647; bx = aa55h for success/55aah on error
648; cx = API subset support bitmap shr by one, thus lsb lost (actually in bp bit 6)
649; dh = extension version on success/ still undefined on error
650; dl = BootDrive (unchanged)
651
652; cs = 0
653; ds = initial cs
654; es = 0
655; ss = 0
656; sp = 07a0Ah (+2h pop di), 07a08h (-2h push dx)
657; stack = 252 (Stack Zero Words) unbalanced, dx on top
658; bp = either 0000h or 04000h
659
660; si = 08201 == NOT (07dfeh)
661; di = 0 <== pop 0000h; (former 07feh)
662
663; cf = ?
664; df = 0
665
666
667; function 08h was used
668;
669; ah = 08h
670; al = ? unkonw globbered
671; bx = 55aah (Note: This is an errorcode, compare 048h version)
672; cx = API subset support bitmap shr by one, thus lsb lost (actually in bp bit 6)
673; dh = extension version on success/ still undefined on error
674; dl = BootDrive (unchanged)
675
676; cs = 0
677; ds = initial cs
678; es = 0
679; ss = 0
680; sp = 07a0Ah (+2h pop di), 07a08h (-2h push dx)
681; stack = 252 (Stack Zero Words) unbalanced, dx on top
682; bp = 0000h
683
684; si = 08201 == NOT (07dfeh)
685; di = 0 <== pop 0000h; (former 07feh)
686
687; cf = ?
688; df = 0
689
690
691; function 048h was used
692;
693; ah = 048h
694; al = ? unkonw globbered
695; bx = aa55h (Note: Compare 008h version)
696; cx = API subset support bitmap shr by one, thus lsb lost (actually in bp bit 6)
697; dh = extension version on success/ still undefined on error
698; dl = BootDrive (unchanged)
699
700; cs = 0
701; ds = initial cs
702; es = 0
703; ss = 0
704; sp = 07a0Ah (+2h pop di), 07a08h (-2h push dx)
705; stack = 252 (Stack Zero Words) unbalanced, dx on top
706; bp = 04000h
707
708; si = 08201 == NOT (07dfeh)
709; di = 0 <== pop 0000h; (former 07feh)
710
711; cf = ?
712; df = 0
713
714
715; do dl, dh stuff here before restoring it
716 pop dx
717
718comment @
719 mov ah, 08h
720; mov ah, 48h
721 or ax, bp
722; mov es, 0 ; already
723; mov di, 0 ; be popped
724 pop di
725; mov ds, buffer seg ; either keep or pop
726 mov si, buffer off
727
728push dx as 08 globbers
729
730 int 13h
731pop dx
732;07dfeh
733; 8201h
734
735@
736
737comment @
738
739 mov ah, 08h
740; mov es, 0 ; already
741; mov di, 0 ; be popped or ignored
742 pop di
743 int 13h
744
745 mov ah, 48h
746 mov ds, buffer seg
747 mov si, buffer off
748
749 or ax, bp
750
751CF set on error
752AH = status (07h) (see #00234)
753CF clear if successful
754AH = 00h
755AL = 00h on at least some BIOSes
756BL = drive type (AT/PS2 floppies only) (see #00242)
757CH = low eight bits of maximum cylinder number
758CL = maximum sector number (bits 5-0)
759high two bits of maximum cylinder number (bits 7-6)
760DH = maximum head number
761DL = number of drives
762ES:DI -> drive parameter table (floppies only)
763
764CF clear if successful
765AH = 00h
766DS:SI buffer filled
767CF set on error
768AH = error code (see #00234)
769
770mov ah
771
772int3
773@
774; proceed intertwined
775
776
777
778
779mov bp, ax
780mov bp, 123h
781or ax, bp
782cmp bp, ax
783cmp bp, 45h
784
785; check installation 13, 41, 55aa
786; intertwined 13, 8, 48
787; intertwined 13, 2, 42
788
789
790; Print and Reset
791;
792; Prints the n-th compressed string and either returns
793; or waits for a key to reset the system.
794;
795; Expects: ds = 0, ?es = 0
796; df = 0
797; cx = string index in string table
798; stack 0/1 ==> return/wait key and reset
799;
800; Globbered Registers: cx = 0, sp (only if no argument was pushed)
801; Reserved Registers: all others
802;
803; Note: 2 Bytes are removed from the stack
804;
805; Example:
806; xor cx, cx ; !!! Important for StringTable calculation of call
807; push x ; x=0 ==> return, x==1 wait key and reset
808; call PAR_StringToPrintFromTable
809;
810
811
812 ; ==> PUSHA --> AX, CX, DX, BX, SP, BP, SI, DI
813
814
815;-;PAR_:
816;-; inc cx ; 1: StringTable[]
817
818
819
820PAR_PressAnyKey:
821 inc cx ; 1: StringTable[1]
822
823;-;PAR_Copyright:
824;-; inc cx ; 1: StringTable[1]
825
826PAR_WelcomeMsg:
827 inc cx ; 1: StringTable[0]
828
829
830Print_And_Reset:
831
832 pusha ; 1:
833
834Print_String:
835 ;save bp bug
836
837 mov ah, 0eh ; 2: Bios print and interpret character Int 10h
838
839;-; mov bh, 0 ; 2: Page number
840;-; mov bl, 3 ; 2: Foreground Color
841 xor bx,bx ; 2: Page = 0, Color = 0
842;-; inc bx ; 1:
843;-; inc bl ; 2:
844
845;VM_INT3
846jmp Print_String_Find_String
847 xor di, di
848
849Print_String_Find_String2:
850
851 mov al, byte ptr ds:[StringTable + di]
852 inc di
853 add al, 0
854 jnz Print_String_Find_String2 ; Character not zero, find next
855
856 loop Print_String_Find_String2 ; Character zero, if (--cx)
857
858 xor si, si ; 2:
859
860Print_String_Next_Character2:
861
862 lea bp, [di]
863 mov al, byte ptr ds:[StringTable + bp + si] ; Fetch str[i]
864 add al, 0 ; 2:
865 jz Print_String_End2 ; ASCII-Z check to end loop
866
867 inc si ; i++
868
869 int 10h ; 2: Bios print and interpret character Int 10h, ah=0eh
870
871 jmp Print_String_Next_Character2
872
873Print_String_End2:
874
875;jmp Print_String_Find_String
876
877nop
878nop
879nop
880;VM_INT3
881;-; xor si, si
882; mov si, StringTable ; 3:
883 mov si, offset StringTable ; 3:
884
885;-; lea si, StringTable ; 4:
886
887Print_String_Find_String:
888
889 lodsb ; 1: mov al, ds:[si]; inc si
890; inc si
891 add al, 0 ; 2: Trigger flags
892 jnz Print_String_Find_String ; 2: Character not zero, find next
893
894 loop Print_String_Find_String ; 2: Character zero, if (--cx)
895
896; xor si, si ; 2:
897
898Print_String_Next_Character:
899
900; lea bp, [di]
901; mov al, byte ptr ds:[StringTable + bp + si] ; Fetch str[i]
902
903inc si
904 lodsb ; 1: mov al, ds:[si]; inc si
905; inc si
906 add al, 0 ; 2: Trigger flags
907 jz Print_String_End ; ASCII-Z check to end loop
908
909; inc si ; i++
910
911 mov ah, 0eh
912 mov al, 64h
913 int 10h ; 2: Bios print and interpret character Int 10h, ah=0eh
914
915 jmp Print_String_Next_Character
916
917
918nop
919nop
920nop
921
922Print_String_End:
923
924 mov bp, sp
925 mov ax, [bp + 12h]
926;-; or ax, ax
927 dec ax
928 jnz Print_String_Return
929
930; test [bp + 12h], 1
931;-; jz Print_String_WaitForKey
932
933
934Print_String_WaitForKey:
935
936 push ax
937
938 call PAR_PressAnyKey
939
940 ; ax = 0 because of pusha/popa
941 ; cx = 0 because of contract
942
943
944Print_And_Reset_ClearKeyboardBuffer:
945
946 ; Clear all keystrokes from keyboard buffer
947
948 mov ah, 01h ; 2: Int 16h, function 01h
949 int 16h ; 2: Check for keystrokes in buffer
950
951 mov ah, 00h ; 2: Int 16h, function 00h
952 ; Note: mov doesn't change zf of previous interrupt call
953
954 ; Leave loop on empty keyboard buffer
955 jz Print_And_Reset_Reset_WaitForKey
956
957 ; 0: ah = 00h, Int 16h, function 00h
958 int 16h ; 2: Remove keystroke from buffer
959
960 jmp Print_And_Reset_ClearKeyboardBuffer
961
962
963Print_And_Reset_Reset_WaitForKey:
964
965 ; Keyboard buffer is now empty and we wait for Any Key
966
967 ; 0: ah = 00h, Int 16h, function 00h
968 int 16h ; 2: Wait till keystroke is in buffer
969
970
971Print_And_Reset_Reset:
972
973;-; RESET_CPU
974
975 cli ; Prohibit interrupts
976
977Reset_L1:
978
979 in al, 064h ; Fetch PS/2 Intel 8042 Keyboard/Auxiliary Device Controller
980 ; status byte
981 test al, 02h ; Check if something is in the input-buffer
982 jnz Reset_L1 ; If so we wait till the buffer is empty
983
984 mov al, 0feh ; We wanna pulse output port bit 0, which is connected to the
985 ; sytem reset line.
986 out 064h, al ; Trigger the reset, by pulsing the bit 0 line of the Intel 8042
987
988 hlt ; Needed by some motherboards, so its not just paranoid programming
989
990
991Print_String_Return:
992
993 popa
994 xor cx, cx ; cx has been globbered, we set it to zero
995 ret 2
996
997Fail_Reset_Disk_System:
998No_Active_Partition_Found:
999; print error and die
1000
1001; --------------------------------------------------------------
1002; Master Boot Record Data
1003; --------------------------------------------------------------
1004
1005; TextAttribute db CONFIG_S1_TEXT_ATTRIBUTE
1006
1007StringTable:
1008 db 00
1009 WelcomeMsg db 'MBRBoot v1.0', 13, 10
1010 Copyright db '(c) By Some Dude', 13, 10, 10, 00
1011 PressAnyKey db 'Press Any Key', 13, 10, 00
1012 StatusMsg1 db 07, 'No Active Partition', 00
1013 StatusMsg2 db 'Booting....', 00
1014
1015
1016 ; Fill up remaining space with zeroes, up to a total of 440 (0x1b8) bytes
1017 db lowword (01B8h - ($ - master_boot_record)) dup (0)
1018
1019 DiskSignature dd 0 ; The harddisk signature
1020 ReservedBytes dw 0 ; Two bytes zero (reserved)
1021
1022
1023 ; MBR Partition Table (4 * 16 (0x10) = 64 (0x40) bytes)
1024 PartitionTable MBR_PartitionTable {}
1025
1026 ; End of Boot Sector Marker
1027 dw 0AA55h
1028
1029
1030end_of_master_boot_record:
1031
1032
1033
1034; --------------------------------------------------------------
1035; --------------------------------------------------------------
1036; Virtual Dynamic Data Sector
1037; --------------------------------------------------------------
1038; --------------------------------------------------------------
1039
1040; Note: This sector follows directly after the MBR, but does not
1041; exist on disk. It is used to reference variables which
1042; are uninitialized and thus would only take space away in
1043; MBR.
1044
1045;ORG (07C00h + (01h * 0200h)) ; Read (Offset 07C00h + (Sector * Sectorsize(512)))
1046
1047virtual_dynamic_data_sector:
1048
1049
1050 BootDrive db ?
1051 BootPartition dw ?
1052
1053end_of_virtual_dynamic_data_sector:
1054
1055
1056
1057BOOTSEGMENT ENDS
1058
1059END master_boot_record