qemu hangs after booting a GNU-EFI os - linux

I was trying to write a "hello world" x86_64 OS with GNU-EFI according to an article:https://wiki.osdev.org/GNU-EFI, but I ran into some problem.
When I boot the img using following command
sudo qemu-system-x86_64 -drive file=$(BUILD_DIR)/$(OSNAME).img -m 256M -cpu qemu64 \
-drive if=pflash,format=raw,unit=0,file="$(OVMF_DIR)/OVMF_CODE.fd",readonly=on \
-drive if=pflash,format=raw,unit=1,file="$(OVMF_DIR)/OVMF_VARS.fd" \
-net none
Qemu hangs after printing Found bootloader on fs0:
I can't find out what cause it.
I suspect I made some mistakes in the Makefile.
Heres the code repo:https://github.com/xubury/myos for reproduce.
BTW, you may need to specify path to gnu-efi and ovmf in the Makefile.
I ran the code under OS: Arch Linux x86_64 and Kernel: 5.11.1-arch1-1
Many thanks in advance!

So, apparently the problem goes away when I put -lgnuefi -lefi at the end of the linkage. But I don't know excatly why. Also, the gnu-efi function should be called using uefi_call_warpper for some ABI compatibility issues.

Related

How to use '-netdev user, hostfwd=...' option in qemu?

thank you for read my problem.
I'm going to debug mips assembly on QEMU environment.
But I was confronted some problem.
I typed this command
qemu-system-mipsel -M malta -kernel vmlinux-2.6.32-5-5kc-malta -hda debian_squeeze_mipsel_standard.qcow2 -append "root=/dev/sda1" -redir tcp:4444::4444 -nographic
And qemu-system-mipsel said me an error
-redir tcp:4444::4444: The -redir option is deprecated. Please use '-netdev user,hostfwd=...' instead.
If -redir option is deprecated, how change my command using by -netdev option???
What's more strange is qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1" -redir tcp:4444::4444 -nographic command is successful on debian_wheezy_mipsel environment!
Is this only debian_squeeze_mipsel problem?
But I can't use debian_wheezy_mipsel... this version couldn't operate apt-get package well. So, I couldn't debug mips binary using by gdb or gcc.
Thank you:)
The QEMU project documents the replacements for deprecated-and-then-removed features in https://wiki.qemu.org/Features/RemovedFeatures -- in this case it says:
The -redir [tcp|udp]:hostport:[guestaddr]:guestport argument is replaced by either -netdev user,id=x,hostfwd=[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport (for pluggable NICs, accompanied with -device …,netdev=x) or -nic user,hostfwd=[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport (for embedded NICs). The new syntax allows different settings to be provided per NIC.
The feature was deprecated in QEMU v2.6.0 and dropped entirely in v3.1.0. So QEMU versions before 2.6 will not complain; QEMU between 2.6 and 3.0 will produce the deprecation warning but work the same as older versions; and 3.1 and later will refuse to start because they don't recognize the option.
In your case I think the malta board uses a pluggable 'pcnet' PCI card, which would imply that you want the "-netdev user,id=x,hostfwd=... -device pcnet,netdev=x" of the two options above. If that doesn't work, try the other instead.

Debugging linux kernel with gdb via QEMU issue

I am newbie in Linux kernel and I'm trying to debug it with gdb via QEMU. My problem is gdb doesn't stop after break start_kernel. More details is below.
My host system is ArchLinux 5.0.10-arch1-1-ARCH x86_64.
Qemu is QEMU emulator version 4.0.0
gdb is GNU gdb (GDB) 8.2.1.
Debugged kernel is linux-4.20.12
I have done following steps:
Compile kernel with
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
CONFIG_GDB_SCRIPTS=y
# CONFIG_DEBUG_INFO_REDUCED is not set
Try to run LFS-8.4 system with it kernel via QEMU
qemu-system-x86_64 lfs-8.4-08052019.raw
System starts good.
Run this system with stop CPU and gdbserver options via QEMU
qemu-system-x86_64 lfs-8.4-08052019.raw -S -s
Start gdb
$ gdb
Load symbols
(gdb) file /mnt/lfs/sources/linux-4.20.12/vmlinux
Reading symbols from /mnt/lfs/sources/linux-4.20.12/vmlinux...done.
Connect to QEMU
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x000000000000fff0 in cpu_hw_events ()
Set break point
(gdb) break start_kernel
Breakpoint 1 at 0xffffffff82761ab5: file init/main.c, line 538.
(I have tried hardware break point hbreak, but result is the same)
Continue
(gdb) c
Continuing.
Further system loads login prompt without any breaks and gdb doesn't show any new messages.
What I do wrong?
UPD: starting QEMU with embed -kernel facility give the same result
qemu-system-x86_64 -kernel /mnt/lfs/sources/linux-4.20.12/arch/x86/boot/bzImage -append 'root=/dev/sda3' -drive file=lfs-8.4-08052019.raw -S -s
UPD2: I have tried to start QEMU without -S key and run target remote localhost:1234 in gdb immediately. QEMU have stopped loading at
Decompressing Linux... Parsing ELF... Performing relocations... done.
Booting kernel.
When I type s in gdb it says
(gdb) s
Cannot find bounds of current function
I suspect that debug symbols in vmlinux isn't related to bzImage. Maybe they was made wrong, but I don't how to make them another way.
UPD3: I have built kernel 2.6 in LFS-8.4 chroot environment. System isn't loaded, but kernel is successfully debugged by method described above! So, I think that it is problem of new kernels. Maybe I should switch off/on something in my 4.20.12 kernel, but I don't know what is exactly. For my purpose (reading Robert Love "Linux Kernel Development") kernel version 2.6 is enough.
You need to pass nokaslr to kernel cmdline.
qemu-system-x86_64 -kernel /mnt/lfs/sources/linux-4.20.12/arch/x86/boot/bzImage -append 'root=/dev/sda3 nokaslr' -drive file=lfs-8.4-08052019.raw -S -s

QEMU Showing Black Screen Only

I compiled my custom kernel with different configs and images like u,zImages. But when I try to run qemu with my image, qemu showing only black screen.
Also I looked at this post but it didn't help me.
EDIT
I just tried to compile kernel with these commands.
make ARCH=arm distclean
make ARCH=arm integrator_defconfig
make ARCH=arm menuconfig
NOTE: I used default menuconfig.
make ARCH=arm CROSS_COMPILE=arm-none-eabi- zImage
qemu-system-arm -M integratorcp -kernel arch/arm/boot/zImage
And last i tried this command;
qemu-system-arm -M integratorcp -kernel arch/arm/boot/zImage -append 'console=ttyAMA0 earlyprintk=ttyAMA0' -serial stdio
NOTE: when i try to use -dtb, qemu giving to me "Unable to copy device tree in memory." error.
"QEMU does nothing with a black screen" almost always means "QEMU is running fine, but the guest code crashed or stopped early in the boot process without sending any output". Almost certainly either your kernel is misconfigured, or your QEMU command line is wrong. You don't give enough information to say which. You need to tell us at least:
what the kernel is you're running and what machine you've configured it for
what the QEMU command line you're using is
Given your updated question with a command line, some suggestions:
tell your guest to use the serial port (use the QEMU option -append 'console=ttyAMA0' to set the guest kernel command line)
either check the serial output view in the GUI, or send it to stdout with -nographic or -serial stdio
enable any earlyprintk or earlycon options in the guest config that you can and on the guest command line, so if the guest fails early you have more chance to catch it
pass the device tree for the kernel with -dtb integratorcp.dtb (use the one from your kernel tree; you'll probably have to tell the kernel makefiles to build it for you)
PS: integratorcp is an absolutely ancient development board -- why do you want to use it?

Guest OS in Qemu generates too much interrupts on irq4

I am facing problem with interrupt in guest OS runing in qemu-2.3.0.
I am loading windriver (Linux kernel-2.6.34.12-grsec) in -nographic mode in Qemu emulator on Ubuntu 14.04 host.
Host details:
>$ uname -a
>$ Linux my-qemu-host 3.13.0-52-generic #86-Ubuntu SMP Mon May 4 04:32:59 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
my command line is:
>$ qemu-system-x86_64 -enable-kvm -nographic -k en-us -kernel ${KERNEL} -cpu kvm64 -smp 4 -m 1G ${NETCFG} -gdb tcp::1234 -append "console=ttyS0,115200 ip=dhcp root=/dev/nfs nfsroot=${NFSROOT}" -hda /home/hda
I am getting following logs in /var/log/kern.log
kernel: serial8250: too much work for irq4
I searched to get rid of this but so many people are suggesting to increase PASS_LIMIT in /serial/8250.c file. this workaround is just avoiding error messages in kern.log file.
Any one having idea how to stop or slow down interrupt frequency?
What exactly are you running i.e. what sort of build? It appears that some hefty serial work is going on (which is expected with embedded).
I just googled how to disable the kernel module for the serial8250 to see if that would help and happened upon this:
http://www.spinics.net/lists/linux-serial/msg12360.html
Another thought, seeing as windriver (if it's this: http://www.windriver.com/products/linux/) then I wouldn't be shocked if a "serial console" is automatically enabled. This too could drive s/w interrupt watchdogs to blacklist them as the can spam quite a bit of info depending on what they're set to output.
Sorry, it's just totally a random guess, but I'm going by pure experience with embedded serial device fun (MIPS) and (ARM) past experiences with generic distros

How to debug my Cross compiled Linux Kernel?

I 've cross compiled a Linux Kernel (for ARM on i686 - using Cross-LFS).
Now I'm trying to boot this Kernel using QEMU.
$ qemu-system-arm -m 128 -kernel /mnt/clfs-dec4/boot/clfskernel-2.6.38.2 --nographic -M versatilepb
Then, it shows this line and waits for infinite time !!
Uncompressing Linux... done, booting the kernel.
So, I want to debug the kernel, so that I can study what exactly is happening.
I'm new to these kernel builds, Can someone please help me to debug my custom built kernel as it is not even showing anything after that statement. Is there any possibility of the kernel being broken? ( I dont think so, b'se it didnot give any error while compiling )
And my aim is to generate a custom build very minimal Linux OS. Any suggestions regarding any tool-chains etc which would be easy & flexible depending on my requirements like drivers etc.,
ThankYou
You can use GDB to debug your kernel with QEMU you can use -s -S options. If you want a simple and reliable toolchain, you can use ELDK from DENX (http://www.denx.de/wiki/DULG/ELDK).
You can install it like this (It's not the last version, but you got the idea):
wget http://ftp.denx.de/pub/eldk/4.2/arm-linux-x86/iso/arm-2008-11-24.iso
sudo mkdir -p /mnt/cdrom (if necessary)
sudo mount -o loop arm-2008-11-24.iso /mnt/cdrom
/mnt/cdrom/install -d $HOME/EMBEDDED_TOOLS/ELDK/
The command above should install the toolchain under $HOLE/EMBEDDED_TOOLS/ELDK (modify it if you need)
echo "export PATH=$PATH:$HOME/EMBEDDED_TOOLS/ELDK/ELDK42/usr/bin" >> $HOME/.bashrc
You can then see the version of your ARM toolchain like this:
arm-linux-gcc -v
You can test a hello_world.c program like this:
arm-linux-gcc hello_world.c -o hello_world
And you type: file hello_wrold to see the target architecture of the binary, it should be something like this:
hello_wrold: ELF 32-bit LSB executable, ARM, version 1 (SYSV)
Now if you want to compile a production kernel, you need to optimize it (i suggest using busybox) and if you want just one for testing now, try this steps:
Create a script to set your chain tool set_toolchain.sh:
#! /usr/bin/sh
PATH=$PATH:$HOME/EMBEDDED_TOOLS/ELDK/ELDK42/usr/bin
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabi-
export PATH ARCH CROSS_COMPILE
And run your script (source ./set_toolchain.sh)
Download a linux kernel and unzip it (Let's assume 2.6.x, it's an old kernel, but there are a lot of chances that it work without compilation errors).
Inside your unzipped kernel:
cd ~/linux-2.6.29/arch/arm/configs
make versatile_defconfig
Here we use versatile chip, you may need to use make menuconfig to modify the option OABI and set it to ARM EABI, this option is under Kernel features menu
After all this steps, you can compile you kernel:
make
if you want verbose compilation make v=1
After this you got your kernel under arch/arm/boot/zImage.
Hope this help.
Regards.
I would suggest to build your kernel by activating the option in the section Kernel hacking of your configuration file.
Then you may use kdb or kgdb which is easier to use but requires another machine running gdb.
`
You can also connect Qemu and GDB. Qemu has the -s and -S options that run a GDB server and allow you to connect to it via TCP to localhost:1234. Then you can load your kernel image (the unzipped one) in GDB and see how far your kernel boots.

Resources