⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memdisk.asm

📁 linux内核
💻 ASM
📖 第 1 页 / 共 2 页
字号:
; -*- fundamental -*- (asm-mode sucks); $Id$; ****************************************************************************;;  memdisk.asm;;  A program to emulate an INT 13h disk BIOS from a "disk" in extended;  memory.;;   Copyright (C) 2001-2005  H. Peter Anvin;;  This program is free software; you can redistribute it and/or modify;  it under the terms of the GNU General Public License as published by;  the Free Software Foundation, Inc., 53 Temple Place Ste 330,;  Boston MA 02111-1307, USA; either version 2 of the License, or;  (at your option) any later version; incorporated herein by reference.; ; ****************************************************************************%ifndef DEPEND%include	"../version.gen"%endif; %define DEBUG_TRACERS			; Uncomment to get debugging tracers%ifdef WITH_EDD%define EDD 1%else%define EDD 0%endif%ifdef DEBUG_TRACERS%macro TRACER	1	call debug_tracer	db %1%endmacro%else	; DEBUG_TRACERS%macro	TRACER	1%endmacro%endif	; DEBUG_TRACERS%define CONFIG_READONLY	0x01%define CONFIG_RAW	0x02%define CONFIG_BIGRAW	0x08		; MUST be 8!		org 0h%define SECTORSIZE_LG2	9		; log2(sector size)%define	SECTORSIZE	(1 << SECTORSIZE_LG2)		; Parameter registers definition; this is the definition		; of the stack frame.%define		P_DS		word [bp+34]%define		P_ES		word [bp+32]%define		P_EAX		dword [bp+28]%define		P_HAX		word [bp+30]%define		P_AX		word [bp+28]%define		P_AL		byte [bp+28]%define		P_AH		byte [bp+29]%define		P_ECX		dword [bp+24]%define		P_HCX		word [bp+26]%define		P_CX		word [bp+24]%define		P_CL		byte [bp+24]%define		P_CH		byte [bp+25]%define		P_EDX		dword [bp+20]%define		P_HDX		word [bp+22]%define		P_DX		word [bp+20]%define		P_DL		byte [bp+20]%define		P_DH		byte [bp+21]%define		P_EBX		dword [bp+16]%define		P_HBX		word [bp+18]%define		P_HBXL		byte [bp+18]%define		P_BX		word [bp+16]%define		P_BL		byte [bp+16]%define		P_BH		byte [bp+17]%define		P_EBP		dword [bp+8]%define		P_BP		word [bp+8]%define		P_ESI		dword [bp+4]%define		P_SI		word [bp+4]%define		P_EDI		dword [bp]%define		P_DI		word [bp]		section .text		; These pointers are used by the installer and		; must be first in the binaryPointers:	dw Int13Start		dw Int15Start		dw PatchArea		dw TotalSizeInt13Start:		; Swap stack		mov [cs:Stack],esp		mov [cs:SavedAX],ax		mov ax,ss		mov [cs:Stack+4],ax		mov ax,cs		mov ss,ax		mov sp,[cs:MyStack]		; See if DL points to our class of device (FD, HD)		push dx		push dx		xor dl,[cs:DriveNo]		pop dx		js .nomatch		; If SF=0, we have a class match here		jz .our_drive		; If ZF=1, we have an exact match		cmp dl,[cs:DriveNo]		jb .nomatch		; Drive < Our drive		dec dl			; Drive > Our drive, adjust drive #.nomatch:		mov ax,[cs:SavedAX]		pushf		call far [cs:OldInt13]		pushf		push bp		mov bp,sp		cmp byte [cs:SavedAX+1],08h		je .norestoredl		cmp byte [cs:SavedAX+1],15h		jne .restoredl		test byte [bp+4],80h	; Hard disk?		jnz .norestoredl.restoredl:		mov dl,[bp+4].norestoredl:		push ax		push ebx		push ds		mov ax,[bp+2]		; Flags		lds ebx,[cs:Stack]		mov [bx+4],al		; Arithmetric flags		pop ds		pop ebx		pop ax		pop bp		lss esp,[cs:Stack]		iret.our_drive:		; Set up standard entry frame		push ds		push es		mov ds,ax		mov es,ax		mov ax,[SavedAX]		pushad		mov bp,sp		; Point BP to the entry stack frame		TRACER 'F'		; Note: AH == P_AH here		cmp ah,Int13FuncsMax		jae Invalid_jump		xor al,al		; AL = 0 is standard entry condition		mov di,ax		shr di,7		; Convert AH to an offset in DI		call [Int13Funcs+di]Done:		; Standard routine for return		mov P_AX,axDoneWeird:		TRACER 'D'		xor bx,bx		mov es,bx		mov bx,[StatusPtr]		mov [es:bx],ah		; Save status		and ah,ah		lds ebx,[Stack]		; This sets the low byte (the arithmetric flags) of the		; FLAGS on stack to either 00h (no flags) or 01h (CF)		; depending on if AH was zero or not.		setnz [bx+4]		; Set CF iff error		popad		pop es		pop ds		lss esp,[cs:Stack]		iretReset:		; Reset affects multiple drives, so we need to pass it on		TRACER 'R'		xor ax,ax		; Bottom of memory		mov es,ax		test dl,dl		; Always pass it on if we are resetting HD		js .hard_disk		; Bit 7 set		; Some BIOSes get very unhappy if we pass a reset floppy		; command to them and don't actually have any floppies.		; This is a bug, but we have to deal with it nontheless.		; Therefore, if we are the *ONLY* floppy drive, and the		; user didn't request HD reset, then just drop the command.		; BIOS equipment byte, top two bits + 1 == total # of floppies		test byte [es:0x410],0C0h		jz success		jmp .pass_on		; ... otherwise pass it to the BIOS.hard_disk:		; ... same thing for hard disks, sigh ...		cmp byte [es:0x475],1	; BIOS variable for number of hard disks		jbe success.pass_on:		pop ax			; Drop return address		popad			; Restore all registers		pop es		pop ds		lss esp,[cs:Stack]	; Restore the stack		and dl,80h		; Clear all but the type bit		jmp far [cs:OldInt13]Invalid:		pop dx			; Drop return addressInvalid_jump:		TRACER 'I'		mov ah,01h		; Unsupported function		jmp short DoneGetDriveType:		test byte [DriveNo],80h		mov bl,02h		; Type 02h = floppy with changeline		jz .floppy		; Hard disks only...		inc bx			; Type = 03h		mov dx,[DiskSize]	; Return the disk size in sectors		mov P_DX,dx		mov cx,[DiskSize+2]		mov P_CX,cx.floppy:		mov P_AH,bl		; 02h floppy, 03h hard disk		pop ax			; Drop return address		xor ax,ax		; Success...		jmp DoneWeird		; But don't stick it into P_AXGetStatus:		xor ax,ax		mov es,ax		mov bx,[StatusPtr]		mov ah,[bx]		; Copy last status		retReadMult:		TRACER 'm'Read:		TRACER 'R'		call setup_regsdo_copy:		TRACER '<'		call bcopy		TRACER '>'		movzx ax,P_AL		; AH = 0, AL = transfer count		retWriteMult:		TRACER 'M'Write:		TRACER 'W'		test byte [ConfigFlags],CONFIG_READONLY		jnz .readonly		call setup_regs		xchg esi,edi		; Opposite direction of a Read!		jmp short do_copy.readonly:	mov ah,03h		; Write protected medium		ret		; Verify integrity; just bounds-checkSeek:Verify:		call setup_regs		; Returns error if appropriate		; And fall through to successCheckIfReady:				; These are always-successful noop functionsRecalibrate:InitWithParms:DetectChange:SetMode:success:		xor ax,ax		; Always successful		retGetParms:		TRACER 'G'		mov dl,[DriveCnt]	; Cached data		mov P_DL,dl		test byte [DriveNo],80h		jnz .hd		mov P_DI,DPT		mov P_ES,cs		mov bl,[DriveType]		mov P_BL,bl.hd:		mov ax,[Cylinders]		dec ax			; We report the highest #, not the count		xchg al,ah		shl al,6		or al,[Sectors]		mov P_CX,ax		mov ax,[Heads]		dec ax		mov P_DH,al		;		; Is this MEMDISK installation check?		;		cmp P_HAX,'ME'		jne .notic		cmp P_HCX,'MD'		jne .notic		cmp P_HDX,'IS'		jne .notic		cmp P_HBX,'K?'		jne .notic		; MEMDISK installation check...		mov P_HAX,'!M'		mov P_HCX,'EM'		mov P_HDX,'DI'		mov P_HBX,'SK'		mov P_ES,cs		mov P_DI,MemDisk_Info.notic:		xor ax,ax		ret;; EDD functions -- only if enabled;%if EDDEDDPresence:		TRACER 'E'		TRACER 'c'		cmp P_BX,55AAh		jne Invalid		mov P_BX,0AA55h		; EDD signature		mov P_AX,02100h		; EDD 1.1		mov P_CX,0001h		; Fixed disk access subset		pop ax			; Drop return address		xor ax,ax		; Success		jmp DoneWeird		; Success, but AH != 0, sigh...EDDRead:		TRACER 'E'		TRACER 'r'		call edd_setup_regs		call bcopy		xor ax,ax		retEDDWrite:		TRACER 'E'		TRACER 'w'		call edd_setup_regs		xchg esi,edi		call bcopy		xor ax,ax		retEDDVerify:EDDSeek:		call edd_setup_regs	; Just bounds checking		xor ax,ax		retEDDGetParms:		TRACER 'E'		TRACER 'p'		mov es,P_DS		mov di,P_SI		mov cx,30		; Length of our DPT		cmp [es:di],cx		jae .oksize		mov cx,26		cmp [es:di],cx		jb .overrun.oksize:		mov [si],cx		; This should be done by the installer...		mov eax,[DiskSize]		mov [si+16],eax		mov si,EDD_DPT		rep movsb		xor ax,ax		ret.overrun:		mov ax,0100h		ret%endif ; EDD		; Set up registers as for a "Read", and compares against disk size.		; WARNING: This fails immediately, even if we can transfer some		; sectors.  This isn't really the correct behaviour.setup_regs:		; Convert a CHS address in P_CX/P_DH into an LBA in eax		; CH = cyl[7:0]		; CL[0:5] = sector (1-based)  CL[7:6] = cyl[9:8]		; DH = head		movzx ecx,P_CX		movzx ebx,cl		; Sector number		and bl,3Fh		dec ebx			; Sector number is 1-based		cmp bx,[Sectors]		jae .overrun		movzx edi,P_DH		; Head number		movzx eax,word [Heads]		cmp di,ax		jae .overrun		shr cl,6		xchg cl,ch		; Now (E)CX <- cylinder number		mul ecx			; eax <- Heads*cyl# (edx <- 0)		add eax,edi		mul dword [Sectors]		add eax,ebx		; Now eax = LBA, edx = 0		;		; setup_regs continues...		;		; Note: edi[31:16] and ecx[31:16] = 0 already		mov di,P_BX		; Get linear address of target buffer		mov cx,P_ES		shl ecx,4		add edi,ecx		; EDI = address to fetch to		movzx ecx,P_AL		; Sector count		mov esi,eax		add eax,ecx		; LBA of final sector + 1		shl esi,SECTORSIZE_LG2	; LBA -> byte offset		add esi,[DiskBuf]	; Get address in high memory		cmp eax,[DiskSize]	; Check the high mark against limit		ja .overrun		shl ecx,SECTORSIZE_LG2-2 ; Convert count to dwords		ret.overrun:	pop ax			; Drop setup_regs return address		mov ax,0200h		; Missing address mark		ret			; Return to Done		; Set up registers as for an EDD Read, and compares against disk size.%if EDDedd_setup_regs:		push es		mov si,P_SI		; DS:SI -> DAPA		mov es,P_DS		mov dx,[es:si]		cmp dx,16		jb .baddapa		cmp dword [es:si+4],-1		je .linear_address		movzx esi,word [es:si+4]	; Offset

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -