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

📄 isoboot.asm

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	and	bx, bx				; ZF = 0
	mov	si, bx
	pop	es
	ret

.resume:
	; We get here if we were only doing part of a lookup
	; This relies on the fact that .success returns bx == si
	xchg	edx, eax			; Directory length in edx
	pop	cx				; Old ISOFlags
	pop	di				; Next filename pointer

	mov	byte [di-1], '\'		; restore the backslash in the filename

	mov	[ISOFlags], cl			; Restore the flags
	jz	.failure			; Did we fail?  If so fail for real!
	jmp	.look_for_slash			; Otherwise, next level

;
; allocate_file: Allocate a file structure
;
;		If successful:
;		  ZF set
;		  BX = file pointer
;		In unsuccessful:
;		  ZF clear
;
allocate_file:
	push	cx
	mov	bx, Files
	mov	cx, MAX_OPEN
.check:
	cmp	dword [bx], byte 0
	je	.found
	add	bx, open_file_t_size		; ZF = 0
	loop	.check
	; ZF = 0 if we fell out of the loop
.found:
	pop	cx
	ret

;
; iso_compare_names:
;	Compare the names DS:SI and DS:DI and report if they are
;	equal from an ISO 9660 perspective.  SI is the name from
;	the filesystem; CX indicates its length, and ';' terminates.
;	DI is expected to end with a null.
;
;	Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
;
iso_compare_names:
	; First, terminate and canonicalize input filename
	push	di
	mov	di, ISOFileName
.canon_loop:
	jcxz	.canon_end
	lodsb
	dec	cx
	cmp	al, ';'
	je	.canon_end
	and	al, al
	je	.canon_end
	stosb
	cmp	di, ISOFileNameEnd-1		; Guard against buffer overrun
	jb	.canon_loop
.canon_end:
	cmp	di, ISOFileName
	jbe	.canon_done
	cmp	byte [di-1], '.'		; Remove terminal dots
	jne	.canon_done
	dec	di
	jmp	short .canon_end
.canon_done:
	mov	[di], byte 0			; Null-terminate string
	pop	di
	mov	si, ISOFileName
.compare:
	lodsb
	mov	ah, [di]
	inc	di
	and	ax, ax
	jz	.success			; End of string for both
	and	al, al				; Is either one end of string?
	jz	.failure			; If so, failure
	and	ah, ah
	jz	.failure
	or	ax, 2020h			; Convert to lower case
	cmp	al, ah
	je	.compare
.failure:
	and	ax, ax				; ZF = 0 (at least one will be nonzero)
.success:
	ret







;
; getfssec: Get multiple clusters from a file, given the file pointer.
;
;  On entry:
;	ES:BX	-> Buffer
;	SI	-> File pointer
;	CX	-> Cluster count; 0FFFFh = until end of file
;  On exit:
;	SI	-> File pointer (or 0 on EOF)
;	CF = 1	-> Hit EOF
;
getfssec:
	cmp	cx, [si+file_left]
	jna	.ok_size
	mov	cx, [si+file_left]

.ok_size:
	mov	bp, cx
	push	cx
	push	si
	mov	eax, [si+file_sector]
	call	getlinsec
	xor	ecx, ecx
	pop	si
	pop	cx

	add	[si+file_sector], ecx
	sub	[si+file_left], ecx
	ja	.not_eof			; CF = 0

	xor	ecx, ecx
	mov	[si+file_sector], ecx		; Mark as unused
	xor	si,si
	stc

.not_eof:
	ret



; INT 13h, AX=4B01h, DL=<passed in value> failed.
; Try to scan the entire 80h-FFh from the end.
spec_query_failed:
	mov	si,spec_err_msg
	call	writemsg

	mov	dl, 0FFh
.test_loop:
	pusha
	mov	ax, 4B01h
	mov	si, spec_packet
	mov	byte [si], 13			; Size of buffer
	int	13h
	popa
	jc	.still_broken

	mov	si, maybe_msg
	call	writemsg
	mov	al, dl
	call	writehex2
	call	crlf

	cmp	byte [sp_drive], dl
	jne	.maybe_broken

	; Okay, good enough...
	mov	si, alright_msg
	call	writemsg
	mov	[DriveNo], dl
.found_drive:
	jmp	found_drive

	; Award BIOS 4.51 apparently passes garbage in sp_drive,
	; but if this was the drive number originally passed in
	; DL then consider it "good enough"
.maybe_broken:
	cmp	byte [DriveNo], dl
	je	.found_drive

.still_broken:
	dec dx
	cmp	dl, 80h
	jnb	.test_loop

fatal_error:
	mov	si, nothing_msg
	call	writemsg

.norge:
	jmp	short .norge



	; Information message (DS:SI) output
	; Prefix with "isolinux: "
	;
writemsg:
	push	ax
	push	si
	mov	si, isolinux_str
	call	writestr
	pop	si
	call	writestr
	pop	ax
	ret

;
; crlf: Print a newline
;
crlf:
	mov	si, crlf_msg
	; Fall through

;
; writestr: write a null-terminated string to the console, saving
;           registers on entry.
;
writestr:
	pushfd
	pushad
.top:
	lodsb
	and	al, al
	jz	.end
	call	writechr
	jmp	short .top
.end:
	popad
	popfd
	ret


;
; writehex[248]: Write a hex number in (AL, AX, EAX) to the console
;
writehex2:
	pushfd
	pushad
	shl	eax, 24
	mov	cx, 2
	jmp	short writehex_common
writehex4:
	pushfd
	pushad
	shl	eax, 16
	mov	cx, 4
	jmp	short writehex_common
writehex8:
	pushfd
	pushad
	mov	cx, 8
writehex_common:
.loop:
	rol	eax, 4
	push	eax
	and	al, 0Fh
	cmp	al, 10
	jae	.high
.low:
	add	al, '0'
	jmp	short .ischar
.high:
	add	al, 'A'-10
.ischar:
	call	writechr
	pop	eax
	loop	.loop
	popad
	popfd
	ret

;
; Write a character to the screen.  There is a more "sophisticated"
; version of this in the subsequent code, so we patch the pointer
; when appropriate.
;

writechr:
	pushfd
	pushad
	mov	ah, 0Eh
	xor	bx, bx
	int	10h
	popad
	popfd
	ret

;
; Get one sector.  Convenience entry point.
;
getonesec:
	mov	bp, 1
	; Fall through to getlinsec

;
; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
;
; Note that we can't always do this as a single request, because at least
; Phoenix BIOSes has a 127-sector limit.  To be on the safe side, stick
; to 32 sectors (64K) per request.
;
; Input:
;	EAX	- Linear sector number
;	ES:BX	- Target buffer
;	BP	- Sector count
;
getlinsec:
	mov si,dapa			; Load up the DAPA
	mov [si+4],bx
	mov bx,es
	mov [si+6],bx
	mov [si+8],eax
.loop2:
	push bp				; Sectors left
	cmp bp,[MaxTransfer]
	jbe .bp_ok
	mov bp,[MaxTransfer]
.bp_ok:
	mov [si+2],bp
	push si
	mov dl,[DriveNo]
	mov ah,42h			; Extended Read
	call xint13
	pop si
	pop bp
	movzx eax,word [si+2]		; Sectors we read
	add [si+8],eax			; Advance sector pointer
	sub bp,ax			; Sectors left
	shl ax,SECTORSIZE_LG2-4		; 2048-byte sectors -> segment
	add [si+6],ax			; Advance buffer pointer
	and bp,bp
	jnz .loop2
	mov eax,[si+8]			; Next sector
	ret

	; INT 13h with retry
xint13:
	mov	byte [RetryCount], retry_count
.try:
	pushad
	int	13h
	jc	.error
	add	sp, byte 8*4			; Clean up stack
	ret
.error:
	mov	[DiskError], ah		; Save error code
	popad
	dec byte [RetryCount]
	jz .real_error
	push ax
	mov al,[RetryCount]
	mov ah,[dapa+2]			; Sector transfer count
	cmp al,2			; Only 2 attempts left
	ja .nodanger
	mov ah,1			; Drop transfer size to 1
	jmp short .setsize
.nodanger:
	cmp al,retry_count-2
	ja .again			; First time, just try again
	shr ah,1			; Otherwise, try to reduce
	adc ah,0			; the max transfer size, but not to 0
.setsize:
	mov [MaxTransfer],ah
	mov [dapa+2],ah
.again:
	pop ax
	jmp .try

.real_error:
	mov	si, diskerr_msg
	call	writemsg
	mov	al, [DiskError]
	call	writehex2
	mov	si, ondrive_str
	call	writestr
	mov	al, dl
	call	writehex2
	call	crlf
	; Fall through to kaboom

;
; kaboom: write a message and bail out.  Wait for a user keypress,
;	  then do a hard reboot.
;
kaboom:
	mov	ax, cs
	mov	ds, ax
	mov	es, ax
	mov	fs, ax
	mov	gs, ax
	sti
	mov	si, err_bootfailed
	call	writestr
	call	getchar
	cli
	mov	word [BIOS_magic], 0	; Cold reboot
	jmp	0F000h:0FFF0h		; Reset vector address

getchar:
.again:
	mov	ah, 1		; Poll keyboard
	int	16h
	jz	.again
.kbd:
	xor	ax, ax		; Get keyboard input
	int	16h
.func_key:
	ret


;
; pollchar: check if we have an input character pending (ZF = 0)
;
pollchar:
	pushad
	mov ah,1		; Poll keyboard
	int 16h
	popad
	ret



isolinux_banner	db CR, LF, 'Loading IsoBoot...', CR, LF, 0
copyright_str	db ' Copyright (C) 1994-2002 H. Peter Anvin', CR, LF, 0
presskey_msg	db 'Press any key to boot from CD', 0
dot_msg		db '.',0

%ifdef DEBUG_MESSAGES
startup_msg:	db 'Starting up, DL = ', 0
spec_ok_msg:	db 'Loaded spec packet OK, drive = ', 0
secsize_msg:	db 'Sector size appears to be ', 0
rootloc_msg:	db 'Root directory location: ', 0
rootlen_msg:	db 'Root directory length: ', 0
rootsect_msg:	db 'Root directory length(sectors): ', 0
fileloc_msg:	db 'SETUPLDR.SYS location: ', 0
filelen_msg:	db 'SETUPLDR.SYS length: ', 0
filesect_msg:	db 'SETUPLDR.SYS length(sectors): ', 0
findfail_msg:	db 'Failed to find file!', 0
startldr_msg:	db 'Starting SETUPLDR.SYS', 0
%endif

nosecsize_msg:	db 'Failed to get sector size, assuming 0800', CR, LF, 0
spec_err_msg:	db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
maybe_msg:	db 'Found something at drive = ', 0
alright_msg:	db 'Looks like it might be right, continuing...', CR, LF, 0
nothing_msg:	db 'Failed to locate CD-ROM device; boot failed.', CR, LF, 0
isolinux_str	db 'IsoBoot: ', 0
crlf_msg	db CR, LF, 0
diskerr_msg:	db 'Disk error ', 0
ondrive_str:	db ', drive ', 0
err_bootfailed	db CR, LF, 'Boot failed: press a key to retry...'
isolinux_dir	db '\LOADER', 0
no_dir_msg	db 'Could not find the LOADER directory.', CR, LF, 0
isolinux_bin	db 'SETUPLDR.SYS', 0
no_isolinux_msg	db 'Could not find SETUPLDR.SYS.', CR, LF, 0

;
; El Torito spec packet
;
		align 8, db 0
spec_packet:	db 13h				; Size of packet
sp_media:	db 0				; Media type
sp_drive:	db 0				; Drive number
sp_controller:	db 0				; Controller index
sp_lba:		dd 0				; LBA for emulated disk image
sp_devspec:	dw 0				; IDE/SCSI information
sp_buffer:	dw 0				; User-provided buffer
sp_loadseg:	dw 0				; Load segment
sp_sectors:	dw 0				; Sector count
sp_chs:		db 0,0,0			; Simulated CHS geometry
sp_dummy:	db 0				; Scratch, safe to overwrite

;
; EBIOS drive parameter packet
;
		align 8, db 0
drive_params:	dw 30				; Buffer size
dp_flags:	dw 0				; Information flags
dp_cyl:		dd 0				; Physical cylinders
dp_head:	dd 0				; Physical heads
dp_sec:		dd 0				; Physical sectors/track
dp_totalsec:	dd 0,0				; Total sectors
dp_secsize:	dw 0				; Bytes per sector
dp_dpte:	dd 0				; Device Parameter Table
dp_dpi_key:	dw 0				; 0BEDDh if rest valid
dp_dpi_len:	db 0				; DPI len
		db 0
		dw 0
dp_bus:		times 4 db 0			; Host bus type
dp_interface:	times 8 db 0			; Interface type
db_i_path:	dd 0,0				; Interface path
db_d_path:	dd 0,0				; Device path
		db 0
db_dpi_csum:	db 0				; Checksum for DPI info

;
; EBIOS disk address packet
;
		align 8, db 0
dapa:		dw 16				; Packet size
.count:		dw 0				; Block count
.off:		dw 0				; Offset of buffer
.seg:		dw 0				; Segment of buffer
.lba:		dd 0				; LBA (LSW)
		dd 0				; LBA (MSW)

		alignb 4, db 0
MaxTransfer	dw 2 ;32				; Max sectors per transfer

		times 2046-($-$$) db 0		; Pad to file offset 2046
		dw 0aa55h			; BootSector signature

⌨️ 快捷键说明

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