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

📄 isoboot.asm

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 ASM
📖 第 1 页 / 共 2 页
字号:
; ****************************************************************************
;
;  isolinux.asm
;
;  A program to boot Linux kernels off a CD-ROM using the El Torito
;  boot standard in "no emulation" mode, making the entire filesystem
;  available.  It is based on the SYSLINUX boot loader for MS-DOS
;  floppies.
;
;   Copyright (C) 1994-2001  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., 675 Mass Ave, Cambridge MA 02139,
;  USA; either version 2 of the License, or (at your option) any later
;  version; incorporated herein by reference.
; 
; ****************************************************************************
;
; THIS FILE IS A MODIFIED VERSION OF ISOLINUX.ASM
; MODIFICATION DONE BY MICHAEL K TER LOUW
; LAST UPDATED 3-9-2002
; SEE "COPYING" FOR INFORMATION ABOUT THE LICENSE THAT APPLIES TO THIS RELEASE
;
; ****************************************************************************
;
; This file is a modified version of ISOLINUX.ASM.
; Modification done by Eric Kohl
; Last update 04-25-2002
;
; ****************************************************************************

; Note: The Makefile builds one version with DEBUG_MESSAGES automatically.
;%define DEBUG_MESSAGES                ; Uncomment to get debugging messages

%define WAIT_FOR_KEY


; ---------------------------------------------------------------------------
;   BEGIN THE BIOS/CODE/DATA SEGMENT
; ---------------------------------------------------------------------------

		absolute 0400h
serial_base	resw 4			; Base addresses for 4 serial ports
		absolute 0413h
BIOS_fbm	resw 1			; Free Base Memory (kilobytes)
		absolute 046Ch
BIOS_timer	resw 1			; Timer ticks
		absolute 0472h
BIOS_magic	resw 1			; BIOS reset magic
		absolute 0484h
BIOS_vidrows	resb 1			; Number of screen rows

;
; Memory below this point is reserved for the BIOS and the MBR
;
		absolute 1000h
trackbuf	resb 8192		; Track buffer goes here
trackbufsize	equ $-trackbuf
;		trackbuf ends at 3000h

		struc open_file_t
file_sector	resd 1			; Sector pointer (0 = structure free)
file_left	resd 1			; Number of sectors left
		endstruc

		struc dir_t
dir_lba		resd 1			; Directory start (LBA)
dir_len		resd 1			; Length in bytes
dir_clust	resd 1			; Length in clusters
		endstruc


MAX_OPEN_LG2	equ 2			; log2(Max number of open files)
MAX_OPEN	equ (1 << MAX_OPEN_LG2)
SECTORSIZE_LG2	equ 11			; 2048 bytes/sector (El Torito requirement)
SECTORSIZE	equ (1 << SECTORSIZE_LG2)
CR		equ 13			; Carriage Return
LF		equ 10			; Line Feed
retry_count	equ 6			; How patient are we with the BIOS?



	absolute 5000h				; Here we keep our BSS stuff

DriveNo		resb 1			; CD-ROM BIOS drive number
DiskError	resb 1			; Error code for disk I/O
RetryCount	resb 1			; Used for disk access retries
TimeoutCount	resb 1			; Timeout counter
ISOFlags	resb 1			; Flags for ISO directory search
RootDir		resb dir_t_size		; Root directory
CurDir		resb dir_t_size		; Current directory
ISOFileName	resb 64			; ISO filename canonicalization buffer
ISOFileNameEnd	equ $


		alignb open_file_t_size
Files		resb MAX_OPEN*open_file_t_size



	section .text
	org 7000h

start:
	cli					; Disable interrupts
	xor	ax, ax				; ax = segment zero
	mov	ss, ax				; Initialize stack segment
	mov	sp, start			; Set up stack
	mov	ds, ax				; Initialize other segment registers
	mov	es, ax
	mov	fs, ax
	mov	gs, ax
	sti					; Enable interrupts
	cld					; Increment pointers

	mov	cx, 2048 >> 2			; Copy the bootsector
	mov	si, 0x7C00			; from 0000:7C00
	mov	di, 0x7000			; to 0000:7000
	rep	movsd				; copy the program
	jmp	0:relocate			; jump into relocated code

relocate:
	; Display the banner and copyright
%ifdef DEBUG_MESSAGES
	mov	si, isolinux_banner		; si points to hello message
	call	writestr			; display the message
	mov	si,copyright_str
	call	writestr
%endif


	; Make sure the keyboard buffer is empty
%ifdef WAIT_FOR_KEY
.kbd_buffer_test:
	call	pollchar
	jz	.kbd_buffer_empty
	call	getchar
	jmp	.kbd_buffer_test
.kbd_buffer_empty:

	; Check for MBR on harddisk
	pusha
	mov	ax, 0201h
	mov	dx, 0080h
	mov	cx, 0001h
	mov	bx, trackbuf
	int	13h
	popa
	jc	.boot_cdrom ; could not read hdd

	push ax
	mov ax, word [trackbuf]
	cmp ax, 0
	je	.boot_cdrom ; no boot sector found (hopefully there are no weird bootsectors which begin with 0)
	pop ax

	; Display the 'Press key' message and wait for a maximum of 5 seconds
	call	crlf
	mov	si, presskey_msg		; si points to 'Press key' message
	call	writestr			; display the message

	mov	byte [TimeoutCount], 5
.next_second:
	mov	eax, [BIOS_timer]		; load current tick counter
	add	eax, 19				; 

.poll_again:
	call	pollchar
	jnz	.boot_cdrom

	mov	ebx, [BIOS_timer]
	cmp	eax, ebx
	jnz	.poll_again

	mov	si, dot_msg			; print '.'
	call	writestr
	dec	byte [TimeoutCount]		; decrement timeout counter
	jz	.boot_harddisk
	jmp	.next_second

.boot_harddisk:
	call	crlf

	; Boot first harddisk (drive 0x80)
	mov	ax, 0201h
	mov	dx, 0080h
	mov	cx, 0001h
	mov	bx, 7C00h
	int	13h
	jnc	.go_hd
	jmp	kaboom
.go_hd:
	mov	ax, cs
	mov	ds, ax
	mov	es, ax
	mov	fs, ax
	mov	gs, ax
	mov	dx, 0080h

	jmp	0:0x7C00
%endif

.boot_cdrom:
%ifdef WAIT_FOR_KEY
	call	crlf
	call	crlf
%endif

	; Save and display the boot drive number
	mov	[DriveNo], dl
%ifdef DEBUG_MESSAGES
	mov	si, startup_msg
	call	writemsg
	mov	al, dl
	call	writehex2
	call	crlf
%endif

	; Now figure out what we're actually doing
	; Note: use passed-in DL value rather than 7Fh because
	; at least some BIOSes will get the wrong value otherwise
	mov	ax, 4B01h			; Get disk emulation status
	mov	dl, [DriveNo]
	mov	si, spec_packet
	int	13h
	jc	near spec_query_failed		; Shouldn't happen (BIOS bug)
	mov	dl, [DriveNo]
	cmp	[sp_drive], dl			; Should contain the drive number
	jne	near spec_query_failed

%ifdef DEBUG_MESSAGES
	mov	si, spec_ok_msg
	call	writemsg
	mov	al, byte [sp_drive]
	call	writehex2
	call	crlf
%endif

found_drive:
	; Get drive information
	mov	ah, 48h
	mov	dl, [DriveNo]
	mov	si, drive_params
	int	13h
	jnc	params_ok

	; mov	si, nosecsize_msg	No use in reporting this
	; call	writemsg

params_ok:
	; Check for the sector size (should be 2048, but
	; some BIOSes apparently think we're 512-byte media)
	;
	; FIX: We need to check what the proper behaviour
	; is for getlinsec when the BIOS thinks the sector
	; size is 512!!!  For that, we need such a BIOS, though...
%ifdef DEBUG_MESSAGES
	mov	si, secsize_msg
	call	writemsg
	mov	ax, [dp_secsize]
	call	writehex4
	call	crlf
%endif


	;
	; Clear Files structures
	;
	mov	di, Files
	mov	cx, (MAX_OPEN*open_file_t_size)/4
	xor	eax, eax
	rep	stosd

	;
	; Now, we need to sniff out the actual filesystem data structures.
	; mkisofs gave us a pointer to the primary volume descriptor
	; (which will be at 16 only for a single-session disk!); from the PVD
	; we should be able to find the rest of what we need to know.
	;
get_fs_structures:
	mov	eax, 16			; Primary Volume Descriptor (sector 16)
	mov	bx, trackbuf
	call	getonesec

	mov	eax, [trackbuf+156+2]
	mov	[RootDir+dir_lba],eax
	mov	[CurDir+dir_lba],eax
%ifdef DEBUG_MESSAGES
	mov	si, rootloc_msg
	call	writemsg
	call	writehex8
	call	crlf
%endif

	mov	eax,[trackbuf+156+10]
	mov	[RootDir+dir_len],eax
	mov	[CurDir+dir_len],eax
%ifdef DEBUG_MESSAGES
	mov	si, rootlen_msg
	call	writemsg
	call	writehex8
	call	crlf
%endif
	add	eax,SECTORSIZE-1
	shr	eax,SECTORSIZE_LG2
	mov	[RootDir+dir_clust],eax
	mov	[CurDir+dir_clust],eax
%ifdef DEBUG_MESSAGES
	mov	si, rootsect_msg
	call	writemsg
	call	writehex8
	call	crlf
%endif

	; Look for the "REACTOS" directory, and if found,
	; make it the current directory instead of the root
	; directory.
	mov	di,isolinux_dir
	mov	al,02h				; Search for a directory
	call	searchdir_iso
	jnz	.dir_found
	mov	si,no_dir_msg
	call	writemsg
	jmp	kaboom

.dir_found:
	mov	[CurDir+dir_len],eax
	mov	eax,[si+file_left]
	mov	[CurDir+dir_clust],eax
	xor	eax,eax				; Free this file pointer entry
	xchg	eax,[si+file_sector]
	mov	[CurDir+dir_lba],eax


	mov	di, isolinux_bin		; di points to Isolinux filename
	call	searchdir			; look for the file
	jnz	.isolinux_opened		; got the file
	mov	si, no_isolinux_msg		; si points to error message
	call	writemsg			; display the message
	jmp	kaboom				; fail boot

.isolinux_opened:
	mov	di, si				; save file pointer

%ifdef DEBUG_MESSAGES
	mov	si, filelen_msg
	call	writemsg
	call	writehex8
	call	crlf
%endif

	mov ecx, eax			; calculate sector count
	shr ecx, 11
	test eax, 0x7FF
	jz .full_sector
	inc ecx
.full_sector:

%ifdef DEBUG_MESSAGES
	mov eax, ecx
	mov	si, filesect_msg
	call	writemsg
	call	writehex8
	call	crlf
%endif

	mov	bx, 0x8000			; bx = load address
	mov	si, di				; restore file pointer
	mov	cx, 0xFFFF			; load the whole file
	call	getfssec			; get the whole file

%ifdef DEBUG_MESSAGES
	mov	si, startldr_msg
	call	writemsg
	call	crlf
%endif

	mov	dl, [DriveNo]			; dl = boot drive
	mov dh, 0					; dh = boot partition
	jmp	0:0x8000			; jump into OSLoader



;
; searchdir:
;
; Open a file
;
;  On entry:
;	DS:DI	= filename
;  If successful:
;	ZF clear
;	SI		= file pointer
;	DX:AX or EAX	= file length in bytes
;  If unsuccessful
;	ZF set
;

;
; searchdir_iso is a special entry point for ISOLINUX only.  In addition
; to the above, searchdir_iso passes a file flag mask in AL.  This is useful
; for searching for directories.
;
alloc_failure:
	xor	ax,ax				; ZF <- 1
	ret

searchdir:
	xor	al,al
searchdir_iso:
	mov	[ISOFlags],al
	call	allocate_file			; Temporary file structure for directory
	jnz	alloc_failure
	push	es
	push	ds
	pop	es				; ES = DS
	mov	si,CurDir
	cmp	byte [di],'\'			; If filename begins with slash
	jne	.not_rooted
	inc	di				; Skip leading slash
	mov	si,RootDir			; Reference root directory instead
.not_rooted:
	mov	eax,[si+dir_clust]
	mov	[bx+file_left],eax
	mov	eax,[si+dir_lba]
	mov	[bx+file_sector],eax
	mov	edx,[si+dir_len]

.look_for_slash:
	mov	ax,di
.scan:
	mov	cl,[di]
	inc	di
	and	cl,cl
	jz	.isfile
	cmp	cl,'\'
	jne	.scan
	mov	[di-1],byte 0			; Terminate at directory name
	mov	cl,02h				; Search for directory
	xchg	cl,[ISOFlags]
	push	di
	push	cx
	push	word .resume			; Where to "return" to
	push	es
.isfile:
	xchg	ax,di

.getsome:
	; Get a chunk of the directory
	mov	si,trackbuf
	pushad
	xchg	bx,si
	mov	cx,1				; load one sector
	call	getfssec
	popad

.compare:
	movzx	eax, byte [si]			; Length of directory entry
	cmp	al, 33
	jb	.next_sector
	mov	cl, [si+25]
	xor	cl, [ISOFlags]
	test	cl, byte 8Eh			; Unwanted file attributes!
	jnz	.not_file
	pusha
	movzx	cx, byte [si+32]		; File identifier length
	add	si, byte 33			; File identifier offset
	call	iso_compare_names
	popa
	je	.success
.not_file:
	sub	edx, eax			; Decrease bytes left
	jbe	.failure
	add	si, ax				; Advance pointer

.check_overrun:
	; Did we finish the buffer?
	cmp	si, trackbuf+trackbufsize
	jb	.compare			; No, keep going

	jmp	short .getsome			; Get some more directory

.next_sector:
	; Advance to the beginning of next sector
	lea	ax, [si+SECTORSIZE-1]
	and	ax, ~(SECTORSIZE-1)
	sub	ax, si
	jmp	short .not_file			; We still need to do length checks

.failure:
%ifdef DEBUG_MESSAGES
	mov	si, findfail_msg
	call	writemsg
	call	crlf
%endif
	xor	eax, eax			; ZF = 1
	mov	[bx+file_sector], eax
	pop	es
	ret

.success:
	mov	eax, [si+2]			; Location of extent
	mov	[bx+file_sector], eax
	mov	eax, [si+10]			; Data length
	push	eax
	add	eax, SECTORSIZE-1
	shr	eax, SECTORSIZE_LG2
	mov	[bx+file_left], eax
	pop	eax
	mov	edx, eax
	shr	edx, 16

⌨️ 快捷键说明

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