这将是一个很长的,所以抓住一些咖啡/茶/ yerba.
如何告诉/强制GNU ld将一个节/符号放在输出ELF文件的特定部分?
具体来说,我不是询问符号的物理/加载地址,而是询问文件中的偏移量.
我正在尝试使用真实世界的BSD内核并使其与Multiboot兼容并由GRUB引导.为了使ELF图像与Multiboot兼容并且可以通过GRUB识别,需要将幻数(0x1BADB002)嵌入到文件的第一个8KiB中.
我指的是Multiboot 0.6.96.
由于原始内核是相当大的代码,我将使用基于OSDev wiki的Bare Bones内核的示例.由于该内核已经符合Multiboot标准,因此我将使用
extra_symbolwith值0xCAFEBABE作为我的问题的示例.
boot.s 包含:
.set CAFEBABE, 0xCAFEBABE
; ... snip ...
.section .extras
extra_symbol:
.long CAFEBABE
Run Code Online (Sandbox Code Playgroud)
.text最简单的选择是将具有该值的符号放在.text
其他任何内容之前:
.text BLOCK(4K) : ALIGN(4K)
{
*(.extras)
*(.multiboot)
*(.text)
}
Run Code Online (Sandbox Code Playgroud)
这对于示例来说很好,但是如果真正的BSD内核.text
在文件中的0x2000(8KiB)之后启动.这种方法不是一种选择.
.text?另一种选择是将整个.extras部分放在前面.text.在我的天真,我希望.text在链接器脚本之前放置这样的部分也会使它出现在输出ELF的前面:
SECTIONS
{
// ... some stuff ...
.extras : { *(.extras) }
.text BLOCK(4K) …Run Code Online (Sandbox Code Playgroud) 我想使用Visual C++为x86机器构建一个嵌入式内核.我有一些C和汇编代码文件要编译,我想以一种与GRUB等多重引导加载程序兼容的方式将它们连接在一起.
在以下 x86 汇编代码中:
dd 0x1BADB002
dd 0x00
dd - (0x1BADB002+0x00)
Run Code Online (Sandbox Code Playgroud)
这些值似乎没有分配给任何变量。那么这段代码有什么作用呢?我听说过它被存储在内存中,但具体在哪里呢?
简而言之:
我有一台带有Win XP,Windows 7和Ubuntu的多重启动机器,我希望我的localhost web项目能够被所有三个操作系统共享.
详细信息:
我最终想要摆脱Windows XP进行Web开发工作,但是我的本地Apache + PHP + MySQL堆栈与我的旧操作系统相关联,我花了一些时间思考将这种设置调整到它的方式现在.
如果我可以将数据库和Web文件放在独立于当前操作系统的位置,那将是很好的,因此我可以使用不同的操作系统重新启动并继续处理相同的项目.
理想情况下,我还想保留和共享其他应用程序的设置和文件(Firefox插件,Opera键盘快捷键,邮件和聊天帐户,Eclipse设置等),但这可能是另一个问题.
如果可能的话,我想避免严重的性能命中.
最后,一旦我选择了解决方案,如果我能找到一种简单的方法将设置从Windows XP设置移植到新的共享环境,那就太好了.特别是:数据库,htdocs文件夹,vhost设置.
VirtualBox或vmware是解决方案吗?或者便携式应用的东西?或者我应该在每个操作系统上运行单独的Apache/MySQL/PHP,然后让它们共享它们的设置和htdocs文件?
谢谢!
我遇到了 Grub 2(和 QEMU 的-kernel)的问题,无法在我的内核中检测到 Multiboot v1 标头。我在之前的单独部分中有标题.text。
linker.ld:
SECTIONS
{
. = 1M;
.multiboot ALIGN(4K) :
{
*(.multiboot)
}
.text ALIGN(4K) :
{
*(.text)
}
[snip]
Run Code Online (Sandbox Code Playgroud)
boot.s (GNU 作为语法):
.set MAGIC, 0x1badb002
.set FLAGS, (1<<0 | 1<<1) # align, provide mem map
.set CHECKSUM, -(MAGIC + FLAGS)
.section .multiboot
.long MAGIC
.long FLAGS
.long CHECKSUM
.section .text
[snip]
Run Code Online (Sandbox Code Playgroud)
我已经验证标题部分是按照幻数指定的方式添加的:
kernel.bin: file format elf32-i386
Contents of section .multiboot:
101000 02b0ad1b 03000000 fb4f52e4 .........OR.
Contents of …Run Code Online (Sandbox Code Playgroud) 我正在开发一个简单的内核,并且一直在尝试实现一个键盘中断处理程序来摆脱端口轮询。我一直在-kernel模式下使用 QEMU (为了减少编译时间,因为使用生成 isogrub-mkrescue需要相当长的时间)并且它工作得很好,但是当我想切换到-cdrom模式时它突然开始崩溃。我不知道为什么。
最终我意识到,当它从 ISO 引导时,它还会在引导内核本身之前运行 GRUB 引导加载程序。我发现 GRUB 可能会将处理器切换到保护模式,这会导致问题。
问题:通常我会简单地初始化中断处理程序,每当我按下一个键时,它就会被处理。但是,当我使用 iso 运行内核并按下一个键时,虚拟机就崩溃了。这发生在 qemu 和 VMWare 中,所以我认为我的中断一定有问题。
请记住,只要我不使用 GRUB,代码就可以正常工作。
interrupts_init()(见下文)是main()内核函数中调用的第一件事。
本质上的问题是:有没有办法让它在保护模式下工作?.
我的内核的完整副本可以在我的GitHub 存储库中找到。一些相关文件:
lowlevel.asm:
section .text
global keyboard_handler_int
global load_idt
extern keyboard_handler
keyboard_handler_int:
pushad
cld
call keyboard_handler
popad
iretd
load_idt:
mov edx, [esp + 4]
lidt [edx]
sti
ret
Run Code Online (Sandbox Code Playgroud)
interrupts.c:
#include <assembly.h> // defines inb() and outb()
#define IDT_SIZE 256
#define …Run Code Online (Sandbox Code Playgroud) \xe2\x80\x98checksum\xe2\x80\x99 的用途是什么?
\n\n字段 \xe2\x80\x98checksum\xe2\x80\x99 是一个 32 位无符号值,当添加到其他魔术字段(即 \xe2\x80\x98magic\xe2\x80\x99 和 \xe2\x80\ x98flags\xe2\x80\x99),必须有一个 32 位无符号和为零。
\n\ndd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))\nRun Code Online (Sandbox Code Playgroud)\n 因此,我阅读了有关处理器模式的信息,然后知道虚拟实模式允许实模式应用程序(例如DOS应用程序,例如BIOS程序)在受保护模式的操作系统中运行。
因此,我的问题是当前系统是否首先以实模式加载,然后再提供更多保护或直接将其保护为虚拟实模式,因为否则,我们必须创建一个从实模式开始的multiboot引导加载程序,然后跳转到虚拟模式。虚拟实模式难道不容易吗?
我想用 Grub2 启动一个自定义内核。我使用了旧的(grub 1)多重引导头:
.set flags, 0x0
.set magic, 0x1badb002
.set checksum, -(magic + flags)
.align 4
.long magic
.long flags
.long checksum
...
movl %eax, magic
Run Code Online (Sandbox Code Playgroud)
但它不适用于 Grub2,所以我搜索了新的 Multiboot 规范并找到了它:http ://bzr.savannah.gnu.org/lh/grub/branches/multiboot2/annotate/head:/doc/multiboot2 .h (它不是真正的规范,它只是一个头文件)
所以,现在我正在使用这个多重引导头:
.set flags, 0x0
.set magic, 0xe85250d6
.set magic_the_second, 0x36d76289
.set checksum, -(magic + flags)
.align 4
.long magic
.long flags
.long checksum
...
movl %eax, magic_the_second
Run Code Online (Sandbox Code Playgroud)
但它也不起作用:没有多重引导头
有什么建议?
谢谢!
我尝试将以下代码用于 Multiboot2 兼容内核的标头,但是当我multiboot2在 grub 中尝试该命令时,它给出了以下错误消息:
错误:不支持的标签:0xc
我的 Multiboot2 标头定义为:
section .multiboot align=4096
mbhead: dd 0xe85250d6
dd 0
dd 76
dd 0 - 76 - 0xe85250d6 ; TODO the linker and assembler get angry if we calculate this with symbols, we need to do this by hand
dw 1 ; multiboot information request
dw 0
dd 20
dd 1
dd 2
dd 6
dw 4 ; console flags
dw 0
dd 12
dd 0x3
dw 5 ; framebuffer settings …Run Code Online (Sandbox Code Playgroud) 有没有一种快速可靠的方法可以找出内存中 Multiboot 1 启动信息的总大小?
\n\n只是为了澄清:我不是在询问 EBX 寄存器中的值所指向的结构的大小,而是在询问内存中所有信息的总大小。
\n\n我目前正在开发 x86 Multiboot 1 兼容内核。该标准不保证 GRUB 将在何处放置此信息或其总大小。标准规定:
\n\n\n\n\n“Multiboot信息结构及其相关子结构可以由引导加载程序放置在内存中的任何位置(当然,为内核和引导模块保留的内存除外)。这是操作系统\xe2\x80\x99的责任以避免覆盖该内存,直到使用完毕为止。”
\n
实际上,这似乎总是在最低 1MB 内存中加载。\n到目前为止,在启动期间,我使用最低 1MB 的标识映射来初始化启动分页结构,以确保可以访问多重启动信息。找出这个结构的位置很简单,但我还没有找到任何关于找到准确尺寸的信息。(最好不要走遍整个结构)。
\n