---
# System prepended metadata

title: 'bootupd: implement BIOS (grub)'

---

# bootupd: implement BIOS (grub)
See https://github.com/coreos/bootupd/issues/53

1) Generating `/usr/lib/bootupd/updates/BIOS.json` will just have the version and timestamp of grub2-tools
    - Add func to command `/usr/bin/bootupctl backend generate-update-metadata /`, add new `src/bios.rs` and implementing Component BIOS for `generate_update_metadata`
        - Q: Run `backend generate-update-metadata /` during `postprocess` installation refer to https://github.com/coreos/fedora-coreos-config/blob/testing-devel/manifests/bootupd.yaml#L13, which will call bootupctl in the repo instead of cosa container, so I run `sudo make install DESTDIR=bootupd`, then copy bootupd/* to cosa `override/rootfs`, and run cosa build, is this correct?
          A: Yes, though it's easier to directly do: sudo make install DESTDIR=/path/to/cosa/overrides/rootfs
          [hhei]: Good suggestion!


        - Q: When insert `insert_component(&mut components, Box::new(bios::BIOS::default()));` (refer to https://github.com/coreos/bootupd/compare/main...HuijingHei:bootupd:bios) to `std::collections::BTreeMap`, which will cause BIOS component run first, but in this case `usr/lib/bootupd/updates` has not yet existed, so it will fail. `usr/lib/bootupd/updates` is created in efi component, also create the directory in BIOS component as the workaround. My question is when running `backend generate-update-metadata /` always get `error: generating metadata failed: No such file or directory (os error 2)`, this is confusing, is there any simple way to get detail error?
          A: Hmm, yes we should automatically create that directory before installing any components I think.  It's fine to also create the directory in bios.rs.  For getting more detailed errors, the usual pattern is to add `.context()` or `.with_context()` - see other uses of that.
          [hhei]: Good suggestion, I will try and add it to bootupd.rs. 


2) run `grub2-install` to install bootloader
    - Add command `bootupd/usr/bin/bootupctl backend install-bios /dev/vdb --boot-directory /tmp/rootfs/boot`
        - Q: to add in `src/bios.rs` to implement component BIOS for `install`, need to call `get_component_update(src_root, self)` to load `usr/lib/bootupd/updates/BIOS.json`, this will need src_root like `efi`, in this case will have 3 parameters, which is different from component install `fn install(&self, src_root: &openat::Dir, dest_root: &str) -> Result<InstalledContent>;`, maybe there are some workarounds for this?

There are a few things going on here.  First this is an interesting topic because we now need to choose either:

 - running grub2-install inside a container (either via bubblewrap or crun)
 - running all of `bootupctl backend install` inside a container.  In this case we don't need `src_root` at all, because we are already in the root.  I like this option the best honestly.

You're right though that to install BIOS we need the underlying block device.  We can add that as a new parameter, and just ignore it in the EFI code path.

Also something to consider: Instead of adding an `install-bios` command, we could ship a config file as part of the OS which says whether to do both BIOS and EFI, like `/usr/lib/bootupd/config.ini` or so.  

Or, even simpler, we could:

- Add an optional `--device` parameter to `backend install`
- Require it to install BIOS
- Default to installing both BIOS and EFI
- Add a `--boot-method-only` flag which installs only for the same mechanism as we used to boot (e.g. we only install BIOS if booted via BIOS, only EFI if booted via EFI)

Do you want to try a PR which just adds the `--device` parameter to start?
[hhei]: Do you mean running `bootupctl backend install --src-root <src-root> --device </dev/vdb> <dest-root>` to install both EFI and BIOS by default?

[walters] Yep!

[hhei]: If run `bootupctl backend install --src-root <src-root> <dest-root>`, will only install EFI?

[walters] Yes, I think we need to do that for now so that we can enable this feature in coreos-assembler by adding the argument.  That said, it may be cleaner to add `--enable-bios` for example too?  Or perhaps better, `--all-components`?



[hhei]: When running `bootupctl backend install --src-root <src-root> --device </dev/vdb> <dest-root>` to install BIOS, if `--src-root` is `/`, easy to call grub2-install as `/usr/sbin/grub2-install`; if `--src-root` is `/tmp/rootfs/ostree/deploy/rhcos/deploy/<sha512sum>.0`, should I chroot to 'src-root' before run `backend install`?

[walters] I'm thinking it's cleaner if we run all of `bootupctl backend install` as a container.  This might be a change to do *first* before landing the bios code.

[hhei]: Do you mean start a fcos/rhcos container and run `bootupctl backend install`? seems like bootc https://github.com/containers/bootc/pull/30




[hhei]: Do you mean `--boot-method-only efi` to only install EFI, `--boot-method-only bios` to only install BIOS? During installation, maybe can not determine which firmware, but maybe my understanding is not correct.

[walters] We can determine which method was used to boot; we do today.  It's basically querying `/sys/firmware/efi` - if that's present it means EFI was used.  But, I think I'd vote for `--all-components` per the above question.

[hhei]: You are correct, if run a container and run `bootupctl backend install`,  can still check `/sys/firmware/efi`, but I think this might be suitable for update. For installation, maybe we can still add `--boot-method bios/efi` to install the specified one. WDYT?


[hhei]: 
Summary:
- Add `--all-components` to install both EFI and BIOS, 
    - For normal installation, chroot to src-root, and run like `bootupctl backend install --all-components --src-root / --device </dev/vdb> <dest-root>`
    - If run in container, as the same command
[walters] What do you mean by "normal installation" here?  I think we need to choose one path or the other.  I'd lean towards having coreos-assembler always run `bootupctl install` in a container.
[hhei]: Yes, you are correct.
- Add `--boot-method bios` to install only bios
    - For normal installation, chroot to src-root, and run like `bootupctl backend install --boot-method bios --src-root / --device </dev/vdb> <dest-root>`
    - If run in container, as the same command
- Add `--boot-method efi` to install only uefi
    - For normal installation, no need to chroot to src-root, no device option, and run like `bootupctl backend install --boot-method efi --src-root <src-root> <dest-root>`
    - If run in container, run like `bootupctl backend install --boot-method efi --src-root / <dest-root>`
[walters] How about `--only-booted` to default to installing only via the mechanism we used to boot?

3) Q: To parse the output of `rpm -q`, maybe it is suitable to create function `pub(crate) fn parse_metadata(stdout: Vec<u8>) -> Result<ContentMetadata>` that can be used by efi and bios when running `/usr/bin/bootupctl backend generate-update-metadata /`, I put it in util.rs, not sure this is the right place.

[walters] Sounds fine to me!

[hhei]: Thanks!