Lowlevel
OffZone => Offtopic => Thema gestartet von: sp am 16. February 2005, 12:50
-
Hallo
ich habe mir überlegt, dass es vielleicht besser ist Grub (oder ähnliches) zu benutzen, anstatt einen eigenen Bootloader zu erstellen. Erstmal jedenfalls.
Mein "OS" liegt im Moment auf einer Diskette, daher wollte ich fragen ob jemand Erfahrung damit hat, mit Grub von Diskette zu booten? Bzw. wie man Grub auf die Diskette bekommt.
sp
PS: Ich nutze Windows.
-
Mit Windows eigendlich kaum möglich weil du ja für GRUB ext2 braucht soweit ich weiß... Aber mit Hurd, Linux etc kein Problem! Für weiteres kann man die GRUB doku zurate ziehen: http://www.gnu.org/software/grub
-
Nee... also soviel ich weiß unterstützt GRUB mehrere Dateisysteme, darunter auch FAT12...
-
Aber soweit ich weiß nur um nen Kernel davon zu laden....
-
Ich hab hier ein SuSE 9.1 als VM, könnte ich damit Grub auf einer Diskette installieren? Also die VM kann auf das Floppy-Laufwerk zugreifen.
-
ja das müsste gehen....
-
Is zwar schon etwas älter, aber GRUB auf Diskette geht, dafür gibts im downloadbereich auf osdever.net sogar nen diskettenimage (läd kernel.bin)
-
Wo is da ein Image? Da is nur der Source... (ich habs runtergeladen)
-
ich hatte es nich runtergeladen, und drüber stand Floppy Images... Naja, errare humanum est
-
Halt, stop ich hab mich geirrt....
Ich hab des falsche runtergelagen...
-
Ich hab die Bin's runterladen und sie dann auf der Diskette installiert. Mittlerweile ist mein Kernel auch Grub-Kompatibel, ist ne feine Sache.
-
Wo gibts die bin's?
Und wegen, dem Multiboot header. Kannst du mir auch mal sagen, wie du dass genau gemachst hast (ich mein mit dem Header)?
-
Wo gibts die bin's?
Google :), auf irgend einem gnu server.
Und wegen, dem Multiboot header. Kannst du mir auch mal sagen, wie du dass genau gemachst hast (ich mein mit demm
Header)?
Nein, das geht nicht in C, man muss eine ASM Datei vor den Kernel linken.
-
Aber auf http://lowlevel.brainsware.org/index.php?pagename=tutorials&showtut_id=2#Programmierung%20eines%20GRUB-kompatiblen%20Kernels wird es mit C gemacht....
Weißt du wo es weitere Infos über den Multiboot-Header gibt, oder kannst du mal bitte deinen posten?
-
Ohh, dann nehme ich meine voreilige Behauptung natürlich zurück.
Ich denke mal, das hier ist der Trick:const unsigned MultibootHeader[12] __attribute__
((section(".text"))) = { /* Header Information */ };
Aber ich bleibe, wie in der Grub-Doku beschrieben, bei der vorgeschobenen ASM Datei, die dann auch die main() aufruft.
So kann ich mir auch alles mögliche (Multiboot-Struct, EAX, etc...) als Parameter übergeben.
Wichtig ist nur, dass du sobald wie möglich deinen eigenen Stack initialisierst.
-
In C gehts irgendwie doch net....
Naja, dann nehm ich doch ASM. Auf http://www.gnu.org/software/grub/ find ich das mit der ASM Datei aber net. Kannst du mir mal bitte den link sagen?
-
In der Grub Dokumentation gibt es ein Beispiel OS, leider find ich es gerade nicht mehr.
Aber das hier sollte dir auch weiterhelfen:
http://www.osdever.net/tutorials/grub.php?the_id=5
-
Ja, da is es aber mit dem elf-format....
Kannst du deine asm datei mal posten?
Bitte....
-
Ich benutze auch ELF, sorry.
Würde ich dir aber auch empfehlen,
macht die Sache viel einfacher.
-
ok, also muss ich meine 2 Dateien
multiboot.asm
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
; The Multiboot header (in NASM syntax)
align 4
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd CHECKSUM
und kernel.c
xxx
kompilieren und dann zu kernel.elf zusammenfügen, oder muss in die "multiboot.asm" was anderes?
Ich hoffe ich nerv mit meinen Fragen net...
-
Ein bisschen mehr muss schon in die ASM Datei, hier ein Beispiel:
[BITS 32]
EXTERN _main
GLOBAL start
jmp start
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
align 4
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd CHECKSUM
start:
push 0
popf
push eax
push ebx
call _main
Und die Kernel.cppint main( multiboot_info_t *boot_info, DWORD magic_code )
{
}
Aber denk an deinen Stack, bevor du zur main springst.
-
Danke! :D
Noch eine Frage zum Stack:
Warum mus ich den Stack initialisieren? Zuwas ist das gut?
-
Ich dreh noch durch!
Wenn ich die Datei hier:
int main(multiboot_info_t *boot_info, DWORD magic_code)
{
char *Text = "Welcome to Protected Mode";
char *VideoMem = (char*)0xB8000;
while(*Text)
{
*VideoMem = *Text;
*VideoMem++;
*VideoMem = 7;
*VideoMem++;
*Text++;
}
return(0);
}
kompilieren will, dann sagt er: Fehler beim Parsen before '*' token
dann hab ich int main(multiboot_info_t *boot_info, DWORD magic_code
in int main(multiboot_info_t, *boot_info, DWORD magic_code
umgeändert, aber trotzdem die gleiche meldung...
-
int main(multiboot_info_t, *boot_info, DWORD magic_code
Das ist natürlich auch nicht richtig.
Damit der Code funktioniert, musst du den Struct multiboot_info_t aus der Grub-Doku einbinden.
Sonst kennt er den Typ nicht.
-
Ich glaub ich stell mich zu dumm für Grub an....
Ich bekomm des einfach net hin!
-
Naja, du kannst boot_info natürlich erst einmal auch weglassen. darfst dann nur nicht ebx pushen.
-
Also, bevor ich dann noch tausendmal frag:
1. Ich mach eine Datei Boot.asm
[BITS 32]
EXTERN main
GLOBAL start
jmp start
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
align 4
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd CHECKSUM
start:
push 0
popf
push eax
call main
(Die unterstriche hab ich weggelassen, weil es unter Linux net anders geht.)
2. Dann noch eine ckernel.c(pp)
int main( DWORD magic_code )
{
char *Text = "Welcome to Protected Mode";
char *VideoMem = (char*)0xB8000;
while(*Text)
{
*VideoMem = *Text;
*VideoMem++;
*VideoMem = 7;
*VideoMem++;
*Text++;
}
return(0);
}
3. dann die boot.asm zu einer *.obj Datei assemblieren und die kernel.c(pp) zu einer *.obj kompilieren.
3. mit dem
OUTPUT_FORMAT("elf32-i386")
INPUT(kernel32.obj ckernel.obj)
ENTRY(entry)
virt = 0xC0000000; /* 3 gig */
phys = 0x100000; /* 1 meg */
SECTIONS
{ .text virt : AT(phys)
{ code = .;
*(.text)
. = ALIGN(4096); }
.data : AT(phys + (data - code))
{ data = .;
*(.data)
. = ALIGN(4096); }
.bss : AT(phys + (bss - code))
{ bss = .;
*(.bss)
*(COMMON)
. = ALIGN(4096); }
end = .; }
linkerfile linken
4. Das ganze von grub laden lassen
5. Hoffen das es funktioniert
So müsste es gehen, oder is es mal wieder total falsch?
-
Die unterstriche hab ich weggelassen, weil es unter Linux net anders geht.
Was hat das den mit Linux zu tun? Das ist doch gehört doch wohl eher zu C.
Sonst einfach zusammenbauen und booten, wenns nicht geht hilft uns vielleicht schon die Fehlermeldung von Grub weiter.
-
Wenn ich die C Datei kompilieren will kommt
Fehler beim Parsen before "magic_code"
-
Was für einen Compiler benutzt du?
Hast du DWORD deklariert ... ?
-
Was für einen Compiler benutzt du?
GCC
Hast du DWORD deklariert ... ?
Halt in der asm Datei...
-
Du musst den Typ auch in C deklarieren.
typedef unsigned long dword;
#define DWORD dword
-
Ha, es geht, aber nun brauch ich nur noch grub
Die Version, die ich hab läde nur eine .bin Datei
-
Oder, es geht schon, aber nun meckert Grub das:
Loading below 1MB is not supportet
-
Du musst dem Linker sagen, dass er ein Offest von 1 MB benutzen soll.
Dann wird Grub dein Kernel, hoffentlicht, ohne Jammern laden und ausführen.
Den Fehler hatte ich beim Ersten Start übrigens auch :).
-
Hallo,
also muss ich doch das
OUTPUT_FORMAT("elf32-i386")
INPUT(kernel32.obj ckernel.obj)
ENTRY(entry)
virt = 0xC0000000; /* 3 gig */
phys = 0x100000; /* 1 meg */
SECTIONS
{ .text virt : AT(phys)
{ code = .;
*(.text)
. = ALIGN(4096); }
.data : AT(phys + (data - code))
{ data = .;
*(.data)
. = ALIGN(4096); }
.bss : AT(phys + (bss - code))
{ bss = .;
*(.bss)
*(COMMON)
. = ALIGN(4096); }
end = .; }
umändern, oder? Wohin lädst duu deinen Kernel?
-
Hier ist das Linker-Script welches ich benutzte, ist allerdings nicht von mir...
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
SECTIONS
{
.text 0x100000:
{
code = .; _code = .; __code = .;
*(.text)
. = ALIGN(4096);
}
.data :
{
__CTOR_LIST__ = .; LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) *(.ctors) LONG(0) __CTOR_END__ = .;
__DTOR_LIST__ = .; LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) *(.dtors) LONG(0) __DTOR_END__ = .;
data = .; _data = .; __data = .;
*(.data)
. = ALIGN(4096);
}
.bss :
{
bss = .; _bss = .; __bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}
-
es geht, danke
-
Noch eine Frage:
Hab ich im pm automatisch einen Stack, wo ich sachen drauf pushen kann?
-
Jain, Grub baut natürlich einen Stack, aber damit kann es, wenn du nicht prüfst wo er liegt und wie groß er ist, zu einem Absturz kommen.
-
Wiedereinmal ne dumme Frage: Wie find ich des raus?
-
Register ESP auslesen und schauen wo sich der Stack befindet.