I am learning the basic of OS making. I have made a multi boot header compliant .asm file and a .c file. The code in the .asm file calls the main function of .c file.
The problem is that QEMU is unable to boot from the file produced after the compilation and linking of the .asm and the .c file .
It simply says that it can't find a bootable device.
Although, I am able to boot from a simple .asm file like :-
mov ax, 0x0e
mov al, 'H'
int 10h
times 510 - ($ - $$) db 0
jmp $
dw 0xaa55
Is there something more which I have to do?
QEMU 2.0.0 does support multiboot
man qemu says:
-kernel bzImage
Use bzImage as kernel image. The kernel can be either a Linux kernel or in multiboot format.
I have uploaded a minimal hello world example at: https://github.com/cirosantilli/x86-bare-metal-examples/tree/dbbed23e4753320aff59bed7d252fb98ef57832f/multiboot
It generates a GAS + C multiboot file, and uses QEMU to run it.
grub-mkrescue can also convert a multiboot binary to a bootable .iso image which is another good approach.
Barry mentions that multiboot2 is not supported. How to generate a multiboot2 image in case you want to test it: How to compile the simple kernel in multiboot2 Spec corrently?
QEMU doesn't have native support for multiboot. Instead, you'll need to create a virtual hard drive image and install some sort of multiboot boot loader (such as grub), then put your multiboot image somewhere on the drive (i.e. in a file on a partition).
As far as actually installing grub onto a virtual HDD, there's multiple ways to do it, but here's the process I always use:
Use qemu-img or dd if=/dev/zero to create your HDD image.
Download a Linux installer ISO (I typically use Arch Linux).
Boot qemu with the blank HDD image and ISO using -hda <HDD-image-filename> -cdrom <ISO-file-name> -boot once=d. The last bit ensures qemu will try to boot from CD first.
Use fdisk/parted/etc to format the disk.
Mount your boot partition (the one you want to install grub to) and use grub-install.
Unmount and shut down the emulator.
Then, you'll be able to boot off the HDD image and use grub or whatever loader you choose to boot your multiboot image.
The reason your simple ASM example works is because you're effectively emulating the MBR, the first sector of a typical hard drive, so QEMU's BIOS will boot from it (specifically, it sees that 0xaa55 signature).
No, QEMU does have native support for the old multiboot spec, although it does not support VBE, ex.. Just compile from a freestanding compiler with the correct legacy multiboot header into an ELF executable and run with the -kernel option
Related
I wrote a short boot code and tried to run it with Qemu with:
qemu-system-arm.exe -M versatilepb -cpu cortex-a9 -kernel boot.bin
I expected the code to be loaded to address 0x8400000 but qemu returned me the error
Trying to execute code outside RAM or ROM at 0x84000000
This usually means one of the following happened:
(1) You told QEMU to execute a kernel for the wrong machine type, and it crashed on startup (eg trying to run a raspberry pi kernel on a versatilepb QEMU machine)
(2) You didn't give QEMU a kernel or BIOS filename at all, and QEMU executed a ROM full of no-op instructions until it fell off the end
(3) Your guest kernel has a bug and crashed by jumping off into nowhere
This is almost always one of the first two, so check your command line and that you are using the right type of kernel for this machine.
If you think option (3) is likely then you can try debugging your guest with the -d debug options; in particular -d guest_errors will cause the log to include a dump of the guest register state at this point.
Execution cannot continue; stopping here.
So I guess my code has not yet started running because it is not loaded into the right place
What am I wrong about?
Thanks
You say "I expected the code to be loaded to address 0x8400000" but QEMU's error message says "0x84000000" which is not the same number (it has an extra 0). This suggests that you have a typo in your linker script or whatever is creating your boot.bin file. (I am assuming that boot.bin is an ELF file, which QEMU loads at the addresses the ELF file specifies, because otherwise it will be loaded into RAM anyhow on the assumption that it's a Linux kernel image capable of self-relocation.)
I have created the USB_DEVICE bootloader for my project. In that I am triggering bootloader when there is data written on valid flash address 0x9D061000. In my application firmware, I am initialising flash, and then writing data on the address 0x9D061000 to go in firmware upgraded mode. My linker scripts are attached below. My firmware size is ~278kB. My other firmware with same linker but size <100KB is working fine with the bootloader. Is it the hex file size error? or did I restricted addresses in linker file. I don't know how to edit the linker file, And I don't got any reference or guide for editing it.
Note: I copy pasted my .ld linker files to txt files.
application_linker_file.txt
bootloader_linker_file.txt
I am using PIC32MX795F512L, MPLABx3.40, Harmony version 1.7.1 ans XC32 compiler version 1.42
I'm working on creating file that I can load with -kernel option of qemu. I mostly mind here u-boot config file that I have found information should be placed somewhere in file. That file have to contain u-boot binary, freebsd kernel and RTOS to run ( so i can choose which kernel to load or do some experimental developement in loading 2 OS at same time - eg. FreeBSD is loaded by u-boot and then FreeBSD loads FreeRTOS on 2nd core - so called ASMP ). It seems there is no tools around to do that in automatic way ( I mean supporting multiple kernels in one flash file ). So I need to know how is u-boot flash file structured to make my own and pass it to qemu emulating am versatilepb.
qemu-system-arm -M versatilepb -m 128M -nographic -kernel myflashfile
So the answer here depends in part on the board you are emulating with QEMU. Next, unfortunately the versatilepb has been dropped from mainline U-Boot some time ago (and being ARM926EJS it is not the ideal core for ASMP, you may wish to try vexpress a9 instead). Now, all of that said, you want -pflash to pass along a binary file you control the contents of as the parallel flash device used by the machine. And you lay that out however you like since you're still using -kernel u-boot.bin to boot the machine. You may however find it easier to use -tftp /some/dir and load the files via the network instead.
I need to modify the ELF loader's kernel implementation of an Ubuntu 14.04 distribution. Having downloaded the sources using:
sudo apt-get source linux-image-$(uname -r)
I ran the configuration script:
make config
in the root source tree. After a seemingly endless sequence of input requests, the script created the .config file needed to build the kernel(or a set of modules). The kernel version I am using is linux-3.13.0 and has the following source tree layout:
$ ls
arch COPYING crypto Documentation dropped.txt FileSystemMakefile fs init Kbuild kernel MAINTAINERS mm README samples security sound ubuntu virt
block CREDITS debian.master drivers elf.dat firmware include ipc Kconfig lib Makefile net REPORTING-BUGS scripts shortcuts tools usr
The ELF loader is located in /path/to/source/fs/binfmt_elf.c. Following this question,in order to compile an individual module it is sufficient to run
make /path/to/module/directory.
In this case that would be:
make ./path/to/source/fs
The compilation is quite lengthy; it takes about twenty minutes(on a virtual machine) and the output is written(by default) in the same directory in which the module is located. I've found the object files by running:
find . -name "*.o"
in /path/to/source/fs. Filtering by name the ELF loader can be located by running:
find . -name "*elf*.o"
In the current sources it is written(by default) in:
/path/to/source/fs/binfmt_elf.o
Having gone through this tutorial, I've noticed that kernel modules have the naming convention [module_name].ko in order to distinguish them from user space object files.
My question is how can I insert the new(modified) ELF loader into the kernel given that the current ELF loader is present(as unloading it may prevent binaries from being executed)?
What you have described is not really compiling a "kernel module" as it is commonly referred to. You have built an object that is statically linked into the kernel and there is no way that you can load just that object into a running kernel.
"kernel module" usually refers to "loadable kernel module" (LKM). Building and loading the fs as an LKM is what you need/want. Take a look at the below HOWTO. Follow that to build the desired fs as an LKM. Then you can just replace that one LKM (.ko) file and reboot (normally you can dynamically remove and insert LKMs but not sure how that will affect something fundamental like the ELF fs - you can try rmmod/modprobe without a reboot first if you ike).
http://www.tldp.org/HOWTO/Module-HOWTO/x73.html
Can a new machine type be added for qemu-system-arm -M <MachineType> without having to recompile qemu or write code? Are there docs to do this? I would like to be able to emulate raspberry pi and pandaboard using qemu.
I know that meego's fork of qemu supports pandaboard, but I am trying to stick with the main stream qemu that I can manage from the apt-get package manager. the main stream qemu now supports beagleboard rev C and beagleboard xm that were previously supported only in the meego fork.
without having to recompile qemu or write code?
No. There must be some code doing the device specific emulation, like for example the way the Raspberry Pi or the Pandaboard implement video output. This is not a matter of just a few config files.
I've been able to emulate the Pi with -M versatilepb: https://raspberrypi.stackexchange.com/questions/165/emulation-on-a-linux-pc/53991#53991 and -M raspi2 has was later added in QEMU 2.6.
Maybe this feature is feasible to implement, see my experience with adding a new platform device: How to add a new device in QEMU source code?
There, I only needed to add a single line to attach a new device to versatilepb:
sysbus_create_simple("lkmc_platform_device", 0x101e9000, pic[18]);
so maybe we could have a config file containing lines of type:
type name regid irq
sysbus lkmc_platform_device 0x101e9000 18
Related: out-of-tree devices: How to create out-of-tree QEMU devices?