I'm reading the Zircon source code: https://fuchsia.googlesource.com/fuchsia/+/master/ and I'm trying to find how the kernel image is linked. That is, where is the start function placed?
For example, on raspberry pi, the kernel.img start function is placed at 0x80000 with a link script like here: https://github.com/bztsrc/raspi3-tutorial/blob/master/01_bareminimum/link.ld
There is the boards directory: https://fuchsia.googlesource.com/fuchsia/+/master/boards/ which has some dependencies for some boards. It adds some needed drivers. However, I couldn't find anywhere where the linking occurs for each board.
What if I want to support a new board? Suppose I want to port Zircon to raspberry pi, so I need to make the start.S, specifically the start function on it, start at 0x80000. How would I instruct the Zircon build system to do it?
There are a handful of layers to understand, some of which are a little different.
Here's the linker script you may be looking for, but it doesn't tell the whole story: https://cs.opensource.google/fuchsia/fuchsia/+/master:zircon/kernel/phys/zbi_executable.gni
Kernel images included in ZBI's are generated around here, depending on configuration:
https://cs.opensource.google/fuchsia/fuchsia/+/master:zircon/kernel/BUILD.gn;l=465
There are also boot-shims, which are used to bridge various worlds to ZBI, some for arm64 are here: https://cs.opensource.google/fuchsia/fuchsia/+/master:zircon/kernel/target/arm64/boot-shim/
These also have the kinds of build parameters you may be looking for:
https://cs.opensource.google/fuchsia/fuchsia/+/master:zircon/kernel/target/arm64/boot-shim/BUILD.gn;l=37
Multiboot is common in the Linux world, and this shim for x64 handles exactly that:
https://cs.opensource.google/fuchsia/fuchsia/+/master:zircon/kernel/target/pc/multiboot/
An example boot shim configuration with minimal dtb interaction is here: https://cs.opensource.google/fuchsia/fuchsia/+/master:zircon/kernel/target/arm64/board/msm8998/boot-shim-config.h;bpv=0
Related
I have cross-compiled a kernel, in an autodidactic manner, on a raspberry pi twice in the past.
This kind of things can sometimes a pain in the ... But fortunately there are some step-by-step tutorials.
So I am wondering whether there are general steps that have to be taken and that are the same on all the embedded systems (rpi, beaglebone, atmega controllers, etc...) in order to successfully cross-compile the kernel and make everything work?
My guess:
1) download the kernel source code
2) generate a .config file (which seems necessary)
3) get into the blue screen to do additional adjustements
with e.g.: make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- menuconfig
4) compile the kernel:
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi-
5) put it on the SD card or anything else
Would this be a correct general scheme for any cross-compilation on an embedded system?
Sorry for my ignorance, as I mentioned above I learned it by myself.
I would like to be able to setup a kernel on any embedded device.
Any more information or explanation would be more than welcome! As it seems this kind of things can always be done in multiple manners, it gets me confused.
I'd say your first two steps haven't much to do with cross-compiling. In fact it just comes down to having a cross toolchain targeting your platform correctly installed on your system.
The CROSS_COMPILE make variable of the kernel doesn't do anything other than prepending the string it is set to to any toolchain command (like e.g. gcc for compiling), so if your cross toolchain is installed in your search path, it would be enough to set it to just the desired target triplet with added hyphen, e.g. in your case CROSS_COMPILE=arm-linux-gnueabi-. This would lead to using the command arm-linux-gnueabi-gcc for compiling and so on.
For other embedded devices, you might need different cross toolchains (depending on their architecture), but the general process would indeed stay the same.
how to make an application in built(like top, vi , etc ) so that they can be put inside the /system/bin automatically on flashing the kernel and can be accessed from the command prompt.
I tried modifying the Makefile for the my application by looking at the example of top utility but could not find it under /system/bin .
I am not sure if I have included the sources of the file in the Makefile correctly.
You need to start with something that the manufacturer provided. Presumably it's a devKit or something. Most modern dev kits ship with either a MFG provided development environment, kernel, sources, etc. Many are based on Yocto Linux.
You can't just compile a binary locally on your PC with whatever version of GCC you have and have it work on an embedded environment. Chances are it's a different architecture (ARM or Freescale or something). There are ways to cross-compile but is some setup involved. Read about cross compiling here: http://en.wikipedia.org/wiki/Cross_compiler
There are development and packaging environments that have been developed by the community but it's not for the faint of heart. In short, start reading: https://www.yoctoproject.org/
I intend to make some changes to XFS filesystem.
Is there a documentation on the steps involved in doing so? I tried google but found nothing of much use. I have a rough understanding of the steps involved (see below), but I am looking for a detailed description so that I don't get stuck on simple things.
Steps in my mind:
Ensure my OS is not using XFS currently (no directories formatted as
XFS)
Download the source of XFS for my kernel version
Make changes to the source file
compile the modified source code (this step requires some conf files, which I am not sure where I can get from)
rmmod the xfs module and then insmod the xfs module so that changes are reflected in the system.
create a new partition, format it with XFS and test if things are alright after my changes.
Looking forward to some useful pointers.
Its OK if the pointers are for some other FS like ext3 or 4 as I believe the details would not vary from FS to FS.
Thanks
Your steps might work, but if you run into any issues you could wind up with an unbootable system.
The modules for the kernel must be built with the same version of compiler as the kernel itself or you'll have trouble. I've been stymied every time I tried to build a module for the kernel that came with the distro because the distribution maintainers invariably used some customized version of the compiler that I was not able to match.
A safer but longer option is install the kernel source package for your distro, and modify the XFS module source as necessary. Then build the entire kernel, including the customized XFS module, following the instructions for your linux distribution. Google for your distro and 'custom linux kernel', you should find dozens of hits.
Once built, you'll want to install your new kernel alongside your old one, and configure the bootloader to make the kernel selectable at boot time. This way even if something goes horribly wrong, you can still boot your system using your existing kernel.
I'm writing my own operating system, and so far I'm only really able to write it in assembly, because I don't really understand how I would set it up with multiple files/languages. I've written bootloaders with executable code in them before, but what I don't understand is how to make the bootloader aware of other files outside of itself. How would I be able to write a bootloader in assembly and then tell it to load, say, a kernel written in C in a different file? Do I have to bundle the .o files from the compilation of the kernel into the fdd image and tell the bootloader to load/execute them or is it more complicated than that?
Since it looks like you're trying to get the hang of system bring up it might be worthwhile to take a look at some "smaller" embedded systems to get a feel for what goes on once power is applied/chip comes out of reset. Take a look at U-Boot here: http://www.denx.de/wiki/U-Boot
It is a very popular bootloader especially for embedded systems and can launch a variety of OS's. The mainline supports a ton of different configurations as well. I think it is relatively straight forward to follow what happens during power up if you are comfortable with C.
To answer your question more specifically for instance with U-Boot you can either build parameters into the u-boot image as to where you are going to load your code, it can read where you image file is stored from a configuration file on powerup, u-boot can load a configuration automatically from your network somewhere, you can even tell u-boot where and what to load from its command line interface. Take a look and see if you have any further questions.
I'm trying to build my own toolchain for an Raspberry-Pi.
I know there are plenty of prebuilt Toolchains. This work is for educational reasons.
I'm following the embedded arm linux from scratch book.
And succeeded in building a gcc and uClib so far.
I'm building for the target arm-unknown-linux-eabi.
Now that it comes to preparing a bootable filesystem i'm questioning myself about the bootloader build.
The part about the bootloader for this System seems to be incomplete.
Now I'm questioning myself how do I build a uboot for this System with my arm-unknown-linux-eabi toolchain.
Do I need to build a toolchain which doesn't depend on linux kernel calls.
My first reasearch lead me to the point that there are separate kind of tool chain
the OS dependent (linux kernel sys-calls etc...) and the ones which don't need to have a kernel underneath. Sometimes refered to as "Bare-Metal" toolchain or "standalone" toolchain.
Some sources mention that it would be possible to build an U-Boot with the linux toolchain.
If this is true why and how should this work?
And if I have to build a second toolchain for "Bare Metal" Toolchain where can I find informations about the difference between these two. Do I need another libstdc?
You can built U-Boot with the same cross-toolchain used to build the kernel - and most probably the rest of the user-space of the system.
A bootloader is - by definition - self-contained and doesn't care about your choice of C-runtime library because it doesn't use it. Therefore the issue of sys-calls doesn't come into it.
A toolchain is always going to need to be hosted by a fully functioning development system - invariably not your target system. Whatever references you see to a 'bare-metal toolchain' are not referring to the compiler's use of sys-calls (it relies heavily on the operating system for I/O). What is important when building bootloaders and kernels is that compiler and linker are configured to produce statically linked code that can run at specific memory address.
In almost all possible ways, there is no difference between the embedded and the Linux toolchain. But there is one exception.
That exception is __clear_cache - a function that can be generated by the compiler and in a "Linux"-toolchain includes a system call to synchronize instruction and data caches. (See http://blogs.arm.com/software-enablement/141-caches-and-self-modifying-code/ for more information about that bit.)
Now, unless you explicitly add a call to that function, the only way I know for it to be invoked is by writing nested functions in C (a GCC extension that should be avoided).
But it is a difference.