 Good morning, and welcome to the presentation about system upgrades with SW updates. So like the agenda of the day, so we're going to start with a short introduction about the system update in the embedded system. I'm going to do a quick introduction about myself as well. After, we're going to speak about the architecture of SW updates, how it works, I mean, how it works. Then we're going to explain how you can customize SW update to fit the needs of your solution, how to adapt SW update to your solution. And then we'll talk about the integration to the different BSP. So there is a lot of talk about Birod, about Yocto. So how do you integrate SW updates in those solutions? We'll finish, I forget at this point, but we'll finish, if we have some times, with a demonstration on the Nitrogen 6X. So about me, a quick introduction. So I'm like an open source enthusiast. I'm working for Witeco, a company located in Bellevue in the Washington state. So it's not really far from here. So basically, I'm mainly working with Android and Linux. Doing BSP adaptation, driver development, more generally speaking, system integration. So the presentation of today has been based highly on the boundary devices. So there is the Sabrolite and the Nitrogen 6X. So the reason for that is this presentation has been made in collaboration with Gary Bison from Boundary Devices. And also Stefano Babic, who is the maintainer of this solution. There is also another board, the WarpX device. So if yesterday you were at the technical showcase, they were showing their device how you could use SW updates on their device. So quick introduction. So why do we need to have a software update solution for your MPD device? The first and more important, the most important reason is for bug fixing and security issue. A few years ago, there was a huge issue in the OpenSSL library with the hotbed issue. And basically, all the secure communication with the different devices wasn't secure anymore. So when you are working with devices, your device, you don't necessarily have an access to the device. So sometimes, you are in the space, in the middle of the ocean, or you don't have any physical access to the targets. So you need to have a way to update your device to basically fix those security issues. Obviously, another reason is to add new features to your device. When you start the development of your solution, you might be using the Linux kernel at a certain state, or you are using some OpenGL library or some other devices at a certain state. Two or three years after, you realize that your video streaming or some of the performance of the board are pretty low. So you want to basically enjoy. You just want to profit like the other new features that have been developed within the two or three years. So this is what you need. Basically, have a system update solution. So there is different solution on the market today. I mean, as you can see, on the different booth, there is Mender where there was a solution. There is resin.io. There is SW update. There is 10 or 15 different solutions, slash framework, to handle, to manage this kind of software updates. So today, we're going to focus only on SW updates. So it's a framework. So it's not an end-to-end solution. It just gives you the tools to basically create a software solution for your target, for your product. It's totally open source. So it's under the GPL v2 license. And it has been created and maintained by Stefano Babic from Dankz. So it's kind of a project related also with U-boot developers. So the idea of the project is to cover all the aspects of the software update solution, from the creation of your image to the download to the target, and also the flashing of the different devices that you want to update. This software has been developed based on the past experience of the different customer and users who are currently using this solution. So this is a solution that is currently used in production and by some customers. At the beginning, there is always some bug in the software. There is always some features missing. And so the more the customer are using these features, the more you're going to have a better solution. I'm just sorry. I forgot to plug my laptop. So also at the end, if I have some time, I would like to show you a practical approach by doing a demonstration of a basic software update on one of my board here. Sorry about that. So the architecture of SW updates. So what do you want to update? So there is different pieces in your solution that you want to update. The first one could be the bootloader. We're not going to cover this in this talk because this is something that generally you don't want to do it. Like the main reason is it's something highly dependent on the features from your SOC, from your board, from the hardware. A lot of SOC doesn't provide a way to have a redundancy of your bootloader in the memory. So it's going to basically load the bootloader at a specific address in the memory, jump to it, and that's all. So if it's failed, the board is not going to boot anymore. So you want to update the kernel as well. I mean, it's something that you definitely want to do, the device tree, the root file system, and also the application data if you want. So the first question that we can have in our mind is, why don't we use a package manager? Most of the distribution, like Debian, Fedora, they have their own package manager where they support updating any packages. It's pretty nice. If you need to update one of the package, it's like the footprints of the update is pretty small. The problem that we have with the package manager is it's not atomic in general. So what we are saying by not being atomic is if there is a poor failure in the middle of the updates, you need to have a human intervention to fix the corruption that the update might have created. It's also really hard for testing and support. So when you develop an embedded product, basically you generally have the manufacturers who's going to create like the software, and it's going to provide a support against some specific version of the libraries or a specific version of the application. So you have a team, like a test team, dedicated to test, like to make sure that everything is supported and working properly. And if you use a package manager, it's really hard to track all the different versions of the libraries that you're going to install. The tracking is really hard for the different version, for the different updates. And obviously, there is more places where things can go wrong. You don't flash only one file, you flash different things. There is a lot of different steps. So it's really based on the experience. So some people tried. And at the end, they just fall back to another solution, more SW updates. So the architecture of SW updates, so it's a standalone binary. So there is the main core features, which is the installer. So this is the main function of the application. So it will lie on a description file that contains the description of your updates. And it's going to be parsed. So there is a different library to handle this parsing of the file. There is also some notification. Because when you are doing an update, you want to know what is the current status, if it's failing, if it's succeed, if it's still in progress. So the notification is going to basically give you the possibility to have this kind of information either in the system log or over the network or anything that you can think about. And you have different handlers. So when you do an update, you want to update different devices. And to access those devices, you have different libraries, different applications. So you have an API who just encapsulates these kind of handlers. And you have also an external API to communicate with some web browsers, some local storage, or some custom protocols. So it's very small, but this is the idea of the project. So when we talk about atomic updates, there is two different techniques to achieve this. The first one is what we call the single copy. The idea of the single copy is your bootloader is going to be responsible to detect that you need to update your system. This detection is obviously not managed by SW updates. But you could just imagine pressing a GPU button on your board, and it's going to fall back to this image. Or it could be the detection of a USB thumb drive with a specific file on it. So the idea is when your board is going to detect that a new update is available, it's going to basically start an init-RAMFS image. So the init-RAMFS is just an image, a small system containing SW update, and it's going to run in the DDR. And so you're not going to use the current file system. So if you flash your root file system and you got a poor failure in the middle, the flags in the bootloader are not going to be updated. So basically the bootloader knows that the update has failed. And so it's going to load again this rescue image to do the update again. And the second solution, which is the most popular, is the double copy, or the double partition. There is a different name for it. So the idea is to have a ping-pong architecture between two partitions. You basically have to duplicate everything. All your partition has to be duplicated. The idea is to have one active partition where your system is currently running, and the other one, the inactive. Just stand by a solution. So your bootloader, the first time, it knows that the active partition is going to be the first SD card. So it's going to run the software on the first partition. And so when you detect a new update, you want to install it. And so you are going from this partition to install the other partition. And so the update is going to update the bootloader, like the different flags, to say, hey, now the new active partition is your other one. So when you are going to reboot your board, the bootloader is going to start this partition instead of this one. So if we imagine a poor failure in the middle of the update, it's totally fine, because we will always have an active partition which is working. Because this one, like the update of the bootloader, is done at the very end. We're sure that both partitions are kind of working. So as the new update, it's a Linux user space application. We could think, I mean, a lot of people are thinking of doing solution either in the bootloader directly, or like a bare metal application. It's more useful. It's more simple to do a Linux user space application, because you can just profit of all the different tools from the Linux kernel, all the drivers, all the different libraries. It's super easy for the parsing. You have the different library, which is available for the Linux application. You have access to all the different drivers from your kernel. So for the networking, for the access to the USB, the master edge, it's more generic than the bootloader. And also, the bootloader, they are well maintained. They are working pretty well, but they don't contain all the bug-fixings that you have in the Linux kernel. It's a full update solution only. So it doesn't support a partial update. So basically, it's either we update the whole image or nothing. So you can think that, oh yeah, it's going to be like a huge image, but you can generate some really small footprint system with SW update in it. I think Stefano was able to generate like a compressed RAM disk of four megabytes. Four megabytes is something that you can even fit in your span of flash. It's generally used for like a rescue image. So if your system is failing to boot, you have a fallback that you can have SW update waiting for an update from over the air or for a master edge. There is different features available. So first, the different interfaces are supported by SW updates. First one, local devices. So your USB, like thumb drive, SD card, UARTs, anything that you can think about. Most popular, you can do like over the air updates. So there is mainly like HTTP, so like a direct link to the file. Some web-based solution. Hubbits, I'm going to talk a little bit about this after. There are some security features. We're going to talk about this at the end of the presentation. But security is a critical and an important point for an update solution. And it supports a lot of different handlers. So the handlers is, as we said, what's going to manage your different features from the kernel. And it supports also a streaming. So basically, you don't have a copy on the target. Because the updates image can be really huge. It can be bigger than your DDR. And so what you want to do sometime is just to, once you receive a stream, you want to do the updates on the fly. So everything starts basically with a file. This file is .sw. It contains basically one file, which is the sw description, which described the whole image. Like this image, so in this sw file, you will have the sw description file. And all the images, all the binaries that are required for your updates. Everything encapsulates into a CPIO archive. So the choice of CPIO is just easy, because it's a simple format that is easy to parse and to use. So yeah, let's see a real example. So this is basically how a description file looks like. You have the main node, I'm not sure if you can see clearly, but you have the main node named Software. So everything is described in the Lua language. And so you describe the whole update. So this is the main block. You can have some broad specific node. For example, here, we choose a nitrogen 6x. It could be the warpx. It could be a big old black. It could be any different hardware. You can specify different attributes. So you can say, hey, this image is only available on the specific revision of the hardware. And after, you have the description of the different handlers. So for example, here, we're going to say, hey, in my image, in my sw file, I have a root fs.exe2 file that I want to flash on this specific device using these specific handlers. And so you can specify also a SHA-256 hash values to make sure that at the end, the update has been properly written to your device. You have also different handlers for the script. So the script that you can run before and after the update if you want to do some modification into your system. So a quick example for the USB. So how does it work is you have the binary on your target. And you just specify the dash i option. And the name of the sw. After, you can specify also a public key if you need the security features. But generally, you want to make it automatic. You want to know when you plug a USB thumb drive that you don't have to do anything on the device. So to do that with USB, you have different solutions depending on Udev or Mdev, like the ones that you are using on your root file system. So there is two tutorials. The first one is a link to do auto mount with Mdev. And the other one is a link to the free electron training on how to do the hot plug-in with Udev. There is a support of OT update. So SW updates support. I mean, they have an embedded web browser inside the solution, which is named Mongoose. So it's a different project, but it has been integrated in SW updates. So you can just start it and access your device from a web browser and select the file and just upload it. You can just specify a direct link to a direct HTTP link. And you can use another solution named HubBit. So HubBit is kind of special. I mean, it's a software updates management solution. It's really hard to describe. I'm not an expert of HubBit. But the idea is you create a software distribution, software module, where you just specify the different files that you want to use. And basically, at the end, we don't see it clearly, but you have the list of the targets that you have on the network. And you have the list of the updates that you created in HubBit. And you can just drag and drop, and you will have a different status of the current updates. So this HubBit is supported via sorry, Qatar daemon into SW updates. So it's a custom daemon that has been developed to support the protocol of HubBits. The deployment of this solution is pretty complicated. You rely on Apache Tomcat on Spring. It's pretty heavy to compile, and it's pretty hard to install on your server. So personally, my advice would be for you to use Docker. So you have different images for Docker that you can use, and it will make your life really easy. If you are not really familiar with Docker, there is plenty of documentation, and there is also some presentation at the ERC. So how do you customize SW updates? So like every open source project, I mean, like for UBoot, the Linux kernel, build routes, you have a Mac menu config. So it just allows you to customize all the different features from SW updates. So for example, if you don't want to support any over-the-air updates, you can just disable the web browser and sorry, Qatar. If you want to disable some specific parser, you can do it. If you want to enable the security features, everything is contained here. So the first thing that you can use to customize SW updates is the hundreds. So the hundreds are going to basically translate the fact that you want to flash an image to the USB to what is supported in Linux, like in your BSP. So the first one that you want to customize is like a handler for FPGA. So there is a lot of products where you have the microprocessors, which is connected to either an FPGA or either a microprocessors. Generally, this kind of protocol, this kind of communication is too specific to have something common, to have a unique API for that. So for your solution, you can just define a custom hundreds. So here it's not doing anything. It's just printing basically like the image. But you have a Lua framework provided by SW updates, where you can just request. And you just define a function. And in this function, you just describe how you communicate to your FPGA or your microprocessors, how you basically update this device. So you don't have to write all the different handlers. There is some provided by the framework. I'm going to show you an example of how it looks like. But basically, you have some for the different flash devices, some for the UB volume, some for the SD card, some to update the UBoot environment, and also the ones that you can create. So just an example for the Spino. So here is just an images where in our SW file, we have a file named UBoot.SB. So in this case, we're going to update the bootloader, which is not necessarily the best example. So we say the handlers is type flash. So we know it's going to use the MTD libraries to do the updates. And we specify the device. There is three other attributes that you can use. For example here, we just want to install it if it's not already installed on the target. So you have different file on the target that SW can use to detect the current version of the bootloader that is installed on your target. And based on that, it can know that if it's required to do the update or not. So an example for the UB volume, so it's always the same things, so you specify the file name and the type. And after, the other attributes are specific to your handlers. You have the SD card, which is the most popular one. So here, we can say, hey, be careful. My image is compressed. So don't forget to uncompress the image before doing the installation. You have some to update the UBOOT environments. So be careful about this one. Obviously, there is no atomic way to update the UBOOT environments. So you need to make sure that in your UBOOT configuration the option for the environment rather than C is enabled. So basically, that UBOOT is writing the environment to different places in your device. So it's really useful if you want to update the boot arcs or modify any parameters in UBOOT. And also for some Lua scripts and some Shell scripts as well that you can use. One feature that is the most useful is what we call the collection. So the collection is what you are going to need, what you are going to use to implement the double copy, the double partition solution. So a collection is basically like a main node that we can call stable, for example. It can be any name except the keyword used by SW update. And so you are going to define basically the main partition. So like the first partition of the SD card and the standby, like the other alternative solution. And so how do you choose? How do you know which one you need to run? Is when you start SW update, so before starting SW update, you need to know what is the current active partition. So once you detect this, you can specify with an option to say, hey, if you receive an update, you need to use this node and not this node. So you always do the ping pong updates. So the detection of the active partition is obviously live to the users. It's really too hardware specific, too specific for SW update to detect this. There is different idea to do that. You could use a flag from your bootloaders, or you could just parse the command line arguments provided by the kernel. So the integration. So the first one, Yocto. I think Yocto is pretty popular everywhere. So Stefano is basically maintaining as well in parallel of SW updates a meta layers for Yocto. So by default, the meta layers only supports a single copy scheme. It doesn't mean that it cannot support a double copy or anything else. It's just by default, what is providing is for this scheme. So you can use bitback SW update, and it's going to generate a file in the time deploy directory. So it's pretty standard. I mean, if you use Yocto, it's pretty standard. Everything is generated at the correct place. So the image generated by bitback SW update is not a SW file. It's just like a init-warmfs that contain SW update, so that you can use to run your different updates. If you want to generate SW updates from Yocto, there is an example for the bigger button black. So you have a recipe provided in the same layer, which is BBB-SW update-image, and it's going to generate at the same place, so in the deploy directory, a file with a dot SW extension. So if you want to customize this in the meta layers, there is the SW-description file, and there is the recipe as well to customize everything that you need. There is also a class that is provided for the customization of your different images. So let's take an example. So for example, you want to load the kernel, because you know the init-warmfs doesn't contain the kernel, so you want to load first at a specific memory address, the kernel. You want to load the device tree if needed. And after you want to load the init-warmfs generated by BitBeck, you want to load it at a specific memory address. And after you just boot it, at the end, you will have a shell with SW update running. The default behavior is basically like waiting for an update from the web browser, but you can customize this to anything that you can think about. And this is where after you can use the SW file that you generated with the other recipe. The other solution is billroute. So billroute, there is a package named SW update, which has been mainline for a few months or a few years. Not sure when it got into the project. So there is a configuration that you can use to enable it. There is a default configuration that you can obviously modify through billroute. So there is an option to make that you can use. So it's make SW update-money-config. It's the same as for the busybox or the other package that supports the k-config. So billroute, when you generate your image, doesn't generate any twimfs. It doesn't generate any SW file. Basically, you have to do everything manually. So the solution, the more standard way, is basically to go to the output images directory where you have your different file. And basically with the script, or you can do it manually, but with the script, you just create the CPIO archive. So the first file that you need to put in the CPIO archive is the SW description file. And after, you just append the other file into the archive that are required by the updates. And so at the end, you will have basically a file like name.sw. So you could use it, for example, on your target. You could mount like your USB thumb drive, run SW updates with a path to the file, and just reboot if everything worked. One of the features which is really interesting for the different customers is to target a specific hardware and software revision. Sometime, like in production, you have two or three different hardware revision. And you don't want to generate three or four different images SW file. So what you can do is you can specify a specific target node. And so this one is going to overwrite the behavior of the parent node. So for example, here, we can think about the NaturallyN6X or the WarpX. They have four different revisions. So we know the update will be the same on the revision 1, 1.0, 1.2, and 1.3. But it's going to be different on the 1.1. Because maybe they change the SD cards, like support, or the EMMC, or just the way on how the board was working. You could have also a generic behavior in the main node and just overwrite a specific behavior in a specific node for a specific revision of your hardware. So the verification of the hardware revision is only available if you enable the option. And how do you specify this information? You have two different files. So you can customize this as well. But in slash ETC hardware revision, you specify the name of the board and the revision of the board. And for the software version is the same. So you can specify the different software install with the version of the software. So an example of the system logs that you can have if it's compatible or not compatible. So the first one, everything is running perfectly. So we can see it detected like a revision 1.2. It's compatible with our updates. In the other case, it detected that the software update was not compatible with the hardware. So you just cancel it. Important features, security. So for the security, there was a lot of conversation on the Google groups and the mailing list to know how to achieve it in the most simple way. And the most simple way. So basically, we sign only the SW description file. The whole image, the whole remaining image is not signed. But once you enable the security features, once you enable the fact that your image is signed, you have to declare a hash value for every images. If you don't specify it, SW update is not going to update the image. The idea is when you install the image on your targets, you know for sure that your description file is correct because you have verified the signatures. And so this file contains the hash values of the different images. And so it just allow you basically to just analyze, just to parse this more like the headers to install the targets. If we sign the whole image, the problem that we have is we need to uncompress. We need to install basically the update on the device before doing the verification. And it can be really tricky if your image is bigger than your memory, basically. So how does it work? You just rely on the open SSL utility from Linux. So you can generate a private key. You generate a public key. And so you have a small command line where you can just use to generate signatures. So once you do that, you are sure that nobody can tamper basically your image. So if we take the example of the root to generate the SW file, it's exactly the same. It's just we added the signatures right after like the description file. And we just generate it on the fly. The signatures, be careful, has to be its monetary. It has to be right after the SW description file. So don't put it after the root FS EXE2, for example, otherwise it's not going to work. And there is also an API for the external programs. So this API is pretty simple. So it's implemented with the smart structures where you have a magic number to make sure of the integrity of the data. You have a type, so a type of message that you want to communicate, and the data that you are exchanging with SW updates. It's basically allow you to define some custom protocol with SW updates. So you can just imagine a client requesting like an install to SW updates. And so SW updates is going to check if it's ready to receive or to start a new update. Once it's ready, it's going to reply with the hack. So once the client receives the hack, it can send all the data, or like the CPIO archive are going to be streamed to the target. And after the customer, even in the middle of the communication, it can request the status of the current update, just to know if it failed, if it succeeded, or if it's still in progress. So this communication is pretty simple. There is some example available in the source code of SW updates if you want to have a better idea. So what are the next steps, basically, of SW updates? The first one, it's like the support of binary data updates. The idea is, OK, like an image is pretty big. You can have an image of 2 gigabytes, 4 gigabytes. And you don't necessarily want to update your leg to send everything. So there is some conversations, there is some discussion where you are all welcome to come and give your idea to have a support of the binary data update in SW updates. It's not something that is going to be implemented if it's going to break, or if we think it's going to break the solution. Obviously, we want to add more handlers, so for the FPGA or any other solution that you can think about. And also, being able to load the plugins at the runtime. At the moment, everything is managed at the compile time. So like the handlers, you cannot define handlers on the fly. So everything you need to recompile, basically, SW updates. We want to add more example and support for the evaluation board. At the moment, we support just like a rescue image, and just like the big urban black in the case of Yocto. There is also, like, we want to add more back-end hook bits. So if you have your own solution and you want to be supporting in SW updates, feel free to open a discussion on the mailing list. And also, the support of a file system-based persistent update status storage is pretty long, this one. So basically, the idea is it's kind of relying on the bootloader or on Uboot for the different flags. You can do whatever you want. Add element is not limited. It's just like the way on how most people are doing. The idea is like a lot of boards, a lot of different solution, doesn't necessary use Uboot or like barebox. They have the custom bootloaders. So the idea is like these flags that the bootloader needs to know like if you need to do an update or like to know which partition it has to boot is to put those flags into like a specific device, like a USB stick or like an EMMC, to have kind of like a standard API to implement this. So before ending the presentation, I just wanted to show you, if it's not going to fail, a demonstration on how it works. I really hope you'll be able to see it. I'm not sure if you can see it's in the back of the room. So basically, I have the nitrogen 6x with build route running on the board. I have like an update file, SW update file available on my USB thumb drive. And so I have like a double partition implementation. So here, I have like a MMC, BLQ0, P1, and P2. And so the idea is I'm currently running, let's check this, I'm currently running on the first partition. So here, like the root device is currently running on the first partition. And the idea is I want to add a new command line. I don't have like the command line file. File is not available. So I want to make an update to have this available. So like the first thing that you want to do is you want to mount your USB thumb drive. You want to check what's available on the thumb drive. And so here, we have like the nitrogen 6x.SW. And so we're going to run the updates. So I'm going to add some logs. So you can increase the log level with the dash L option. And we're going to specify the dash I option. OK, my keyboard. And here, it's a double partition. So you need to specify which one you want to update. Otherwise, by default, it's going to take the first one. So here, I want to update the other partition. So the update is running. We got some information. It's currently found like the installer, 6x40. So let's see like if it really works. So you can reboot the board. Should we fast? I really hope. OK, it's starting. So let's check which partition we are running. So here, it changed. So we are now booting from the partition tool. So it's going to be indicated here. And if we check, we have now the file command line available. So it's a basic example explaining the double partition. I got the file for this demo like available. So let's zoom a little bit with this one. And here is the one that I have in my different slides. So I'm not sure you can see it clearly. It's pretty dark. But basically, the idea is you define your double partition, your collection, with the main node. But this is not the one that we use. We specify. We said, hey, we want to update this partition basically. And we have also a custom script to update the bootloader like an environment. So there is different resources available. So there is a nice documentation about SW updates. It's well maintained. It describes almost everything, anything about the piece of the software. There is a lot of examples, a lot of support about this. There is different presentation available on the web about SW updates. There was one from Stefano Babic directly at the ELCE 2014. I provided a link to the Hockbeek Docker if you want to use it. There is a readme to explain how you can set up this. There is also like an article from Bondari devices explaining how to use SW updates. So feel free to use it. And there is also like a mailing list that you can use to submit your patches or to start like a discussion with the different developers or users of the projects. So this is the end of my presentation. So if anyone has a question. Yep, OK. I just wanted to add one comment. If you're using open embedded or Yachto and using the meta SW update layer, if you set the environment variables for your signing key, you can have it also generate those hashes on the signature for the SW update file as part of the build so you don't have to do it manually. Exactly, yeah. Forgot to specify this, but yeah. There is a lot of different like variable in Yachto that you can define to customize the process. I'll have a couple of questions. First of all, very good presentation. When you mentioned streamed payloads, update payloads, do you support or do you think of supporting the future binary diffs or any kind of different payloads? So the binary diff, the idea is not necessary to support them. There is some discussion about supporting a binary data updates, but it's kind of complicated to support them. I mean, to really support them. I mean, it's easy to implement this, but it's kind of more complicated if you really want to have a stable solution for that. So yes, the plan is to add these kind of features, but there is no deadlines. There is no plan on when it's going to be available. OK, my second question is, you mentioned some point hardware compatibility in your description file. What is the, how do you define the handle that actually queries for that specific revision? So everything has to be done. OK, I think it was, yeah, this one. So like this information, you basically have a file on your system, which is slash ETC hardware revision. And it has to be generated before running SW update. I mean, SW update cannot do like any detection about the hardware. So you have like the user has to describe it. And it's the same for the software version. I can pass my third question, because it was already asked by the person before me. And my last one is, do you have any generic interface with U-boot, for example? Do you have any mechanism, the UAM or FW tools, whatever? So the interface with U-boots is like the communication is relying with the library, it's like the live U-boot environment. The idea is not to rely on any bootloaders. I mean, U-boot is just like an example, because Stefano is from Danx and also supporting U-boot as well. But the idea is also to support any kind of bootloaders. So having a common framework with the bootloader would be really tricky, because there is no standard way to communicate with it. Maybe later, I don't know. Yeah, the idea is that U-boot being one of the most used nowadays in the voice that we see around us would make sense to have a little bit of support in that regard. So there is a support. There is a handler for U-boot. There is a handler that you can use, and where you can just specify the name and the new value of your environment. And so basically, SW update is linked against this library, and it's going to manage the communication with U-boot. So there is already a handler. There is already a standard API to communicate with U-boots. But there is not a standard API to communicate to any bootloader. OK. There is also, for example, there is some discussion about greb, so how to update the argument from greb as well. So that's why they want to have more something for the flags that you're putting in your SD card or in your MMC. So you don't really basically communicate anymore with the bootloader, but you just create a common place that is common between the kernel and the bootloaders. And they can both use. It's basically the idea to implement kind of like a standard API for the communication with the bootloader. Any other question? Thank you very much. And if you. Thank you very much.