Most Efficient way of customizing x86_64 install image

I have an Atom x5 box on which I run Openwrt. Being minimal, it has no normal serial UART interface, so the grub.cfg needs 4 simple sed-able edits. Without those edits it just won’t boot. This is an ext4, EFI, combined install w the standard /boot, / and BIOS partitions.

I’d rather use the vanilla images, if possible. But I also don’t want to go in and futz about every time I upgrade…

Rather than reinventing the wheel, I thought maybe someone here that is already aware of leverage that I could use in owut or sysupgrade would have an idea or two.

Is there a really natural way to script this?

Also, am I correct that in assuming that there is no way to configure GRUB from /etc?

TIA, davy

I've never found a way to do this sort of thing. Every now and then I dig through https://openwrt.org/docs/techref/process.boot, specifically the grub boot loader example about halfway down, and it seems like we need some new hooks somewhere to effect any changes to grub.cfg prior to boot.

Also hand-in-hand with this is the inability to get sysupgrade to restore anything to /boot, as the sequence is out of order (I don't think /boot is mounted when sysupgrade does its restore; the save backup works and you can get /boot files in the backup, it just doesn't restore).

A bit of digging and I found this: Attended Sysupgrade: keep grub.cfg edits to prevent failed boots & physical keyboard commands every upgrade - #2 by frollic

The user u=ikjadoon seems to say that whitelisting the file in /boot worked for him but I’d like to verify that it will work on my setup. iirc, he doesn’t specify ext4 vs squashfs or anything else.

I’ll see if I can duplicate it when I’m back home next week.

Of course, I can just delete the orig grub.cfg and replace it with the edited version, after gunziping, mounting /boot , then unmounting and gzipping again. Makes me tired just thinking about it… :laughing:

I've still not had a chance to check @frollic 's thread regarding grub.cfg edits... that is on the checklist plus one other thing to look at, since it's solution posted here in the docs...

  1. keep grub.cfg edits : Attended Sysupgrade: keep grub.cfg edits to prevent failed boots & physical keyboard commands every upgrade - #2 by frollic
  2. retain size of the rootfs partition and filesystem : https://openwrt.org/docs/guide-user/advanced/expand_root

These are similar since they are problems that come up w/ upgrading on Intel/AMD/etc/x86 boxes... BOTH problems/issues came back to bite me when I upgraded from 25.12.2->25.12.3.

I did come up with a script to take care of #1, but I haven't tested it out yet, and it just feels kludgy to do something like that... but maybe it is the only way.

#2's problem/raison d'etre is something that is inherently an issue with upgrading on the ext4 combined x86_64 setups.

In these cases I grab me a default config for the target, then I do my customization, and then I just include this file with the --files= directive, and overwrite the defaults :person_shrugging: comments welcome

The OP (original poster, a.k.a. me) mentioned that:

While I have the toolchains all set up to build my own images, the intent is to avoid this.

Is there a way to pass the --files= directive to the online image builder? Maybe a way to pass this through sysupgrade or owut?

This cannot be done on first boot, since the bad (vanilla) grub.cfg is what prevents the device from booting. It can happen during the build process (as you mention) or after the build (with the script that I've written). Either one is kludgy, which is what I wanted to avoid, as in the original post.

Also, it might well be doable during the install, as https://openwrt.org/docs/guide-user/advanced/expand_root shows some similar moves, but with a different goal.

@efahl you can answer that, don't you?

I'm sorry that I've missed this details.
But I'm still puzzled what's the issue here? You have a working modification of the file based on the defaults? That's more then fair enough.

Pardon me. I still can not share your feelings regarding building in/adding a config file. :person_shrugging:

If by "online image builder", you're referring to firmware-selector.openwrt.org, then yes, that's the "Script to run on first boot (uci-defaults)" field. In owut you'd use the --init-script option (https://openwrt.org/docs/guide-user/installation/sysupgrade.owut#using_a_uci-defaults_script). The LuCI ASU app has a partial implementation, as described in that owut doc page.

Since sysupgrade itself doesn't do anything to images, it has no bearing on this.

Let's please let this thread be just about the OP's original question...and lets leave any puzzlement, need for pardons, fairness or a disinclinations for sharing aside... and make it about the original question as stated.

I have stage 4 cancer (urachal, quite rare), and as such I have limited energy (and perhaps time). I'd like to make everything turnkey and automated, with an absolute (relative) amount of intervention = no kludges.

Thank you for understanding.

Thank you, @efahl , that pretty much seals it. I'd looked into the first-run uci-defaults today in a bit more detail, and as you suggested, it prolly won't work in this case. But thank you for the pointers. It makes sense now.

You were right in your original comment - what I'm asking for has to happen in the build process, just after, or during the install process... but before first boot.

In Buildroot, there is a post-processing option which I used for a few specific customizing things - its a handy thing to have in the back pocket... but again, I want to keep this strictly vanilla.

So I think my script will have to be "it". Again, thanks for the pointers.

davy

So again. It's the image builder which just does that. You do not need to compile firmware from scratch.
The image builder does only glue together binary files and configs.

Btw how did you boot in the first place when without your modifications the device does not boot...

And still the image builder and all it's wrapper provide just that.

Good luck. Best to you.

Ok, just confirmed that imagebuilder does not support writing to the /boot partition using FILES=.

I grabbed the x86/64 imagebuilder, untarred it, then made a handful of dummy test files:

$ find files/ -type f
files/boot/grub/grub.cfg
files/etc/uci-defaults/00_hello
files/etc/bort/o-hello

Run a build (verbose with logging so I could look at the voluminous output):

$ make image FILES=files V=sc -j1 > build.log 2>&1

Resulting in the /etc files being created on the rootfs (cat confirms they are as expected).

$ find -name '*hello'
./build_dir/target-x86_64_musl/root-x86/etc/uci-defaults/00_hello
./build_dir/target-x86_64_musl/root-x86/etc/bort/o-hello
./files/etc/uci-defaults/00_hello
./files/etc/bort/o-hello

But the grub.cfg is either ignored or overwritten by the imagebuilder's grub scripts:

$ find -name grub.cfg | xargs wc -l
  13 ./build_dir/target-x86_64_musl/linux-x86_64/tmp/openwrt-x86-64-generic-squashfs-combined.img.gz.boot/boot/grub/grub.cfg
  13 ./build_dir/target-x86_64_musl/linux-x86_64/tmp/openwrt-x86-64-generic-ext4-combined.img.gz.boot/boot/grub/grub.cfg
  13 ./build_dir/target-x86_64_musl/linux-x86_64/tmp/openwrt-x86-64-generic-targz-combined.img.gz.boot/boot/grub/grub.cfg
  13 ./build_dir/target-x86_64_musl/linux-x86_64/tmp/openwrt-x86-64-generic-squashfs-combined-efi.img.gz.boot/boot/grub/grub.cfg
  13 ./build_dir/target-x86_64_musl/linux-x86_64/tmp/openwrt-x86-64-generic-ext4-combined-efi.img.gz.boot/boot/grub/grub.cfg
  13 ./build_dir/target-x86_64_musl/linux-x86_64/tmp/openwrt-x86-64-generic-targz-combined-efi.img.gz.boot/boot/grub/grub.cfg
   1 ./files/boot/grub/grub.cfg

So, in order to effect any change in the installed grub.cfg, we'd need to hack one/all of the templates, or add some make variable and rewrite the code here to inject something while running the templates.


Templates here:

$ find -name 'grub-*.cfg'
./target/linux/x86/image/grub-efi.cfg
./target/linux/x86/image/grub-iso.cfg
./target/linux/x86/image/grub-pc.cfg

They all look pretty much like this:

$ cat ./target/linux/x86/image/grub-efi.cfg
@SERIAL_CONFIG@
@TERMINAL_CONFIG@

set default="0"
set timeout="@TIMEOUT@"
search -l kernel -s root

menuentry "@TITLE@" {
        linux /boot/vmlinuz @GPT_ROOTPART@ @CMDLINE@ noinitrd
}
menuentry "@TITLE@ (failsafe)" {
        linux /boot/vmlinuz failsafe=true @GPT_ROOTPART@ @CMDLINE@ noinitrd
}

Uh? I'm pretty sure I've done that but for the x86 ext combined image.

Could this be an explanation?

Edit ps. I did so a few weeks back to remove the grub wait timeout from my image used for virtual x86.

Yes, I'm using the ext4-combined-efi* variant. Thank you both @efahl and @_bernd .

I'm not sure what the preponderance of x86* users have for hardware... not sure of the prevalence of x86* boxes that need this special non-serial grub.cfg like I do. I want to be respectful and mindful of the time/effort/sweat-equity that devs invest in the project.

The templates are interesting... IIUC, the grub-pc.cfg must be for legacy BIOS systems? The grub-iso.cfg ... hmmm... not sure.

That stuff ^^^^^ always fascinates me... :smiley:

I've just tested out my script - it works, and I was thinking that I could run it from owut using the --pre-install flag...

Oho! I had not thought of that. The pre-install script is run just after the image is downloaded to /tmp/firmware.bin and validated, but before sysupgrade /tmp/firmware.bin is executed, so you could gunzip it, losetup/mount, mangle it and re-gzip it... (I'm not going to say I love it, but it might be the lowest-friction way of getting the job done.)

When I read the man pages for owut, it looked like there was a lot to pull from, poke at, smash buttons, whatever. I figured there must be a hook or nook somewhere...

Will try it on the 25.12.4 upgrade in a few hours when things settle down on the server. It looks swamped right now.

Another approach I'd thought about was a package (.apk) that would simply replace the standard /boot/grub/grub.cfg with the non-serial version, say call it grub2-grub.cfg-no-serial-*.apk. Not sure how to approach that, though.

If grub2-grub.cfg-no-serial-*.apk.existed as a package, then it could be selected from the Firmware Selector tool, already baked-in to the image and on the manifest. Not sure how this would rank on the friction-index in comparison to users just using the script that I came up with (and will test out thoroughly).

A precedent for such a package (conceptually, not parallel in the strict sense, having different function) could be the luci-app-advanced-reboot . It isn't employed on a lot of hardware units, but on the ones where it does fit (like the Linksys E8450) it is extremely useful - it fills a niche very nicely.

Again, I have no idea how many OpenWrt users are running x86 boards/boxes won't boot with the serial declarations in grub.cfg.