Yocto Space Profiling Using KSize - yocto

I have a Yocto build that I am trying to shrink. I have removed a lot of unnecessary code by building core-image-full-cmdline. The Yocto mega manual mentions that to strip the size of your kernel you can use the ksize.py script in the project build directory. When I run this script I get an output of all 0s. This cannot be correct as I have a working SD card image with a booting kernel.

As I remember, you need to execute the script in the kernel folder. The script scan the current folder.
cd /path/to/kernel
python /path/to/ksize.py
(use python2 or 3 depending the current Yocto branch)

#PierreOlivier is right, you need to run this specifically from the kernel build directory (not the kernel source directory), in my case it is:
$ cd tmp/work/qemuarm64-poky-linux/linux-yocto/5.15.14+gitAUTOINC+72e4eafb6b_f77b2ba7d5-r0/linux-qemuarm64-standard-build
$ ../../../../../../../scripts/tiny/ksize.py
Linux Kernel total | text data bss
--------------------------------------------------------------------------------
vmlinux 20936031 | 15461191 4784912 689928
--------------------------------------------------------------------------------
fs/built-in.a 4548119 | 3862922 640608 44589
drivers/built-in.a 3991696 | 3591409 339384 60903
kernel/built-in.a 3104792 | 2078218 834883 191691
net/built-in.a 3083322 | 2731018 305491 46813
Additionally I recommend you try setting either:
DISTRO="poky-tiny"
or
PREFERRED_PROVIDER_linux-yocto = "linux-yocto-tiny"
Which would build a smaller kernel and/or rootfs as reference (assuming you are using linux-yocto and poky), you may set this on your local.conf

Related

Yocto Bitbake fails to find wrapper headers (include_next stind.h no such file)

I'm trying to create a bitbake recipe to build some source code that resides in a local folder (as opposed to fetching from a remote repo).
After running bitbake, I expect to have an executable file and a shared library in the resulting image.
The source code includes three CMakeLists.
So far, I'm able to:
Run cmake by itself to build the source code on my host and on the target (i.e. not using bitbake)
Using my .bb file, correctly point to the source code by using the variable OECMAKE_SOURCEPATH.
start running cmake using the default do_compile()
The build fails during do_compile() with the error:
In file included from /home/myname/UDS_Server_Integration/src/3rdparty/udsdoip/UDSSrvonDOIP/DoIPSrvProcess/Inc/typedefs.h:29,
| from /home/myname/UDS_Server_Integration/src/3rdparty/udsdoip/UDSSrvonDOIP/DoIPSrvProcess/Src/DOIP/DOIP.h:32,
| from /home/myname/UDS_Server_Integration/src/3rdparty/udsdoip/UDSSrvonDOIP/DoIPSrvProcess/Src/ISOUDS/ISOUDS_MAIN/ISOUDS_Server_Cfg.h:30,
| from /home/myname/UDS_Server_Integration/src/3rdparty/udsdoip/UDSSrvonDOIP/DoIPSrvProcess/Src/ISOUDS/ISOUDS_ClearDiagInfo/ISOUDS_ClearDiagInfo_Cfg.c:25:
| /home/myname/project/nxp_s32/build_s32g274asbc2/tmp/work/aarch64-ms-linux/embitel-uds/1.0.0-r0/recipe-sysroot-native/usr/lib/aarch64-ms-linux/gcc/aarch64-ms-linux/10.2.0/include/stdint.h:9:16: fatal error: stdint.h: No such file or directory
| 9 | # include_next <stdint.h>
| | ^~~~~~~~~~
| compilation terminated.
| make[2]: *** [CMakeFiles/uds-server.dir/build.make:264: CMakeFiles/uds-server.dir/src/3rdparty/udsdoip/UDSSrvonDOIP/DoIPSrvProcess/Src/ISOUDS/ISOUDS_ClearDiagInfo/ISOUDS_ClearDiagInfo_Cfg.c.o] Error 1
| In file included from /home/myname/UDS_Server_Integration/src/3rdparty/udsdoip/UDSSrvonDOIP/DoIPSrvProcess/Inc/typedefs.h:29,
| from /home/myname/UDS_Server_Integration/src/3rdparty/udsdoip/UDSSrvonDOIP/DoIPSrvProcess/Src/DOIP/DOIP.h:32,
| from /home/myname/UDS_Server_Integration/src/3rdparty/udsdoip/UDSSrvonDOIP/DoIPSrvProcess/Src/ISOUDS/ISOUDS_MAIN/ISOUDS_Server_Cfg.h:30,
| from /home/myname/UDS_Server_Integration/src/3rdparty/udsdoip/UDSSrvonDOIP/DoIPSrvProcess/Src/ISOUDS/ISOUDS_CntrlDTCSetting/ISOUDS_CntrlDTCSetting.c:13:
| /home/myname/project/nxp_s32/build_s32g274asbc2/tmp/work/aarch64-ms-linux/embitel-uds/1.0.0-r0/recipe-sysroot-native/usr/lib/aarch64-ms-linux/gcc/aarch64-ms-linux/10.2.0/include/stdint.h:9:16: fatal error: stdint.h: No such file or directory
| 9 | # include_next <stdint.h>
| | ^~~~~~~~~~
However, stdint.h does exist. I looked up what "include_next" is and it's a "wrapper header". I think GCC is using this to modify the headers for the target environment, i.e. this is a cross-compiler issue. I assume this would indicate that cmake is not configured correctly for cross-compilation, or not looking in the correct location for the modified headers.
I have never encountered this problem building other source code for the same target environment using the same cross-compiler. My .bb recipe is also written using the same variables as for other packages. I even compared the CMakeOutput.log and CMakeCache.txt for this failing recipe and other successful recipes and saw that most of the relevant variables were set with the same values.
This led me to believe this could be an issue with the CMakeLists.txt and not having configured cmake correctly for this particular source code.
I have tried adding -DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 based on this thread.
I have also avoided directly setting the cross-compiler based on this.
However, I'm at a loss for what I could be missing.
Other issues I've referenced:
Referencing gcc with yocto recipe Makefile, unable to find stdint
Here are my CMakeLists for reference:
cmake_minimum_required(VERSION 3.13)
project("MyUDS"
VERSION "1.0.0"
LANGUAGES C)
include(GNUInstallDirs)
## --- C++ build flags ---
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_FLAGS "-MMD -MP -O4 -fcommon")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11")
# Set version
set(PROJECT_VERSION_MAJOR 0 CACHE STRING "")
set(PROJECT_VERSION_MINOR 0 CACHE STRING "")
set(PROJECT_VERSION_PATCH 0 CACHE STRING "")
set(PROJECT_VERSION_BUILD 0 CACHE STRING "")
# changes binary and library outputs to ./build/bin and ./build/lib
# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
add_library(uds-server SHARED)
set_target_properties(uds-server PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR})
add_subdirectory(src/3rdparty/udsdoip)
----- CMakeLists in src/3rdparty/udsdoip ------
file(GLOB_RECURSE sched_sources ${CMAKE_CURRENT_SOURCE_DIR}/UDSSrvonDOIP/DoIPSrvProcess/Sched/*.c)
add_executable(udsserver ${sched_sources})
target_link_libraries(udsserver uds-server pthread)
target_include_directories(
udsserver
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/UDSSrvonDOIP/DoIPSrvProcess/Inc
${CMAKE_CURRENT_SOURCE_DIR}/UDSSrvonDOIP/DoIPSrvProcess/Sched/Inc
...
${CMAKE_CURRENT_SOURCE_DIR}/UDSSrvonDOIP/DoIPSrvProcess/Src/Inc
)
add_subdirectory(UDSSrvonDOIP/DoIPSrvProcess)
install(TARGETS udsserver DESTINATION bin)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/service/uds_server.sh DESTINATION bin)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/service/uds_server.service
DESTINATION /etc/systemd/system
)
----- CMakeLists in UDSSrvonDOIP/DoIPSrvProcess ------
project(lib-uds-server)
# Enable helper debugging messages
target_compile_definitions(
uds-server PUBLIC DEBUG_SOCKCOMM DOIP_SERVER_PRINT_TCP_RX_PACKET_DATA DOIP_SERVER_PRINT_FOUND_NET_DEVS
)
file(GLOB_RECURSE isouds_sources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c)
target_sources(uds-server PRIVATE ${isouds_sources})
target_include_directories(
uds-server
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Inc
${CMAKE_CURRENT_SOURCE_DIR}/Sched
${CMAKE_CURRENT_SOURCE_DIR}/Sched/Inc
...
${CMAKE_CURRENT_SOURCE_DIR}/Src/ISOUDS/ISOUDSSecurDtaTrans
)
install(TARGETS uds-server
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
Found the issue, and it's a bit of a dumb mistake.
I was not inheriting the CMake C flags set by Yocto that are needed for the cross-compile environment. So no matter what flags I added in my .bb recipe file, they were being overridden in the source code CMakeLists.txt.
Here, where I was setting the C flags, I was not inheriting Yocto's flags.
set(CMAKE_C_FLAGS "-MMD -MP -O4 -fcommon")
I should have used the existing flags and appended the ones specific to my source code like this:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MMD -MP -O4 -fcommon")
This got my build working.

Where on disk is the BIOS file used by Simics?

(I saw one of my previous posts didn't actually answer the "where's the BIOS file used by simics?" question, so I renamed the previous one and am pulling that question out and making it standalone here.)
I can see the BIOS code for a default "targets\qsp-x86\firststeps.simics" invocation by just stepping through the debugger from the start. But if I want to see the full binary, is there a specific file somewhere I can look at?
you can check "bios" attribute on motherboard image:
simics> board.mb->bios
"%simics%/targets/qsp-x86/images/SIMICSX58IA32X64_1_0_0_bp_r.fd"
You can specify what BIOS image to use by bios_image script parameter to qsp-clear-linux.simics scripts.
Help info for the script:
$ ./simics -h targets/qsp-x86/qsp-clear-linux.simics
System:
bios_image - existing file or NIL
BIOS file.
Default value:
"%simics%/targets/qsp-x86/images/SIMICSX58IA32X64_1_0_0_bp_r.fd"
you can run with your own BIOS like this:
$ ./simics -e '$bios_image=my-bios.bin' targets/qsp-x86/qsp-clear-linux.simics
Now the BIOS is not quite handled consistently with some other things. Typically in Simics, disks and similar things are images. You can list them using list-persistent-images and resolve locations using lookup-file:
simics> list-persistent-images
┌─────────────────────┬────────────┬───────────────────────────────────────────────────────┐
│Image │Unsaved data│File(s) (read-only/read-write) │
├─────────────────────┼────────────┼───────────────────────────────────────────────────────┤
│board.disk0.hd_image │ no│%simics%/targets/qsp-x86/images/cl-b28910-v2.craff (ro)│
│board.disk1.hd_image │ no│ │
│board.mb.sb.spi_image│ yes│%simics%/targets/qsp-x86/images/spi-flash.bin (ro) │
└─────────────────────┴────────────┴───────────────────────────────────────────────────────┘
simics> lookup-file "%simics%/targets/qsp-x86/images/spi-flash.bin"
"/disk1/simics-6/simics-qsp-x86-6.0.47/targets/qsp-x86/images/spi-flash.bin"
The BIOS in the QSP is just loaded straight into target memory for execution. Which is a bit of a cheat for convenience.
Upon searching around, I found the following folder:
C:\Users\yourusername\AppData\Local\Programs\Simics\simics-qsp-x86-6.0.44\targets\qsp-x86\images
Inside that folder are the following 3 files:
SIMICSX58IA32X64_1_0_0_bp_r.fd
SIMICSX58IA32X64-ahci.fd
spi-flash. bin
Both SIMICSX58IA32X64_1_0_0_bp_r. fd and SIMICSX58IA32X64-ahci.fd have UEFI filevolume headers at the start, and a seeming BIOS entry point at the end. The spi-flash. bin seems to have a placeholder of the flash descriptor which would go at the start of the flash, but is mostly empty. So I believe Intel basically either stitches these together in memory, or possibly just uses the spi-flash. bin to allow for "soft strap" configuration or somesuch (since it's a virtual MCH/ICH anyway.)

How to remove getty#tty1 link in yocto dunfell branch at time of compiliation

I am building linux system for raspberrypi4 but for some reason I need to remove getty#tty1 service in yocto.
I have created systemd_%.bbappend file for that.
Host PC is Ubuntu 18.04
this is working with warrior branch
Now, I am trying to compile with dunfell branch in yocto
but at the time of systemd compiling it gives an error like
"cannot remove /etc/systemd/system/getty.target.wants/getty#tty1, no such file or deirectory
But at the end, In final image there I can see getty#tty1.service
Also I can't find any other receipe that creates this link.
systemd_%.bbappend looks like this
DESCRIPTION = "Customization of systemD services."
do_install_append() {
rm ${D}${sysconfdir}/systemd/system/getty.target.wants/getty#tty1.service
}
FILES_${PN} += "${sysconfdir}/systemd/system"
REQUIRED_DISTRO_FEATURES= "systemd"
Thanks
Margish
On more recent versions of systemd (like the one in Yocto dunfell), the links to services are not created by the build system (ninja), but instead by running systemctl preset-all on the running system after installation (see here). This command reads the systemd preset files to determine which units to enable or disable by default.
In Yocto, what this means is that instead of the links being created as part of the systemd recipe, systemctl preset-all is run as part of the IMAGE_PREPROCESS_COMMAND during image creation in image.bbclass (see here). This is why the old method of deleting the symbolic links in /etc/systemd/system from the systemd recipe no longer works.
Instead, what you need to do is modify the 90-systemd.preset file to disable the getty#tty1 preset (or any other default system service) by changing the below line:
enable getty#.service
to this:
disable getty#.service
You can accomplish this using a bbappend file as follows*:
# systemd_%.bbappend
do_install_append() {
# Disable getty#tty1 from starting at boot time.
sed -i -e "s/enable getty#.service/disable getty#.service/g" ${D}${systemd_unitdir}/system-preset/90-systemd.preset
}
*https://stackoverflow.com/a/67505478/286701

Yocto - creating a dependency for WIC to cpio.gz image

I'm creating a small Yocto distro that should work in RAM on tmpfs. I use the WIC configuration in the following way:
part /boot --source bootimg-efi --sourceparams="loader=grub-efi,initrd=${PN}-${MACHINE}.cpio.gz,file=${PN}-${MACHINE}.cpio.gz" --ondisk sda --label msdos --active --align 1024
bootloader --ptable gpt --timeout=0 --append="rootfstype=tmpfs rootflags=size=2G console=ttyS0,115200 console=tty0"
I also add IMAGE_FSTYPES_append = " cpio.gz " to my local.conf, so it builds the cpio.gz archive from my rootfs.
My problem is very straightforward - when WIC runs, it tries to create the wic file before it is done with creating the rootfs cpio.gz, and therefore the build fails. What I need is to create a dependency, something that will hold WIC scripts until the cpio.gz is ready. Does anyone know how to achieve it? Can, for instance, WKS_FILE_DEPENDS be used?
Here is the failure:
| ERROR: _exec_cmd: cp .../poky/build/tmp/deploy/images/genericx86-64/core-image-minimal-genericx86-64.cpio.gz .../poky/build/tmp/work/genericx86_64-poky-linux/core-image-minimal/1.0-r0/deploy-core-image-minimal-image-complete/core-image-minimal-genericx86-64-20191121151711/tmp.wic.k00ckxmk/hdd/boot returned '1' instead of 0
| output: cp: cannot stat '.../poky/build/tmp/deploy/images/genericx86-64/core-image-minimal-genericx86-64.cpio.gz': No such file or directory
Currently I bypass the problem by running the wic tool manually after the build. I had to use IMAGE_FSTYPES_remove = " wic wic.bmap hddimg " in my local.conf for that. The command for running wic then is:
wic create ../meta-mylayer/wic/myimage.wks -e core-image-minimal
Thanks!
EDIT:
Maybe the problem is not in creating the required dependency, but in the way I create the image? I just want a UEFI boot, a kernel, and a cpio.gz file with a complete rootfs which will gets mounted on boot. This is not an initramfs, but a complete rootfs that I need there. Except the problematic dependency the resulting image does exactly what I need.
You can specify the dependency with WIC in 2 ways.
Using do_image_wic: The final task to create the WIC is do_image_wic. So you can add dependency for creating your initrd/initramfs image to this task as below,
do_image_wic[depends] += "image-base-initramfs:do_image_complete"
You need to specify this in your WIC image creation recipe. For this example,
DESCRIPTION = "My image"
inherit core-image
export IMAGE_BASENAME = "image-base"
IMAGE_FSTYPES = "wic.xz"
DEPENDS += "image-base-initramfs"
do_image_wic[depends] += "image-base-initramfs:do_image_complete"
WKS_FILES = "my.wks"
Here image-base is used for creating the WIC using my.wks. It waits for the initramfs to complete the building. In image-base-initramfs you will create the initramfs image.
To add, you can also do this with INITRAMFS_IMAGE when using kernel fitImage.
Using WKS_FILE_DEPENDS: You can add any bitbake recipe to dependency before creating the WIC image. Adding image-base-initramfs to this variable will wait for it to complete the initramfs image. We also have WKS_FILE_DEPENDS_BOOTLOADERS when depending on bootloader to complete in WIC creation.

Auditd in Yocto

I'm trying to add auditd to Yocto linux.
I added the selinux layer and it's dependent layers: openembedded-core and meta-virtualization.
I added the layers to bblayers.conf.
I added DISTRO_FEATURES_append = " acl xattr pam selinux"
and PREFERRED_PROVIDER_virtual/refpolicy ?= "refpolicy-mls" to the local.conf file.
After building (by using bitbake core-image-base) and running the qemu, the kauditd process is running, but all user-space tools are not.
The /etc/audit folder is not exist ,non of the audit's config files exists (audit.rules) and no user-space audit process is running.
In the layer's info it is declared - "User space tools for kernel auditing".
What I am missing?
Thanks.
I think I found something that will answer your question: If you know what an example binary or library you expect to be in the target image, you can find what recipe the executable is in, and then add that package to the image.
Start with the name of a binary or library you expect to be in the image and run the following. For me, I am using a CAN bus executable called candump. I wonder what recipe it's in? To find out, I issue:
devtool search candump
Which returns:
can-utils
If nothing is returned, I'd double check your conf/bblayers.conf so that the layer you think it may be in is actually being seen by your build system. If you are unsure, take a look at the link below which points to OpenEmbedded which has a handy search utility for packages.
After you find the recipe, you can then include that recipe into your build.
Here is a good reference in doing what I think you're asking on the OpenEmbedded website:
https://wiki.yoctoproject.org/wiki/Cookbook:Example:Adding_packages_to_your_OS_image
I just added auditd to my system. This is what I did.
First I got the repository checked out.
cd /path/to/yocto
git clone git://git.yoctoproject.org/meta-selinux
cd meta-selinux
# checkout the branch matching the Yocto release you are on
git checkout thud
Then I added auditd to my build.
cd /path/to/build
bitbake-layers add-layer /path/to/yocto/meta-selinux
cat >> conf/local.conf <<'END'
IMAGE_INSTALL_append = " auditd"
END
bitbake my_normal_image_target
Even though the Yocto recipe is called audit, the package name is auditd.
Of course, auditd without selinux is useless but it did attempt to run (journalctl -u auditd) and /etc/audit exists.
FWIW: To get auditd to a point where it reports say, login success/failure, I had to do a few more things. I'm not just adding it to a standard Yocto image, but to a custom image and custom machine. I'm already using systemd so I didn't have to change that (the layer seems to indicate it's required?). My local.conf looked like this.
# enable selinux
DISTRO_FEATURES_append = " acl xattr pam selinux"
# set the policy
PREFERRED_PROVIDER_virtual/refpolicy ?= "refpolicy-mls"
# install selinux packages and auditd
IMAGE_INSTALL_append = " packagegroup-core-selinux auditd"
# tell the kernel to enable selinux (non-enforcing) and audting
APPEND_append = " selinux=1 enforcing=0 audit=1"
I also had to change linux-yocto_selinux.inc to load selinux.cfg later. Probably layer/recipe ordering could have solved this too?
-SRC_URI += "${#bb.utils.contains('DISTRO_FEATURES', 'selinux', 'file://selinux.cfg', '', d)}"
+SRC_URI_append = "${#bb.utils.contains('DISTRO_FEATURES', 'selinux', 'file://selinux.cfg', '', d)}"
With all that in place, I see audit logs in my journal.