[00:00.000 --> 00:17.600] So, hi everyone, welcome to my talk, welcome to Bearbox and first of all, can all of you [00:17.600 --> 00:25.240] raise your hands who ever heard of Bearbox or, okay, that's quite some, and who use it [00:25.240 --> 00:34.120] actually in some projects? Okay, that's more than I thought. Okay, as I thought, I'm Marco, [00:34.120 --> 00:40.360] I'm from Pentatonix, I'm an embedded software developer, yeah, my tasks are related to kernel, [00:40.360 --> 00:47.480] to bootloader, to BSP stuff, graphics stuff and so on and so on. Most of the time I contribute [00:47.480 --> 00:54.520] my work to upstream, sometimes not. I live in the north of Germany, yeah, and that's it. [00:55.560 --> 01:00.680] And again, there is just a brief introduction to Bearbox who is not becoming familiar with, [01:01.240 --> 01:09.160] and then let's add a new driver, so an example, then add a new board so you can see how you can [01:09.160 --> 01:13.240] add your own board and upstream it to Bearbox because we always welcome new boards, [01:13.960 --> 01:17.960] and then we make a short hands-on, hopefully we have some time for it. [01:18.920 --> 01:26.360] And yeah, okay, then welcome to Bearbox. Bearbox started in the [01:27.480 --> 01:36.520] 2007 as a patchlet of Uboot, and the patchlet was called Uboot v2. This patchlet was retracted, [01:36.520 --> 01:45.240] and then, yeah, Sasha renamed it and here, made an official fork of it in 2009. [01:45.240 --> 01:51.880] We have monthly releases, we have mainline support in PDX test, and we have mainline [01:51.880 --> 01:57.880] support in BuildWood, and we wanted to have mainline support in Yocto and Open Embedded Core. [01:58.760 --> 02:06.360] I sent patches just yesterday, you can find the link below or in the slides. Please, [02:06.360 --> 02:12.120] any discussion is welcome. And if it's not getting into Open Embedded Core, yeah, [02:12.120 --> 02:22.280] you can pull it from Meta PDX or Meta Bearbox. And okay, yeah, we have 330 contributors around, [02:22.280 --> 02:31.400] and yeah, it sounds not that much, but we are living, Bearbox is living, we have around [02:31.960 --> 02:42.040] 1,400 commits per year, and okay, the graph is not that optimal, it would be, yeah, [02:42.040 --> 02:53.320] wise all the time, but yeah, 1,400, it's not that bad. And we are alive, so let's add a new driver. [02:53.320 --> 03:01.880] And what are our design decisions in Bearbox? We are coming from Linux, we don't want to re-render [03:01.880 --> 03:10.120] the third time or the tenth time, so we are taking the Linux device driver model and stripping it down [03:10.120 --> 03:17.400] to bootloader use case. All the configuration is done via device tree since day one, since we get [03:17.400 --> 03:26.520] forked, and yeah, device tree and Kconfig, some of it, most of it, device tree, and we also, [03:27.400 --> 03:34.120] since we re-use the Linux device driver model, we also re-use the driver frameworks. We just strip [03:34.120 --> 03:42.200] it down to met our requirements and then push it, and it's mostly just in copy and paste [03:42.280 --> 03:49.640] with small adaptions. So then, let's add a new driver. As I said, it's in copy and paste, [03:50.360 --> 03:55.960] copy it from the Linux source, copy it to the Bearbox source, and then adapt the code. So how [03:55.960 --> 04:04.520] does it look? And some example, I took the clock from some workshop, and I made a div, you can see [04:04.520 --> 04:17.080] the div above, it's Linux 6.1 or 6.2, so it's 6.2, blah, blah, and yeah, just adapt the headers, [04:17.080 --> 04:23.640] because, okay, of course, Bearbox does not have all those headers, and replace them with some [04:23.640 --> 04:31.880] Bearbox headers, and then replace some functions we do not support. That's not very important, [04:31.880 --> 04:41.240] it's just replace some functions, remove it, or replace it, yeah. So we adapted the driver, [04:41.240 --> 04:49.320] we are finally done. So we have ported our new clock driver for this workshop. So we have changed [04:49.320 --> 04:58.360] 50 lines of code for a driver of size about 171 lines of code. This makes about one percent or [04:58.360 --> 05:03.400] two percent of adapted code, and we ported the driver to Bearbox to a bootloader. [05:06.040 --> 05:13.000] Most of the time, when you port a driver, clock drivers are a bit specific, but some drivers [05:14.040 --> 05:21.720] do IRQ, and Bearbox, we don't have IRQs, so you need to port it to some polling [05:21.720 --> 05:26.840] mechanism, but we have helpers for that. So we are welcome you to port your driver, [05:26.840 --> 05:32.920] or your driver of choice you need into a bootloader. So then, after we ported the driver, [05:32.920 --> 05:38.600] we need to compile it. So let's add a K-config in the makefile, because we are kernel-related [05:39.480 --> 05:48.440] bootloader. So let's add a K-config menu entry, and at the makefile, it looks like a kernel. So [05:49.080 --> 05:54.680] then we are finally done. We need to enable it, we need to compile it, and we have everything. [05:54.680 --> 05:59.960] And of course, we can test it with what? With the Linux device tree, because we are [05:59.960 --> 06:06.760] the device tree based, and we, since we are using the complete driver from Linux, we also [06:06.760 --> 06:12.040] have the complete bindings from Linux. So we can use the upstream Linux device tree. You don't [06:12.920 --> 06:19.800] have to do anything, just copy and paste. So yeah, feels like writing a kernel driver, [06:19.800 --> 06:29.560] isn't it? To me, at least. So to sum up this a bit, the Bearbox drivers are just a stripped-down [06:29.560 --> 06:38.840] Linux version driver, and drivers can be ported with little effort. There may be some more effort [06:38.840 --> 06:45.240] if you have more complex drivers, or if you port frameworks. But by frameworks, [06:45.240 --> 06:50.520] that really depends. There are some really easy frameworks, and there are some frameworks which [06:50.520 --> 06:59.400] are huge. So I added some examples, which frameworks we already support. A very decent one is the [06:59.400 --> 07:07.800] NetDSA. I think some of you know the DSA stuff, this distributed architecture for switches. [07:08.920 --> 07:16.200] I think it's called distributed switch architecture, anyway. And we support it in Bearbox, [07:16.200 --> 07:23.560] because we are using the NetDSA framework from Linux. So we can do NetDSA with bootloader, [07:23.560 --> 07:30.920] so you can speak with your switch like you do in Linux. So that's very impressive for a bootloader. [07:32.120 --> 07:38.680] And yeah, then let's move on. We have added our driver. Let's move on and add a new board. [07:39.560 --> 07:44.120] Before we can add a new board, I wanted to explain you some stuff, some [07:45.160 --> 07:51.000] internals of Bearbox. I don't want to go into details, because we don't have that much time. [07:51.000 --> 07:58.520] If we have more time at the end, I will show some more examples. And yeah, of course, [07:58.520 --> 08:04.040] you can raise your hand if you have questions in the end. Anyway, we have a single binary [08:04.040 --> 08:11.240] in Bearbox, which you flash to the target. But this is composed of several components. [08:11.240 --> 08:16.760] One of it is the socketer. This is really, yeah, one of it is the socketer. Then we have this [08:16.760 --> 08:24.200] prebootloader. Then we have some firmware blobs like device tree, like third-party firmware blobs, [08:25.240 --> 08:33.000] TFA or ATF or DDR firmware. Yeah, depends on your socket also. And then we have the [08:33.000 --> 08:41.560] actual bootloader. So as you can see, there is a singleton image, but it's composed of different [08:41.560 --> 08:50.120] firmwares or different blobs. In Bearbox, we do this composing for the prebootloader and for [08:50.120 --> 08:56.760] the firmware and for the actual bootloader, we do a link it together. And the socketer is appended. [08:58.600 --> 09:04.600] So, yeah, also the socketer is very search-specific. And this appending mechanism depends [09:05.480 --> 09:15.160] on this image creation tool, which is also so specific. So then also some booting stuff need [09:15.160 --> 09:25.800] to be known before you can add the board. Most or most modern socks are booting from a bootworm. [09:25.800 --> 09:31.480] So you plug in the check and then the bootworm comes up. The bootworm loads some stuff from, [09:32.120 --> 09:38.280] yeah, the boot medium you configured via some GBIOs or some pins. And then it's loading the, [09:39.480 --> 09:45.400] yeah, some kilobytes into some static RAM. And then it jumps to the static RAM and then executes [09:45.400 --> 09:51.560] the reboot loader and then the bootloader and the bootloader finally decrypt. So now look [09:51.560 --> 09:59.880] into deeper and add a new board. So as I said, the bootworm is loading this socketer. It's decoding [09:59.880 --> 10:05.640] this socketer. It's really search-specific and it's executing the software which was loaded from [10:05.640 --> 10:16.840] the boot medium. Then the reboot loader gets loaded by the bootworm and set up the DRAM. [10:17.640 --> 10:26.120] And then it's loading the real bootloader to the DRAM after it set it up to DRAM. And then [10:27.080 --> 10:34.680] it jumps to the actual bootloader. Or if you have some more decent socks like RV8 based socks, [10:34.680 --> 10:40.040] then it's jumping to the TFA and the TFA is jumping to the bootloader which we previously [10:40.040 --> 10:47.400] loaded to the DRAM. So, okay, now we know it and now we add the reboot loader stuff. [10:48.600 --> 10:55.720] The reboot loader stuff don't have any support of device fee or so. It's a kind of low level [10:55.800 --> 11:04.600] stuff. It's kind of dirty stuff. Anyway, in Bellbox, everything starts at the entry function. [11:04.600 --> 11:12.600] The entry function is always the first point where it starts. And, okay, let's add iMix 8MN [11:12.600 --> 11:20.920] EVK with this entry function. We have some helper functions after we load it into the DRAM. And then [11:21.000 --> 11:31.880] we are calling the NXP. This is some bot specific code which we get here. And this set up the UART. [11:31.880 --> 11:39.400] So, we have a reboot loader low level debug stuff. And then as the function calls start ATF, [11:39.400 --> 11:46.840] this function set up the DDR as I said. It loads the Bellbox to the DRAM or DDR and starts the TFA. [11:46.840 --> 11:54.520] And the TFA is then jumping into the loaded image or into the given image, into the image [11:54.520 --> 12:03.960] which we loaded previously at the specific address we told TFA. And after we loaded this, [12:05.560 --> 12:11.640] we get started by this last function and that's the actually Bellbox entry function. [12:12.120 --> 12:19.960] And here you can see the reboot loader is passing the device tree. So, the reboot loader [12:19.960 --> 12:25.880] contains also loaded the device tree and is passing the device tree finally to Bellbox. So, [12:25.880 --> 12:32.440] Bellbox is just running with the device tree. So, now let's come into the Bellbox to the boot [12:32.440 --> 12:38.520] lawyer. This is the stuff where all the magic happens, where all your bot specific fix ups [12:39.240 --> 12:46.040] does happen. Like you have some overlays for some displays, you have different displays, [12:46.040 --> 12:52.120] do some detection and then apply device tree overlays. So, your device tree is finally [12:53.240 --> 12:57.880] finished, finally fixed up for the kernel and the kernel don't have to do anything. [12:58.840 --> 13:09.960] This can, such stuff can happen in the board code. And yeah, such a board code is also a [13:09.960 --> 13:16.360] driver in Bellbox and after the board code finished to load everything and do all the magic, [13:16.360 --> 13:22.760] it jumps to the kernel. So, as you can see here, this is the entry function for a board code. [13:23.160 --> 13:30.600] Again, this looks again for me to a kernel, like a kernel driver. You have some [13:30.600 --> 13:40.120] driver structure where you can put all the functions and you have this computable which [13:40.120 --> 13:47.400] is also checked and then depending on the computable which is given, the driver is loaded [13:47.400 --> 13:55.000] or executed or not. And then you have the board function and within the board function [13:57.080 --> 14:04.200] you do this magic stuff, I told you. You do detect where to come from, do some magic stuff [14:04.760 --> 14:09.880] and set up. This is some kind of special in Bellbox. We have some Bellbox update handler. [14:10.760 --> 14:21.080] This is some kind of, yeah, you know this magic in the Submarine where you can have some scripts [14:21.640 --> 14:28.040] to load something from MMC to some magic addresses and here are magic addresses and here are magic [14:28.040 --> 14:35.720] addresses and there are involved five commands or so. In Bellbox we have the Bellbox update command [14:35.720 --> 14:41.560] and this is the handler for it. We just forget the handler and in Bellbox we can just call [14:41.560 --> 14:51.400] Bellbox update and finished. So, there is just one command involved. And yeah, then finally [14:51.400 --> 14:57.800] the board code is fixing up the file and then it, yeah, finished and starting the kernel. [14:58.600 --> 15:02.920] And the kernel is do all the remaining stuff. So, that's not part of my talk. [15:03.880 --> 15:12.440] And yeah, okay. So, we have added a driver, we have added a new board and everything apart, [15:12.440 --> 15:23.720] the pre-boot loader stuff feels like a kernel to me. So, I hope I can make you a bit excited about [15:24.680 --> 15:32.440] you can visit the link. This is a Bellbox hosted online on the tiny emulator. [15:34.360 --> 15:36.440] Yeah, just click on it and you can try it out. [15:39.080 --> 15:46.280] Yeah, what else? Bellbox. Bellbox has, now it's coming to the improved part. [15:46.280 --> 15:53.160] Bellbox has a rich shell with auto-completion. This shell has history. This shell supports [15:53.160 --> 15:59.240] scripting and so on. This shell is also called what you would see when you visit the link. [16:00.680 --> 16:09.480] What do we have also? We do also have 30FI systems. This means no more commands and offsets like [16:09.480 --> 16:18.680] you know from Reboot. It's just copy A to B. It's like Unix. It's like Linux. So, we have LS, [16:18.680 --> 16:25.160] we have RM, we have AutoMount. You know AutoMount from system D where you visit some directory and [16:25.880 --> 16:33.880] magic happens and it gets mounted automatically. We also do have that in our bootloader. [16:34.680 --> 16:40.680] And we also have memory mapped IO access. So, we can visit it or we can check the [16:40.680 --> 16:47.640] memory. We can manipulate the memory via MD, via memory write. So, MV. [16:49.560 --> 16:56.120] And yeah, as I said earlier, we have this Bellbox Update command, which is pretty amazing [16:56.120 --> 17:03.240] because it's hiding all the ugly stuff. It's just Bellbox Update and you are done. [17:04.360 --> 17:11.080] And also pretty amazing in Bellbox. We have multi image support. It's some language of Bellbox. [17:11.960 --> 17:22.280] It's something you are compiling Bellbox. And then with one compile, with one dev config, [17:22.280 --> 17:29.480] we can build 100 or more boards. And this is something I wanted to show you right now with [17:29.480 --> 17:42.040] enhanced one. So, now it's, I hope everything works as expected. So, yes. [17:47.400 --> 17:54.280] Is it readable or should I increase the size? Okay. So, [17:59.880 --> 18:07.640] it's just a small script I wrote. It does nothing. Just, it applies, make dev config, [18:07.640 --> 18:12.360] then it enters the dev config. So, I can show you something about Bellbox. So, it's like, [18:12.360 --> 18:19.640] again, it's like a Linux kernel. And here you can see system types. And here you can see [18:19.640 --> 18:23.640] all the boards we have enabled. So, all the boards, not just one board. [18:24.440 --> 18:33.800] And, okay, exit. Yeah, everything is fine. And then it's calling make compile. So, okay, [18:33.800 --> 18:43.640] that's nothing fancy here about. The fancy starts at the end. Let that happen. [18:43.640 --> 19:01.080] And, hopefully. So, okay, now we are at the end. We are finished compiling all these stuff. [19:01.080 --> 19:06.280] And now we are building our images. And we are building around, as I said, we are building [19:06.280 --> 19:14.600] around 100 images right now with one command, with one dev config. And that's pretty amazing, [19:14.600 --> 19:27.320] because I know how some, or I know BSPs where you have just two different Uboot configs to have [19:27.320 --> 19:34.280] one Uboot for an SD card and one Uboot for an EMMC or one Uboot for on spy and one Uboot [19:34.280 --> 19:40.840] for an SD. That's not the kind we are working. We are saying one image will all them. So, [19:42.040 --> 19:47.560] and then also you compile it and you can select as many boards as you want. [19:48.520 --> 19:58.200] As soon as, yeah, it has some limitation. This must be the same. So, we, or the architecture. So, [19:58.280 --> 20:05.320] this was it. I mix seven. Sorry, I mix four, seven. So, all I mix six and so on and so on. [20:06.040 --> 20:07.880] And now we can see [20:11.080 --> 20:11.480] cat. [20:11.480 --> 20:28.440] So, now I can demo build [20:33.320 --> 20:34.440] flash images. [20:35.400 --> 20:40.040] So, we have built [20:42.440 --> 20:51.000] 132 images just in one minute. And that's not doable with Uboot, at least with my knowledge, [20:51.000 --> 20:59.080] I can't do it with Uboot. And yeah, of course, then as I said, we have this, [20:59.800 --> 21:16.040] or if it would work, yeah, we have this online barebox. And then we also have an editor. [21:16.680 --> 21:24.440] We have also VI, but VI is not that good working within the web. But we have also added and then [21:24.440 --> 21:35.320] we can edit some stuff like going here and hitting blah blah or ha ha. Anyway, as you could have seen [21:35.320 --> 21:50.840] this script. And Uboot first time. It's nothing special. It's just a script which checks some [21:50.840 --> 22:00.680] environment variable. And then that's it. I want it just half an hour ago. And then [22:05.480 --> 22:16.280] we can handle this and see, okay, global first time ref is not set. And then we can say, okay, [22:17.240 --> 22:26.920] since we have history, we can move up. And I didn't edit it. Okay, then we say global [22:30.760 --> 22:31.720] first time ref. [22:36.520 --> 22:42.200] Oh, nope. Also auto completion. [22:42.200 --> 22:53.960] So global first time ref. And then Uboot first time. And then we say hello first time 20, [22:55.080 --> 23:02.600] yeah, 23. And yeah, that was a short head on. It's pretty amazing barebox. I really, [23:03.800 --> 23:09.160] I really would like it to see you if you have contributed barebox, if you send patches, [23:09.160 --> 23:15.000] if you bring your board to mainline and let us enjoy barebox.