Adding upstream version 3.50~pre5.
[syslinux-debian/hramrach.git] / memdisk / memdisk.asm
blob90779cb5f35d1ee4a45be10380a65807041f967e
1 ; -*- fundamental -*- (asm-mode sucks)
2 ; ****************************************************************************
4 ; memdisk.asm
6 ; A program to emulate an INT 13h disk BIOS from a "disk" in extended
7 ; memory.
9 ; Copyright (C) 2001-2007 H. Peter Anvin
11 ; This program is free software; you can redistribute it and/or modify
12 ; it under the terms of the GNU General Public License as published by
13 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
14 ; Boston MA 02111-1307, USA; either version 2 of the License, or
15 ; (at your option) any later version; incorporated herein by reference.
17 ; ****************************************************************************
19 %ifndef DEPEND
20 %include "../version.gen"
21 %endif
23 ; %define DEBUG_TRACERS ; Uncomment to get debugging tracers
25 %ifdef WITH_EDD
26 %define EDD 1
27 %else
28 %define EDD 0
29 %endif
31 %ifdef DEBUG_TRACERS
33 %macro TRACER 1
34 call debug_tracer
35 db %1
36 %endmacro
38 %else ; DEBUG_TRACERS
40 %macro TRACER 1
41 %endmacro
43 %endif ; DEBUG_TRACERS
45 %define CONFIG_READONLY 0x01
46 %define CONFIG_RAW 0x02
47 %define CONFIG_SAFEINT 0x04
48 %define CONFIG_BIGRAW 0x08 ; MUST be 8!
50 org 0h
52 %define SECTORSIZE_LG2 9 ; log2(sector size)
53 %define SECTORSIZE (1 << SECTORSIZE_LG2)
55 ; Parameter registers definition; this is the definition
56 ; of the stack frame.
57 %define P_DS word [bp+34]
58 %define P_ES word [bp+32]
59 %define P_EAX dword [bp+28]
60 %define P_HAX word [bp+30]
61 %define P_AX word [bp+28]
62 %define P_AL byte [bp+28]
63 %define P_AH byte [bp+29]
64 %define P_ECX dword [bp+24]
65 %define P_HCX word [bp+26]
66 %define P_CX word [bp+24]
67 %define P_CL byte [bp+24]
68 %define P_CH byte [bp+25]
69 %define P_EDX dword [bp+20]
70 %define P_HDX word [bp+22]
71 %define P_DX word [bp+20]
72 %define P_DL byte [bp+20]
73 %define P_DH byte [bp+21]
74 %define P_EBX dword [bp+16]
75 %define P_HBX word [bp+18]
76 %define P_HBXL byte [bp+18]
77 %define P_BX word [bp+16]
78 %define P_BL byte [bp+16]
79 %define P_BH byte [bp+17]
80 %define P_EBP dword [bp+8]
81 %define P_BP word [bp+8]
82 %define P_ESI dword [bp+4]
83 %define P_SI word [bp+4]
84 %define P_EDI dword [bp]
85 %define P_DI word [bp]
87 section .text
88 ; These pointers are used by the installer and
89 ; must be first in the binary
90 Pointers: dw Int13Start
91 dw Int15Start
92 dw PatchArea
93 dw TotalSize
95 Int13Start:
96 ; Swap stack
97 mov [cs:Stack],esp
98 mov [cs:SavedAX],ax
99 mov ax,ss
100 mov [cs:Stack+4],ax
101 mov ax,cs
102 mov ss,ax
103 mov sp,[cs:MyStack]
105 ; See if DL points to our class of device (FD, HD)
106 push dx
107 push dx
108 xor dl,[cs:DriveNo]
109 pop dx
110 js .nomatch ; If SF=0, we have a class match here
111 jz .our_drive ; If ZF=1, we have an exact match
112 cmp dl,[cs:DriveNo]
113 jb .nomatch ; Drive < Our drive
114 dec dl ; Drive > Our drive, adjust drive #
115 .nomatch:
116 mov ax,[cs:SavedAX]
117 pushf
118 call far [cs:OldInt13]
119 pushf
120 push bp
121 mov bp,sp
122 cmp byte [cs:SavedAX+1],08h
123 je .norestoredl
124 cmp byte [cs:SavedAX+1],15h
125 jne .restoredl
126 test byte [bp+4],80h ; Hard disk?
127 jnz .norestoredl
128 .restoredl:
129 mov dl,[bp+4]
130 .norestoredl:
131 push ax
132 push ebx
133 push ds
134 mov ax,[bp+2] ; Flags
135 lds ebx,[cs:Stack]
136 mov [bx+4],al ; Arithmetric flags
137 pop ds
138 pop ebx
139 pop ax
140 pop bp
141 lss esp,[cs:Stack]
142 iret
144 .our_drive:
145 ; Set up standard entry frame
146 push ds
147 push es
148 mov ds,ax
149 mov es,ax
150 mov ax,[SavedAX]
151 pushad
152 mov bp,sp ; Point BP to the entry stack frame
153 TRACER 'F'
154 ; Note: AH == P_AH here
155 cmp ah,[Int13MaxFunc]
156 ja Invalid_jump
157 xor al,al ; AL = 0 is standard entry condition
158 mov di,ax
159 shr di,7 ; Convert AH to an offset in DI
160 call [Int13Funcs+di]
162 Done: ; Standard routine for return
163 mov P_AX,ax
164 DoneWeird:
165 TRACER 'D'
166 xor bx,bx
167 mov es,bx
168 mov bx,[StatusPtr]
169 mov [es:bx],ah ; Save status
170 and ah,ah
172 lds ebx,[Stack]
173 ; This sets the low byte (the arithmetric flags) of the
174 ; FLAGS on stack to either 00h (no flags) or 01h (CF)
175 ; depending on if AH was zero or not.
176 setnz [bx+4] ; Set CF iff error
177 popad
178 pop es
179 pop ds
180 lss esp,[cs:Stack]
181 iret
183 Reset:
184 ; Reset affects multiple drives, so we need to pass it on
185 TRACER 'R'
186 xor ax,ax ; Bottom of memory
187 mov es,ax
188 test dl,dl ; Always pass it on if we are resetting HD
189 js .hard_disk ; Bit 7 set
190 ; Some BIOSes get very unhappy if we pass a reset floppy
191 ; command to them and don't actually have any floppies.
192 ; This is a bug, but we have to deal with it nontheless.
193 ; Therefore, if we are the *ONLY* floppy drive, and the
194 ; user didn't request HD reset, then just drop the command.
195 ; BIOS equipment byte, top two bits + 1 == total # of floppies
196 test byte [es:0x410],0C0h
197 jz success
198 jmp .pass_on ; ... otherwise pass it to the BIOS
199 .hard_disk:
200 ; ... same thing for hard disks, sigh ...
201 cmp byte [es:0x475],1 ; BIOS variable for number of hard disks
202 jbe success
204 .pass_on:
205 pop ax ; Drop return address
206 popad ; Restore all registers
207 pop es
208 pop ds
209 lss esp,[cs:Stack] ; Restore the stack
210 and dl,80h ; Clear all but the type bit
211 jmp far [cs:OldInt13]
214 Invalid:
215 pop dx ; Drop return address
216 Invalid_jump:
217 TRACER 'I'
218 mov ah,01h ; Unsupported function
219 jmp short Done
221 GetDriveType:
222 test byte [DriveNo],80h
223 mov bl,02h ; Type 02h = floppy with changeline
224 jz .floppy
225 ; Hard disks only...
226 inc bx ; Type = 03h
227 mov dx,[DiskSize] ; Return the disk size in sectors
228 mov P_DX,dx
229 mov cx,[DiskSize+2]
230 mov P_CX,cx
231 .floppy:
232 mov P_AH,bl ; 02h floppy, 03h hard disk
233 pop ax ; Drop return address
234 xor ax,ax ; Success...
235 jmp DoneWeird ; But don't stick it into P_AX
237 GetStatus:
238 xor ax,ax
239 mov es,ax
240 mov bx,[StatusPtr]
241 mov ah,[bx] ; Copy last status
244 ReadMult:
245 TRACER 'm'
246 Read:
247 TRACER 'R'
248 call setup_regs
249 do_copy:
250 TRACER '<'
251 call bcopy
252 TRACER '>'
253 movzx ax,P_AL ; AH = 0, AL = transfer count
256 WriteMult:
257 TRACER 'M'
258 Write:
259 TRACER 'W'
260 test byte [ConfigFlags],CONFIG_READONLY
261 jnz .readonly
262 call setup_regs
263 xchg esi,edi ; Opposite direction of a Read!
264 jmp short do_copy
265 .readonly: mov ah,03h ; Write protected medium
268 ; Verify integrity; just bounds-check
269 Seek:
270 Verify:
271 call setup_regs ; Returns error if appropriate
272 ; And fall through to success
274 CheckIfReady: ; These are always-successful noop functions
275 Recalibrate:
276 InitWithParms:
277 DetectChange:
278 SetMode:
279 success:
280 xor ax,ax ; Always successful
283 GetParms:
284 TRACER 'G'
285 mov dl,[DriveCnt] ; Cached data
286 mov P_DL,dl
287 test byte [DriveNo],80h
288 jnz .hd
289 mov P_DI,DPT
290 mov P_ES,cs
291 mov bl,[DriveType]
292 mov P_BL,bl
293 .hd:
294 mov ax,[Cylinders]
295 dec ax ; We report the highest #, not the count
296 xchg al,ah
297 shl al,6
298 or al,[Sectors]
299 mov P_CX,ax
300 mov ax,[Heads]
301 dec ax
302 mov P_DH,al
305 ; Is this MEMDISK installation check?
307 cmp P_HAX,'ME'
308 jne .notic
309 cmp P_HCX,'MD'
310 jne .notic
311 cmp P_HDX,'IS'
312 jne .notic
313 cmp P_HBX,'K?'
314 jne .notic
316 ; MEMDISK installation check...
317 mov P_HAX,'!M'
318 mov P_HCX,'EM'
319 mov P_HDX,'DI'
320 mov P_HBX,'SK'
321 mov P_ES,cs
322 mov P_DI,MemDisk_Info
324 .notic:
325 xor ax,ax
328 ; EDD functions -- only if enabled
330 %if EDD
331 EDDPresence:
332 TRACER 'E'
333 TRACER 'c'
335 cmp P_BX,55AAh
336 jne Invalid
337 mov P_BX,0AA55h ; EDD signature
338 mov P_AX,02100h ; EDD 1.1
339 mov P_CX,0001h ; Fixed disk access subset
340 pop ax ; Drop return address
341 xor ax,ax ; Success
342 jmp DoneWeird ; Success, but AH != 0, sigh...
344 EDDRead:
345 TRACER 'E'
346 TRACER 'r'
348 call edd_setup_regs
349 call bcopy
350 xor ax,ax
353 EDDWrite:
354 TRACER 'E'
355 TRACER 'w'
357 call edd_setup_regs
358 xchg esi,edi
359 call bcopy
360 xor ax,ax
363 EDDVerify:
364 EDDSeek:
365 call edd_setup_regs ; Just bounds checking
366 xor ax,ax
369 EDDGetParms:
370 TRACER 'E'
371 TRACER 'p'
373 mov es,P_DS
374 mov di,P_SI
375 mov cx,30 ; Length of our DPT
376 cmp [es:di],cx
377 jae .oksize
379 mov cx,26
380 cmp [es:di],cx
381 jb .overrun
384 .oksize:
385 mov [si],cx
387 ; This should be done by the installer...
388 mov eax,[DiskSize]
389 mov [si+16],eax
391 mov si,EDD_DPT
392 rep movsb
394 xor ax,ax
397 .overrun:
398 mov ax,0100h
400 %endif ; EDD
402 ; Set up registers as for a "Read", and compares against disk size.
403 ; WARNING: This fails immediately, even if we can transfer some
404 ; sectors. This isn't really the correct behaviour.
405 setup_regs:
407 ; Convert a CHS address in P_CX/P_DH into an LBA in eax
408 ; CH = cyl[7:0]
409 ; CL[0:5] = sector (1-based) CL[7:6] = cyl[9:8]
410 ; DH = head
411 movzx ecx,P_CX
412 movzx ebx,cl ; Sector number
413 and bl,3Fh
414 dec ebx ; Sector number is 1-based
415 cmp bx,[Sectors]
416 jae .overrun
417 movzx edi,P_DH ; Head number
418 movzx eax,word [Heads]
419 cmp di,ax
420 jae .overrun
421 shr cl,6
422 xchg cl,ch ; Now (E)CX <- cylinder number
423 mul ecx ; eax <- Heads*cyl# (edx <- 0)
424 add eax,edi
425 mul dword [Sectors]
426 add eax,ebx
427 ; Now eax = LBA, edx = 0
430 ; setup_regs continues...
432 ; Note: edi[31:16] and ecx[31:16] = 0 already
433 mov di,P_BX ; Get linear address of target buffer
434 mov cx,P_ES
435 shl ecx,4
436 add edi,ecx ; EDI = address to fetch to
437 movzx ecx,P_AL ; Sector count
438 mov esi,eax
439 add eax,ecx ; LBA of final sector + 1
440 shl esi,SECTORSIZE_LG2 ; LBA -> byte offset
441 add esi,[DiskBuf] ; Get address in high memory
442 cmp eax,[DiskSize] ; Check the high mark against limit
443 ja .overrun
444 shl ecx,SECTORSIZE_LG2-2 ; Convert count to dwords
447 .overrun: pop ax ; Drop setup_regs return address
448 mov ax,0200h ; Missing address mark
449 ret ; Return to Done
451 ; Set up registers as for an EDD Read, and compares against disk size.
452 %if EDD
453 edd_setup_regs:
454 push es
455 mov si,P_SI ; DS:SI -> DAPA
456 mov es,P_DS
458 mov dx,[es:si]
459 cmp dx,16
460 jb .baddapa
462 cmp dword [es:si+4],-1
463 je .linear_address
465 movzx esi,word [es:si+4] ; Offset
466 movzx edi,word [es:si+6] ; Segment
467 shl edi,4
468 add esi,edi
470 jmp .got_address
472 .linear_address:
473 cmp dx,24 ; Must be large enough to hold linear address
474 jb .baddapa
476 cmp dword [es:si+20],0 ; > 4 GB addresses not supported
477 jne .overrun
479 mov esi,[es:si+16]
481 .got_address:
482 cmp dword [es:si+12],0 ; LBA too large?
483 jne .overrun
485 movzx ecx, word [es:si+2] ; Sectors to transfer
486 mov edi,[es:si+8] ; Starting sector
487 mov eax,edi
488 add eax,ecx
489 jc .overrun
490 cmp eax,[DiskSize]
491 ja .overrun
493 shl ecx,SECTORSIZE_LG2-2 ; Convert to dwords
494 shl edi,SECTORSIZE_LG2 ; Convert to an offset
495 add edi,[DiskBuf]
496 pop es
499 .baddapa:
500 mov ax,0100h ; Invalid command
501 pop es
502 pop ax ; Drop setup_regs return address
505 .overrun:
506 and word [es:si+2],0 ; No sectors transferred
507 mov ax,0200h
508 pop es
509 pop ax
512 %endif ; EDD
516 ; INT 15h intercept routines
518 int15_e820:
519 cmp edx,534D4150h ; "SMAP"
520 jne near oldint15
521 cmp ecx,20 ; Need 20 bytes
522 jb err86
523 push ds
524 push cs
525 pop ds
526 and ebx,ebx
527 jne .renew
528 mov ebx,E820Table
529 .renew:
530 add bx,12 ; Advance to next
531 mov eax,[bx-4] ; Type
532 and eax,eax ; Null type?
533 jz .renew ; If so advance to next
534 mov [es:di+16],eax
535 mov eax,[bx-12] ; Start addr (low)
536 mov [es:di],eax
537 mov ecx,[bx-8] ; Start addr (high)
538 mov [es:di+4],ecx
539 mov eax,[bx] ; End addr (low)
540 mov ecx,[bx+4] ; End addr (high)
541 sub eax,[bx-12] ; Derive the length
542 sbb ecx,[bx-8]
543 mov [es:di+8],eax ; Length (low)
544 mov [es:di+12],ecx ; Length (high)
545 cmp dword [bx+8],-1 ; Type of next = end?
546 jne .notdone
547 xor ebx,ebx ; Done with table
548 .notdone:
549 mov eax,edx ; "SMAP"
550 pop ds
551 mov ecx,20 ; Bytes loaded
552 int15_success:
553 mov byte [bp+6], 02h ; Clear CF
554 pop bp
555 iret
557 err86:
558 mov byte [bp+6], 03h ; Set CF
559 mov ah,86h
560 pop bp
561 iret
563 Int15Start:
564 push bp
565 mov bp,sp
566 cmp ax,0E820h
567 je near int15_e820
568 cmp ax,0E801h
569 je int15_e801
570 cmp ax,0E881h
571 je int15_e881
572 cmp ah,88h
573 je int15_88
574 oldint15: pop bp
575 jmp far [cs:OldInt15]
577 int15_e801:
578 mov ax,[cs:Mem1MB]
579 mov cx,ax
580 mov bx,[cs:Mem16MB]
581 mov dx,bx
582 jmp short int15_success
584 int15_e881:
585 mov eax,[cs:Mem1MB]
586 mov ecx,eax
587 mov ebx,[cs:Mem16MB]
588 mov edx,ebx
589 jmp short int15_success
591 int15_88:
592 mov ax,[cs:MemInt1588]
593 jmp short int15_success
596 ; Routine to copy in/out of high memory
597 ; esi = linear source address
598 ; edi = linear target address
599 ; ecx = 32-bit word count
601 ; Assumes cs = ds = es
603 bcopy:
604 push eax
605 push ebx
606 push edx
607 push ebp
609 mov bx, real_int15_stub
611 test byte [ConfigFlags], CONFIG_RAW|CONFIG_SAFEINT
612 jz .anymode
614 smsw ax ; Unprivileged!
615 test al,01h
616 jnz .protmode
618 .realmode:
619 test byte [ConfigFlags], CONFIG_RAW
620 jnz .raw
622 ; We're in real mode with CONFIG_SAFEINT, invoke INT 15h
623 ; directly if the vector is unchanged, otherwise invoke
624 ; the *old* INT 15h vector.
626 push ds
627 xor ax, ax
628 mov fs,ax
630 cmp word [4*0x15], Int15Start
631 jne .changed
633 mov ax, cs
634 cmp word [4*0x15+2], ax
635 jne .changed
637 pop ds
638 jmp .anymode ; INT 15h unchanged, safe to execute
640 .changed: ; INT 15h modified, execute *old* INT 15h
641 pop ds
642 mov bx, fake_int15_stub
643 jmp .anymode
645 .raw:
646 TRACER 'r'
647 ; We're in real mode, do it outselves
649 pushfd ; <A>
650 push ds ; <B>
651 push es ; <C>
656 xor ebx,ebx
657 mov bx,cs
658 shl ebx,4
659 lea edx,[Shaker+ebx]
660 mov [Shaker+2],edx
662 ; Test to see if A20 is enabled or not
663 xor ax,ax
664 mov ds,ax
665 dec ax
666 mov es,ax
668 mov ax,[0]
669 mov bx,ax
670 xor bx,[es:10h]
671 not ax
672 mov [0],ax
673 mov dx,ax
674 xor dx,[es:10h]
675 not ax
676 mov [0],ax
678 or dx,bx
679 push dx ; <D> Save A20 status
680 jnz .skip_a20e
682 mov ax,2401h ; Enable A20
683 int 15h
684 .skip_a20e:
685 mov dl,[ConfigFlags]
686 and dx,CONFIG_BIGRAW
687 add dx,8
688 ; DX = 16 for BIGRAW, 8 for RAW
689 ; 8 is selector for a 64K flat segment,
690 ; 16 is selector for a 4GB flat segment.
692 lgdt [cs:Shaker]
693 mov eax,cr0
694 or al,01h
695 mov cr0,eax
697 mov bx,16 ; Large flat segment
698 mov ds,bx
699 mov es,bx
701 a32 rep movsd
703 ; DX has the appropriate value to put in
704 ; the registers on return
705 mov ds,dx
706 mov es,dx
708 and al,~01h
709 mov cr0,eax
711 pop dx ; <D> A20 status
712 pop es ; <C>
713 pop ds ; <B>
715 and dx,dx
716 jnz .skip_a20d
717 mov ax,2400h ; Disable A20
718 int 15h
719 .skip_a20d:
720 popfd ; <A>
721 jmp .done
723 .protmode:
724 TRACER 'p'
725 .anymode:
727 .copy_loop:
728 push esi
729 push edi
730 push ecx
731 cmp ecx,4000h
732 jna .safe_size
733 mov ecx,4000h
734 .safe_size:
735 push ecx ; Transfer size this cycle
736 mov eax, esi
737 mov [Mover_src1], si
738 shr eax, 16
739 mov [Mover_src1+2], al
740 mov [Mover_src2], ah
741 mov eax, edi
742 mov [Mover_dst1], di
743 shr eax, 16
744 mov [Mover_dst1+2], al
745 mov [Mover_dst2], ah
746 mov si,Mover
747 mov ah, 87h
748 shl cx,1 ; Convert to 16-bit words
749 call bx ; INT 15h stub
750 pop eax ; Transfer size this cycle
751 pop ecx
752 pop edi
753 pop esi
754 jc .error
755 lea esi,[esi+4*eax]
756 lea edi,[edi+4*eax]
757 sub ecx, eax
758 jnz .copy_loop
759 ; CF = 0
760 .error:
761 .done:
762 pop ebp
763 pop edx
764 pop ebx
765 pop eax
768 real_int15_stub:
769 int 15h
770 cli ; Some BIOSes enable interrupts on INT 15h
773 fake_int15_stub:
774 pushf
775 call far [OldInt15]
779 %ifdef DEBUG_TRACERS
780 debug_tracer: pushad
781 pushfd
782 mov bp,sp
783 mov bx,[bp+9*4]
784 mov al,[cs:bx]
785 inc word [bp+9*4]
786 mov ah,0Eh
787 mov bx,7
788 int 10h
789 popfd
790 popad
792 %endif
794 section .data
795 alignb 2
796 Int13Funcs dw Reset ; 00h - RESET
797 dw GetStatus ; 01h - GET STATUS
798 dw Read ; 02h - READ
799 dw Write ; 03h - WRITE
800 dw Verify ; 04h - VERIFY
801 dw Invalid ; 05h - FORMAT TRACK
802 dw Invalid ; 06h - FORMAT TRACK AND SET BAD FLAGS
803 dw Invalid ; 07h - FORMAT DRIVE AT TRACK
804 dw GetParms ; 08h - GET PARAMETERS
805 dw InitWithParms ; 09h - INITIALIZE CONTROLLER WITH DRIVE PARAMETERS
806 dw Invalid ; 0Ah
807 dw Invalid ; 0Bh
808 dw Seek ; 0Ch - SEEK TO CYLINDER
809 dw Reset ; 0Dh - RESET HARD DISKS
810 dw Invalid ; 0Eh
811 dw Invalid ; 0Fh
812 dw CheckIfReady ; 10h - CHECK IF READY
813 dw Recalibrate ; 11h - RECALIBRATE
814 dw Invalid ; 12h
815 dw Invalid ; 13h
816 dw Invalid ; 14h
817 dw GetDriveType ; 15h - GET DRIVE TYPE
818 dw DetectChange ; 16h - DETECT DRIVE CHANGE
819 %if EDD
820 dw Invalid ; 17h
821 dw Invalid ; 18h
822 dw Invalid ; 19h
823 dw Invalid ; 1Ah
824 dw Invalid ; 1Bh
825 dw Invalid ; 1Ch
826 dw Invalid ; 1Dh
827 dw Invalid ; 1Eh
828 dw Invalid ; 1Fh
829 dw Invalid ; 20h
830 dw ReadMult ; 21h - READ MULTIPLE
831 dw WriteMult ; 22h - WRITE MULTIPLE
832 dw SetMode ; 23h - SET CONTROLLER FEATURES
833 dw SetMode ; 24h - SET MULTIPLE MODE
834 dw Invalid ; 25h - IDENTIFY DRIVE
835 dw Invalid ; 26h
836 dw Invalid ; 27h
837 dw Invalid ; 28h
838 dw Invalid ; 29h
839 dw Invalid ; 2Ah
840 dw Invalid ; 2Bh
841 dw Invalid ; 2Ch
842 dw Invalid ; 2Dh
843 dw Invalid ; 2Eh
844 dw Invalid ; 2Fh
845 dw Invalid ; 30h
846 dw Invalid ; 31h
847 dw Invalid ; 32h
848 dw Invalid ; 33h
849 dw Invalid ; 34h
850 dw Invalid ; 35h
851 dw Invalid ; 36h
852 dw Invalid ; 37h
853 dw Invalid ; 38h
854 dw Invalid ; 39h
855 dw Invalid ; 3Ah
856 dw Invalid ; 3Bh
857 dw Invalid ; 3Ch
858 dw Invalid ; 3Dh
859 dw Invalid ; 3Eh
860 dw Invalid ; 3Fh
861 dw Invalid ; 40h
862 dw EDDPresence ; 41h - EDD PRESENCE DETECT
863 dw EDDRead ; 42h - EDD READ
864 dw EDDWrite ; 43h - EDD WRITE
865 dw EDDVerify ; 44h - EDD VERIFY
866 dw Invalid ; 45h - EDD LOCK/UNLOCK MEDIA
867 dw Invalid ; 46h - EDD EJECT
868 dw EDDSeek ; 47h - EDD SEEK
869 dw EDDGetParms ; 48h - EDD GET PARAMETERS
870 %endif
872 Int13FuncsEnd equ $
873 Int13FuncsCnt equ (Int13FuncsEnd-Int13Funcs) >> 1
875 %if EDD
876 EDD_DPT:
877 .length dw 30
878 ; Bit 0 - DMA boundaries handled transparently
879 ; Bit 3 - Device supports write verify
880 .info dw 0009h
881 .cylinders dd 0 ; No physical geometry
882 .heads dd 0 ; No physical geometry
883 .sectors dd 0 ; No physical geometry
884 .totalsize dd 0, 0 ; Total number of sectors
885 .bytespersec dw SECTORSIZE
886 .eddtable dw -1, -1 ; Invalid EDD table
888 %endif
890 alignb 8, db 0
891 Shaker dw ShakerEnd-$
892 dd 0 ; Pointer to self
893 dw 0
895 Shaker_RMDS: dd 0x0000ffff ; 64K data segment
896 dd 0x00009300
898 Shaker_DS: dd 0x0000ffff ; 4GB data segment
899 dd 0x008f9300
901 ShakerEnd equ $
903 alignb 8, db 0
906 Mover dd 0, 0, 0, 0 ; Must be zero
907 dw 0ffffh ; 64 K segment size
908 Mover_src1: db 0, 0, 0 ; Low 24 bits of source addy
909 db 93h ; Access rights
910 db 00h ; Extended access rights
911 Mover_src2: db 0 ; High 8 bits of source addy
912 dw 0ffffh ; 64 K segment size
913 Mover_dst1: db 0, 0, 0 ; Low 24 bits of target addy
914 db 93h ; Access rights
915 db 00h ; Extended access rights
916 Mover_dst2: db 0 ; High 8 bits of source addy
917 Mover_dummy2: dd 0, 0, 0, 0 ; More space for the BIOS
919 alignb 4, db 0
920 MemDisk_Info equ $ ; Pointed to by installation check
921 MDI_Bytes dw 27 ; Total bytes in MDI structure
922 MDI_Version db VER_MINOR, VER_MAJOR ; MEMDISK version
924 PatchArea equ $ ; This gets filled in by the installer
926 DiskBuf dd 0 ; Linear address of high memory disk
927 DiskSize dd 0 ; Size of disk in blocks
928 CommandLine dw 0, 0 ; Far pointer to saved command line
930 OldInt13 dd 0 ; INT 13h in chain
931 OldInt15 dd 0 ; INT 15h in chain
933 OldDosMem dw 0 ; Old position of DOS mem end
934 BootLoaderID db 0 ; Boot loader ID from header
935 ; ---- MDI structure ends here ---
936 Int13MaxFunc db Int13FuncsCnt-1 ; Max INT 13h function (to disable EDD)
938 db 0, 0 ; pad
939 MemInt1588 dw 0 ; 1MB-65MB memory amount (1K)
941 Cylinders dw 0 ; Cylinder count
942 Heads dw 0 ; Head count
943 Sectors dd 0 ; Sector count (zero-extended)
945 Mem1MB dd 0 ; 1MB-16MB memory amount (1K)
946 Mem16MB dd 0 ; 16MB-4G memory amount (64K)
948 DriveNo db 0 ; Our drive number
949 DriveType db 0 ; Our drive type (floppies)
950 DriveCnt db 0 ; Drive count (from the BIOS)
952 ConfigFlags db 0 ; Bit 0 - readonly
954 MyStack dw 0 ; Offset of stack
955 StatusPtr dw 0 ; Where to save status (zeroseg ptr)
957 DPT times 16 db 0 ; BIOS parameter table pointer (floppies)
959 ; End patch area
961 Stack dd 0 ; Saved SS:ESP on invocation
962 dw 0
963 SavedAX dw 0 ; AX saved on invocation
965 alignb 4, db 0 ; We *MUST* end on a dword boundary
967 E820Table equ $ ; The installer loads the E820 table here
968 TotalSize equ $ ; End pointer