Add address aliases for freedos and msdos
[syslinux.git] / memdisk / memdisk.asm
blobf175ef43a0aa9c01a7b7255e68652af6536d6e89
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 2001-2008 H. Peter Anvin - All Rights Reserved
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
94 dw IretPtr
96 IretPtr equ Int13Start.iret
97 Int13Start:
98 ; Swap stack
99 mov [cs:Stack],esp
100 mov [cs:SavedAX],ax
101 mov ax,ss
102 mov [cs:Stack+4],ax
103 mov ax,cs
104 mov ss,ax
105 mov sp,[cs:MyStack]
107 ; See if DL points to our class of device (FD, HD)
108 push dx
109 push dx
110 xor dl,[cs:DriveNo]
111 pop dx
112 js .nomatch ; If SF=0, we have a class match here
113 jz .our_drive ; If ZF=1, we have an exact match
114 cmp dl,[cs:DriveNo]
115 jb .nomatch ; Drive < Our drive
116 dec dl ; Drive > Our drive, adjust drive #
117 .nomatch:
118 mov ax,[cs:SavedAX]
119 pushf
120 call far [cs:OldInt13]
121 pushf
122 push bp
123 mov bp,sp
124 cmp byte [cs:SavedAX+1],08h
125 je .norestoredl
126 cmp byte [cs:SavedAX+1],15h
127 jne .restoredl
128 test byte [bp+4],80h ; Hard disk?
129 jnz .norestoredl
130 .restoredl:
131 mov dl,[bp+4]
132 .norestoredl:
133 push ax
134 push ebx
135 push ds
136 mov ax,[bp+2] ; Flags
137 lds ebx,[cs:Stack]
138 mov [bx+4],al ; Arithmetric flags
139 pop ds
140 pop ebx
141 pop ax
142 pop bp
143 lss esp,[cs:Stack]
144 .iret: iret
146 .our_drive:
147 ; Set up standard entry frame
148 push ds
149 push es
150 mov ds,ax
151 mov es,ax
152 mov ax,[SavedAX]
153 pushad
154 mov bp,sp ; Point BP to the entry stack frame
155 TRACER 'F'
156 ; Note: AH == P_AH here
157 cmp ah,[Int13MaxFunc]
158 ja Invalid_jump
159 xor al,al ; AL = 0 is standard entry condition
160 mov di,ax
161 shr di,7 ; Convert AH to an offset in DI
162 call [Int13Funcs+di]
164 Done: ; Standard routine for return
165 mov P_AX,ax
166 DoneWeird:
167 TRACER 'D'
168 xor bx,bx
169 mov es,bx
170 mov bx,[StatusPtr]
171 mov [es:bx],ah ; Save status
172 and ah,ah
174 lds ebx,[Stack]
175 ; This sets the low byte (the arithmetric flags) of the
176 ; FLAGS on stack to either 00h (no flags) or 01h (CF)
177 ; depending on if AH was zero or not.
178 setnz [bx+4] ; Set CF iff error
179 popad
180 pop es
181 pop ds
182 lss esp,[cs:Stack]
183 iret
185 Reset:
186 ; Reset affects multiple drives, so we need to pass it on
187 TRACER 'R'
188 xor ax,ax ; Bottom of memory
189 mov es,ax
190 test dl,dl ; Always pass it on if we are resetting HD
191 js .hard_disk ; Bit 7 set
192 ; Some BIOSes get very unhappy if we pass a reset floppy
193 ; command to them and don't actually have any floppies.
194 ; This is a bug, but we have to deal with it nontheless.
195 ; Therefore, if we are the *ONLY* floppy drive, and the
196 ; user didn't request HD reset, then just drop the command.
197 ; BIOS equipment byte, top two bits + 1 == total # of floppies
198 test byte [es:0x410],0C0h
199 jz success
200 jmp .pass_on ; ... otherwise pass it to the BIOS
201 .hard_disk:
202 ; ... same thing for hard disks, sigh ...
203 cmp byte [es:0x475],1 ; BIOS variable for number of hard disks
204 jbe success
206 .pass_on:
207 pop ax ; Drop return address
208 popad ; Restore all registers
209 pop es
210 pop ds
211 lss esp,[cs:Stack] ; Restore the stack
212 and dl,80h ; Clear all but the type bit
213 jmp far [cs:OldInt13]
216 Invalid:
217 pop dx ; Drop return address
218 Invalid_jump:
219 TRACER 'I'
220 mov ah,01h ; Unsupported function
221 jmp short Done
223 GetDriveType:
224 test byte [DriveNo],80h
225 mov bl,02h ; Type 02h = floppy with changeline
226 jz .floppy
227 ; Hard disks only...
228 inc bx ; Type = 03h
229 mov dx,[DiskSize] ; Return the disk size in sectors
230 mov P_DX,dx
231 mov cx,[DiskSize+2]
232 mov P_CX,cx
233 .floppy:
234 mov P_AH,bl ; 02h floppy, 03h hard disk
235 pop ax ; Drop return address
236 xor ax,ax ; Success...
237 jmp DoneWeird ; But don't stick it into P_AX
239 GetStatus:
240 xor ax,ax
241 mov es,ax
242 mov bx,[StatusPtr]
243 mov ah,[bx] ; Copy last status
246 ReadMult:
247 TRACER 'm'
248 Read:
249 TRACER 'R'
250 call setup_regs
251 do_copy:
252 TRACER '<'
253 call bcopy
254 TRACER '>'
255 movzx ax,P_AL ; AH = 0, AL = transfer count
258 WriteMult:
259 TRACER 'M'
260 Write:
261 TRACER 'W'
262 test byte [ConfigFlags],CONFIG_READONLY
263 jnz .readonly
264 call setup_regs
265 xchg esi,edi ; Opposite direction of a Read!
266 jmp short do_copy
267 .readonly: mov ah,03h ; Write protected medium
270 ; Verify integrity; just bounds-check
271 Seek:
272 Verify:
273 call setup_regs ; Returns error if appropriate
274 ; And fall through to success
276 CheckIfReady: ; These are always-successful noop functions
277 Recalibrate:
278 InitWithParms:
279 DetectChange:
280 EDDDetectChange:
281 EDDLock:
282 SetMode:
283 success:
284 xor ax,ax ; Always successful
287 GetParms:
288 TRACER 'G'
289 mov dl,[DriveCnt] ; Cached data
290 mov P_DL,dl
291 test byte [DriveNo],80h
292 jnz .hd
293 mov P_DI,DPT
294 mov P_ES,cs
295 mov bl,[DriveType]
296 mov P_BL,bl
297 .hd:
298 mov ax,[Cylinders]
299 dec ax ; We report the highest #, not the count
300 xchg al,ah
301 shl al,6
302 or al,[Sectors]
303 mov P_CX,ax
304 mov ax,[Heads]
305 dec ax
306 mov P_DH,al
309 ; Is this MEMDISK installation check?
311 cmp P_HAX,'ME'
312 jne .notic
313 cmp P_HCX,'MD'
314 jne .notic
315 cmp P_HDX,'IS'
316 jne .notic
317 cmp P_HBX,'K?'
318 jne .notic
320 ; MEMDISK installation check...
321 mov P_HAX,'!M'
322 mov P_HCX,'EM'
323 mov P_HDX,'DI'
324 mov P_HBX,'SK'
325 mov P_ES,cs
326 mov P_DI,MemDisk_Info
328 .notic:
329 xor ax,ax
332 ; EDD functions -- only if enabled
334 %if EDD
335 EDDPresence:
336 TRACER 'E'
337 TRACER 'c'
339 cmp P_BX,55AAh
340 jne Invalid
341 mov P_BX,0AA55h ; EDD signature
342 mov P_AX,03000h ; EDD 3.0
343 mov P_CX,0003h ; Bit 0 - Fixed disk access subset
344 ; Bit 1 - Locking and ejecting subset
345 pop ax ; Drop return address
346 xor ax,ax ; Success
347 jmp DoneWeird ; Success, but AH != 0, sigh...
349 EDDRead:
350 TRACER 'E'
351 TRACER 'r'
353 call edd_setup_regs
354 call bcopy
355 xor ax,ax
358 EDDWrite:
359 TRACER 'E'
360 TRACER 'w'
362 call edd_setup_regs
363 xchg esi,edi
364 call bcopy
365 xor ax,ax
368 EDDVerify:
369 EDDSeek:
370 call edd_setup_regs ; Just bounds checking
371 xor ax,ax
374 EDDGetParms:
375 TRACER 'E'
376 TRACER 'p'
378 mov es,P_DS
379 mov di,P_SI
380 mov si,EDD_DPT
382 lodsw ; Length of our DPT
383 mov cx,[es:di]
384 cmp cx,26 ; Minimum size
385 jb .overrun
387 cmp cx,ax
388 jb .oksize
389 mov cx,ax
391 .oksize:
392 mov ax,cx
393 stosw
394 dec cx
395 dec cx
396 rep movsb
398 xor ax,ax
401 .overrun:
402 mov ax,0100h
404 %endif ; EDD
406 ; Set up registers as for a "Read", and compares against disk size.
407 ; WARNING: This fails immediately, even if we can transfer some
408 ; sectors. This isn't really the correct behaviour.
409 setup_regs:
411 ; Convert a CHS address in P_CX/P_DH into an LBA in eax
412 ; CH = cyl[7:0]
413 ; CL[0:5] = sector (1-based) CL[7:6] = cyl[9:8]
414 ; DH = head
415 movzx ecx,P_CX
416 movzx ebx,cl ; Sector number
417 and bl,3Fh
418 dec ebx ; Sector number is 1-based
419 cmp bx,[Sectors]
420 jae .overrun
421 movzx edi,P_DH ; Head number
422 movzx eax,word [Heads]
423 cmp di,ax
424 jae .overrun
425 shr cl,6
426 xchg cl,ch ; Now (E)CX <- cylinder number
427 mul ecx ; eax <- Heads*cyl# (edx <- 0)
428 add eax,edi
429 mul dword [Sectors]
430 add eax,ebx
431 ; Now eax = LBA, edx = 0
434 ; setup_regs continues...
436 ; Note: edi[31:16] and ecx[31:16] = 0 already
437 mov di,P_BX ; Get linear address of target buffer
438 mov cx,P_ES
439 shl ecx,4
440 add edi,ecx ; EDI = address to fetch to
441 movzx ecx,P_AL ; Sector count
442 mov esi,eax
443 add eax,ecx ; LBA of final sector + 1
444 shl esi,SECTORSIZE_LG2 ; LBA -> byte offset
445 add esi,[DiskBuf] ; Get address in high memory
446 cmp eax,[DiskSize] ; Check the high mark against limit
447 ja .overrun
448 shl ecx,SECTORSIZE_LG2-2 ; Convert count to dwords
451 .overrun: pop ax ; Drop setup_regs return address
452 mov ax,0200h ; Missing address mark
453 ret ; Return to Done
455 ; Set up registers as for an EDD Read, and compares against disk size.
456 %if EDD
457 edd_setup_regs:
458 push es
459 mov si,P_SI ; DS:SI -> DAPA
460 mov es,P_DS
462 mov dx,[es:si]
463 cmp dx,16
464 jb .baddapa
466 cmp dword [es:si+4],-1
467 je .linear_address
469 movzx ebx,word [es:si+4] ; Offset
470 movzx edi,word [es:si+6] ; Segment
471 shl edi,4
472 add ebx,edi
473 jmp .got_address
475 .linear_address:
476 cmp dx,24 ; Must be large enough to hold
477 ; linear address
478 jb .baddapa
480 cmp dword [es:si+20],0 ; > 4 GB addresses not supported
481 mov ax,0900h ; "Data boundary error" - bogus, but
482 ; no really better code available
483 jne .error
485 mov ebx,[es:si+16]
487 .got_address:
488 cmp dword [es:si+12],0 ; LBA too large?
489 jne .overrun
491 movzx ecx, word [es:si+2] ; Sectors to transfer
492 mov esi,[es:si+8] ; Starting sector
493 mov eax,esi
494 add eax,ecx
495 jc .overrun
496 cmp eax,[DiskSize]
497 ja .overrun
499 shl ecx,SECTORSIZE_LG2-2 ; Convert to dwords
500 shl esi,SECTORSIZE_LG2 ; Convert to an offset
501 add esi,[DiskBuf]
502 mov edi,ebx
503 pop es
506 .baddapa:
507 mov ax,0100h ; Invalid command
508 pop es
509 pop ax ; Drop setup_regs return address
512 .overrun:
513 mov ax,0200h ; "Address mark not found" =
514 ; LBA beyond end of disk
515 .error:
516 and word [es:si+2],0 ; No sectors transferred
517 pop es
518 pop ax
521 EDDEject:
522 mov ax,0B200h ; Volume Not Removable
525 %endif ; EDD
529 ; INT 15h intercept routines
531 int15_e820:
532 cmp edx,534D4150h ; "SMAP"
533 jne near oldint15
534 cmp ecx,20 ; Need 20 bytes
535 jb err86
536 push ds
537 push cs
538 pop ds
539 and ebx,ebx
540 jne .renew
541 mov ebx,E820Table
542 .renew:
543 add bx,12 ; Advance to next
544 mov eax,[bx-4] ; Type
545 and eax,eax ; Null type?
546 jz .renew ; If so advance to next
547 mov [es:di+16],eax
548 mov eax,[bx-12] ; Start addr (low)
549 mov [es:di],eax
550 mov ecx,[bx-8] ; Start addr (high)
551 mov [es:di+4],ecx
552 mov eax,[bx] ; End addr (low)
553 mov ecx,[bx+4] ; End addr (high)
554 sub eax,[bx-12] ; Derive the length
555 sbb ecx,[bx-8]
556 mov [es:di+8],eax ; Length (low)
557 mov [es:di+12],ecx ; Length (high)
558 cmp dword [bx+8],-1 ; Type of next = end?
559 jne .notdone
560 xor ebx,ebx ; Done with table
561 .notdone:
562 mov eax,edx ; "SMAP"
563 pop ds
564 mov ecx,20 ; Bytes loaded
565 int15_success:
566 mov byte [bp+6], 02h ; Clear CF
567 pop bp
568 iret
570 err86:
571 mov byte [bp+6], 03h ; Set CF
572 mov ah,86h
573 pop bp
574 iret
576 Int15Start:
577 push bp
578 mov bp,sp
579 cmp ax,0E820h
580 je near int15_e820
581 cmp ax,0E801h
582 je int15_e801
583 cmp ax,0E881h
584 je int15_e881
585 cmp ah,88h
586 je int15_88
587 oldint15: pop bp
588 jmp far [cs:OldInt15]
590 int15_e801:
591 mov ax,[cs:Mem1MB]
592 mov cx,ax
593 mov bx,[cs:Mem16MB]
594 mov dx,bx
595 jmp short int15_success
597 int15_e881:
598 mov eax,[cs:Mem1MB]
599 mov ecx,eax
600 mov ebx,[cs:Mem16MB]
601 mov edx,ebx
602 jmp short int15_success
604 int15_88:
605 mov ax,[cs:MemInt1588]
606 jmp short int15_success
609 ; Routine to copy in/out of high memory
610 ; esi = linear source address
611 ; edi = linear target address
612 ; ecx = 32-bit word count
614 ; Assumes cs = ds = es
616 bcopy:
617 push eax
618 push ebx
619 push edx
620 push ebp
622 mov bx, real_int15_stub
624 test byte [ConfigFlags], CONFIG_RAW|CONFIG_SAFEINT
625 jz .anymode
627 smsw ax ; Unprivileged!
628 test al,01h
629 jnz .protmode
631 .realmode:
632 test byte [ConfigFlags], CONFIG_RAW
633 jnz .raw
635 ; We're in real mode with CONFIG_SAFEINT, invoke INT 15h
636 ; directly if the vector is unchanged, otherwise invoke
637 ; the *old* INT 15h vector.
639 push ds
640 xor ax, ax
641 mov fs,ax
643 cmp word [4*0x15], Int15Start
644 jne .changed
646 mov ax, cs
647 cmp word [4*0x15+2], ax
648 jne .changed
650 pop ds
651 jmp .anymode ; INT 15h unchanged, safe to execute
653 .changed: ; INT 15h modified, execute *old* INT 15h
654 pop ds
655 mov bx, fake_int15_stub
656 jmp .anymode
658 .raw:
659 TRACER 'r'
660 ; We're in real mode, do it outselves
662 pushfd ; <A>
663 push ds ; <B>
664 push es ; <C>
669 xor ebx,ebx
670 mov bx,cs
671 shl ebx,4
672 lea edx,[Shaker+ebx]
673 mov [Shaker+2],edx
675 ; Test to see if A20 is enabled or not
676 xor ax,ax
677 mov ds,ax
678 dec ax
679 mov es,ax
681 mov ax,[0]
682 mov bx,ax
683 xor bx,[es:10h]
684 not ax
685 mov [0],ax
686 mov dx,ax
687 xor dx,[es:10h]
688 not ax
689 mov [0],ax
691 or dx,bx
692 push dx ; <D> Save A20 status
693 jnz .skip_a20e
695 mov ax,2401h ; Enable A20
696 int 15h
697 .skip_a20e:
698 mov dl,[ConfigFlags]
699 and dx,CONFIG_BIGRAW
700 add dx,8
701 ; DX = 16 for BIGRAW, 8 for RAW
702 ; 8 is selector for a 64K flat segment,
703 ; 16 is selector for a 4GB flat segment.
705 lgdt [cs:Shaker]
706 mov eax,cr0
707 or al,01h
708 mov cr0,eax
710 mov bx,16 ; Large flat segment
711 mov ds,bx
712 mov es,bx
714 a32 rep movsd
716 ; DX has the appropriate value to put in
717 ; the registers on return
718 mov ds,dx
719 mov es,dx
721 and al,~01h
722 mov cr0,eax
724 pop dx ; <D> A20 status
725 pop es ; <C>
726 pop ds ; <B>
728 and dx,dx
729 jnz .skip_a20d
730 mov ax,2400h ; Disable A20
731 int 15h
732 .skip_a20d:
733 popfd ; <A>
734 jmp .done
736 .protmode:
737 TRACER 'p'
738 .anymode:
740 .copy_loop:
741 push esi
742 push edi
743 push ecx
744 cmp ecx,4000h
745 jna .safe_size
746 mov ecx,4000h
747 .safe_size:
748 push ecx ; Transfer size this cycle
749 mov eax, esi
750 mov [Mover_src1], si
751 shr eax, 16
752 mov [Mover_src1+2], al
753 mov [Mover_src2], ah
754 mov eax, edi
755 mov [Mover_dst1], di
756 shr eax, 16
757 mov [Mover_dst1+2], al
758 mov [Mover_dst2], ah
759 mov si,Mover
760 mov ah, 87h
761 shl cx,1 ; Convert to 16-bit words
762 call bx ; INT 15h stub
763 pop eax ; Transfer size this cycle
764 pop ecx
765 pop edi
766 pop esi
767 jc .error
768 lea esi,[esi+4*eax]
769 lea edi,[edi+4*eax]
770 sub ecx, eax
771 jnz .copy_loop
772 ; CF = 0
773 .error:
774 .done:
775 pop ebp
776 pop edx
777 pop ebx
778 pop eax
781 real_int15_stub:
782 int 15h
783 cli ; Some BIOSes enable interrupts on INT 15h
786 fake_int15_stub:
787 pushf
788 call far [OldInt15]
792 %ifdef DEBUG_TRACERS
793 debug_tracer: pushad
794 pushfd
795 mov bp,sp
796 mov bx,[bp+9*4]
797 mov al,[cs:bx]
798 inc word [bp+9*4]
799 mov ah,0Eh
800 mov bx,7
801 int 10h
802 popfd
803 popad
805 %endif
807 section .data
808 alignb 2
809 Int13Funcs dw Reset ; 00h - RESET
810 dw GetStatus ; 01h - GET STATUS
811 dw Read ; 02h - READ
812 dw Write ; 03h - WRITE
813 dw Verify ; 04h - VERIFY
814 dw Invalid ; 05h - FORMAT TRACK
815 dw Invalid ; 06h - FORMAT TRACK AND SET BAD FLAGS
816 dw Invalid ; 07h - FORMAT DRIVE AT TRACK
817 dw GetParms ; 08h - GET PARAMETERS
818 dw InitWithParms ; 09h - INITIALIZE CONTROLLER WITH DRIVE PARAMETERS
819 dw Invalid ; 0Ah
820 dw Invalid ; 0Bh
821 dw Seek ; 0Ch - SEEK TO CYLINDER
822 dw Reset ; 0Dh - RESET HARD DISKS
823 dw Invalid ; 0Eh
824 dw Invalid ; 0Fh
825 dw CheckIfReady ; 10h - CHECK IF READY
826 dw Recalibrate ; 11h - RECALIBRATE
827 dw Invalid ; 12h
828 dw Invalid ; 13h
829 dw Invalid ; 14h
830 dw GetDriveType ; 15h - GET DRIVE TYPE
831 dw DetectChange ; 16h - DETECT DRIVE CHANGE
832 %if EDD
833 dw Invalid ; 17h
834 dw Invalid ; 18h
835 dw Invalid ; 19h
836 dw Invalid ; 1Ah
837 dw Invalid ; 1Bh
838 dw Invalid ; 1Ch
839 dw Invalid ; 1Dh
840 dw Invalid ; 1Eh
841 dw Invalid ; 1Fh
842 dw Invalid ; 20h
843 dw ReadMult ; 21h - READ MULTIPLE
844 dw WriteMult ; 22h - WRITE MULTIPLE
845 dw SetMode ; 23h - SET CONTROLLER FEATURES
846 dw SetMode ; 24h - SET MULTIPLE MODE
847 dw Invalid ; 25h - IDENTIFY DRIVE
848 dw Invalid ; 26h
849 dw Invalid ; 27h
850 dw Invalid ; 28h
851 dw Invalid ; 29h
852 dw Invalid ; 2Ah
853 dw Invalid ; 2Bh
854 dw Invalid ; 2Ch
855 dw Invalid ; 2Dh
856 dw Invalid ; 2Eh
857 dw Invalid ; 2Fh
858 dw Invalid ; 30h
859 dw Invalid ; 31h
860 dw Invalid ; 32h
861 dw Invalid ; 33h
862 dw Invalid ; 34h
863 dw Invalid ; 35h
864 dw Invalid ; 36h
865 dw Invalid ; 37h
866 dw Invalid ; 38h
867 dw Invalid ; 39h
868 dw Invalid ; 3Ah
869 dw Invalid ; 3Bh
870 dw Invalid ; 3Ch
871 dw Invalid ; 3Dh
872 dw Invalid ; 3Eh
873 dw Invalid ; 3Fh
874 dw Invalid ; 40h
875 dw EDDPresence ; 41h - EDD PRESENCE DETECT
876 dw EDDRead ; 42h - EDD READ
877 dw EDDWrite ; 43h - EDD WRITE
878 dw EDDVerify ; 44h - EDD VERIFY
879 dw EDDLock ; 45h - EDD LOCK/UNLOCK MEDIA
880 dw EDDEject ; 46h - EDD EJECT
881 dw EDDSeek ; 47h - EDD SEEK
882 dw EDDGetParms ; 48h - EDD GET PARAMETERS
883 dw EDDDetectChange ; 49h - EDD MEDIA CHANGE STATUS
884 %endif
886 Int13FuncsEnd equ $
887 Int13FuncsCnt equ (Int13FuncsEnd-Int13Funcs) >> 1
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
905 Mover dd 0, 0, 0, 0 ; Must be zero
906 dw 0ffffh ; 64 K segment size
907 Mover_src1: db 0, 0, 0 ; Low 24 bits of source addy
908 db 93h ; Access rights
909 db 00h ; Extended access rights
910 Mover_src2: db 0 ; High 8 bits of source addy
911 dw 0ffffh ; 64 K segment size
912 Mover_dst1: db 0, 0, 0 ; Low 24 bits of target addy
913 db 93h ; Access rights
914 db 00h ; Extended access rights
915 Mover_dst2: db 0 ; High 8 bits of source addy
916 Mover_dummy2: dd 0, 0, 0, 0 ; More space for the BIOS
918 alignb 4, db 0
919 MemDisk_Info equ $ ; Pointed to by installation check
920 MDI_Bytes dw 27 ; Total bytes in MDI structure
921 MDI_Version db VER_MINOR, VER_MAJOR ; MEMDISK version
923 PatchArea equ $ ; This gets filled in by the installer
925 DiskBuf dd 0 ; Linear address of high memory disk
926 DiskSize dd 0 ; Size of disk in blocks
927 CommandLine dw 0, 0 ; Far pointer to saved command line
929 OldInt13 dd 0 ; INT 13h in chain
930 OldInt15 dd 0 ; INT 15h in chain
932 OldDosMem dw 0 ; Old position of DOS mem end
933 BootLoaderID db 0 ; Boot loader ID from header
934 ; ---- MDI structure ends here ---
935 Int13MaxFunc db Int13FuncsCnt-1 ; Max INT 13h function (to disable EDD)
937 db 0, 0 ; pad
938 MemInt1588 dw 0 ; 1MB-65MB memory amount (1K)
940 Cylinders dw 0 ; Cylinder count
941 Heads dw 0 ; Head count
942 Sectors dd 0 ; Sector count (zero-extended)
944 Mem1MB dd 0 ; 1MB-16MB memory amount (1K)
945 Mem16MB dd 0 ; 16MB-4G memory amount (64K)
947 DriveNo db 0 ; Our drive number
948 DriveType db 0 ; Our drive type (floppies)
949 DriveCnt db 0 ; Drive count (from the BIOS)
951 ConfigFlags db 0 ; Bit 0 - readonly
953 MyStack dw 0 ; Offset of stack
954 StatusPtr dw 0 ; Where to save status (zeroseg ptr)
956 DPT times 16 db 0 ; BIOS parameter table pointer (floppies)
957 %if EDD
958 EDD_DPT:
959 .length dw 30
960 .info dw 0029h
961 ; Bit 0 - DMA boundaries handled transparently
962 ; Bit 3 - Device supports write verify
963 ; Bit 5 - Media is lockable
964 .cylinders dd 0 ; Filled in by installer
965 .heads dd 0 ; Filled in by installer
966 .sectors dd 0 ; Filled in by installer
967 .totalsize dd 0, 0 ; Filled in by installer
968 .bytespersec dw SECTORSIZE
969 .eddtable dw -1, -1 ; Invalid DPTE pointer
971 %endif
973 ; End patch area
974 Stack dd 0 ; Saved SS:ESP on invocation
975 dw 0
976 SavedAX dw 0 ; AX saved on invocation
978 alignb 4, db 0 ; We *MUST* end on a dword boundary
980 E820Table equ $ ; The installer loads the E820 table here
981 TotalSize equ $ ; End pointer