Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Odroid HC2 #101

Closed
anupcshan opened this issue Dec 25, 2021 · 15 comments
Closed

Support for Odroid HC2 #101

anupcshan opened this issue Dec 25, 2021 · 15 comments

Comments

@anupcshan
Copy link
Contributor

I have Gokrazy operating on an Odroid HC2 and have been using it for 2-3 months now. I have a partially functional bootery setup going to continuously validate that the hardware works as expected and verify kernel upgrades (needs some change to how cmdline.txt gets updated for testboot - will bring that up once this issue is resolved).

There are a couple of issues that needed to be solved:

  1. Support MBR-only partition table. This hardware has a weird booting scheme, loading bootloader blobs from fixed locations on disk (sectors 1-2048). That clobbers most of the GPT (everything after the primary header is overwritten) and I'm forced to switch back to MBR.
  2. Support for writing/updating bootloader blobs at arbitrary positions on the bootable block device.
  3. Add more entries to kernelGlobs list.

The solutions I've come up with so far is:

  1. Allow kernel package to optionally emit a YAML manifest that describes any requirements for this kernel/device (like MBR-only partition table, custom kernel globs and listing extra blobs). See example.
  2. Support MBR-only partition table and parse that information from kernel manifest.
  3. Write bootloader binaries - changes to tools, gokrazy and updater. This change is not complete (only works for updates, not for initial image creation). Essentially, there's a new update endpoint (/update/blockdev) that will allow arbitrary writes to the block device. This is potentially dangerous and can seriously mess things up if there's a bug somewhere. An alternative would be to register a fixed set of named offsets and max lengths (like, bl1.bin being at offset 512 and of max length 15K, updatable via /update/bl1.bin).

Let me know if folks have thoughts or suggestions or objections to anything above.

To be clear, I'm not looking for someone to actually support gokrazy on this device (happy to do that myself) - I just want to avoid forks and go.mod replace directives in a bunch of places :)

@stapelberg
Copy link
Contributor

Good job on getting the Odroid HC2 to work with gokrazy! :)

It’s really unfortunate that the Odroid platform is GPT-incompatible. Using the MBR/GPT hybrid nicely works across all currently supported systems (e.g. Raspberry Pi and x86_64) and keeps differences between installations to a minimum.

Some early feedback to your changes:

  1. The kernel repository doesn’t seem like the right place for the configuration you’re introducing. I’d rather treat this as configuration to the gokrazy packer. Also, I’d prefer TOML over YAML.
  2. Yes, I agree that introducing named update handlers (/update/bl1.bin) is a better choice than the /update/blockdev handler :)

In general, if you want to contribute supporting code like this (MBR-only mode) to the packer, it needs to be continuously tested or it will bitrot (and/or other development will break it accidentally). One way to do so would be to integrate your bootery instance into the official CI.

@stapelberg stapelberg changed the title Support for a new device Support for Odroid HC2 Dec 25, 2021
@anupcshan
Copy link
Contributor Author

Good job on getting the Odroid HC2 to work with gokrazy! :)

It’s really unfortunate that the Odroid platform is GPT-incompatible. Using the MBR/GPT hybrid nicely works across all currently supported systems (e.g. Raspberry Pi and x86_64) and keeps differences between installations to a minimum.

Yeah, the bootloader scheme for this device is quite unfortunate and pretty rigid. The bootloader itself does support GPT (backup GPT table, if its intact). But I ran into issues with Linux refusing to boot with broken primary GPT. Also, relying on backup GPT at the end of the device makes it harder to build an image file - it has to be exactly the same size as the disk being written to.

Some early feedback to your changes:

  1. The kernel repository doesn’t seem like the right place for the configuration you’re introducing. I’d rather treat this as configuration to the gokrazy packer. Also, I’d prefer TOML over YAML.
  2. Yes, I agree that introducing named update handlers (/update/bl1.bin) is a better choice than the /update/blockdev handler :)

Sounds good. I'll prepare some commits for these.

In general, if you want to contribute supporting code like this (MBR-only mode) to the packer, it needs to be continuously tested or it will bitrot (and/or other development will break it accidentally). One way to do so would be to integrate your bootery instance into the official CI.

OK - you'll need to walk me through what's involved.

@anupcshan
Copy link
Contributor Author

Here's an example TOML file - https://github.com/anupcshan/odroidbake/blob/main/odroidhc2.toml

@anupcshan
Copy link
Contributor Author

@stapelberg Thanks for all the reviews! At this point, I can do a build/update/bootery cycle using https://github.com/anupcshan/odroidbake without any forks.

This is one outstanding item around CI for mbr-only mode. I was thinking about having a modified version of https://github.com/gokrazy/gokrazy/blob/master/integration/uefiboot/uefiboot_test.go with the following changes:

  • Build an image with -device_type=qemutestingmbr (this will be registered in internal/deviceconfig as requiring MBR/no-GPT and a dummy root device file, like vmlinuz).
  • Launch qemu using SeaBIOS (default) instead of OVMF.
  • In addition to existing checks, also validate rootdevice file is present at the right location on disk.

I've tested out the booting with just MBR part - this was pretty easy to do. I don't think the root dev checks should be that much work.

This way, anyone can repro/run tests on their local machine (and its already part of regular CI). What do you think?

@stapelberg
Copy link
Contributor

@stapelberg Thanks for all the reviews! At this point, I can do a build/update/bootery cycle using https://github.com/anupcshan/odroidbake without any forks.

Very nice!

This way, anyone can repro/run tests on their local machine (and its already part of regular CI). What do you think?

Yeah, an additional integration test (possibly sharing a bunch of code with the existing uefiboot test) for the odroid setup sounds good.

Afterwards, we should include your bootery setup in our CI, too.

@anupcshan
Copy link
Contributor Author

@stapelberg Thanks for all the reviews! At this point, I can do a build/update/bootery cycle using https://github.com/anupcshan/odroidbake without any forks.

Very nice!

This way, anyone can repro/run tests on their local machine (and its already part of regular CI). What do you think?

Yeah, an additional integration test (possibly sharing a bunch of code with the existing uefiboot test) for the odroid setup sounds good.

Relevant PRs are all out/being merged.

Afterwards, we should include your bootery setup in our CI, too.

Let me know what is involved here.

@stapelberg
Copy link
Contributor

Thanks for getting this all in place :)

For the CI adjustments, I think we need to add an extra bootery call in the gokrazy/kernel repository’s CI: https://github.com/gokrazy/kernel/blob/b9f59d355d8a06323bd7e9121c02a453a3682f1a/.github/workflows/pull.yml#L41

The gokrazy/firmware and gokrazy/rpi-eeprom repositories are not relevant for the odroid AFAIU.

The new extra BOOTERY_URL needs to be stored as an encrypted repository secret so that only the GitHub CI will be able to access it. The format looks like this: http://gokrazy:secretpassword@bakery.gokrazy.org:8037/testboot.

Please set up a hostname (google “dyndns” if you’re unfamiliar) under which your bakery/bootery setup can be reached. I believe GitHub CI uses IPv4 only, so IPv6 connectivity is not sufficient.

You can then email me the URL directly and I can set it up in the CI.

@anupcshan
Copy link
Contributor Author

Thanks for getting this all in place :)

For the CI adjustments, I think we need to add an extra bootery call in the gokrazy/kernel repository’s CI: https://github.com/gokrazy/kernel/blob/b9f59d355d8a06323bd7e9121c02a453a3682f1a/.github/workflows/pull.yml#L41

Ah OK. I can't use gokrazy/kernel, because its a different architecture (aarch64 vs arm32). Instead, the kernel package I use is in https://github.com/anupcshan/gokrazy-odroidxu4-kernel. It has automated kernel upgrades as well as automated bootloader (u-boot) updates. Most of that utilizes the tools in https://github.com/gokrazy/autoupdate.

One key difference from gokrazy/kernel is the way bootery is involved in test booting. I wanted to avoid exposing bootery publicly (even with auth). So, I came up with https://github.com/anupcshan/gokrazyci/tree/main/cmd/gokr-autotestboot to poll for outstanding PRs, perform a testboot and trigger a merge (basically gokr-boot, but it in a loop). gokr-autotestboot runs on the bootery machine (a Raspberry Pi 3 running Gokrazy).

All of this has been running for at least a couple of weeks now.

Apologies for the confusion - I thought there was some kind of device integration test when gokrazy/gokrazy or tools code gets upgraded.

The gokrazy/firmware and gokrazy/rpi-eeprom repositories are not relevant for the odroid AFAIU.

The new extra BOOTERY_URL needs to be stored as an encrypted repository secret so that only the GitHub CI will be able to access it. The format looks like this: http://gokrazy:secretpassword@bakery.gokrazy.org:8037/testboot.

Please set up a hostname (google “dyndns” if you’re unfamiliar) under which your bakery/bootery setup can be reached. I believe GitHub CI uses IPv4 only, so IPv6 connectivity is not sufficient.

You can then email me the URL directly and I can set it up in the CI.

@stapelberg
Copy link
Contributor

Ah, understood! I suppose then the only remaining step is to add your repositories and a picture of the device to https://gokrazy.org/platforms/, and ideally some documentation to https://gokrazy.org/userguide/ :)

Apologies for the confusion - I thought there was some kind of device integration test when gokrazy/gokrazy or tools code gets upgraded.

No, changes to those repositories are currently only tested in CI, not on-device.

@stapelberg
Copy link
Contributor

BTW, we now have https://gokrazy.org/platforms/#community, so that’d be a natural place to mention your odroid repositories, too :)

@anupcshan
Copy link
Contributor Author

BTW, we now have https://gokrazy.org/platforms/#community, so that’d be a natural place to mention your odroid repositories, too :)

Neat! I'll try and get to adding the documentation this week.

@Merovius
Copy link

@anupcshan I just got an HC4. I assume much of what you did for the HC2 would transfer to that. So I'd be pretty interested in that documentation :) And thanks for the effort you already put into it.

@anupcshan
Copy link
Contributor Author

@Merovius Nice!

HC2/HC4 have different architectures (armhf vs arm64) - so, they won't be directly compatible. But a lot of the scaffolding work should still be beneficial for you (especially everything around u-boot). https://github.com/anupcshan/gokrazy-odroidxu4-kernel is a fork of https://github.com/gokrazy/kernel which builds U-boot/kernel for HC2. I think you should be able to reuse a lot of that, with appropriate config changes.

I've sent out a change to document HC2 support in #151.

@anupcshan
Copy link
Contributor Author

I'm going to call this task done - I've been running gokrazy on 2 Odroid HC2 devices for the last 2 years without too many issues. Haven't had to do much in terms of maintenance other than periodically fixing u-boot or kernel breakages.

I'd love to be able to use the external disk support in this machine as an alternate /perm, but this can be tracked as a separate issue which is not specific to this device.

@stapelberg
Copy link
Contributor

I'd love to be able to use the external disk support in this machine as an alternate /perm, but this can be tracked as a separate issue which is not specific to this device.

filed #236 to track this feature

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants