问题描述
为了从闪存驱动器启动,我们在实模式下使用BIOS中断13h加载磁盘,并指定了磁盘0x80.如此链接
In order to boot from flash memory drive we load disks using the BIOS interrupt 13h in real mode with specifying the disk 0x80. Another disks should be accessed by 0x81, 0x82... as mentioned over this link
我正在尝试制作简单的GRUB .
我的第一步是从闪存驱动器启动(将MBR加载到0x7C00并打印一条消息,作为正确启动的证明)并读取我的主HDD(我假设它的编号为0x81,并且前15个扇区需要重新启动)再次进入0x7C00.
My very first step is to boot from flash memory drive (Load MBR into 0x7C00 and print a message as a proof of correct boot) and read the my main HDD (which I assume it is numbered 0x81 and that the first 15 sectors are needed for booting) again into 0x7C00.
我想这个天真的主意应该让我进入主硬盘的引导加载程序,但这不是预期的.你能告诉我出什么问题了吗.
I suppose that this naive idea should drop me into my main HDD's bootloader, but it is not as expected. Would you please tell me what is wrong.
顺便问一下,我应该如何获得HDD的数量?
By the way, how should I get the numbers of HDDs?
请注意,我的主硬盘包含带有多个操作系统的grub2.
Please note that my main HDD contains grub2 with several operating systems.
对我来说,这是一个理论上的问题,但是由于注释的要求,我添加了代码.
For me this is a theoretical question, but I added the code due to a request in comments.
bootloader.asm:
[bits 16]
[org 0x7C00]
; The bootloader is in charge of writing BPB into MBR in addition to installing this code.
; Then a second sector is written to the drive, this is where the FAT is allocated.
LOADER_OFFSET equ 0x1000
jmp short main
nop
%include "ASM/BPB.asm"
main:
xor ax, ax
mov ds, ax
mov es, ax
; Save the boot drive. Basically it should be 0x80
mov [BOOT_DRIVE], dl
mov ax, 0x0000 ; End of stack
; Lock and create stack
cli
mov ss, ax
mov sp, 0x0000
sti
mov ah, 0x0e
mov al, 'X'
int 0x10
; Load the second sector into memory at LOADER_OFFSET
mov bx, LOADER_OFFSET
mov al, 1
mov cl , 0x02
mov dl, [BOOT_DRIVE]
call disk_load
; Call the loader using segmentation
jmp 0x0000:LOADER_OFFSET
; Global variables
BOOT_DRIVE db 0
%include "ASM/disk_load.asm"
; Bootsector padding
times 510-($-$$) db 0
dw 0xAA55
第二阶段bootloader- loader.asm:
[bits 16]
[org 0x1000]
KERNEL_OFFSET equ 0x7C00
_start:
xor ax, ax
xor bx, bx
mov ah, 0x0e
mov al, 'Y'
int 0x10
mov bx, KERNEL_OFFSET
mov al, 15
mov dl , 0x81
mov cl , 0x01
call disk_load
jmp 0x7C0:0000
%include "ASM/disk_load.asm"
times 512-($-$$) db 0
BPB.asm:
BPB:
iOEM db "mkfs.fat" ; 0x03 ; OEM String
iSectSize dw 512 ; 0x0B ; Bytes per sector
iClustSize db 0x40 ; 0x0D ; Sectors per cluster
iResSect dw 0x1 ; 0x0E ; # of reserved sectors. For now, it should be 1
; 0x0E ; unless we need more space to write the bootstrap
; 0x0E ; sector
iFatCnt db 2 ; 0x10 ; # of fat copies
iRootSize dw 1024 ; 0x11 ; size of root directory
iTotalSect dw 0 ; 0x13 ; total #of sectors if below 32 MB
iMedia db 0xF8 ; 0x15 ; Media Descriptor
iFatSize dw 256 ; 0x16 ; Size of each FAT
iTrackSect dw 62 ; 0x18 ; Sectors per track
iHeadCnt dw 63 ; 0x1A ; number of read-write heads
iHiddenSect dd 0 ; 0x1C ; number of hidden sectors
iSect32 dd 0x003c3000 ; 0x20 ; # of sectors if over 32 MB
EBPB:
iBootDrive db 80 ; 0x24 ; holds drive that the boot sector came from
iReserved db 0 ; 0x25 ; reserved, empty
iBootSign db 0x29 ; 0x26 ; extended boot sector signature
iVolID dd 0xA8B531B1 ; 0x27 ; disk serial
acVolLabel db "BIOSver", 0x20, 0x20, 0x20, 0x20 ; 0x2B ; just placeholder. We don't yet use volume labels.
acFSType db "FAT16", 0x20, 0x20, 0x20 ; 0x36 ; file system type
disk_load.asm:
disk_load:
push dx
mov ah , 0x02
mov ch , 0x00
mov dh , 0x00
int 0x13
jc disk_error
pop dx
ret
disk_error:
pop si
pop ax
pop cx
pop dx
jmp $
; Variables
SECTORS db 0
制作文件:
ASFLAGS=-g3
all: os.img
os.img: bootloader.bin loader.bin
cat bin/bootloader.bin bin/loader.bin > bin/os.img
bootloader.bin: ASM/bootloader.asm
nasm $(ASFLAGS) $^ -f bin -o bin/$@
loader.bin: ASM/loader.asm
nasm $(ASFLAGS) $^ -f bin -o bin/$@
clean:
rm -f bin/*.* bin/* os.img
此代码应在屏幕上显示XY
,然后将控制权传递给HDD的引导程序.但是我得到的只是XY
打印在屏幕上.
This code should print XY
to screen and then pass control to the HDD's bootsector. But what I am getting is just XY
printed to the screen.
推荐答案
回答我自己的问题,灵感来自于Micheal Petch的上述评论:主要有两个问题:1.使用模拟器并不一定意味着所有驱动器都已加载,这是我的情况2.使用jmp 0x100:0000将磁盘扇区加载到0x0000:0x1000.
Answering my own question inspired from the above comments from Micheal Petch:There are mainly two problems:1. Using emulator does not necessarily means that all drives are loaded which was my case2. Loading the disk sectors to 0x0000:0x1000 with jmp 0x100:0000.
此外,如 rufus 代码(即闪存到0x81,主硬盘到0x80).
In addition, chainloading requires overwriting interrupt 13 to re-arrange the numbers of boot devices as explained in rufus code (i.e. Flash memory to 0x81 and main HDD to 0x80).
这篇关于最简单的链式加载启动管理器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!