 So hi, everyone. There are some seats at the front. I won't be spitting or throwing any water at anybody, so don't worry about that. So I'm here to talk about U-boot, and I'll get straight into it. I've got a slightly messy setup here because I've got these two screens, but we'll see how we go. So I'll briefly cover what is U-boot. I'm assuming most of you know that because otherwise you wouldn't have come. I'm going to talk about complexity in firmware, which I think is increasing and how U-boot can help with some of that, and obviously talk about some of the new things in U-boot the last several years. And I'll do a demo at the end, and we'll see how that goes as well. So U-boot is a universal bootloader. So kind of boot anything on anything is kind of the idea. It's been going for about 20 years. There's about 6,000 commits a year. There's quite a lot of active development, different architecture and so on. And there are four releases each year. It's got a lot of code, mostly in C. It's got some Python tools as well. And it's got a lot of similarity to Linux if you're familiar with that. It's the same code style. It uses Kconfig. It also has some compatibility layers. So you can port drivers over from Linux and subsystems over from Linux without too much pain. And it has a CI that covers a large subset of the features. And in general, U-boot's on the forefront of embedded technology, firmware technology, largely because people are trying to get things done. They are using U-boot. They're trying to figure out how to do it in U-boot. So why is U-boot so popular? It's largely the feature set, what it has in the features. But it's also easy to hack. It's pretty easy to get in there and add a new command for something or add some new feature for something. There are subsystems and layers and so on, but it's not out of control. And quite importantly, it's single threaded. There's no locking. It's not trying to be an operating system. So it's pretty easy to work with. It should be fairly open to new ideas and features, and it has a consistent release schedule. So let's talk about complexity. Everything's getting more complex in this world. Even coming to Prague seems to be harder than it used to be. Everything in our lives is becoming more electronic, more online, and the devices that we use to deal with that are all online and so on. The SOCs we use have a lot more features in them than they used to have, and they all need firmware. That firmware needs to be packaged somehow into an image, and again, that's getting more complicated. We've got security requirements and the difficulty of making sure that the code that we're running is the code we're supposed to be running. Ten years ago, that was the less common. We also have the boot flow, which is now jumping through multiple projects, different binaries and so on in order to get to an operating system. Finally, we have a proliferation of devices. So you buy a model, there are five other models that are similar, but don't have quite the same features. So they have different firmware and so on. How do you deal with that? I'm just going to go through a couple of examples on this. First of all, SOC complexity. Now, how many of you have heard of U-boots driver model? Yeah, okay. All right. So I'm not going to cover that other than just to say that it exists and it allows you to deal with this complexity fairly well. You know, you have a tree of devices, they can be in certain classes, they can have relationships, they can have private data and a lot of that sort of stuff is dealt with for you and device tree is used to pull it all together. So in the same way as done in Linux on ARM. So here you've got a device tree and here you've got some devices in a Rockchip platform just showing you the list that you get when you're running U-boot. So that's a very important part of this. So one of the most complicated things is clocks. And if you look at the datasheet, they've even given up these days, I think, putting a clock tree diagram in them, but they used to have an attempt. But the nice thing is with this driver model you can just say, please give me the MMC device. It will go and set up the clocks that are needed to do that. It'll do the pin mark sign that's needed to set that up. It'll turn on any power domains that need to be turned on and you'll get the device. Now that's really, really complicated to do manually and hacking around on the datasheet and so on. You need the pin control drivers and power supply drivers and so on to be in there, but once they are, it works well. Another example is configuration. So I mentioned multiple models, different models of different types. So with a device tree, you essentially can say, well, the only difference in these... the code is the same. The u-boot is identical. The only difference is the device tree because the device tree can set the configuration. It can set what devices are present and not present and that sort of thing. So it's really powerful to be able to do that because you can build your firmware once and sort of inject the device tree that you need. Maybe even the factory. And that's fairly well evolved at this point in u-boot. You can also pass configuration between firmware components and I'll mention that a little bit later. So just about packaging. I mean, I'm pretty sure if I went around each of you and if you're doing firmware packaging, you've got your own way of doing it. There's a lot of different ways of doing it. And it doesn't seem that difficult at the beginning so you start sort of putting some scripts together and so on and then you end up with this entire build system just related to packaging your firmware. So BinMan is an attempt. It's a part of u-boot, but it is applicable to other projects. We're using it with Zephyr, for example. It essentially lets you to describe the image in a data format. You can say, well, this thing has a... It's called u-boot.rom. We run make-image for this bit. We put SPL in it. We have the u-boot image and then, you know, this is just made up. But it gives you the idea, you know, it's basically a list of things that you want in the image. And the BinMan basically just goes and pulls all the files in and produces this image the way you want it. It also supports things like fit and fit and CBFS and things like that. So it can kind of generate these pieces and you end up with either a binary you can put on an MMC or a spy flash or something like that. The nice thing about having this data description is when you want to change it. It's very easy. You know, you just go and change this offset or you just go and add some new thing in here and run it again and you get a different image. And the other thing is that you can actually look at it later. You can look at an image and you can see what's in the image rather than having to decode it with all sorts of random tools. It also deals with the other problem I find with firmware is trying to find a tool that you need to sign it or to build it or whatever for each chip. So that's done there too. So standard boot is an attempt to sort of make this, make booting more standard in new boot. So many of you be familiar with the boot M command which is kind of how things are traditionally being done. There is a very powerful format called flat image tree which basically lets you specify a kernel, RAM disk, whatever it might be or even firmware images and signature verification hashes and so on. But as to finding out what to actually boot and which media it's on and so on people have traditionally relied on scripts for that. And there's been a thing called distro boot which is basically a set of U-boot scripts that are built into U-boot to handle that which has been around for some years. So standard boot is aiming to add a higher level interface essentially a way for U-boot to really understand what is out there and what's available to boot. So there are three basic concepts. There's a boot dev which is essentially a media device that can provide an operating system or something like that. So that could be MMC or it could be USB. But this is a device on top of those media devices so it has special things like please let me scan you and things like that. It also has a boot flow. Now boot flow is just an operating system that you want to boot. And the purpose of a boot dev essentially is to provide a way, provide some boot flows and they get and the thing that finds them is a boot math. So these three things work together it's a little bit hard to get your head round but if you imagine that you have to go and hunt for these things in certain ways. Chrome OS is different from Android is different from Ubuntu for example and so you have boot maths for each of those and then you can find what you need to boot. So I think that's a pretty simple concept. It's super hard to get right and it's still sort of in the process of conversion. So Uboot has quite a lot of UEFI support. There's a UEFI layer in Uboot which is sort of distro friendly and it can boot these distros essentially which are UEFI applications essentially and there's support for UEFI secure boot, capsule update and so on. Because it uses the existing Uboot drivers you can just turn it on and it kind of works. You don't need to configure it anyway particularly and there is a boot manager support in there as well. What you can see at the bottom is there's something to boot, finding this thing and then booting it and this is using the UEFI layer to do that. And by the by, a Uboot can also run as an UEFI application meaning that you boot into you boot from something else. But there is also this other thing going on called verified boot for embedded VBE. So this is intending for those of you who don't wish to use UEFI and I will point out a lot of embedded devices typically just boot into the operating system they're not trying to be Ubuntu and that kind of thing in Debian. So this is, the attempt here is to say well if we're not going to use UEFI what would it look like? Now I did a talk about this last year there were a couple of talks last year so I'm not going to talk about it in any detail but essentially it tries to build on the existing technology that people are familiar with like the Uboot, like the fit and extend that so that the operating system can tell you what it needs before you jump to it. It's essentially at the moment the way UEFI works is you jump to the operating system's stub it then calls back to Uboot constantly saying tell me this, tell me this, give me this and then eventually jumps on to boot Linux. So the attempt here is to say well let's just describe in the data structure what we actually want what the operating system actually wants so we would just do it and then when it's done we pass all that information on. I think a potentially simpler approach. So we also have documentation so I guess many of you familiar with Sphinx which is what Uboot's moved to is I guess there used to be a Uboot manual many years ago and it just sort of died. The good thing about this is it's part of the source code so when you do a patch to add a new command in that patch you add the documentation for the command and hopefully the test for the command as well. So that is a departure perhaps from the way things used to be done but the documentation is kind of pretty kind of a text file so it's pretty easy to write and it seems to be working pretty well and quite a bit of the documentation has been converted. I would just mention that some of these slides have a little future bubble that just refers to something that is happening in the future in determinate future. So the other thing is that's been expanded considerably in the last few years is testing and CI. So I don't know if any of you are going to any of these effort talks but there was one on emulators earlier today. Uboot makes a lot of use of that so you can kind of run Uboot and you can on your Linux workstation essentially and use spy flash on it and you're just really using an emulator spy flash and there's a lot of that sort of thing and it's great for tests because you can write these tests that simply use these devices that are not really there, they just emulate it but they're really fast and so on and you can make the emulators do things that you want to test. So there's been a lot of use of that. This is showing a GitLab view of all these different things that are running. This has just started up and you can run these tests and so it's sort of environment where if someone sees a patch and there's no test you can say hey where's your test and in most cases it's not too difficult to write a test for it. Now I mentioned this earlier about device tree. One of the problems though is that Uboot adopted device tree roughly the same time as Linux and the bindings don't always match by which I mean that they use different properties and nodes and so on so that's something that's being resolved over time. The other problem is Uboot has not been able to upstream its schema requirements to essentially what was Linux but that's changed as well. So there is now a DT schema thing and some willingness to accept those patches. So it's definitely made a change to how we're thinking about device tree in Uboot. The idea though is essentially that you get the device tree from Linux and you can use it in Uboot and so long as you've got the drivers and so on you won't have all of them, you don't need all of them then you can use that same device tree. And there's also a live tree which is a hierarchical structure and we're seeing more usage of that as well. There's quite a number of minor things so kconfig although Uboot has had kconfig since I don't know as long as I've been involved perhaps 2014 or something there's still been a lot of these old config hash to find configs in the header files and so on. So those are now gone as I think earlier this year and essentially it's now possible to write a board implementation that doesn't have a kconfig file because the text environment the environment can now be in a text file with a fault environment. So these are somewhat minor things perhaps but it is much nicer than it used to be. Okay so link time optimisation I presume you know what that is, it just makes your board take about four times as long to build but it's 5% smaller like that but it is a win generally so it's something that's almost turned on by default for ARM I think but it's certainly working pretty well and then there's this thing called events. So I'm not a huge fan of weak functions some of you may think they're wonderful and great get out of jail card I don't like them very much because you can't really see where the call is ending up just assembling the code and putting a printf in or whatever so events basically you publish the event and then these other places will receive the event and do something with it and that can be done in a you can see the list of those spies they're called just by using a dumper tool so they're not very easy to find than weak functions So another thing that's been going on behind the scenes is this idea of communicating between projects because if you've got these different phases of Yubut and other projects they currently kind of get built individually they get configured individually and it's kind of a pain because you have to do all that and make sure it's consistent but they've got different configuration systems and so on so one step towards improving that is a thing called the firmware handoff and you can have a look at the link there this is a specification for a simple sort of tagged data structure you just have a tag and some data essentially that is can be specific to a project or can be shared between projects and that I hope will see us being able to say things like right well your SD RAM starts here pass that through here and this thing says well I want you to load here pass that through there and so on so you can the firmware can become more cohesive even though it's built from different projects it can sort of behave somewhat more intelligently than just blindly crashing when you do the wrong thing so on networking I guess there's been quite a few changes here there's TCPP support and therefore WGet which is kind of handy TFTP is a bit more limited so it's good to have that there's also IPv6 support in a new NetworkFi API the other thing that's going on is there's been some discussion about what to do in the future should the project move to lightweight IP and using that or should continue with its own network stack so there's discussions about that and that's fairly common in a lot of areas right I think the MTD stack is straight out of Linux on the risk 5 and x86 side there's boards arriving booting distros on x86 is supported we're pending some patches and there have been some enhancements to core boot support so essentially one of the ways you can be used as a core boot payload on an x86 device so you boot core boot it starts up it does everything including setting up ACPI tables and so on and then it jumps into you boot to actually boot the OS and so that that's become a little more polished now with the ability to boot find the UART without any trouble and that kind of thing tracing so this is essentially execution of your program and the thing about booting is you want it to be fast but you don't know why it's slow and so tracing can help you figure that out you essentially turn it on it records the starting entry of functions in a memory area you export that memory area over the network or whatever to your computer and then you can run these tools to see what was actually going on so this has been a new boot for a long time but was recently updated to support the new trace command interface which is in common with Linux and there's also a thing called boot stage which has been in there forever which is but that only really does timing it doesn't really allow you to debug it very easily another thing that seems really minor but I called it out specifically as a site click subsystem so I said that Uboot is single threaded and doesn't have interrupts and so on and that certainly makes it easy to work with but it can be annoying because when you type for example USB scan or USB start you you have to wait and it goes off and waits for the amount of time on each device at the specs as it has to and so on and it can take several seconds if you've got a lot of ports or if you just sort of said USB start and it would sort of do it in the background and maybe report them at the end or something like that and so that's something that's potentially possible with this because essentially what happens is whenever Uboot is idle it jumps into this site click schedule routine and that is used for the watchdog for resetting the watchdog and that's been there forever but now you can use it for other things as well and you've got some ideas there about what it could be used for but I think I'm looking forward to seeing where that actually goes and what can be done with it another sort of this is very sort of experimental and new but there is a thing called Expo so an Expo is essentially a set of screens that you can show to the user and the screens are called scenes there's always an attempt to avoid using words that are commonly in the codebase so if you're wondering why these names are so strong, are so strange that's why but the idea essentially you can set up this scene, the user can interact with it perhaps move on to the next one and so on and it's a little bit like the BIOS menu in your in your x86 PC for example it's in an attempt to provide something a bit like that and as I say it's still under development and so on but you can see some of the elements of that in the codebase today so what I'm going to do now is attempt to do a little bit of a demo of some of these things and to some extent this is going to depend on how lucky I am and how patient you are but we'll see how we go so what I'm going to do I've got my little thing over there that's not what I want I want this thing okay so I'm going to type things and see what happens so this is me running QMU on a on a uboot.rom that I already built to boot Ubuntu you can see the screen come up there sorry it's all sort of a bit over the top of each other but you get the idea and there you can see oops now I've stuffed up my cursor but there you can see it booting Ubuntu I'm not going to let it actually boot but that was the what you see on this display is it going off and hunting for these different devices doing a for boot flows essentially it found this one we're going to boot that boot flow and that's obviously using the ufi layer and then it goes off and does the boot so that's essentially what that's the the what do you call it the standard boot working and I can stop it and do this so you can kind of see it it got two boot flows and list them you can see them there and I can boot that boot 0 or boot 1 or whatever it was set up to boot just the first one so that's the standard boot feature you can see here the method that was used which is efi the state that was in and so on where it came from so that's a little bit of a look at standard boot now somehow or other I need to get out of that oh is it is it QMU sorry I get confused so that's that and back over here I just want to show you the image that we are running there so this is a bit small how am I going to make that bigger so here we have an image this is the uboot.rom that we were just running and it's showing you the insides of the image with bin man so this has been produced by bin man so I can actually go and look at it and see what it contains and while I'm here I'll just show you the tool situation so I can look at the tools that are available that bin man knows about for building these images I noticed that this flip tool is not present this one so I can do fetch missing and it can see that flip tool is missing so it goes off to trusted firmware downloads that are now I can type flip tool so that's the intent of being able to actually use the build the image firmware images really easily and so to get your image into bin man you have to be able to provide the tool that people can actually use for it let me push this tree up to up to the CI and then I'll see if I can get that open so this is just showing you the thing that's running now if it's a little bit small as you can see so I can make it smaller but here it is running and so on and you can go in here and have a look at the things that it's doing and get a feel for what's going on so if you're not familiar with GitLab this is GitLab it's a bit like GitHub but maybe more suitable for devices and so on so that's that and what else was I going to do I was going to show tracing but I'm going to show you something I collected here this is the flame graph that you can come in here and click on and you can kind of work your way around it and see different things and you can see the call structure so it works pretty well the mechanism for actually running the trace is essentially something like this you run you run your boot you you look at the stats and you can see that it's it's already overflowed its buffer but it's been recording it since we started you then run this command to dump the call data out to RAM this is all running in Sandbox of course and then you save that file out to your file system and so now I've got a file which I can run to convert to you know to with the prof tool essentially run to convert it to a flame graph or to whatever I want and I can use trace command and so on so that's the tracing side of it and then the final thing I wanted to quickly show you was this this thing and so I'm just going to run these little commands to convert the configuration over and just run this Sandbox and so this is essentially now it's over here this is just the configuration editor I was talking about so you can go in here and it's just like a little user interface thing feature in your boot under development so yeah that's all I've got to talk about so thank you for listening and I guess we have a few minutes for questions if people have questions how long would we have for the questions I should probably learn that myself finishes in 10 minutes alright so we have time does anyone have a question this mic here thank you for the talk you mentioned at the start the direction to use a single u-boot and different device trace per bot is that a future direction is that something I can do right now because of all the if-deaths and the weak which I would assume would clash with this yes you can do it now it's been actually been around for a long time in fact back when Chrome OS was using this we had truly desires for getting into to device tree if your drivers you know if you're using the same drivers it's super easy or if you can have a super set of them some of the drivers I see for an SOC will say if it's this architecture if it's this architecture then yeah you're going to have problems but in general it's pretty easy to do and it's been around for a while yeah I mentioned it is because it's becoming more relevant today than it was hello thank you for the presentation yes I wanted to know for the x86 way of booting so I saw in the demo it's already working like replacing a BIOS but I was wondering if it can also work like a UFI image like being loaded by the BIOS like sort of an IPX so do you mean UFI on the computer booting into Yubu? yeah exactly yes you can do that Yubu can run either as a payload where it sort of takes over the machine completely or as an app an EFI app the app is less developed the payload has been around for a long time so it depends what mode you want okay thank you down the back you're just trying to make a run aren't you that's what it's all about thank you I have a few questions about standard booting the first one is is it possible or maybe already implemented to set priorities based on the device type for example a removable SD card should be booted first before internal emmc before a non flash if all of those are present on the system yes it has a priority system at the moment it starts with what it assumes to be fast devices each boot dev has a priority and you can set that so yeah the last one is network it'll always try that last but when you say emmc removable versus non I don't think it makes a distinction at the moment so you would need to put that in there somehow you can also hard code it if you set the boot targets environment variable to the ones you want to try in order it will do that okay thanks and kind of related would it make sense to implement something similar for the SPL because basically for now the SPL boot order is hard coded into the device tree like first try to load your boot from the same device and so on and would it make sense to have some kind of boot flow or boot dev selection enumerating all the storage devices present on the system and try to load your boot the actual you would payload from one of those priority the nature of all boot loaders as they become operating systems the nature of SPL as it becomes you boot so sure there's actually a talk I think at this conference about putting the LCD display into SPL so boot Santa boot is implemented entirely with driver model and driver model can be turned on or it is turned on generally in SPL but you can simply enable drivers and they'll work it avoids using BSS and things like that that are a pain in SPL so yeah I think if you really wanted to do it with some K config fiddling yes you could probably do that yeah yeah I have a question at the front a comment I'm coming I'm coming I have I have a comment that SPL actually can iterate over a couple of boot methods already so it's just there yes I think we're talking here about the standard boot methods but yeah that's going to be confusing but yes that's right it does you have a set of what are they called boot targets or something I think boot targets it's in common SPL SPL.c there is a weak function there oh lovely you can probably measure the number of weak functions yes sorry I just have a thing about weak functions anything else this is really outrageous what you're doing with all this running around what do you suggest for runtime configuration for your boot to detect the hardware and for example choose between different device trees so having the same binary running on different variants of the hardware is there a standard way to do this well if you think about it the way Linux does it is you give it the correct device tree and your boot will choose that and pass it on to do it is in SPL you choose the device tree you want and when you boot U-boot you give it that device tree and you can put them in a fit and essentially boot that that's implemented today if you want to do something more clever than that then you'd have to implement it yourself I don't think there is actually a strange device tree selection thing right at the beginning of U-boot proper I think America is nodding his head pardon oh yeah DT reselect yes so you kind of jump into U-boot with a DT and then select a different one very early on so you can actually do that as well yeah I mean pretty much every case that anyone can imagine if someone has hit in real hardware and has tried to implement it in U-boot so tends to be the case that you end up being there can the same be applied to SPL because for example many boards has DRAM configuration in device tree and it's useful to switch between one of the others by detecting the hardware and choosing which device tree to use in SPL do you have the same thing or something like that or something working on on that so if you look at the Rockchip 2032 88 boards the Chromebooks have that they have a property in there which is the DDR config and there's four different ones I think for different DRAMs and at runtime it looks at the ID pins on the board to decide which one it is and uses it so yeah that's implemented and you can do it easily enough so we're just about out of time does anyone have a super quick question otherwise we're going to wrap it up here alright well thanks thanks for coming and really appreciate you looking to see you