source: bootcd/isolinux/syslinux-6.03/memdisk/memdisk.inc @ dd1be7c

Last change on this file since dd1be7c was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 25.9 KB
Line 
1; -*- fundamental -*- (asm-mode sucks)
2; ****************************************************************************
3;
4;  memdisk.inc
5;
6;  A program to emulate an INT 13h disk BIOS from a "disk" in extended
7;  memory.
8;
9;   Copyright 2001-2009 H. Peter Anvin - All Rights Reserved
10;   Copyright 2009 Intel Corporation; author: H. Peter Anvin
11;   Portions copyright 2009 Shao Miller [El Torito code, mBFT, safe hook]
12;
13;  This program is free software; you can redistribute it and/or modify
14;  it under the terms of the GNU General Public License as published by
15;  the Free Software Foundation, Inc., 53 Temple Place Ste 330,
16;  Boston MA 02111-1307, USA; either version 2 of the License, or
17;  (at your option) any later version; incorporated herein by reference.
18;
19; ****************************************************************************
20
21%include "../version.gen"
22
23; %define DEBUG_TRACERS                 ; Uncomment to get debugging tracers
24
25%ifdef DEBUG_TRACERS
26
27%macro TRACER   1
28        call debug_tracer
29        db %1
30%endmacro
31%macro WRITEHEX2 0-1 al
32%ifnidni %1,al
33        push ax
34        mov al,%1
35        call writehex2
36        pop ax
37%else
38        call writehex2
39%endif
40%endmacro
41%macro WRITEHEX4 0-1 ax
42%ifnidni %1,ax
43        push ax
44        mov ax,%1
45        call writehex4
46        pop ax
47%else
48        call writehex4
49%endif
50%endmacro
51%macro WRITEHEX8 0-1 eax
52%ifnidni %1,eax
53        push eax
54        mov eax,%1
55        call writehex8
56        pop eax
57%else
58        call writehex8
59%endif
60%endmacro
61
62%else   ; DEBUG_TRACERS
63
64%macro  TRACER  1
65%endmacro
66%macro WRITEHEX2 0-1
67%endmacro
68%macro WRITEHEX4 0-1
69%endmacro
70%macro WRITEHEX8 0-1
71%endmacro
72
73%endif  ; DEBUG_TRACERS
74
75; Flags we test our configuration against
76%define CONFIG_READONLY 0x01
77%define CONFIG_RAW      0x02
78%define CONFIG_SAFEINT  0x04
79%define CONFIG_BIGRAW   0x08            ; MUST be 8!
80
81                org 0h
82
83%define SECTORSIZE      (1 << SECTORSIZE_LG2)
84
85                ; Parameter registers definition; this is the definition
86                ; of the stack frame.
87%define         P_DS            word [bp+34]
88%define         P_ES            word [bp+32]
89%define         P_EAX           dword [bp+28]
90%define         P_HAX           word [bp+30]
91%define         P_AX            word [bp+28]
92%define         P_AL            byte [bp+28]
93%define         P_AH            byte [bp+29]
94%define         P_ECX           dword [bp+24]
95%define         P_HCX           word [bp+26]
96%define         P_CX            word [bp+24]
97%define         P_CL            byte [bp+24]
98%define         P_CH            byte [bp+25]
99%define         P_EDX           dword [bp+20]
100%define         P_HDX           word [bp+22]
101%define         P_DX            word [bp+20]
102%define         P_DL            byte [bp+20]
103%define         P_DH            byte [bp+21]
104%define         P_EBX           dword [bp+16]
105%define         P_HBX           word [bp+18]
106%define         P_HBXL          byte [bp+18]
107%define         P_BX            word [bp+16]
108%define         P_BL            byte [bp+16]
109%define         P_BH            byte [bp+17]
110%define         P_EBP           dword [bp+8]
111%define         P_BP            word [bp+8]
112%define         P_ESI           dword [bp+4]
113%define         P_SI            word [bp+4]
114%define         P_EDI           dword [bp]
115%define         P_DI            word [bp]
116
117                section .text
118                ; These pointers are used by the installer and
119                ; must be first in the binary
120Pointers:       dw Int13Start
121                dw Int15Start
122                dw MemDisk_Info         ; Portions are patched by installer
123                dw TotalSize
124                dw IretPtr
125
126IretPtr         equ Int13Start.iret
127Int13Start:
128                jmp strict near .SafeHookEnd ; 3-byte jump
129                db '$INT13SF'           ; Signature for "safe hook"
130                db 'MEMDISK '           ; Vendor ID
131                dd 0                    ; SEG:OFF of previous INT 13h hook
132                                        ; Must be filled in by installer
133                dd 0                    ; "Safe hook" flags
134; ---- "Safe hook" structure ends here ---
135
136; This next field should be guaranteed at this position after the
137; "safe hook" structure.  This allows for a MEMDISK OS driver to
138; immediately find out the particular parameters using the mBFT
139; and MDI structures.  This binary will have the offset to the mBFT
140; in this field to begin with, so the installer knows where the mBFT
141; is.  This is akin to the "Pointers" section above.  The installer
142; will refill this field with the physical address of the mBFT for
143; future consumers, such as OS drivers.
144                dd mBFT                 ; Offset from hook to the mBFT
145
146.SafeHookEnd:
147                cmp word [cs:Recursive],0
148                jne recursive
149
150                ; Swap stack
151                mov [cs:Stack],esp
152                mov [cs:Stack+4],ss
153                mov [cs:SavedAX],ax
154                mov ax,cs
155                mov ss,ax
156                mov sp,[cs:MyStack]
157
158%if ELTORITO
159                cmp word [cs:SavedAX],4a00h     ; El Torito function?
160                jae our_drive                   ; We grab it
161%endif
162                ; See if DL points to our class of device (FD, HD)
163                push dx
164                push dx
165                xor dl,[cs:DriveNo]
166                pop dx
167                js .nomatch             ; If SF=0, we have a class match here
168                                        ; 0x00 the sign bit for FD
169                                        ; 0x80 the sign bit for HD
170                jz our_drive            ; If ZF=1, we have an exact match
171                cmp dl,[cs:DriveNo]
172                jb .nomatch             ; Drive < Our drive
173                cmp dl,[cs:DriveShiftLimit]
174                jae .nomatch            ; Drive > The maximum drive
175                                        ; number that we will shift for.
176                                        ; This leaves any higher-up BIOS
177                                        ; drives alone, such as an optical
178                                        ; disc drive 0xA0 or 0xE0
179                dec dl                  ; Drive > Our drive, adjust drive #
180.nomatch:
181                TRACER '!'
182                WRITEHEX2 dl
183                TRACER ','
184                mov ax,[cs:SavedAX]
185                WRITEHEX4
186                inc word [cs:Recursive]
187                pushf
188                call far [cs:OldInt13]
189                pushf
190                dec word [cs:Recursive]
191                push bp
192                mov bp,sp
193                cmp byte [cs:SavedAX+1],08h     ; Get drive params function?
194                je .norestoredl                 ; DL = number of drives
195                cmp byte [cs:SavedAX+1],15h     ; Get disk type function?
196                jne .restoredl
197                test byte [bp+4],80h            ; Hard disk?
198                jnz .norestoredl                ; CX:DX = size of device
199.restoredl:
200                mov dl,[bp+4]
201.norestoredl:
202                push ax
203                push ebx
204                push ds
205                mov ax,[bp+2]           ; Flags
206                lds ebx,[cs:Stack]
207                mov [bx+4],al           ; Arithmetic flags
208                pop ds
209                pop ebx
210                pop ax
211                pop bp
212                lss esp,[cs:Stack]
213.iret:          iret
214
215recursive:
216                TRACER '@'
217jmp_oldint13:
218                jmp far [cs:OldInt13]
219
220our_drive:
221                ; Set up standard entry frame
222                push ds
223                push es
224                mov ds,ax
225                mov es,ax
226                mov ax,[SavedAX]
227                pushad
228                mov bp,sp               ; Point BP to the entry stack frame
229                TRACER 'F'
230                WRITEHEX4
231                ; Note: AX == P_AX here
232                cmp ah,Int13FuncsCnt-1
233                ja Invalid_jump
234%if ELTORITO
235                mov al,[CD_PKT.type]    ; Check if we are in
236                cmp al,0                ; El Torito no emulation mode
237                ja .emulation           ; No.  We support the function
238                cmp ah,3fh              ; Yes.  We must not support functions
239                jbe Invalid_jump        ; 0 through 3Fh.  Check and decide
240.emulation:
241%endif
242                xor al,al               ; AL = 0 is standard entry condition
243                mov di,ax
244                shr di,7                ; Convert AH to an offset in DI
245                call [Int13Funcs+di]
246
247Done:           ; Standard routine for return
248                mov P_AX,ax
249DoneWeird:
250                TRACER 'D'
251                xor bx,bx
252                mov es,bx
253                mov bx,[StatusPtr]
254                mov [es:bx],ah          ; Save status
255                and ah,ah
256
257                lds ebx,[Stack]
258                ; This sets the low byte (the arithmetic flags) of the
259                ; FLAGS on stack to either 00h (no flags) or 01h (CF)
260                ; depending on if AH was zero or not.
261                setnz [bx+4]            ; Set CF iff error
262                popad
263                pop es
264                pop ds
265                lss esp,[cs:Stack]
266                iret
267
268Reset:
269                ; Reset affects multiple drives, so we need to pass it on
270                TRACER 'R'
271                xor ax,ax               ; Bottom of memory
272                mov es,ax
273                test dl,dl              ; Always pass it on if we are
274                                        ; resetting HD
275                js .hard_disk           ; Bit 7 set
276                ; Some BIOSes get very unhappy if we pass a reset floppy
277                ; command to them and don't actually have any floppies.
278                ; This is a bug, but we have to deal with it nontheless.
279                ; Therefore, if we are the *ONLY* floppy drive, and the
280                ; user didn't request HD reset, then just drop the command.
281                ; BIOS equipment byte, top two bits + 1 == total # of floppies
282                test byte [es:0x410],0C0h
283                jz success
284                jmp .pass_on            ; ... otherwise pass it to the BIOS
285.hard_disk:
286                ; ... same thing for hard disks, sigh ...
287                cmp byte [es:0x475],1   ; BIOS variable for number of hard
288                                        ; disks
289                jbe success
290
291.pass_on:
292                pop ax                  ; Drop return address
293                popad                   ; Restore all registers
294                pop es
295                pop ds
296                lss esp,[cs:Stack]      ; Restore the stack
297                and dl,80h              ; Clear all but the type bit
298                jmp jmp_oldint13
299
300
301Invalid:
302                pop dx                  ; Drop return address
303Invalid_jump:
304                TRACER 'I'
305                mov ah,01h              ; Unsupported function
306                jmp short Done
307
308GetDriveType:
309                test byte [DriveNo],80h
310                mov bl,02h              ; Type 02h = floppy with changeline
311                jz .floppy
312                ; Hard disks only!  DO NOT set CX:DX for floppies...
313                ; it apparently causes Win98SE DOS to go into an loop
314                ; resetting the drive over and over.  Sigh.
315                inc bx                  ; Type = 03h
316                mov dx,[DiskSize]       ; Return the disk size in sectors
317                mov P_DX,dx
318                mov cx,[DiskSize+2]
319                mov P_CX,cx
320.floppy:
321                mov P_AH,bl             ; 02h floppy, 03h hard disk
322                pop ax                  ; Drop return address
323                xor ax,ax               ; Success...
324                jmp DoneWeird           ; But don't stick it into P_AX
325
326GetStatus:
327                xor ax,ax
328                mov es,ax
329                mov bx,[StatusPtr]
330                mov ah,[bx]             ; Copy last status
331                ret
332
333ReadMult:
334                TRACER 'm'
335Read:
336                TRACER 'R'
337                call setup_regs
338do_copy:
339                TRACER '<'
340                call bcopy
341                TRACER '>'
342                movzx ax,P_AL           ; AH = 0, AL = transfer count
343                ret
344
345WriteMult:
346                TRACER 'M'
347Write:
348                TRACER 'W'
349                test byte [ConfigFlags],CONFIG_READONLY
350                jnz .readonly
351                call setup_regs
352                xchg esi,edi            ; Opposite direction of a Read!
353                jmp short do_copy
354.readonly:      mov ah,03h              ; Write protected medium
355                ret
356
357                ; Verify integrity; just bounds-check
358Seek:
359Verify:
360                call setup_regs         ; Returns error if appropriate
361                ; And fall through to success
362
363CheckIfReady:                           ; These are always-successful noop functions
364Recalibrate:
365InitWithParms:
366DetectChange:
367EDDDetectChange:
368EDDLock:
369SetMode:
370success:
371                xor ax,ax               ; Always successful
372                ret
373
374GetParms:
375                TRACER 'G'
376                mov dl,[DriveCnt]       ; Cached data
377                mov P_DL,dl
378                test byte [DriveNo],80h
379                jnz .hd
380                mov P_DI,DPT
381                mov P_ES,cs
382                mov bl,[DriveType]
383                mov P_BL,bl
384.hd:
385                mov ax,[Cylinders]
386                dec ax                  ; We report the highest #, not the count
387                xchg al,ah
388                shl al,6
389                or al,[Sectors]
390                mov P_CX,ax
391                mov ax,[Heads]
392                dec ax
393                mov P_DH,al
394
395                ;
396                ; Is this MEMDISK installation check?
397                ;
398                cmp P_HAX,'ME'
399                jne .notic
400                cmp P_HCX,'MD'
401                jne .notic
402                cmp P_HDX,'IS'
403                jne .notic
404                cmp P_HBX,'K?'
405                jne .notic
406
407                ; MEMDISK installation check...
408                mov P_HAX,'!M'
409                mov P_HCX,'EM'
410                mov P_HDX,'DI'
411                mov P_HBX,'SK'
412                mov P_ES,cs
413                mov P_DI,MemDisk_Info
414
415.notic:
416                xor ax,ax
417                ret
418;
419; EDD functions -- only if enabled
420;
421%if EDD
422EDDPresence:
423                TRACER 'E'
424                TRACER 'c'
425
426                cmp P_BX,55AAh
427                jne Invalid
428                mov P_BX,0AA55h         ; EDD signature
429                mov P_AX,03000h         ; EDD 3.0
430                mov P_CX,0007h          ; Bit 0 - Fixed disk access subset
431                                        ; Bit 1 - Locking and ejecting subset
432                                        ; Bit 2 - EDD subset
433                pop ax                  ; Drop return address
434                xor ax,ax               ; Success
435                jmp DoneWeird           ; Success, but AH != 0, sigh...
436
437EDDRead:
438                TRACER 'E'
439                TRACER 'r'
440
441                call edd_setup_regs
442                call bcopy
443                xor ax,ax
444                ret
445
446EDDWrite:
447                TRACER 'E'
448                TRACER 'w'
449
450                call edd_setup_regs
451                xchg esi,edi            ; Opposite direction of a Read!
452                call bcopy
453                xor ax,ax
454                ret
455
456EDDVerify:
457EDDSeek:
458                call edd_setup_regs     ; Just bounds checking
459                xor ax,ax
460                ret
461
462EDDGetParms:
463                TRACER 'E'
464                TRACER 'p'
465
466                mov es,P_DS
467                mov di,P_SI
468                mov si,EDD_DPT
469
470                lodsw                   ; Length of our DPT
471                mov cx,[es:di]
472                cmp cx,26               ; Minimum size
473                jb .overrun
474
475                cmp cx,ax
476                jb .oksize
477                mov cx,ax
478
479.oksize:
480                mov ax,cx
481                stosw
482                dec cx
483                dec cx
484                rep movsb
485
486                xor ax,ax
487                ret
488
489.overrun:
490                mov ax,0100h
491                ret
492%endif ; EDD
493
494                ; Set up registers as for a "Read", and compares against disk
495                ; size.
496                ; WARNING: This fails immediately, even if we can transfer some
497                ; sectors.  This isn't really the correct behaviour.
498setup_regs:
499
500                ; Convert a CHS address in P_CX/P_DH into an LBA in eax
501                ; CH = cyl[7:0]
502                ; CL[0:5] = sector (1-based)  CL[7:6] = cyl[9:8]
503                ; DH = head
504                movzx ecx,P_CX
505                movzx ebx,cl            ; Sector number
506                and bl,3Fh
507                dec ebx                 ; Sector number is 1-based
508                cmp bx,[Sectors]
509                jae .overrun
510                movzx edi,P_DH          ; Head number
511                movzx eax,word [Heads]
512                cmp di,ax
513                jae .overrun
514                shr cl,6
515                xchg cl,ch              ; Now (E)CX <- cylinder number
516                mul ecx                 ; eax <- Heads*cyl# (edx <- 0)
517                add eax,edi
518                mul dword [Sectors]
519                add eax,ebx
520                ; Now eax = LBA, edx = 0
521
522                ;
523                ; setup_regs continues...
524                ;
525                ; Note: edi[31:16] and ecx[31:16] = 0 already
526                mov di,P_BX             ; Get linear address of target buffer
527                mov cx,P_ES
528                shl ecx,4
529                add edi,ecx             ; EDI = address to fetch to
530                movzx ecx,P_AL          ; Sector count
531                mov esi,eax
532                add eax,ecx             ; LBA of final sector + 1
533                shl esi,SECTORSIZE_LG2  ; LBA -> byte offset
534                add esi,[DiskBuf]       ; Get address in high memory
535                cmp eax,[DiskSize]      ; Check the high mark against limit
536                ja .overrun
537                shl ecx,SECTORSIZE_LG2-2 ; Convert count to dwords
538                ret
539
540.overrun:       pop ax                  ; Drop setup_regs return address
541                mov ax,0200h            ; Missing address mark
542                ret                     ; Return to Done
543
544                ; Set up registers as for an EDD Read, and compares against disk size.
545%if EDD
546edd_setup_regs:
547                push es
548                mov si,P_SI             ; DS:SI -> DAPA
549                mov es,P_DS
550
551                mov dx,[es:si]
552                cmp dx,16
553                jb .baddapa
554
555                cmp dword [es:si+4],-1
556                je .linear_address
557
558                movzx ebx,word [es:si+4]        ; Offset
559                movzx edi,word [es:si+6]        ; Segment
560                shl edi,4
561                add ebx,edi
562                jmp .got_address
563
564.linear_address:
565                cmp dx,24               ; Must be large enough to hold
566                                        ; linear address
567                jb .baddapa
568
569                cmp dword [es:si+20],0  ; > 4 GB addresses not supported
570                mov ax,0900h            ; "Data boundary error" - bogus, but
571                                        ; no really better code available
572                jne .error
573
574                mov ebx,[es:si+16]
575
576.got_address:
577                cmp dword [es:si+12],0          ; LBA too large?
578                jne .overrun
579
580                movzx ecx, word [es:si+2]       ; Sectors to transfer
581                mov esi,[es:si+8]               ; Starting sector
582                mov eax,esi
583                add eax,ecx
584                jc .overrun
585                cmp eax,[DiskSize]
586                ja .overrun
587
588                shl ecx,SECTORSIZE_LG2-2        ; Convert to dwords
589                shl esi,SECTORSIZE_LG2          ; Convert to an offset
590                add esi,[DiskBuf]
591                mov edi,ebx
592                pop es
593                ret
594
595.baddapa:
596                mov ax,0100h            ; Invalid command
597                pop es
598                pop ax                  ; Drop setup_regs return address
599                ret
600
601.overrun:
602                mov ax,0200h            ; "Address mark not found" =
603                                        ; LBA beyond end of disk
604.error:
605                and word [es:si+2],0    ; No sectors transferred
606                pop es
607                pop ax
608                ret
609
610EDDEject:
611                mov ax,0B200h           ; Volume Not Removable
612                ret
613%if ELTORITO
614ElToritoTerminate:
615                TRACER 'T'
616                mov ax,[cs:SavedAX]
617                cmp al,1                ; We only support query, not terminate
618                jne ElToritoErr         ; Fail
619                cmp dl,7fh              ; Terminate all?
620                je .doit
621                cmp dl,[cs:DriveNo]     ; Terminate our drive?
622                je .doit
623                jmp ElToritoErr         ; Fail
624.doit:          mov es,P_DS             ; Caller's DS:SI pointed to packet
625                mov di,P_SI             ; We'll use ES:DI
626                mov si,CD_PKT.size      ; First byte is packet size
627                xor cx,0                ; Empty our count
628                ;mov cl,[ds:si]         ; We'll copy that many bytes
629                mov cl,13h
630                rep movsb               ; Copy until CX is zero
631                mov ax,0                ; Success
632                ret
633ElToritoEmulate:
634ElToritoBoot:
635ElToritoCatalog:
636ElToritoErr:
637                TRACER '!'
638                mov ax,100h             ; Invalid parameter
639                ret
640%endif ; ELTORITO
641%endif ; EDD
642
643;
644; INT 15h intercept routines
645;
646int15_e820:
647                cmp edx,534D4150h       ; "SMAP"
648                jne oldint15
649                cmp ecx,20              ; Need 20 bytes
650                jb err86
651                push ds
652                push cs
653                pop ds
654                push edx                ; "SMAP"
655                and ebx,ebx
656                jne .renew
657                mov ebx,E820Table
658.renew:
659                add bx,12               ; Advance to next
660                mov eax,[bx-4]          ; Type
661                and eax,eax             ; Null type?
662                jz .renew               ; If so advance to next
663                mov [es:di+16],eax
664                mov eax,[bx-12]         ; Start addr (low)
665                mov edx,[bx-8]          ; Start addr (high)
666                mov [es:di],eax
667                mov [es:di+4],edx
668                mov eax,[bx]            ; End addr (low)
669                mov edx,[bx+4]          ; End addr (high)
670                sub eax,[bx-12]         ; Derive the length
671                sbb edx,[bx-8]
672                mov [es:di+8],eax       ; Length (low)
673                mov [es:di+12],edx      ; Length (high)
674                cmp dword [bx+8],-1     ; Type of next = end?
675                jne .notdone
676                xor ebx,ebx             ; Done with table
677.notdone:
678                pop eax                 ; "SMAP"
679                mov edx,eax             ; Some systems expect eax = edx = SMAP
680                mov ecx,20              ; Bytes loaded
681                pop ds
682int15_success:
683                mov byte [bp+6], 02h    ; Clear CF
684                pop bp
685                iret
686
687err86:
688                mov byte [bp+6], 03h    ; Set CF
689                mov ah,86h
690                pop bp
691                iret
692
693Int15Start:
694                push bp
695                mov bp,sp
696                cmp ax,0E820h
697                je near int15_e820
698                cmp ax,0E801h
699                je int15_e801
700                cmp ax,0E881h
701                je int15_e881
702                cmp ah,88h
703                je int15_88
704oldint15:       pop bp
705                jmp far [cs:OldInt15]
706
707int15_e801:                             ; Get mem size for > 64 MB config
708                mov ax,[cs:Mem1MB]
709                mov cx,ax
710                mov bx,[cs:Mem16MB]
711                mov dx,bx
712                jmp short int15_success
713
714int15_e881:                             ; Get mem size for > 64 MB config
715                                        ; 32-bit code
716                mov eax,[cs:Mem1MB]
717                mov ecx,eax
718                mov ebx,[cs:Mem16MB]
719                mov edx,ebx
720                jmp short int15_success
721
722int15_88:                               ; Get extended mem size
723                mov ax,[cs:MemInt1588]
724                jmp short int15_success
725
726;
727; Routine to copy in/out of high memory
728; esi = linear source address
729; edi = linear target address
730; ecx = 32-bit word count
731;
732; Assumes cs = ds = es
733;
734bcopy:
735                push eax
736                push ebx
737                push edx
738                push ebp
739
740                mov bx, real_int15_stub
741
742                test byte [ConfigFlags], CONFIG_RAW|CONFIG_SAFEINT
743                jz .anymode             ; Always do the real INT 15h
744
745                smsw ax                 ; Unprivileged!
746                test al,01h
747                jnz .protmode           ; Protmode -> do real INT 15h
748
749.realmode:
750                ; Raw or Safeint mode, and we're in real mode...
751
752                test byte [ConfigFlags], CONFIG_SAFEINT
753                jnz .fakeint15
754
755.raw:
756                TRACER 'r'
757                ; We're in real mode, do it outselves
758
759                pushfd                  ; <A>
760                push ds                 ; <B>
761                push es                 ; <C>
762
763                cli
764                cld
765
766                xor ebx,ebx
767                mov bx,cs
768                shl ebx,4
769                lea edx,[Shaker+ebx]
770                mov [Shaker+2],edx
771
772                ; Test to see if A20 is enabled or not
773                xor ax,ax
774                mov ds,ax
775                dec ax
776                mov es,ax
777
778                mov ax,[0]
779                mov bx,ax
780                xor bx,[es:10h]
781                not ax
782                mov [0],ax
783                mov dx,ax
784                xor dx,[es:10h]
785                not ax
786                mov [0],ax
787
788                or dx,bx
789                push dx                 ; <D> Save A20 status
790                jnz .skip_a20e
791
792                mov ax,2401h            ; Enable A20
793                int 15h
794.skip_a20e:
795                mov dl,[ConfigFlags]
796                and dx,CONFIG_BIGRAW
797                add dx,8
798                ; DX = 16 for BIGRAW, 8 for RAW
799                ;  8 is selector for a 64K flat segment,
800                ; 16 is selector for a 4GB flat segment.
801
802                lgdt [cs:Shaker]
803                mov eax,cr0
804                or al,01h
805                mov cr0,eax
806
807                mov bx,16               ; Large flat segment
808                mov ds,bx
809                mov es,bx
810
811                a32 rep movsd
812
813                ; DX has the appropriate value to put in
814                ; the registers on return
815                mov ds,dx
816                mov es,dx
817
818                and al,~01h
819                mov cr0,eax
820
821                pop dx                  ; <D> A20 status
822                pop es                  ; <C>
823                pop ds                  ; <B>
824
825                and dx,dx
826                jnz .skip_a20d
827                mov ax,2400h            ; Disable A20
828                int 15h
829.skip_a20d:
830                popfd                   ; <A>
831                jmp .done
832
833.fakeint15:
834                ; We're in real mode with CONFIG_SAFEINT, invoke the
835                ; original INT 15h vector.  We used to test for the
836                ; INT 15h vector being unchanged here, but that is
837                ; *us*; however, the test was wrong for years (always
838                ; negative) so instead of fixing the test do what we
839                ; tested and don't bother probing.
840                mov bx, fake_int15_stub
841
842.protmode:
843                TRACER 'p'
844.anymode:
845
846.copy_loop:
847                push esi
848                push edi
849                push ecx
850                cmp ecx,4000h
851                jna .safe_size
852                mov ecx,4000h
853.safe_size:
854                push ecx        ; Transfer size this cycle
855                mov eax, esi
856                mov [Mover_src1], si
857                shr eax, 16
858                mov [Mover_src1+2], al
859                mov [Mover_src2], ah
860                mov eax, edi
861                mov [Mover_dst1], di
862                shr eax, 16
863                mov [Mover_dst1+2], al
864                mov [Mover_dst2], ah
865                mov si,Mover
866                mov ah, 87h
867                shl cx,1        ; Convert to 16-bit words
868                call bx         ; INT 15h stub
869                pop eax         ; Transfer size this cycle
870                pop ecx
871                pop edi
872                pop esi
873                jc .error
874                lea esi,[esi+4*eax]
875                lea edi,[edi+4*eax]
876                sub ecx, eax
877                jnz .copy_loop
878                ; CF = 0
879.error:
880.done:
881                pop ebp
882                pop edx
883                pop ebx
884                pop eax
885                ret
886
887real_int15_stub:
888                int 15h
889                cli             ; Some BIOSes enable interrupts on INT 15h
890                ret
891
892fake_int15_stub:
893                pushf
894                call far [OldInt15]
895                cli
896                ret
897
898%ifdef DEBUG_TRACERS
899debug_tracer:   pushad
900                pushfd
901                mov bp,sp
902                mov bx,[bp+9*4]
903                mov al,[cs:bx]
904                inc word [bp+9*4]
905                mov ah,0Eh
906                mov bx,7
907                int 10h
908                popfd
909                popad
910                ret
911
912writehex2:      pushad
913                pushfd
914                mov cx,2
915                ror eax,4
916                jmp writehex_common
917writehex4:      pushad
918                pushfd
919                mov cx,4
920                ror eax,12
921                jmp writehex_common
922writehex8:      pushad
923                pushfd
924                mov cx,8
925                ror eax,28
926writehex_common:
927.loop:          push cx
928                push eax
929                and al,0Fh
930                cmp al,10
931                jb .isdec
932                add al,'a'-'0'-10
933.isdec:         add al,'0'
934                mov ah,0Eh
935                mov bx,7
936                int 10h
937                pop eax
938                rol eax,4
939                pop cx
940                loop .loop
941                popfd
942                popad
943                ret
944%endif
945
946                section .data align=16
947                alignb 2
948Int13Funcs      dw Reset                ; 00h - RESET
949                dw GetStatus            ; 01h - GET STATUS
950                dw Read                 ; 02h - READ
951                dw Write                ; 03h - WRITE
952                dw Verify               ; 04h - VERIFY
953                dw Invalid              ; 05h - FORMAT TRACK
954                dw Invalid              ; 06h - FORMAT TRACK AND SET BAD FLAGS
955                dw Invalid              ; 07h - FORMAT DRIVE AT TRACK
956                dw GetParms             ; 08h - GET PARAMETERS
957                dw InitWithParms        ; 09h - INITIALIZE CONTROLLER WITH
958                                        ;       DRIVE PARAMETERS
959                dw Invalid              ; 0Ah
960                dw Invalid              ; 0Bh
961                dw Seek                 ; 0Ch - SEEK TO CYLINDER
962                dw Reset                ; 0Dh - RESET HARD DISKS
963                dw Invalid              ; 0Eh
964                dw Invalid              ; 0Fh
965                dw CheckIfReady         ; 10h - CHECK IF READY
966                dw Recalibrate          ; 11h - RECALIBRATE
967                dw Invalid              ; 12h
968                dw Invalid              ; 13h
969                dw Invalid              ; 14h
970                dw GetDriveType         ; 15h - GET DRIVE TYPE
971                dw DetectChange         ; 16h - DETECT DRIVE CHANGE
972%if EDD
973                dw Invalid              ; 17h
974                dw Invalid              ; 18h
975                dw Invalid              ; 19h
976                dw Invalid              ; 1Ah
977                dw Invalid              ; 1Bh
978                dw Invalid              ; 1Ch
979                dw Invalid              ; 1Dh
980                dw Invalid              ; 1Eh
981                dw Invalid              ; 1Fh
982                dw Invalid              ; 20h
983                dw ReadMult             ; 21h - READ MULTIPLE
984                dw WriteMult            ; 22h - WRITE MULTIPLE
985                dw SetMode              ; 23h - SET CONTROLLER FEATURES
986                dw SetMode              ; 24h - SET MULTIPLE MODE
987                dw Invalid              ; 25h - IDENTIFY DRIVE
988                dw Invalid              ; 26h
989                dw Invalid              ; 27h
990                dw Invalid              ; 28h
991                dw Invalid              ; 29h
992                dw Invalid              ; 2Ah
993                dw Invalid              ; 2Bh
994                dw Invalid              ; 2Ch
995                dw Invalid              ; 2Dh
996                dw Invalid              ; 2Eh
997                dw Invalid              ; 2Fh
998                dw Invalid              ; 30h
999                dw Invalid              ; 31h
1000                dw Invalid              ; 32h
1001                dw Invalid              ; 33h
1002                dw Invalid              ; 34h
1003                dw Invalid              ; 35h
1004                dw Invalid              ; 36h
1005                dw Invalid              ; 37h
1006                dw Invalid              ; 38h
1007                dw Invalid              ; 39h
1008                dw Invalid              ; 3Ah
1009                dw Invalid              ; 3Bh
1010                dw Invalid              ; 3Ch
1011                dw Invalid              ; 3Dh
1012                dw Invalid              ; 3Eh
1013                dw Invalid              ; 3Fh
1014                dw Invalid              ; 40h
1015                dw EDDPresence          ; 41h - EDD PRESENCE DETECT
1016                dw EDDRead              ; 42h - EDD READ
1017                dw EDDWrite             ; 43h - EDD WRITE
1018                dw EDDVerify            ; 44h - EDD VERIFY
1019                dw EDDLock              ; 45h - EDD LOCK/UNLOCK MEDIA
1020                dw EDDEject             ; 46h - EDD EJECT
1021                dw EDDSeek              ; 47h - EDD SEEK
1022                dw EDDGetParms          ; 48h - EDD GET PARAMETERS
1023                dw EDDDetectChange      ; 49h - EDD MEDIA CHANGE STATUS
1024%if ELTORITO                            ; EDD El Torito Functions
1025                                        ; ELTORITO _must_ also have EDD
1026                dw ElToritoEmulate      ; 4Ah - Initiate Disk Emulation
1027                dw ElToritoTerminate    ; 4Bh - Terminate Disk Emulation
1028                dw ElToritoBoot         ; 4Ch - Initiate Disk Emu. and Reboot
1029                dw ElToritoCatalog      ; 4Dh - Return Boot Catalog
1030%endif ; ELTORITO
1031%endif ; EDD
1032
1033Int13FuncsEnd   equ $
1034Int13FuncsCnt   equ (Int13FuncsEnd-Int13Funcs) >> 1
1035
1036
1037                alignb 8, db 0
1038Shaker          dw ShakerEnd-$-1        ; Descriptor table limit
1039                dd 0                    ; Pointer to self
1040                dw 0
1041
1042Shaker_RMDS:    dd 0x0000ffff           ; 64K data segment
1043                dd 0x00009300
1044
1045Shaker_DS:      dd 0x0000ffff           ; 4GB data segment
1046                dd 0x008f9300
1047
1048ShakerEnd       equ $
1049
1050                alignb 8, db 0
1051
1052Mover           dd 0, 0, 0, 0           ; Must be zero
1053                dw 0ffffh               ; 64 K segment size
1054Mover_src1:     db 0, 0, 0              ; Low 24 bits of source addy
1055                db 93h                  ; Access rights
1056                db 00h                  ; Extended access rights
1057Mover_src2:     db 0                    ; High 8 bits of source addy
1058                dw 0ffffh               ; 64 K segment size
1059Mover_dst1:     db 0, 0, 0              ; Low 24 bits of target addy
1060                db 93h                  ; Access rights
1061                db 00h                  ; Extended access rights
1062Mover_dst2:     db 0                    ; High 8 bits of source addy
1063Mover_dummy2:   dd 0, 0, 0, 0           ; More space for the BIOS
1064
1065                alignb 16, db 0
1066mBFT:
1067; Fields common to all ACPI tables
1068                dd '    '               ; ACPI signature ("mBFT")
1069                                        ; This is filled-in by the installer
1070                                        ; to avoid an accidentally valid mBFT
1071                dd mBFT_Len             ; ACPI table length
1072                db 1                    ; ACPI revision
1073                db 0                    ; ACPI table checksum
1074                db 'MEMDSK'             ; ACPI OEM ID
1075                db 'Syslinux'           ; ACPI OEM table ID
1076                dd 0                    ; ACPI OEM revision
1077                dd 0                    ; ACPI ASL compiler vendor ID
1078                dd 0                    ; ACPI ASL compiler revision
1079; The next field is mBFT-specific and filled-in by the installer
1080                dd 0                    ; "Safe hook" physical address
1081
1082; Note that the above ends on a DWORD boundary.
1083; The MDI has always started at such a boundary.
1084; Portions of the MDI are patched by the installer
1085MemDisk_Info    equ $                   ; Pointed to by installation check
1086MDI_Bytes       dw MDI_Len              ; Total bytes in MDI structure
1087MDI_Version     db VERSION_MINOR, VERSION_MAJOR ; MEMDISK version
1088
1089DiskBuf         dd 0                    ; Linear address of high memory disk
1090DiskSize        dd 0                    ; Size of disk in blocks
1091CommandLine     dw 0, 0                 ; Far pointer to saved command line
1092
1093OldInt13        dd 0                    ; INT 13h in chain
1094OldInt15        dd 0                    ; INT 15h in chain
1095
1096OldDosMem       dw 0                    ; Old position of DOS mem end
1097BootLoaderID    db 0                    ; Boot loader ID from header
1098                db 0                    ; pad
1099
1100DPT_ptr         dw 0                    ; If nonzero, pointer to DPT
1101                                        ; Original DPT pointer follows
1102
1103MDI_Len         equ $-MemDisk_Info
1104mBFT_Len        equ $-mBFT              ; mBFT includes the MDI
1105
1106; ---- MDI structure ends here ---
1107DriveShiftLimit db 0ffh                 ; Installer will probe for
1108                                        ; a range of contiguous drives.
1109                                        ; Any BIOS drives above this region
1110                                        ; shall not be impacted by our
1111                                        ; shifting behaviour
1112                db 0                    ; pad to a DWORD
1113                dw 0                    ; pad to a QWORD
1114MemInt1588      dw 0                    ; 1MB-65MB memory amount (1K)
1115
1116Cylinders       dw 0                    ; Cylinder count
1117Heads           dw 0                    ; Head count
1118Sectors         dd 0                    ; Sector count (zero-extended)
1119
1120Mem1MB          dd 0                    ; 1MB-16MB memory amount (1K)
1121Mem16MB         dd 0                    ; 16MB-4G memory amount (64K)
1122
1123DriveNo         db 0                    ; Our drive number
1124DriveType       db 0                    ; Our drive type (floppies)
1125DriveCnt        db 0                    ; Drive count (from the BIOS)
1126
1127ConfigFlags     db 0                    ; Bit 0 - readonly
1128
1129MyStack         dw 0                    ; Offset of stack
1130StatusPtr       dw 0                    ; Where to save status (zeroseg ptr)
1131
1132DPT             times 16 db 0           ; BIOS parameter table pointer (floppies)
1133OldInt1E        dd 0                    ; Previous INT 1E pointer (DPT)
1134
1135%if EDD
1136EDD_DPT:
1137.length         dw 30
1138.info           dw 0029h
1139                ; Bit 0 - DMA boundaries handled transparently
1140                ; Bit 3 - Device supports write verify
1141                ; Bit 5 - Media is lockable
1142.cylinders      dd 0                    ; Filled in by installer
1143.heads          dd 0                    ; Filled in by installer
1144.sectors        dd 0                    ; Filled in by installer
1145.totalsize      dd 0, 0                 ; Filled in by installer
1146.bytespersec    dw SECTORSIZE
1147.eddtable       dw -1, -1               ; Invalid DPTE pointer
1148.dpikey         dw 0BEDDh               ; Device Path Info magic
1149.dpilen         db 2ch                  ; DPI len
1150.res1           db 0                    ; Reserved
1151.res2           dw 0                    ; Reserved
1152.bustype        dd 'MEM '               ; Host bus type (4 bytes, space padded)
1153.inttype        dd 'MEMORY  '           ; Interface type (8 bytes, spc. padded)
1154.intpath        dd 0, 0                 ; Interface path
1155.devpath        dd 0, 0, 0, 0           ; Device path
1156.res3           db 0                    ; Reserved
1157.chksum         db 0                    ; DPI checksum
1158
1159%if ELTORITO
1160; El Torito CD Specification Packet - mostly filled in by installer
1161CD_PKT:
1162.size           db 13h  ; Packet size (19 bytes)
1163.type           db 0    ; Boot media type (flags)
1164.driveno        db 0E0h ; INT 13h drive number
1165.controller     db 0    ; Controller index
1166.start          dd 0    ; Starting LBA of image
1167.devno          dw 0    ; Device number
1168.user_buf       dw 0    ; User buffer segment
1169.load_seg       dw 0    ; Load segment
1170.sect_count     dw 0    ; Emulated sectors to load
1171.geom1          db 0    ; Cylinders bits 0 thru 7
1172.geom2          db 0    ; Sects/track 0 thru 5, cyls 8, 9
1173.geom3          db 0    ; Heads
1174%endif ; ELTORITO
1175
1176%endif ; EDD
1177
1178; End patch area
1179
1180                alignb 4, db 0
1181Stack           dd 0                    ; Saved SS:ESP on invocation
1182                dw 0
1183SavedAX         dw 0                    ; AX saved on invocation
1184Recursive       dw 0                    ; Recursion counter
1185
1186                alignb 4, db 0          ; We *MUST* end on a dword boundary
1187
1188E820Table       equ $                   ; The installer loads the E820 table here
1189TotalSize       equ $                   ; End pointer
Note: See TracBrowser for help on using the repository browser.