Buildroot doesn't have uImage option for kernel - linux-kernel

I'm building a Linux kernel for the c-sky platform, and in "Kernel binary format", there is no option for uImage, only vmlinux. But my board requires a uImage. And if it can't find it it will boot to default rom, which is not what I want. So I'm wondering, what do I need to do to get the uImage option? I noticed that it is there for some other architectures/platforms like ARM. But not for my arch, c-sky.
Can anyone help me?
Thanks!

In the Linux kernel, different architectures have different available image formats. uImage is available in Linux, but not enabled in Buildroot.
There are 2 ways you can produce uImage.
The Manual way (OK for preliminary testing):
In menuconfig -> Kernel, set:
Kernel binary format = custom target
Kernel image target name = uImage
make host-uboot-tools
make linux
Step 2 is required because to build uImage you need the mkimage tool from host-uboot-tools. Using a "custom image" Buildroot is unaware of that and the build would fail without step 2.
The correct way:
Just enable the uImage format in Buildroot for the C-Sky architecture. This simple patch should be enough:
diff --git a/linux/Config.in b/linux/Config.in
index 1a50958ea146..c89c12b433be 100644
--- a/linux/Config.in
+++ b/linux/Config.in
## -211,7 +211,7 ## config BR2_LINUX_KERNEL_UIMAGE
depends on BR2_arc || BR2_arm || BR2_armeb || \
BR2_powerpc || BR2_powerpc64 || BR2_powerpc64le || \
BR2_sh || BR2_mips || BR2_mipsel || \
- BR2_mips64 || BR2_mips64el || BR2_xtensa
+ BR2_mips64 || BR2_mips64el || BR2_xtensa || BR2_csky
select BR2_PACKAGE_HOST_UBOOT_TOOLS
config BR2_LINUX_KERNEL_APPENDED_UIMAGE
This allows to select Kernel binary format = uImage and build normally without the need to manually build host-uboot-tools before Linux.

Related

(arm-none-eabi-gcc) creating .elf binary from bootloader + 2 x firmware image

I'm developing for a STM32F429 with CLion and trying to create a merged .elf file from three .elf files.
The layout of the merged .elf file should look like this:
Bootloader.elf (maximum 256K, but can vary in size)
FirmwareImage.elf (always 384K, fills up allotted space for 1st firmware image)
FirmwareImage.elf (always 384K, fills up allotted space for 2nd firmware image)
This makes 1M exactly in total.
I've tried to converting the .elf files to .bin (with arm-none-eabi-objcopy) and creating a 1M .bin file with a custom tool I wrote. I can confirm the layout of the .bin this creates is correct.
I then convert the generated .bin file back to .elf with:
arm-none-eabi-objcopy -I binary -O elf32-little --change-section-address .data=0x08000000 in.bin out.elf
The data section address change is to reflect the start of flash memory in the STM32F429.
When I try to flash this file using openocd, it fails with:
Error: invalid ELF file, no program headers
Is there a way of skipping the .elfs -> .bin -> .elf conversion and go directly from .elfs -> .elf? Or otherwise, insert the program headers? I doubt these are actually used during flashing.
I know I could tell openocd to use the generated .bin file directly by specifing the flash address. But CLion won't let openocd flash .bin files from its arm-embedded plugin, only .elf files.
Edit:
At the moment I'm using these linker scripts, adapted from ST's official one. There is quite a bit going on in them.
I might just be able to use a single linker script to achieve this. I could have the following code:
extern "C" __attribute__((__section__(".bootloader"))) void runBootloader()
{
Platform platform;
DFUBootloader bootloader(platform);
}
extern "C" __attribute__((__section__(".image1"))) void runApplication1()
{
Platform platform;
Application application(platform);
}
extern "C" __attribute__((__section__(".image2"))) void runApplication2()
{
Platform platform;
Application application(platform);
}
If these linker places these symbols at the right locations, would the symbols used by them end up in the correct place as well? The firmware image has to be duplicated to fill up both firmware pages, so all the symbols used by the application as well have to be duplicated.
It looks like merging multiple .elf files in the way I described is not possible, or at least not very trivial.
I have found a workaround for my problem trough. Although CLion is incapable getting openocd to flash .bin files (its builtin openocd launch command uses .elf), It's easy to create a custom CMake target that flashes the merged .bin with the following command:
openocd -f board/stm32f429discovery.cfg -c "program merged_image.bin exit 0x08000000"

Is there a way to add kexec functionality to busybox initrd?

I have 3 MB of SPI flash on my board and I am able to pack the bzImage, busybox initrd and coreboot ROM into this SPI flash. I am also able to boot to the shell , all using the ROM kernel-as-bootloader.
I have bigger kernel on the USB device. I am also able to detect the USB and mount it. But the problem is busybox does not seem to have kexec utility. I cannot use any other initrd package because my cpio (uncompressed) size should not go beyond 1.4 MB due to memory constraints. U-root has kexec support but the minimal image size easily reaches 3MB or at least, I couldn't find a way to built it lesser than that size.
Hence, is there a way to add kexec support to busybox (compile static binary and copy to initrd? ) or any other initrd package that can suffice the need within 1.4MB size?
EDIT
This post suggests that there may be kexec support available in busybox, but I couldn't find any trace of it. In fact the request to add kexec-tools to busybox was done over a decade ago. But when I did grep in the busybox, I saw no traces of it.
The kexec binary from kexec-tools takes about 300KB (x86_64 with -Os). Even if it would be added to busybox, it wouldn't get much smaller than that because it does need to do fairly complicated things that are not done anywhere else in busybox.
If you don't have even 300KB left, then you should probably remove configuration options from busybox itself to save space. With uClibc, you can also remove some options you don't need, like wchar and threading. Make sure you use static linking, it saves a little bit of space.
The following Buildroot defconfig generates an initramfs of exactly 1.4MB.
BR2_x86_64=y
BR2_x86_corei7=y
BR2_STATIC_LIBS=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y
BR2_TOOLCHAIN_EXTERNAL_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/x86-64-core-i7/tarballs/x86-64-core-i7--uclibc--stable-2018.11-1.tar.bz2"
BR2_TOOLCHAIN_EXTERNAL_GCC_7=y
BR2_TOOLCHAIN_EXTERNAL_HEADERS_4_1=y
BR2_TOOLCHAIN_EXTERNAL_LOCALE=y
BR2_PACKAGE_KEXEC=y
BR2_PACKAGE_KEXEC_ZLIB=y
BR2_TARGET_ROOTFS_CPIO=y
# BR2_TARGET_ROOTFS_TAR is not set
We could build a version of kexec for busybox which results in a 220K static linked binary like so:
Use musl
Strip the binary with strip (Maybe it could reduce the size even more?)
Disable unused features via ./configure --without-<FEATURE>
KEXEC_VERSION=2.0.24
KEXEC=kexec-tools-$KEXEC_VERSION
curl -LO https://mirrors.edge.kernel.org/pub/linux/utils/kernel/kexec/$KEXEC.tar.xz
tar xf $KEXEC.tar.xz
cd $KEXEC
CC=musl-gcc LDFLAGS=-static ./configure \
--without-lzma \
--without-xen \
--sbindir=/bin
make
strip build/sbin/kexec
file buils/sbin/kexec # -> [...] statically linked, stripped
du -h build/sbin/kexec # -> 220K [...]
Still not great, but yeah.. Let us know if you could shrink it even more :-)

KBUILD_DEFCONFIG_KMACHINE ?= defconfig_file does not work as expected

KBUILD_DEFCONFIG_KMACHINE ?= defconfig_file does not work as I expected.
First lesson I learned: defconfig != .config
Bare-Kernel-Build (without yocto): A new defconfig file below arch/arm/config/xy_defconfig created by make savedefconfig is not equal to the .config file. I assume the linux kernel expand some symbols and create the final .config.
Yocto-Build: Here comes the issue: Yocto can not correctly handle the defconfig file below arch/arm/config/xy_defconfig. When building the linux-kernel with yocto.. the kernel is half size and not bootable. This results, because yocto does not expand the missing symbols in .config, which a make defconfig would do.
How do you handle the issue?
Update:
Figured out an additional make xy_defconfig do the trick and creates the correct .config file. It is a ugly hack, any better ideas are very welcome.
Added this to my custom linux-xy.bb file.
KBUILD_DEFCONFIG ?= xy_defconfig
do_makedefconfig() {
oe_runmake -C ${B} ARCH=${ARCH} $KBUILD_DEFCONFIG
}
addtask do_makedefconfig after do_configme before do_compile
First copy your defconfig to sources/meta-mylayer/recipes-kernel/linux
and write a .bbappend file for linux recipe
linux-ti_%.bbappend
FILESEXTRAPATHS_prepend : "${THISDIR}:"
SRC_URI += "file://your-defconfig"
2. open sources/meta-mylayer/conf/machine/your-machine.conf add below line,
search the macro if already present or nor using grep -inr "INTREE_DEFCONFIG"
INTREE_DEFCONFIG_pn-linux-ti = "am335x_phytec_defconfig"
if the macro already present in the same file replace defconfig name.
kernel-yocto approach
The KBUILD_DEFCONFIG variable is handled by kernel-yocto class, so you need to inherit it. It is usually done indirectly through include file linux-yocto.inc, so you should have this line you linux recipe:
require recipes-kernel/linux/linux-yocto.inc
Please note that KBUILD_DEFCONFIG_KMACHINE consists of two parts. The first one is variable name (KBUILD_DEFCONFIG) and the second one is kernel machine override (KMACHINE). So you need to change the override to fit your machine. That's why the KMACHINE part is written in italics in the documentation [1]. There is an example for RPi from the documentation:
KBUILD_DEFCONFIG_raspberrypi2 = "bcm2709_defconfig"
The KMACHINE is set in linux-yocto.inc to the MACHINE variable by default.
handle in-tree defconfig by hand
We are using in-tree defconfig without the kernel-yocto class. linux.inc from meta-oe layer is used. I don't know if this is a best practice. Here is our linux recipe (it is reduced to a bare minimum):
require recipes-kernel/linux/linux.inc
PV = "your_version"
SRC_URI = "your_sources"
do_configure_prepend() {
bbnote "Copying defconfig"
cp ${S}/arch/${ARCH}/configs/YOUR_defconfig ${WORKDIR}/defconfig
}
[1] https://www.yoctoproject.org/docs/2.4/mega-manual/mega-manual.html#var-KBUILD_DEFCONFIG

Where can I find U-boot's makefile line that creates symbolic links?

I am using U-boot on a arm64 system. I found it rather odd that U-boot does not have a folder for this architecture ( there is no folder aarch64 in arch ). This would not allow me to compile it using the command:
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=aarch64
instead I have to use :
make CROSS_COMPILE=aarch64-linux-gnu-
However, I was stubborn and decided to force this a bit and copied the arch/arm folder onto arch/aarch64
However ( sigh, as expected ) I have some issues now under the form that U-boot creates some symbolic links to folders. Example : proc -> proc-arm and arch -> arch-armv8
However these links are placed in the arm folder, not in the aarch64 folder.
I have tried to modify the mkconfig file, but it still doesn't seem to work.
Apparently U-boot is a bit of a trickster. After specifically enforcing the board configuration :
if [ "${ARCH}" -a "${ARCH}" != "${arch}" ]; then
echo "Failed: \$ARCH=${ARCH}, should be '${arch}' for ${BOARD_NAME}" 1>&2
exit 1
fi
It goes on to forcefully switch to arm:
# Test above needed aarch64, now we need arm
#
if [ "${arch}" = "aarch64" ]; then
arch="arm"
fi
I think I also understand why they chose to do this. A quick review of my commit revealed a lot of duplicate code, which would be much harder to track.

Add linker option to boost build on HPUX

On HPUX I need to use the +h link option to get the boost 1.39.0 shared libraries to contain correct paths.
-Wl,+h$(SPACE)-Wl,$(<[-1]:D=)
(From http://www.nabble.com/HPUX-aCC:-Howto-avoid-building-boost-libraries-containing-absolute-library-path-references-when-calling-bjam-install-td17619511.html)
I've tested that this works by hacking the gcc.jam toolset file:
796c796
< "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS)
---
> "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -Wl,+h$(SPACE)-Wl,$(<[-1]:D=) -Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" "$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" $(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) -shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) -l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) $(OPTIONS) $(USER_OPTIONS)
But now I want a permanent solution, and I can't work out how.
First I tried putting a bjam conditional in the actions link.dll section, but that section contains shell commands.
Then I tried adding the extra section to the OPTIONS variable for those targets. But that didn't seem to have any effect on the link.
Finally I tried creating a separate toolset as a copy of gcc.jam (hpuxgcc.jam), but I couldn't get that to work at all. I guess there are more places I need to change variable names, but the Jam syntax is beyond what I understand.
Does anyone have some better idea how to get this to work? Or should I just convert the hacky version into a patch I run before building Boost? Surely there's a better way?
Are guess the question is either:
a) How do I (conditional on the platform) add the text to the linker command in the gcc.jam
Or:
b) How do I create a new toolset based on gcc.jam?
Which ever is easier...
What does -h option do? Does it set the "soname"? If so, note the HAVE_SONAME and SONAME_OPTION use in the same action. Then, note the block of code in gcc.jam where it is set:
if [ os.name ] != NT && [ os.name ] != OSF && [ os.name ] != HPUX && [ os.name ] != AIX
{
# OSF does have an option called -soname but it does not seem to work as
# expected, therefore it has been disabled.
HAVE_SONAME = "" ;
SONAME_OPTION = -h ;
}
You can tweak this according to your platform.
I suggest you follow up with this on boost-boost#lists.boost.org, which is much better place for Boost.Build questions than stack overflow.

Resources