Grub Error 13

来自osdev
跳到导航 跳到搜索

GRUB Error 13: Invalid or unsupported executable format:

GRUB 是GNU Multiboot规范的参考实现,通常被大多数32位OS开发人员使用。 它的优点是作为一个(显然)预先编写的引导程序,有更多的代码来处理各种BIOS的怪癖,而不是任何个人都值得自己去做。

有关更多信息,请参阅以下帖子: http://forum.osdev.org/viewtopic.php?f=1&t=21158&start=0.

但是,许多人在使GRUB识别其内核的可执行映像方面遇到问题。

以下是GRUB关于ELF文件的臭名昭著的ERROR 13的解决方案。

示例来源

GNU Multiboot规范要求Multiboot头在内核可执行文件的前8KB内的4字节边界上对齐。 如果你的内核映像不符合此描述,GRUB将立即发生Error 13错误。

链接器脚本 提供了链接器关于如何在内核可执行文件中定位内核的可执行部分的详细信息。 你不受限制(使用ELF;有一些可执行格式将你限制在特定于格式的部分)仅限于ELF推荐的部分。 你可以在内核可执行映像中定义任意数量的节,并使用链接器脚本将它们放置到你认为合适的位置。 我们假设本文使用GNU ld链接器。

在定义了多重引导头选项的asm源文件中,编辑多重引导头,如下所示: (本文不会详细介绍GNU Multiboot规范。 我只是告诉你一些小的更改以使 “围绕” 标题)

;; 移除从Bare Bones教程复制/粘贴的.text节;)
section .__mbHeader

align 0x4
;在此复制/粘贴当前的多重引导标头

;; 重新定位在这里定义.text节。

这有什么用? 我们已将多重引导标头放入由NASM生成的可重定位文件中的单独ELF部分。 当链接器正在浏览对象文件时,它将每个对象文件中的部分符号放置在最终内核映像中相应的输出部分中。

我们如何告诉链接器放置__内核映像前8KB中的mbHeader ELF部分? 从技术上讲,如果内核文件变得过大,没有办法保证它会在那里。 到那时,你可能必须发明一种特殊的技术来手动编辑输出对象文件,并将Multiboot标头放置在前8 k中。 不管你怎么做。。。不管你怎么做。 简单的解决方案是确保内核映像不会变得“太大”。 同样,从技术上讲,即使是单片内核的映像也不应该增长那么大,即使你尝试了。

链接器被告知使用.__mbHeader节作为输出文件中的第一节,如下所示:

yourLinkerScript.ld

/*This is the SECTIONS command in your ld script. Locate it.*/
SECTIONS {
   /* 你的链接器脚本中有一个通用形式的命令:
    * . = 0xXXXXXXXX;
    * 你应将其保留在适当的位置,然后将部分放在.__mbHeader在那行下面。
    **/
   .__mbHeader : {
      *(.__mbHeader)
   }

   /* 其他部分在这里。 编辑脚本后。 如果你复制/粘贴了Bare Bones ld脚本,则.text部分位于此处。*/
   /*...*/
}

换句话说,我们只需在SECTIONS命令的顶部插入.__mbHeader节的行,告诉ld首先放置.__mbHeader节。

一两点注意点,因为大量复制/粘贴实际上不会注意到以下几点: 我们假设你的内核实际上没有链接到更高的地址。 如果是,则应将.__mbHeader链接器命令的第一行编辑为如下所示:

.__mbHeader : AT( ADDR(.__mbHeader) - YOUR_KERNEL\'S_VIRTUAL_OFFSET_HERE ) {

如果你正确执行此操作 (并且不应该那么困难),你的内核不应再发出该错误13消息, 如果以正确的格式链接内核,GRUB应该能够很好地加载内核。

另见

文章

论坛主题

外部链接