Lowlevel

Lowlevel => Softwareentwicklung => Thema gestartet von: OsDevNewbie am 21. May 2012, 16:31

Titel: Booten mit Grub
Beitrag von: OsDevNewbie am 21. May 2012, 16:31
Hallo Community,
ich habe schon alles mögliche versucht und gesucht, aber ich bekomme es einfach nicht hin mit Grub meinen Kernel zu starten. Eine Bootfähige CD mit Grub drauf bekomme ich hin und mein Kernel ist auch drauf, aber Grub bootet einfach nicht davon. Ich mache die Cd wie es hier beschrieben wird: http://www.lowlevel.eu/wiki/Grand_Unified_Bootloader#CD-Image_herstellen (http://www.lowlevel.eu/wiki/Grand_Unified_Bootloader#CD-Image_herstellen)
Ich arbeite auf Ubuntu. Ich wollte auch schon eine Eltorito CD erstellen, aber die Datei stage2_eltorito ist auf meinem Dateisystem nicht vorhanden. Ich hoffe ihr könnt mir helfen.

Noch eine Frage:
Laut dem Wiki muss die Startaddresse 1MB sein. Aber ist es normal, dass beim compilierten Kernel dann angezeigt wird, dass er 1MB gross sei, obwohl er viel kleiner ist?
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 21. May 2012, 18:37
Hi,

ich habe schon alles mögliche versucht und gesucht, aber ich bekomme es einfach nicht hin mit Grub meinen Kernel zu starten. Eine Bootfähige CD mit Grub drauf bekomme ich hin und mein Kernel ist auch drauf, aber Grub bootet einfach nicht davon.
Das widerspricht sich irgendwie. Entweder die CD ist bootfähig, oder sie ist es nicht. Welche Schritte hast du durchgeführt, und was genau passiert, wenn du von der CD bootest?

Die Datei stage2_eltorito gibt es nur, wenn du GRUB Legacy installiert hast. Bei Ubuntu ist standardmäßig GRUB 2 installiert. Deswegen ist das für dich erstmal nicht relevant, solange du nicht den Bootloader deines Systems wechseln willst.

Laut dem Wiki muss die Startaddresse 1MB sein. Aber ist es normal, dass beim compilierten Kernel dann angezeigt wird, dass er 1MB gross sei, obwohl er viel kleiner ist?
Das ist nicht normal. Wie sieht denn dein Linker-Skript aus, und wie rufst du den Linker auf?
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 22. May 2012, 19:35
Hallo,
also ich arbeite mit Eclipse. Ich habe dort in den Eigenschaften dann einfach ein Flag angegeben mit dem Linkerscript, das wie folgt lautet:
/*  Bei _start soll die Ausfuehrung losgehen */
ENTRY(_start)

/*
 * Hier wird festgelegt, in welcher Reihenfolge welche Sektionen in die Binary
 * geschrieben werden sollen
 */
SECTIONS
{
    /*
     * . ist die aktuelle Position in der Datei. Wir wollen den Kernel wie gehabt
     * an 1 MB laden, also muessen wir dort die erste Sektion hinlegen
     */
    . = 0x100000;

    /*
     * Der Multiboot-Header muss zuerst kommen (in den ersten 8 kB).
     * Die Standardsektionen einfach hintereinander weg einbinden.
     */
    .text : {
        *(multiboot)
        *(.text)
    }
    .data ALIGN(4096) : {
        *(.data)
    }
    .rodata ALIGN(4096) : {
        *(.rodata)
    }
    .bss ALIGN(4096) : {
        *(.bss)
    }
}

Also die CD ist zwar bootfähig und Grub meldet sich auch, aber danach gelange ich in die Shell und wenn ich von dort aus meinen Kernel via
kernel /kernel
boot
starten will, meldet er, er kenne den Befehl "kernel" nicht (In einem Linux-Forum habe ich gelesen, dass es so gehen soll).
Die CD mache ich via
#!/bin/sh
#Konstanten
PFAD=/tmp/kernel
AUSGABE=./os.iso

#lese Pfad zum Kernel und Name ein
read KERNEL

mkdir ${PFAD}
rm ${PFAD}/*
cp ${KERNEL} ${PFAD}/kernel

grub-mkrescue -o ${AUSGABE} ${PFAD}

Aber irgendwie kommt auch kein Menu obwohl eins kommen sollte:
Meine grub.cfg:
set timeout=15
set default=0

menuentry "OS"
{
multiboot /kernel
boot
}
Ich hoffe ihr könnt mir helfen.
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 22. May 2012, 19:48
Ist dein Ubuntu ein 64-Bit System?

Die Befehle in der Shell sollten dieselben wie in der grub.cfg sein, also multiboot /kernel und dann boot. (Das mit kernel gilt nur für GRUB Legacy, nicht für GRUB 2)

Die grub.cfg sollte so eigentlich auch funktionieren. Landet die denn im Verzeichnis boot/grub/ auf dem ISO-Abbild? Dein Skript scheint die ja nicht mit in das Verzeichnis zu kopieren.
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 22. May 2012, 20:18
Ist dein Ubuntu ein 64-Bit System?
ja

Landet die denn im Verzeichnis boot/grub/ auf dem ISO-Abbild?
Nein dort steht dann nur
insmod part_acorn
insmod part_amiga
insmod part_apple
insmod part_bsd
insmod part_gpt
insmod part_msdos
insmod part_sun
insmod part_sunpc
source /boot/grub/grub.cfg

Dein Skript scheint die ja nicht mit in das Verzeichnis zu kopieren.
Wo muss ich es hin kopieren?
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 22. May 2012, 20:52
Ist dein Ubuntu ein 64-Bit System?
ja
Dann glaube ich, dass die große Datei daher kommt, dass du für 64-Bit kompilierst. Du solltest Eclipse beibringen, dass es für 32-Bit kompilieren soll. Ich weiß nicht wie es geht, aber irgendwie musst du in die CFLAGS den Parameter -m32, in die LDFLAGS -melf_i386 reinkriegen.

Du kannst übrigens prüfen, ob es wirklich eine 64-Bit Datei ist, indem du mal objdump -f kernel ausführst.

Wo muss ich es hin kopieren?

Du musst das Verzeichnis boot/grub in deinem ${PFAD} Verzeichnis erstellen, und dann die Datei nach ${PFAD}/boot/grub/grub.cfg kopieren. (Soweit ich weiß.)
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 22. May 2012, 22:08
Dann glaube ich, dass die große Datei daher kommt, dass du für 64-Bit kompilierst. Du solltest Eclipse beibringen, dass es für 32-Bit kompilieren soll. Ich weiß nicht wie es geht, aber irgendwie musst du in die CFLAGS den Parameter -m32, in die LDFLAGS -melf_i386 reinkriegen.
Aber ich programmiere doch für den Long Mode? Muss ich da nicht 64-Bit compilieren?
Du kannst übrigens prüfen, ob es wirklich eine 64-Bit Datei ist, indem du mal objdump -f kernel ausführst.
Die Ausgabe davon ist:
V0.0.1:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x000000000010000c
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 22. May 2012, 22:43
Dann glaube ich, dass die große Datei daher kommt, dass du für 64-Bit kompilierst. Du solltest Eclipse beibringen, dass es für 32-Bit kompilieren soll. Ich weiß nicht wie es geht, aber irgendwie musst du in die CFLAGS den Parameter -m32, in die LDFLAGS -melf_i386 reinkriegen.
Aber ich programmiere doch für den Long Mode? Muss ich da nicht 64-Bit compilieren?
Dann schon. Die nächste Frage wäre dann, ob GRUB da mitmacht. Aber ich würde sagen, das ist ein Problem, das du erst im nächsten Schritt angehen solltest. (Es sei denn du willst das Booten von CD erstmal zurückstellen.)
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 23. May 2012, 17:56
Hallo nochmal,
das Menue kommt zwar jetzt, aber er sagt er finde den Bootheader nicht. Warum?
Mein Bootheader lautet:
MB_MAGIC = 0x1BADB002 #Magicnumber - Erkennungsmerkmal für GRUB
MB_FLAGS = 0 #Flags (keine)
MB_CHECKSUM = -(MB_MAGIC + MB_FLAGS) #Prüfsumme

.section multiboot
.align 4
.int MB_MAGIC
.int MB_FLAGS
.int MB_CHECKSUM
...

Die disassemblierte Binärdatei lautet so:
Disassembly of section .text:

0000000000100000 <_start-0xc>:
  100000: 02 b0 ad 1b 00 00    add    0x1bad(%rax),%dh
  100006: 00 00                add    %al,(%rax)
  100008: fe 4f 52              decb   0x52(%rdi)
  10000b: e4 31                in     $0x31,%al
Und das steht ganz am Anfang.
Danke erstmal für deine Hilfe.
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 23. May 2012, 20:21
Das liegt vermutlich daran, dass der Kernel 1 MB groß ist. Dann ist der Multibootheader nicht mehr in den ersten 8 KByte und GRUB findet den nicht mehr. Ich weiß nicht genau, warum das Problem auftritt, aber es scheint etwas mit der Größe der Pages von x86-64 zu tun haben. Du könntest entweder den Kernel nach 0x200000 (oder ein Vielfaches davon) linken, oder du übergibst dem Linker den Parameter -z max-page-size=0x1000.
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 23. May 2012, 21:00
[...] oder du übergibst dem Linker den Parameter -z max-page-size=0x1000.
Und was macht das?
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 23. May 2012, 21:06
Keine Ahnung. Ich hab es hier gefunden, aber da wird es auch nicht erklärt. http://wiki.osdev.org/Creating_a_64-bit_kernel#My_kernel_is_way_too_big.21.21.21
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 23. May 2012, 21:51
Ich hab das jetzt gemacht und der Kernel ist jetzt wirklich nicht mehr 1MB gross sondern nur noch 26KB. Aber er findet den Multibootheader immer noch nicht. Ist es normal, dass GRUB selbst ein MB benötigt?
Jetzt meldet GRUB: "error: out of memory". Was soll das bedeuten?
Danke.
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 02. June 2012, 14:44
Hallo,
ich habe es geschafft, dass GRUB bootet. Aber danach kommt dieses Bild (siehe Anhang). Der Cursor oben links blinkt dabei, was aber nicht vom Kernel kommen kann, da ich aus Testzwecken als erste Aktion einen String ausgeben lasse der aber nicht kommt. Funktioniert GRUB nicht richtig, denn ich habe auf der Fehlerliste der TODO-Liste (http://www.lowlevel.eu/wiki/TODO#.C3.9Cberarbeiten.2FFehler_beheben) gesehen, dass die GRUB-CD nicht richtig funktioniert. Ist diese Information noch Aktuell?
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 02. June 2012, 15:34
Wenn dann liegt das Problem nicht bei GRUB sondern an der Anleitung. Du kannst ja auch mal die von osdev.org ausprobieren: http://wiki.osdev.org/GRUB_2

Es könnte auch an deinem Kernel liegen. Ich weiß nicht, ob qemu 64-Bit-ELFs laden kann (ich glaube nicht), aber du kannst es ja mal versuchen, indem du qemu mit den Parametern -kernel pfad/zum/kernel aufrufst.
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 02. June 2012, 15:41
Hallo,
also
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 02. June 2012, 16:13
Ich hab mal ein wenig experimentiert. GRUB2 bootet zwar den Kernel, aber springt nicht in den Long Mode. Das musst du tun, und zwar mit Code der für den 32-Bit Modus kompiliert ist.
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 03. June 2012, 00:03
Das weiss ich schon. Aber bei mir bootet der nicht. Ich habe dir mal meine ISO geschickt und meinen Kompilierten Kernel.
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 03. June 2012, 00:37
Bei mir ist leider nichts angekommen. Kannst du das irgendwo hochladen (rapidshare, dropbox, ...)?
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 03. June 2012, 00:50
Ich habe es nochmal versucht. Jetzt sollte etwas angekommen sein.
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 03. June 2012, 00:54
Jup, schau ich mir mal an.
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 03. June 2012, 01:26
Also, wenn ich das CD-Image in meinem qemu boote (qemu -cdrom os.iso), bekomm ich die Meldung

error: out of memory.
error: no loaded kernel.

Das liegt daran, dass wohl 128 MB RAM nicht ausreichen. Wenn ich den RAM auf 512 MB setze komm ich auch bis zu dem blinkenden Cursor.

Das Problem kann man auch sehen, wenn man den Kernel mal mit objdump -x V0.0.1 analysiert.
    LOAD off    0x00000000000000c0 vaddr 0x0000000000100000 paddr 0x0000000000100000 align 2**5
         filesz 0x0000000000001268 memsz 0x00000000060120a0 flags rwx

Am memsz sieht man, dass der Kernel ziemlich genau 100 MB Speicher braucht. Keine Ahnung warum GRUB dadraus so viel mehr macht, aber auf jeden Fall ist das ein Problem mit dem Kernel.

Weiter im Listing von objdump sieht man folgende Symbole an diesen hohen Adressen:
0000000006112040 g     O .bss 0000000000000010 gdtr
...
0000000006112050 g     O .bss 000000000000000c gdt_entry
0000000006112060 g     O .bss 0000000000000040 cr3
Da die alle im .bss-Segment liegen, schließe ich erstmal, dass irgendwas an der Definition des .bss-Segments im Linkerskript nicht richtig ist. Wenn du allerdings immer noch das Linkerskript aus deinem zweiten Post verwendest, dann weiß ich auch nicht was da falsch sein soll.

Eigentlich wollte ich jetzt noch mehr erzählen, was alles nicht funktioniert, aber ich steig auch gerade nicht durch, was qemu mit dem Kernel macht. Ist schon zu spät für sowas. Deswegen nur so viel: Das Problem ist definitiv, dass du einen 64-Bit-Kernel erstellst. Der kann nicht ausgeführt werden. Du musst den Compiler und den Linker anweisen 32-Bit-Code zu erzeugen. Das geht, indem du GCC als Flags -m32 übergibst und LD -melf_i386. Für AS ist --32 nötig. Wenn du zum Linken oder Assemblieren GCC verwendest, sollte bei beiden aber auch -m32 gehen. Keine Ahnung wie genau man das Eclipse beibringt, aber wenn du das mit dem Linkerskript hingekriegt hast, sollte auch das gehen. Wenn nicht, solltest du Eclipse nicht mehr zum Kompilieren verwenden, sondern nur noch als Editor. In einer Shell make eintippen (oder Pfeil-nach-oben + Enter) ist auch nicht viel umständlicher.
Titel: Re: Booten mit Grub
Beitrag von: OsDevNewbie am 03. June 2012, 01:52
Hallo,
aber wie kann ich dann einen 64-Bit Kernel erstellen, wenn ich ihn mit 32-Bit compilieren soll/muss?
Titel: Re: Booten mit Grub
Beitrag von: Jidder am 03. June 2012, 02:12
Willst du vielleicht nicht erstmal einen 32-Bit-Kernel schreiben? Das ist etwas einfacher.

Wenn nicht: Du musst trotzdem einen kleinen 32-Bit-"Kernel" schreiben, der nichts anderes macht als in den 64-Bit-Modus zu wechseln, die Binary des 64-Bit Kernels zu laden, diese korrekt im virtuellen Adressraum zu platzieren und dann dahinspringen. (Das heißt du brauchst zwei Binaries, die erste ist der Loader und die zweite der Kernel, den du dann als Multiboot-Modul lädst.)

Die Alternative wäre, dass du 32-Bit- und 64-Bit-Code zu einer Binary kombinierst. Du könntest zum Beispiel mit .code32 den Assembler anweisen 32-Bit-Code zu generieren, damit du in den Long Mode wechseln kannst. Das hab ich allerdings bisher nicht ausprobiert. Möglicherweise kannst du sogar 32-Bit C-Code dazulinken, aber auch das hab ich nicht ausprobiert.