Linux x86 bootloader

Linux x86 bootloader,第1张

概述我试图在nasm中构建一个简单的x86 Linux引导程序. Linux bzImage从第一个扇区开始存储在磁盘分区sda1上. 我从bzImage(15个扇区)读取实际模式代码到0x7E00开始的内存中. 但是,当我跳入代码时,它只是挂起,没有任何反应. 我已经在sda上为主启动记录创建了代码.如果我只是附上,我可能是最好的 整个东西.我想知道为什么它只是在跳远指令后挂起. [BITS 16] 我试图在nasm中构建一个简单的x86 Linux引导程序.

linux bzImage从第一个扇区开始存储在磁盘分区sda1上.

我从bzImage(15个扇区)读取实际模式代码到0x7E00开始的内存中.
但是,当我跳入代码时,它只是挂起,没有任何反应.

我已经在sda上为主启动记录创建了代码.如果我只是附上,我可能是最好的
整个东西.我想知道为什么它只是在跳远指令后挂起.

[BITS 16]%define BOOTSEG 0x7C0 %define BOOTADDR (BOOTSEG * 0x10)%define HDRSEG (BOOTSEG + 0x20)%define HDRADDR (HDRSEG * 0x10)%define KERNSEG (HDRSEG + 0x20)[ORG BOOTADDR]entry_section:    cli    jmp     startstart:    ; Clear segments    xor     ax,ax    mov     ds,ax      mov     es,ax    mov     gs,ax    mov     fs,ax    mov     ss,ax    mov     sp,BOOTADDR    ; Lots of room for it to grow down from here    ; Read all 15 sectors of realmode code in the kernel    mov     ah,0x42    mov     si,dap    mov     dl,0x80    int     0x13    jc  bad    ; Test magic number of kernel header    mov     eax,DWord [HDRADDR + 0x202]    cmp     eax,'HdrS'    jne     bad    ; Test jump instruction is there    mov     al,byte [KERNSEG * 16]    cmp     al,0xEB    jne     bad    xor     ax,ax      ; Kernel entry code will set ds = ax    xor     bx,bx      ; Will also set ss = dx    jmp     DWord KERNSEG:0; Simple function to report an error and haltbad:    mov     al,"B"    call    putc    jmp     halt; Param: char in al putc:    mov     ah,0X0E        mov     bh,0x0F    xor     bl,bl      int     0x10    rethalt:    hlt    jmp     halt; Begin data sectiondap:                ; disk address packet    db  0x10            ; Size of dap in bytes    db  0               ; Unused    DW  15              ; Number of sectors to read    DW  0               ; Offset where to place data    DW  HDRSEG          ; Segment where to place data    dd  0x3F            ; Low order of start addres in sectors    dd  0               ; High order of start address in sectors; End data sectiontimes 446-($-$$) db 0   ; padding to make the MBR 512 bytes; Hardcoded partition entrIEspart_boot:    DW 0x0180,0x0001,0xFE83,0x3c3f,0x003F,0x0000,0xF3BE,0x000Epart_sda2:    DW 0x0000,0x3D01,0xFFFF,0xF3FD,0x000E,0x5AF0,0x01B3part_sda3:    DW 0xFE00,0x4EED,0x01C2,0xb113,0x001Dpart_sda4:    DW 0x0000,0x0000DW 0xAA55   ; Magic number at relative address 510mbrend:     ; relative address 512
解决方法 假设您的代码是引导加载程序(因此不是MBR):

>除非必须,否则永远不要禁用IRQ. BIOS需要它们才能正常工作,并且无论如何都会在某些BIOS功能中启用它们(例如,在磁盘功能中等待“扇区传输”IRQ).因为您的代码只是加载并将控制传递给更多实模式代码(例如,并且没有切换到保护模式或涉及任何内容),您没有理由在整个引导加载程序中的任何位置禁用IRQ.
>对于实模式寻址,它通常更清晰/更容易使用0x0000:0x7C00而不是0x07C0:0x0000.您似乎试图混合两者(例如,为前者设置段寄存器,但为后者定义BOOTSEG和HDRSEG).
>分区表包含“扩展分区”而不是“主分区”,因此您的分区表是错误的(并且应该是空白/空的).
>引导加载程序不应假设任何特定/硬编码的“起始LBA”(分区的“起始LBA”取决于最终用户在安装 *** 作系统时如何分区磁盘).您需要从MBR的主分区表中确定分区的“起始LBA”,这通常是希望MBR离开DS:SI指向分区的分区表条目.
>您不应该假设您从“BIOS设备0x80”启动. MBR应该将DL设置为正确的设备编号,并且如果(例如) *** 作系统安装在第二个硬盘驱动器上,则应该没有理由说明您的代码不起作用.
>你的硬编码“开始LBA阅读”(在DAP中)是错误的.由于历史原因,每个轨道可能有63个扇区,而您的分区从第64个扇区开始.这意味着LBA扇区0x3F是分区中的第一个扇区(它是您的引导加载程序),并不是内核的第一个扇区.我假设内核的第一个扇区可能是LBA扇区0x40(分区的第二个扇区).
>“扇区数”也不应该是硬编码的.您需要加载内核的开头并检查它,并确定要从中加载的扇区数.
>通常512个字节(实际上更像是446个字节)对于体面的引导加载程序来说太小了.引导加载程序的前512个字节应加载引导加载程序的其余部分(剩下的每个备用字节用于改进错误处理 – 例如puts(“尝试加载引导加载程序时读取错误”)而不仅仅是putc(‘B “)).其他所有内容(加载内核片段,设置视频模式,在“实模式内核头”字段中设置正确的值等)应该在其他扇区中,而不是在第一个扇区中.

请注意,计算机引导的方式经过精心设计,以便任何MBR都可以链接任何磁盘的任何分区上的任何 *** 作系统;并且MBR可以是允许安装多个OS的更大的(例如,引导管理器)的一部分(例如,用户可以使用漂亮的菜单或某些东西来选择MBR的代码应该链加载哪个分区).此设计允许用户随时使用任何其他内容替换MBR(或引导管理器),而不会影响任何已安装的 *** 作系统(或导致所有已安装的 *** 作系统需要修复).举一个简单的例子,用户应该能够拥有12个不同的分区,这些分区都包含你的引导加载程序和一个独立/独立的linux版本,然后安装任何引导管理器(例如GRUB,Plop,GAG,MasterBooter等)想要随时.

对于你的代码挂起的原因,考虑到所有代码都需要重写,这并不是很重要.如果你很好奇,我强烈建议在带有调试器(例如Bochs)的模拟器中运行它,以便你可以准确地检查发生了什么(例如,在0x00007E00转储内存以查看它包含的内容,将JMP单步执行看看正在执行什么,等等.

总结

以上是内存溢出为你收集整理的Linux x86 bootloader全部内容,希望文章能够帮你解决Linux x86 bootloader所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/1032433.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存