【问题标题】:You need to load your kernel first Error您需要先加载内核错误
【发布时间】:2016-11-22 11:41:41
【问题描述】:

现在当我选择 Custom OS 时,当我从 GRUB 的菜单中执行我的操作系统时,我得到一个紫色背景:

error: secure boot forbids loading module from (hdo, gpt7)/boot/grub/x86_64-efi/multiboot.mod
error: You need to load your kernel first    
Press any key to continue . . .

.. 我不一定明白为什么会这样。让我给你看看我的文件:

loader.S:

#Global MultiBoot Kernel Recongnzation
.set MAGIC, 0x1BADB002
.set FLAGS , (1<<0 | 1<<1)
.set CHECKSUM, -(MAGIC + FLAGS)

#Putting in object file
.section .multiboot
    .long MAGIC
    .long FLAGS
    .long CHECKSUM


.section .text

    .extern kernelMain
    .globl loader

        loader:
                mov $kernel_stack , %esp
                push %eax
                push %ebx
                call kernelMain

        _eof:
             cli
             hlt 
             jmp _eof


.section .bss
.space 2*1024*1024 #2 MiB
kernel_stack:

生成文件:

GPPARAMS =  -m32 -Iinclude -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -Wno-write-strings
ASPARAMS =  --32
LDPARAMS =  -melf_i386
objects = kernel.o loader.o 

all:
    g++ -m32 -Iinclude -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -Wno-write-strings  -o kernel.o -c kernel.cc
    as $(ASPARAMS) -o loader.o loader.S

mykernel.bin : linker.ld $(objects)
    ld $(LDPARAMS) -T $< -o $@ $(objects)

install: mykernel.bin
    sudo cp $< /boot/mykernel.bin

clean:
      rm $(objects)

kernel.cc:

int strlen(char* str)
{
        int l=0;
        while(str[l]!='\0')l++;
        return l;
}

void printf(char *str)
{
        unsigned short* ViedoMemory = (unsigned short*)0xb8000;

        for(int i=0; str[i]!='\0'; ++i)
                ViedoMemory[i]= (ViedoMemory[i] & 0xFF00)|str[i];
}



extern "C" void kernelMain(void* multiboot_structure, unsigned int magicnumber)
{
    printf("Hello World");
    while(1);
}

linker.ld:

ENTRY(loader)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)

SECTIONS
{
  . = 0x0100000;

  .text :
  {
    *(.multiboot)
    *(.text*)
    *(.rodata)
  }

  .data  :
  {
    start_ctors = .;
    KEEP(*( .init_array ));
    KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
    end_ctors = .;

    *(.data)
  }

  .bss  :
  {
    *(.bss)
  }

  /DISCARD/ : 
  { 
    *(.fini_array*) 
    *(.comment) 
  }
}

现在我如何加载它是首先由makefile完成:

make
make mykernel.bin
make install

然后我当然在/boot/grub/grub.cfg 中添加了这个:

### BEGIN MYKERNEL
menuentry 'Operating System Tut'{
  multiboot /boot/mykernel.bin
  boot
}
### END MYKERNEL ###

然后当我执行sudo reboot 并从下拉列表中选择Operating System Tut 时,它会出现我之前描述的错误:

error: secure boot forbids loading module from (hdo, gpt7)/boot/grub/x86_64-efi/multiboot.mod

error: You need to load your kernel first

Press any key to continue . . .

再一次,我不明白为什么内核没有首先加载......我们将不胜感激。

【问题讨论】:

  • 它没有卡在启动中。查看屏幕的左上角。它说Hello World。我认为您的问题与GRUB配置更相关,但也可能与您的硬件交互,但确实很难说。
  • 这些问题超出了所提问题的范围。你不妨看看OSDev Wiki。您可以编写一个循环来简单地在当前屏幕的所有单元格中放置一个具有适当属性的空格。在 80x25 的文本显示器上,有 2000 个单元,每个单元 2 个字节。至于写入您指定 row 和 col 的另一个位置 ViedoMemory[row*80+col+i]= (ViedoMemory[row*80+col+i] &amp; 0xFF00)|str[i]; 。 80 是列数。如果您处于具有不同列数的文本模式,则必须更改它
  • 我不是-Wno-write-strings 的粉丝。我建议不要这样做,只需修改您的函数 strlenprintf 以使用 const char *str 而不是 char *str
  • 你问了关于如何确定行数的问题,我回答了这个问题,我回答了关于必须进行地址计算才能将事物放在一行/列的问题。那个视频很简单。你现在想做的事情比那个视频复杂得多(是的,我之前看过)。与几乎所有其他方法相比,使用视频模式工作非常容易当您处于保护模式时,事情并不容易。
  • 我尝试在 QEmu 上运行该内核,但没有成功...视频 2 展示了如何在 VirtualBox 中运行它 :-)

标签: c++ x86 gnu-assembler osdev grub


【解决方案1】:

尝试关闭 BIOS 中的 Secure Boot 选项,看看是否有不同的结果。启用此选项后,固件会检查您的引导加载程序是否已签名,如果未签名,或者其签名与存储在 NVRAM 中的密钥不对应,或者是否在 NVRAM 中被列入黑名单,则会阻止其执行。

Managing EFI Boot Loaders for Linux: Dealing with Secure Boot

【讨论】:

  • 请问先生您是如何进入 BIOS 的?
  • @Dsafds 当您打开计算机时,您应该会看到主板制造商的启动画面,同时在此屏幕上按删除键(有时会有所不同,取决于品牌 - 您可以查看不过)进入 BIOS。
  • key因厂商而异,一般为DEL或F2。
  • 好的,我设法从 BIOS 禁用安全启动。但现在它给了我一个空的紫色屏幕.. 它假设给我一个地狱世界,正如你从 C++ 文件中看到的那样
  • 那么引导工作了吗?问题似乎是您现在的printf 实现,或其他问题。
猜你喜欢
  • 2019-05-05
  • 1970-01-01
  • 2012-06-12
  • 1970-01-01
  • 1970-01-01
  • 2019-09-24
  • 2019-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多