Bare metal Raspberry Pi 2: Generating an SD card image for QEMU emulation - raspberry-pi

I've recently been getting into bare metal development for the Raspberry Pi 2, and having some success. Admittedly I've hesitated to buy an actual physical device until I feel I can do something useful with it, for the time being I've been emulating the device using qemu 2.11.0.
So far I've developed multicore capabilities for my kernel, as well as simple Serial I/O, but I feel I'd like to get much further before working with a physical device.
My issue right now is that I'm trying to learn how to place my kernel onto an SD card image and boot qemu-system-arm from that SD card image, so I can properly emulate a kernel loaded from the raspberry pi 2 bootloader.
I've gotten as far as grabbing the SD card contents from https://github.com/raspberrypi/firmware ... aster/boot, and using the following script to create the image and load my kernel into it. I've seen that people have figured out how to load Raspbian from an emulated SD card, so I figure I can do the same.
#!/bin/bash
OUTPUT_IMG=os.img
OUTPUT_IMG_SIZE=40
TEMP_MOUNT_DIR="$(mktemp -d)"
# the SD card boot partition contents are in this folder...
OUTPUT_IMG_CONTENTS_DIR="./sd"
OS_DIR="${HOME}/os"
OS_BINARY="${OS_DIR}/kernel.bin"
dd if=/dev/null of=${OUTPUT_IMG} bs=1M seek=${OUTPUT_IMG_SIZE}
mkfs.fat -F 32 ${OUTPUT_IMG}
sudo mount -t vfat -o loop ${OUTPUT_IMG} ${TEMP_MOUNT_DIR}
make -C ${OS_DIR} clean
make -C ${OS_DIR}
sudo cp -r ${OUTPUT_IMG_CONTENTS_DIR} ${TEMP_MOUNT_DIR}
sudo cp ${OS_BINARY} "${TEMP_MOUNT_DIR}/kernel.img"
The only issue is that qemu doesn't seem to boot from this image using the following command:
qemu-system-arm -machine raspi2 -serial file:serial.log -sd ./dev/os.img
I've tried a few different combinations, but to no avail.
I can see from hooking GDB that the kernel is simply not booting from this card image. Loading the kernel directly into qemu with the -kernel argument works otherwise perfectly.
I was wondering if anyone here had any insight on how to accomplish this!
Any help here would be greatly appreciated!

Your command won't work because you haven't passed QEMU either a guest BIOS or a guest kernel to run. The QEMU arm boards aren't like the x86 PC machine, which always automatically runs a guest BIOS image. If you want to run a BIOS (probably UEFI?) you need to find a suitable BIOS blob and pass it to QEMU with the -bios argument. Then QEMU will run the BIOS code, which will hopefully include SD card drivers to load the kernel and so on off the SD card.
Just using -kernel is much simpler...

After doing a bit of reading and searching online, as well as a bit of help from other contributors such as Peter Maydell with his answer above, I think I've answered my own question. Unless I'm mistaken qemu-system-arm does not fully emulate the Raspberry Pi boot process, and instead just loads the kernel specified with the -kernel argument by loading the binary into the guest system's memory and jumping to the entry point. It doesn't look like any additional hardware bootloading is emualted for -M raspi2 unfortunately.
Can ARM qemu system emulator boot from card image without kernel param?
This question is similar and contains some more useful details on this issue, relating to qemu-system-arm as a whole..

Related

How to get U-Boot to Load and Run a Bare-Metal Binary on the Raspberry Pi 3 Model B+? [closed]

Closed. This question is not about programming or software development. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 8 days ago.
Improve this question
I have a Raspberry Pi Model 3B+. Currently, I can successfully load this exact kernel8.img file (which is just a raw binary) from this tutorial bare metal following the instructions outlined in the tutorial's README as shown below:
... you can download a raspbian image, dd it to the SD card, mount it and delete the unnecessary .img files. Whichever you prefer. What's important, you'll create kernel8.img with these tutorials which must be copied to the root directory on the SD card, and no other .img files should exists there.
The serial output after the above kernel8.img is running successfully looks something like this:
EMMC: GPIO set up
EMMC: reset OK
sd_clk divisor 00000068, shift 00000006
EMMC: Sending command 00000000 arg 00000000
EMMC: Sending command 08020000 arg 000001AA
EMMC: Sending command 37000000 arg 00000000
EMMC: Sending command 29020000 arg 51FF8000
EMMC: CMD_SEND_OP_COND returned VOLTAGE CCS 0000000040F98000
...
However, I would like to load that kernel8.img file via U-Boot and TFTP so that I don't have to keep plugging/unplugging microSD cards.
I have a functioning TFTP server and I have loaded U-Boot onto the Raspberry Pi successfully.
The physical address the kernel image gets loaded to bare metal is 0x80000 as explained by the tutorial:
Important note, for AArch64 the load address is 0x80000, and not 0x8000 as with AArch32.
The kernel8.img's file-type is also just a raw binary:
$ file kernel8.img
kernel8.img: data
As such, I've run the following two U-Boot commands:
tftp 0x80000 rpi3bp/kernel8.img
go 0x80000
However, as shown below, I'm getting some garbled mess once the binary is running: ��ogK�S��rK.
...
U-Boot> tftp 0x80000 rpi3bp/kernel8.img
lan78xx_eth Waiting for PHY auto negotiation to complete........ done
Using lan78xx_eth device
TFTP from server 192.168.0.198; our IP address is 192.168.0.111
Filename 'rpi3bp/kernel8.img'.
Load address: 0x80000
Loading: ################################################## 6.6 KiB
603.5 KiB/s
done
Bytes transferred = 6808 (1a98 hex)
U-Boot> go 0x80000
## Starting application at 0x00080000 ��ogK�S��rK
According to this SO post (as shown below), the go command is all that is required to get a bare-metal binary running on U-boot.
If you have issues executing your binary when using the go command,
then the problem lies with your program, e.g. taking control of the
processor and initializing its C environment.
However, I know for a fact that the kernel image runs fine bare-metal using the Raspberry Pi's default bootloader. So what could be the issue here and why can't I seem to get that kernel image running via U-Boot?
Edit 1:
Here's some context on how I set up U-Boot on the Raspberry Pi. Currently, the Raspberry Pi's bootloader is booting U-Boot in 64-bit mode. The Raspberry Pi's bootloader is configured via the config.txt file and below is my config.txt file:
enable_uart=1
arm_64bit=1
kernel=u-boot.bin
Documentation on the arm_64bit option is here:
arm_64bit
If set to non-zero, forces the kernel loading system to assume a
64-bit kernel, starts the processors up in 64-bit mode, and sets
kernel8.img to be the kernel image loaded, unless there is an explicit
kernel option defined in which case that is used instead. Defaults to
0 on all platforms.
The issue is related to the fact that U-Boot uses UART1 on the Raspberry Pi and the binary I'm trying to run uses UART0 as explained by #sawdust below:
Per U-Boot's DT, it appears that U-Boot uses UART1 on gpios 14&15. The
standalone uses UART0 on the same gpios. So that explains both (a)
getting output from two programs on same pin, and (b) why removing
uart_init() failed. Since U-Boot sets up UART0 for Bluetooth, perhaps
the standalone does not expect that; hence a goofy baudrate. An
oscilloscope could easily verify that.
I know this to be true because I modified the code in uart.c to use UART1 instead and I can now see sensible serial output now.
However, it is still unclear to me why despite the seemingly valid initialisation of UART0 in this part of the code, UART0 does not seem to output legible characters at the right baud rate.

How to find out who loads specific Linux kernel module?

I built a certain driver as module (m) for Linux, the spi-imx by NXP. Nontheless, Linux probes this driver when booting. I'm struggling to find out what process/other module/driver requests this spi-imx driver. A depmod does not show any dependencies between the spi-imx an other modules (except for the spidev as submodule).
After some research, I found out that Linux automatically (?) calls modprobe when it detects a new device. So does Linux actually call modprobe because the ecSPI'S status in the device tree as "okay"? If so, how can I prevent this? I would like to dynamically load the spi-imx from a user space application via modprobe. The story behind it: a coprocessor uses this SPI line in parallel to the Linux boot process. This interferes of course and interrupts the coprocessor's use of the SPI line. When the coprocessor has finished its transfer via SPI (a boot mechanism as well), it should hand over the SPI line to Linux.
I'm very thankful for any kind of tips, links, hints and comments on this.
Thanks a lot for the answers. As you guys mentioned, I also found out that Linux itself probes the device if present ("okay").
One possible solution is to complete cut off the modprobe call via an entry like "install spi-imx /bin/false" in the *.conf file. But that makes it impossible to load the driver via modprobe, for Linux and for user space.
"blacklist spi-imx" inside a *.conf located at /etc/modprobe.d/ is the way to prevent Linux from probing the driver when booting. After that, a modprobe from user space can successfully load the driver afterwards.
Thanks again & best regards

iMX6: MSI-X not working in Linux PCIe device driver

I'm trying to get MSI-X working on an iMX6 (Freescale/NXP/Qualcomm) CPU in Linux v4.1 for a PCIe character device driver. Whenever I call either pci_enable_msix() or pci_enable_msix_range() or pci_enable_msix_exact() I get an EINVAL value returned. I do have the CONFIG_PCI_MSI option selected in the kernel configuration and I am also able to get single MSI working with pci_enable_msi(), but I cannot get multiple MSI working either.
I have tested my driver code on an Intel i7 running kernel v3 with the same PCIe hardware attached and I was able to get MSI-X working without any problems so I know my code is correctly written and the hardware is correctly functioning.
When running on the iMX6 I can use lspci -v to view that the hardware has MSI-X capabilities and see the number of IRQs it allows. I can even get the same correct number in my driver when calling pci_msix_vec_count().Questions
Are there any other kernel configuration flags I need to set?
Is there anything specific to the iMX6 CPU I need to consider?
Does anyone have any experience with the iMX6 and either MSI-X or
multiple MSI?

Raspberry Pi 3 OpenWrt

I have a trouble build OpenWrt with SD card.
I download the source, git://github.openwrt.org/openwrt.git and run "make menuconfig", set target "brcm27xx", "brcm2710", "Raspberry Pi 3 Model B".
And finish the configuration, build success.
Using "sudo dd if=openwrt....img of=/dev/sdb bs=2M", I create SD card.
When I boot Raspberry Pi 3 with creating SD card, the Kernel message with error.
run "mount"
/dev/root/ type ext4 ro(read-only) file system.
What is the problem!! Because of this I can not do anything...
Please Help me...
I have been using dd for a while now and it is both very powerful and very unforgiving, in the sense that your console will suggest the writing of the image is concluded but in actuality it has not. My images constantly failed for much the same reason as yours so now use my alternative command line, see below....
sudo dd if=openwrt....img of=/dev/sdb bs=2M
Here is my suggestion
sudo dd if=openwrt....img of=/dev/sdb bs=4096 conv=sync,notrunc status=progress; sudo sync
the last command may be unnecessary as sync is defined within dd command line. remember all of the above is one a line command not two wrap is ok I hope this helps you
This question is almost a year old and people might come across this in the future.
To run OpenWRT/LEDE on Raspberry Pi, you need to flash an image on a microSD. You may download the images through this link(Just search for the particular RPi Model): https://openwrt.org/toh/views/toh_fwdownload
Then from personal experience, I use Etcher to flash the image on the microSD. You may download it through this link: https://etcher.io/
Hope this helps someone out there. :)

Is it possible to boot the Raspberry Pi in Secure Mode?

I am currently developing a small OS on my Raspberry Pi, that I install by replacing the kernel.img file on the /boot partition of my SD card. By the time my code is run, the CPU is already in Normal Mode, so I can't have access to the Secure world / Trustzone area.
Is it possible to modify the boot process of the Raspberry to be able to start executing my code in Secure mode ?
Best,
V.
In fact you don't have to do anything but stop being stupid like me.
As explained here:
https://raspberrypi.stackexchange.com/questions/14953/is-it-possible-to-boot-the-raspberry-pi-in-secure-mode
When the NS bit of the SCR register is 0, it means that you are in Secure Mode, which is the case at boot on my Raspberry. I had the meaning of this bit backwards, sorry !