syslinux-3.08-2 sources from FC4
[bootcd.git] / syslinux / memdisk / memdisk.asm
1 ; -*- fundamental -*- (asm-mode sucks)
2 ; $Id: memdisk.asm,v 1.29 2005/04/29 06:08:03 hpa Exp $
3 ; ****************************************************************************
4 ;
5 ;  memdisk.asm
6 ;
7 ;  A program to emulate an INT 13h disk BIOS from a "disk" in extended
8 ;  memory.
9 ;
10 ;   Copyright (C) 2001-2004  H. Peter Anvin
11 ;
12 ;  This program is free software; you can redistribute it and/or modify
13 ;  it under the terms of the GNU General Public License as published by
14 ;  the Free Software Foundation, Inc., 53 Temple Place Ste 330,
15 ;  Boston MA 02111-1307, USA; either version 2 of the License, or
16 ;  (at your option) any later version; incorporated herein by reference.
17
18 ; ****************************************************************************
19
20 %ifndef DEPEND
21 %include        "../version.gen"
22 %endif
23
24 ; %define DEBUG_TRACERS                 ; Uncomment to get debugging tracers
25
26 %ifdef DEBUG_TRACERS
27
28 %macro TRACER   1
29         call debug_tracer
30         db %1
31 %endmacro
32
33 %else   ; DEBUG_TRACERS
34
35 %macro  TRACER  1
36 %endmacro
37
38 %endif  ; DEBUG_TRACERS
39
40 %define CONFIG_READONLY 0x01
41 %define CONFIG_RAW      0x02
42 %define CONFIG_BIGRAW   0x08            ; MUST be 8!
43
44                 org 0h
45
46 %define SECTORSIZE_LG2  9               ; log2(sector size)
47 %define SECTORSIZE      (1 << SECTORSIZE_LG2)
48
49                 ; Parameter registers definition; this is the definition
50                 ; of the stack frame.
51 %define         P_DS            word [bp+34]
52 %define         P_ES            word [bp+32]
53 %define         P_EAX           dword [bp+28]
54 %define         P_HAX           word [bp+30]
55 %define         P_AX            word [bp+28]
56 %define         P_AL            byte [bp+28]
57 %define         P_AH            byte [bp+29]
58 %define         P_ECX           dword [bp+24]
59 %define         P_HCX           word [bp+26]
60 %define         P_CX            word [bp+24]
61 %define         P_CL            byte [bp+24]
62 %define         P_CH            byte [bp+25]
63 %define         P_EDX           dword [bp+20]
64 %define         P_HDX           word [bp+22]
65 %define         P_DX            word [bp+20]
66 %define         P_DL            byte [bp+20]
67 %define         P_DH            byte [bp+21]
68 %define         P_EBX           dword [bp+16]
69 %define         P_HBX           word [bp+18]
70 %define         P_HBXL          byte [bp+18]
71 %define         P_BX            word [bp+16]
72 %define         P_BL            byte [bp+16]
73 %define         P_BH            byte [bp+17]
74 %define         P_EBP           dword [bp+8]
75 %define         P_BP            word [bp+8]
76 %define         P_ESI           dword [bp+4]
77 %define         P_SI            word [bp+4]
78 %define         P_EDI           dword [bp]
79 %define         P_DI            word [bp]
80
81                 section .text
82                 ; These pointers are used by the installer and
83                 ; must be first in the binary
84 Pointers:       dw Int13Start
85                 dw Int15Start
86                 dw PatchArea
87                 dw TotalSize
88
89 Int13Start:
90                 ; Swap stack
91                 mov [cs:Stack],esp
92                 mov [cs:SavedAX],ax
93                 mov ax,ss
94                 mov [cs:Stack+4],ax
95                 mov ax,cs
96                 mov ss,ax
97                 mov sp,[cs:MyStack]
98
99                 ; See if DL points to our class of device (FD, HD)
100                 push dx
101                 push dx
102                 xor dl,[cs:DriveNo]
103                 pop dx
104                 js .nomatch             ; If SF=0, we have a class match here
105                 jz .our_drive           ; If ZF=1, we have an exact match
106                 cmp dl,[cs:DriveNo]
107                 jb .nomatch             ; Drive < Our drive
108                 dec dl                  ; Drive > Our drive, adjust drive #
109 .nomatch:
110                 mov ax,[cs:SavedAX]
111                 pushf
112                 call far [cs:OldInt13]
113                 pushf
114                 push bp
115                 mov bp,sp
116                 cmp byte [cs:SavedAX+1],08h
117                 je .norestoredl
118                 cmp byte [cs:SavedAX+1],15h
119                 jne .restoredl
120                 test byte [bp+4],80h    ; Hard disk?
121                 jnz .norestoredl
122 .restoredl:
123                 mov dl,[bp+4]
124 .norestoredl:
125                 push ax
126                 push ebx
127                 push ds
128                 mov ax,[bp+2]           ; Flags
129                 lds ebx,[cs:Stack]
130                 mov [bx+4],al           ; Arithmetric flags
131                 pop ds
132                 pop ebx
133                 pop ax
134                 pop bp
135                 lss esp,[cs:Stack]
136                 iret
137
138 .our_drive:
139                 ; Set up standard entry frame
140                 push ds
141                 push es
142                 mov ds,ax
143                 mov es,ax
144                 mov ax,[SavedAX]
145                 pushad
146                 mov bp,sp               ; Point BP to the entry stack frame
147                 TRACER 'F'
148                 ; Note: AH == P_AH here
149                 cmp ah,Int13FuncsMax
150                 jae Invalid_jump
151                 xor al,al               ; AL = 0 is standard entry condition
152                 mov di,ax
153                 shr di,7                ; Convert AH to an offset in DI
154                 call [Int13Funcs+di]
155
156 Done:           ; Standard routine for return
157                 mov P_AX,ax
158 DoneWeird:
159                 TRACER 'D'
160                 xor bx,bx
161                 mov es,bx
162                 mov bx,[StatusPtr]
163                 mov [es:bx],ah          ; Save status
164                 and ah,ah
165
166                 lds ebx,[Stack]
167                 ; This sets the low byte (the arithmetric flags) of the
168                 ; FLAGS on stack to either 00h (no flags) or 01h (CF)
169                 ; depending on if AH was zero or not.
170                 setnz [bx+4]            ; Set CF iff error
171                 popad
172                 pop es
173                 pop ds
174                 lss esp,[cs:Stack]
175                 iret
176
177 Reset:
178                 ; Reset affects multiple drives, so we need to pass it on
179                 TRACER 'R'
180                 test dl,dl              ; Always pass it on if we are resetting HD
181                 js .pass_on             ; Bit 7 set
182                 ; Some BIOSes get very unhappy if we pass a reset floppy
183                 ; command to them and don't actually have any floppies.
184                 ; This is a bug, but we have to deal with it nontheless.
185                 ; Therefore, if we are the *ONLY* floppy drive, and the
186                 ; user didn't request HD reset, then just drop the command.
187                 xor ax,ax               ; Bottom of memory
188                 mov es,ax
189                 ; BIOS equipment byte, top two bits + 1 == total # of floppies
190                 test byte [es:0x410],0C0h       
191                 jz success
192                 ; ... otherwise pass it to the BIOS
193 .pass_on:
194                 pop ax                  ; Drop return address
195                 popad                   ; Restore all registers
196                 pop es
197                 pop ds
198                 lss esp,[cs:Stack]      ; Restore the stack
199                 and dl,80h              ; Clear all but the type bit
200                 jmp far [cs:OldInt13]
201
202
203 Invalid:
204                 pop dx                  ; Drop return address
205 Invalid_jump:
206                 TRACER 'I'
207                 mov ah,01h              ; Unsupported function
208                 jmp short Done
209
210 GetDriveType:
211                 test byte [DriveNo],80h
212                 mov bl,02h              ; Type 02h = floppy with changeline
213                 jz .floppy
214                 ; Hard disks only...
215                 inc bx                  ; Type = 03h
216                 mov dx,[DiskSize]       ; Return the disk size in sectors
217                 mov P_DX,dx
218                 mov cx,[DiskSize+2]
219                 mov P_CX,cx
220 .floppy:
221                 mov P_AH,bl             ; 02h floppy, 03h hard disk
222                 pop ax                  ; Drop return address
223                 xor ax,ax               ; Success...
224                 jmp short DoneWeird     ; But don't stick it into P_AX
225
226 GetStatus:
227                 xor ax,ax
228                 mov es,ax
229                 mov bx,[StatusPtr]
230                 mov ah,[bx]             ; Copy last status
231                 ret
232
233 ReadMult:
234                 TRACER 'm'
235 Read:
236                 TRACER 'R'
237                 call setup_regs
238 do_copy:
239                 TRACER '<'
240                 call bcopy
241                 TRACER '>'
242                 movzx ax,P_AL           ; AH = 0, AL = transfer count
243                 ret
244
245 WriteMult:
246                 TRACER 'M'
247 Write:
248                 TRACER 'W'
249                 test byte [ConfigFlags],CONFIG_READONLY
250                 jnz .readonly
251                 call setup_regs
252                 xchg esi,edi            ; Opposite direction of a Read!
253                 jmp short do_copy
254 .readonly:      mov ah,03h              ; Write protected medium
255                 ret
256
257                 ; Verify integrity; just bounds-check
258 Seek:
259 Verify:
260                 call setup_regs         ; Returns error if appropriate
261                 ; And fall through to success
262
263 CheckIfReady:                           ; These are always-successful noop functions
264 Recalibrate:
265 InitWithParms:
266 DetectChange:
267 SetMode:
268 success:
269                 xor ax,ax               ; Always successful
270                 ret
271
272 GetParms:
273                 TRACER 'G'
274                 mov dl,[DriveCnt]       ; Cached data
275                 mov P_DL,dl
276                 test byte [DriveNo],80h
277                 jnz .hd
278                 mov P_DI,DPT
279                 mov P_ES,cs
280                 mov bl,[DriveType]
281                 mov P_BL,bl
282 .hd:
283                 mov ax,[Cylinders]
284                 dec ax                  ; We report the highest #, not the count
285                 xchg al,ah
286                 shl al,6
287                 or al,[Sectors]
288                 mov P_CX,ax
289                 mov ax,[Heads]
290                 dec ax
291                 mov P_DH,al
292
293                 ;
294                 ; Is this MEMDISK installation check?
295                 ;
296                 cmp P_HAX,'ME'
297                 jne .notic
298                 cmp P_HCX,'MD'
299                 jne .notic
300                 cmp P_HDX,'IS'
301                 jne .notic
302                 cmp P_HBX,'K?'
303                 jne .notic
304
305                 ; MEMDISK installation check...
306                 mov P_HAX,'!M'
307                 mov P_HCX,'EM'
308                 mov P_HDX,'DI'
309                 mov P_HBX,'SK'
310                 mov P_ES,cs
311                 mov P_DI,MemDisk_Info
312
313 .notic:
314                 xor ax,ax
315                 ret
316                 
317                 ; Set up registers as for a "Read", and compares against disk size
318 setup_regs:
319
320                 ; Convert a CHS address in P_CX/P_DH into an LBA in eax
321                 ; CH = cyl[7:0]
322                 ; CL[0:5] = sector (1-based)  CL[7:6] = cyl[9:8]
323                 ; DH = head
324                 movzx ecx,P_CX
325                 movzx ebx,cl            ; Sector number
326                 and bl,3Fh
327                 dec ebx                 ; Sector number is 1-based
328                 cmp bx,[Sectors]
329                 jae .overrun
330                 movzx edi,P_DH          ; Head number
331                 movzx eax,word [Heads]
332                 cmp di,ax
333                 jae .overrun
334                 shr cl,6
335                 xchg cl,ch              ; Now (E)CX <- cylinder number
336                 mul ecx                 ; eax <- Heads*cyl# (edx <- 0)
337                 add eax,edi
338                 mul dword [Sectors]
339                 add eax,ebx
340                 ; Now eax = LBA, edx = 0
341
342                 ;
343                 ; setup_regs continues...
344                 ;
345                 ; Note: edi[31:16] and ecx[31:16] = 0 already
346                 mov di,P_BX             ; Get linear address of target buffer
347                 mov cx,P_ES
348                 shl ecx,4
349                 add edi,ecx             ; EDI = address to fetch to
350                 movzx ecx,P_AL          ; Sector count
351                 mov esi,eax
352                 add eax,ecx             ; LBA of final sector + 1
353                 shl esi,SECTORSIZE_LG2  ; LBA -> byte offset
354                 add esi,[DiskBuf]       ; Get address in high memory
355                 cmp eax,[DiskSize]      ; Check the high mark against limit
356                 ja .overrun
357                 shl ecx,SECTORSIZE_LG2-2 ; Convert count to 32-bit words
358                 ret
359
360 .overrun:       pop ax                  ; Drop setup_regs return address
361                 mov ax,0200h            ; Missing address mark
362                 ret                     ; Return to Done
363
364 int15_e820:
365                 cmp edx,534D4150h       ; "SMAP"
366                 jne near oldint15
367                 cmp ecx,20              ; Need 20 bytes
368                 jb err86
369                 push ds
370                 push cs
371                 pop ds
372                 and ebx,ebx
373                 jne .renew
374                 mov ebx,E820Table
375 .renew:
376                 add bx,12               ; Advance to next
377                 mov eax,[bx-4]          ; Type
378                 and eax,eax             ; Null type?
379                 jz .renew               ; If so advance to next
380                 mov [es:di+16],eax
381                 mov eax,[bx-12]         ; Start addr (low)
382                 mov [es:di],eax
383                 mov ecx,[bx-8]          ; Start addr (high)
384                 mov [es:di+4],ecx
385                 mov eax,[bx]            ; End addr (low)
386                 mov ecx,[bx+4]          ; End addr (high)
387                 sub eax,[bx-12]         ; Derive the length
388                 sbb ecx,[bx-8]
389                 mov [es:di+8],eax       ; Length (low)
390                 mov [es:di+12],ecx      ; Length (high)
391                 cmp dword [bx+8],-1     ; Type of next = end?
392                 jne .notdone
393                 xor ebx,ebx             ; Done with table
394 .notdone:
395                 mov eax,edx             ; "SMAP"
396                 pop ds
397                 mov ecx,20              ; Bytes loaded
398 int15_success:
399                 mov byte [bp+6], 02h    ; Clear CF
400                 pop bp
401                 iret
402
403 err86:
404                 mov byte [bp+6], 03h    ; Set CF
405                 mov ah,86h
406                 pop bp
407                 iret
408
409 Int15Start:
410                 push bp
411                 mov bp,sp
412                 cmp ax,0E820h
413                 je near int15_e820
414                 cmp ax,0E801h
415                 je int15_e801
416                 cmp ax,0E881h
417                 je int15_e881
418                 cmp ah,88h
419                 je int15_88
420 oldint15:       pop bp
421                 jmp far [cs:OldInt15]
422                 
423 int15_e801:
424                 mov ax,[cs:Mem1MB]
425                 mov cx,ax
426                 mov bx,[cs:Mem16MB]
427                 mov dx,bx
428                 jmp short int15_success
429
430 int15_e881:
431                 mov eax,[cs:Mem1MB]
432                 mov ecx,eax
433                 mov ebx,[cs:Mem16MB]
434                 mov edx,ebx
435                 jmp short int15_success
436
437 int15_88:
438                 mov ax,[cs:MemInt1588]
439                 jmp short int15_success
440
441 ;
442 ; Routine to copy in/out of high memory
443 ; esi = linear source address
444 ; edi = linear target address
445 ; ecx = 32-bit word count 
446 ;
447 ; Assumes cs = ds = es
448 ;
449 bcopy:
450                 push eax
451                 push ebx
452                 push edx
453                 push ebp
454
455                 test byte [ConfigFlags],CONFIG_RAW
456                 jz .anymode
457
458                 smsw ax                 ; Unprivileged!
459                 test al,01h
460                 jnz .protmode
461
462 .realmode:
463                 TRACER 'r'
464                 ; We're in real mode, do it outselves
465
466                 pushfd
467                 push ds
468                 push es
469
470                 cli
471                 cld
472
473                 xor ebx,ebx
474                 mov bx,cs
475                 shl ebx,4
476                 lea edx,[Shaker+ebx]
477                 mov [Shaker+2],edx
478
479                 ; Test to see if A20 is enabled or not
480                 xor ax,ax
481                 mov ds,ax
482                 dec ax
483                 mov es,ax
484
485                 mov ax,[0]
486                 mov bx,ax
487                 xor bx,[es:10h]
488                 not ax
489                 mov [0],ax
490                 mov dx,ax
491                 xor dx,[es:10h]
492                 not ax
493                 mov [0],ax
494
495                 or dx,bx
496                 push dx                 ; Save A20 status
497                 jnz .skip_a20e
498
499                 mov ax,2401h            ; Enable A20
500                 int 15h
501 .skip_a20e:
502                 mov dl,[ConfigFlags]
503                 and dx,CONFIG_BIGRAW
504                 add dx,8
505                 ; DX = 16 for BIGRAW, 8 for RAW
506                 ;  8 is selector for a 64K flat segment,
507                 ; 16 is selector for a 4GB flat segment.        
508
509                 lgdt [cs:Shaker]
510                 mov eax,cr0
511                 or al,01h
512                 mov cr0,eax
513
514                 mov bx,16               ; Large flat segment
515                 mov ds,bx
516                 mov es,bx
517
518                 a32 rep movsd
519
520                 ; DX has the appropriate value to put in
521                 ; the registers on return
522                 mov ds,dx
523                 mov es,dx
524
525                 and al,~01h
526                 mov cr0,eax
527
528                 pop es
529                 pop ds
530
531                 pop dx                  ; A20 status
532                 and dx,dx
533                 jnz .skip_a20d
534                 mov ax,2400h            ; Disable A20
535                 int 15h
536 .skip_a20d:
537                 popfd
538                 jmp .done
539
540 .protmode:
541                 TRACER 'p'
542 .anymode:
543
544 .copy_loop:
545                 push esi
546                 push edi
547                 push ecx
548                 cmp ecx,4000h
549                 jna .safe_size
550                 mov ecx,4000h
551 .safe_size:
552                 push ecx        ; Transfer size this cycle
553                 mov eax, esi
554                 mov [Mover_src1], si
555                 shr eax, 16
556                 mov [Mover_src1+2], al
557                 mov [Mover_src2], ah
558                 mov eax, edi
559                 mov [Mover_dst1], di
560                 shr eax, 16
561                 mov [Mover_dst1+2], al
562                 mov [Mover_dst2], ah
563                 mov si,Mover
564                 mov ah, 87h
565                 shl cx,1        ; Convert to 16-bit words
566                 int 15h
567                 cli             ; Some BIOSes enable interrupts on INT 15h
568                 pop eax         ; Transfer size this cycle
569                 pop ecx
570                 pop edi
571                 pop esi
572                 jc .error
573                 lea esi,[esi+4*eax]
574                 lea edi,[edi+4*eax]
575                 sub ecx, eax
576                 jnz .copy_loop
577                 ; CF = 0
578 .error:
579 .done:
580                 pop ebp
581                 pop edx
582                 pop ebx
583                 pop eax
584                 ret
585
586 %ifdef DEBUG_TRACERS
587 debug_tracer:   pushad
588                 pushfd
589                 mov bp,sp
590                 mov bx,[bp+9*4]
591                 mov al,[cs:bx]
592                 inc word [bp+9*4]
593                 mov ah,0Eh
594                 mov bx,7
595                 int 10h
596                 popfd
597                 popad
598                 ret
599 %endif
600
601                 section .data
602                 alignb 2
603 Int13Funcs      dw Reset                ; 00h - RESET
604                 dw GetStatus            ; 01h - GET STATUS
605                 dw Read                 ; 02h - READ
606                 dw Write                ; 03h - WRITE
607                 dw Verify               ; 04h - VERIFY
608                 dw Invalid              ; 05h - FORMAT TRACK
609                 dw Invalid              ; 06h - FORMAT TRACK AND SET BAD FLAGS
610                 dw Invalid              ; 07h - FORMAT DRIVE AT TRACK
611                 dw GetParms             ; 08h - GET PARAMETERS
612                 dw InitWithParms        ; 09h - INITIALIZE CONTROLLER WITH DRIVE PARAMETERS
613                 dw Invalid              ; 0Ah
614                 dw Invalid              ; 0Bh
615                 dw Seek                 ; 0Ch - SEEK TO CYLINDER
616                 dw Reset                ; 0Dh - RESET HARD DISKS
617                 dw Invalid              ; 0Eh
618                 dw Invalid              ; 0Fh
619                 dw CheckIfReady         ; 10h - CHECK IF READY
620                 dw Recalibrate          ; 11h - RECALIBRATE
621                 dw Invalid              ; 12h
622                 dw Invalid              ; 13h
623                 dw Invalid              ; 14h
624                 dw GetDriveType         ; 15h - GET DRIVE TYPE
625                 dw DetectChange         ; 16h - DETECT DRIVE CHANGE
626 %if 0
627                 dw Invalid              ; 17h
628                 dw Invalid              ; 18h
629                 dw Invalid              ; 19h
630                 dw Invalid              ; 1Ah
631                 dw Invalid              ; 1Bh
632                 dw Invalid              ; 1Ch
633                 dw Invalid              ; 1Dh
634                 dw Invalid              ; 1Eh
635                 dw Invalid              ; 1Fh
636                 dw Invalid              ; 20h
637                 dw ReadMult             ; 21h - READ MULTIPLE
638                 dw WriteMult            ; 22h - WRITE MULTIPLE
639                 dw SetMode              ; 23h - SET CONTROLLER FEATURES
640                 dw SetMode              ; 24h - SET MULTIPLE MODE
641                 dw Invalid              ; 25h - IDENTIFY DRIVE
642                 dw Invalid              ; 26h
643                 dw Invalid              ; 27h
644                 dw Invalid              ; 28h
645                 dw Invalid              ; 29h
646                 dw Invalid              ; 2Ah
647                 dw Invalid              ; 2Bh
648                 dw Invalid              ; 2Ch
649                 dw Invalid              ; 2Dh
650                 dw Invalid              ; 2Eh
651                 dw Invalid              ; 2Fh
652                 dw Invalid              ; 30h
653                 dw Invalid              ; 31h
654                 dw Invalid              ; 32h
655                 dw Invalid              ; 33h
656                 dw Invalid              ; 34h
657                 dw Invalid              ; 35h
658                 dw Invalid              ; 36h
659                 dw Invalid              ; 37h
660                 dw Invalid              ; 38h
661                 dw Invalid              ; 39h
662                 dw Invalid              ; 3Ah
663                 dw Invalid              ; 3Bh
664                 dw Invalid              ; 3Ch
665                 dw Invalid              ; 3Dh
666                 dw Invalid              ; 3Eh
667                 dw Invalid              ; 3Fh
668                 dw Invalid              ; 40h
669                 dw EDDPresence          ; 41h - EDD PRESENCE DETECT
670                 dw EDDRead              ; 42h - EDD READ
671                 dw EDDWrite             ; 43h - EDD WRITE
672                 dw EDDVerify            ; 44h - EDD VERIFY
673                 dw Invalid              ; 45h - EDD LOCK/UNLOCK MEDIA
674                 dw Invalid              ; 46h - EDD EJECT
675                 dw EDDSeek              ; 47h - EDD SEEK
676                 dw EDDGetParms          ; 48h - EDD GET PARAMETERS
677 %endif
678
679 Int13FuncsEnd   equ $
680 Int13FuncsMax   equ (Int13FuncsEnd-Int13Funcs) >> 1
681
682                 alignb 8, db 0
683 Shaker          dw ShakerEnd-$
684                 dd 0                    ; Pointer to self
685                 dw 0
686
687 Shaker_RMDS:    dd 0x0000ffff           ; 64K data segment
688                 dd 0x00009300
689
690 Shaker_DS:      dd 0x0000ffff           ; 4GB data segment
691                 dd 0x008f9300
692
693 ShakerEnd       equ $
694
695                 alignb 8, db 0
696
697
698 Mover           dd 0, 0, 0, 0           ; Must be zero
699                 dw 0ffffh               ; 64 K segment size
700 Mover_src1:     db 0, 0, 0              ; Low 24 bits of source addy
701                 db 93h                  ; Access rights
702                 db 00h                  ; Extended access rights
703 Mover_src2:     db 0                    ; High 8 bits of source addy
704                 dw 0ffffh               ; 64 K segment size
705 Mover_dst1:     db 0, 0, 0              ; Low 24 bits of target addy
706                 db 93h                  ; Access rights
707                 db 00h                  ; Extended access rights
708 Mover_dst2:     db 0                    ; High 8 bits of source addy
709 Mover_dummy2:   dd 0, 0, 0, 0           ; More space for the BIOS
710
711                 alignb 4, db 0
712 MemDisk_Info    equ $                   ; Pointed to by installation check
713 MDI_Bytes       dw 27                   ; Total bytes in MDI structure
714 MDI_Version     db VER_MINOR, VER_MAJOR ; MEMDISK version
715
716 PatchArea       equ $                   ; This gets filled in by the installer
717
718 DiskBuf         dd 0                    ; Linear address of high memory disk
719 DiskSize        dd 0                    ; Size of disk in blocks
720 CommandLine     dw 0, 0                 ; Far pointer to saved command line
721
722 OldInt13        dd 0                    ; INT 13h in chain
723 OldInt15        dd 0                    ; INT 15h in chain
724
725 OldDosMem       dw 0                    ; Old position of DOS mem end
726 BootLoaderID    db 0                    ; Boot loader ID from header
727 ; ---- MDI structure ends here ---
728                 db 0, 0, 0              ; pad
729
730 MemInt1588      dw 0                    ; 1MB-65MB memory amount (1K)
731
732 Cylinders       dw 0                    ; Cylinder count
733 Heads           dw 0                    ; Head count
734 Sectors         dd 0                    ; Sector count (zero-extended)
735
736 Mem1MB          dd 0                    ; 1MB-16MB memory amount (1K)
737 Mem16MB         dd 0                    ; 16MB-4G memory amount (64K)
738
739 DriveNo         db 0                    ; Our drive number
740 DriveType       db 0                    ; Our drive type (floppies)
741 DriveCnt        db 0                    ; Drive count (from the BIOS)
742
743 ConfigFlags     db 0                    ; Bit 0 - readonly
744
745 MyStack         dw 0                    ; Offset of stack
746 StatusPtr       dw 0                    ; Where to save status (zeroseg ptr)
747
748 DPT             times 16 db 0           ; BIOS parameter table pointer (floppies)
749
750                 ; End patch area
751
752 Stack           dd 0                    ; Saved SS:ESP on invocation
753                 dw 0
754 SavedAX         dw 0                    ; AX saved on invocation
755
756                 alignb 4, db 0          ; We *MUST* end on a dword boundary
757
758 E820Table       equ $                   ; The installer loads the E820 table here
759 TotalSize       equ $                   ; End pointer