That's just in the PXE driver AFAIK.. shouldn't be an issue here.
kragen 21 hours ago [-]
I think "leveraged this coding methodology" is an unjustifiably positive way to describe the results of the process. I think "spread this disease" would be more accurate. UTF-16 strings, really? VFAT? PE32+ is maybe justifiable (I'd prefer ELF, but that's because it's more familiar, not because it's actually better), but VFAT? And even in 01998 it should have been apparent that UTF-16 was not a sane format for strings, much less in 02005 when the EFI → UEFI transition happened.
To me, UEFI is like "leveraging the waste disposal methodology" of dumping your toxic waste in a lake. Yes, it's more convenient for you, but it does lasting damage and causes years of suffering for millions of people; and eventually somebody else has to clean up your mess, at far greater cost than if you'd just done something sensible to begin with.
I could probably say the same thing about X-Windows.
doublepg23 19 hours ago [-]
I've never _actually_ implemented a filesystem, but when researching OS dev it seemed like FAT32 was pretty close to what you'd write as a minimum viable filesystem while being a very well known quantity.
kragen 19 hours ago [-]
Yes, I think that's a fair assessment, although the fractal of stupid runs deep in FAT32: a separate 5-bit field for seconds within a minute? Separate fixed-width fields for filename and extension? A 4 GiB file size limit?
But, although FAT32 does indeed have the virtue of relative simplicity, that's no excuse for VFAT.
doublepg23 19 hours ago [-]
I might be unfamiliar with the terms - is there a distinction between FAT32 and VFAT?
duskwuff 17 hours ago [-]
VFAT is the way that some operating systems implement long filenames in FAT - PROGRA~1 and whatnot. It's pretty messy.
fredoralive 7 hours ago [-]
Windows 95 introduced long filenames to FAT, and implements the file system in the VFAT.VXD driver. “VFAT” is thus sometimes thus shorthand for FAT with “Windows style long filenames”. It can be applied to all variants of FAT, such as FAT16 and FAT32.
FAT32 is a variant of FAT introduced in the mid 90s with Windows 95 OSR2 that better supports large hard drives (beyond size limits, cluster sizes were getting too large on FAT16 drives etc.).
JdeBP 13 hours ago [-]
Not really, no. Linux regards various ways of looking at the same on-disc filesystem format as distinct filesystem types: msdos, umsdos, vfat. Old Microsoft doco from the 1990s that is still lying around explains things in the way that they historically progressed rather than structurally, describing VFAT as an extension of FAT32.
The reality, certainly in respect of the headlined subject, is that the bitness of the FAT and the style of the root directory (fixed location or variable length) are the only meaningful variants. In 2026, no-one aims not to support long filenames on FAT, and EFI understands them natively. EFI copes with all three bitnesses. And it does the conventional thing of variable length root directory on 32-bit and fixed-length root directory on 16-bit and 12-bit.
FAT is a very poor filesystem format, and no, it's not a minimum filesystem format if one is writing one's own operating system. It's a lazy filesystem format, inasmuch as the cross-development tooling for it exists. But if one were writing a minimum filesystem for one's own operating system, one could start from much better places. FAT is not minimal by any reasonable definition even if one is not writing one's own operating system, and requires an awful lot of hoops to be jumped through that are only there because one is being compatible with the cross-development tooling, several decades of historical changes, and whatnot.
One could use the original UFS, for example. LEAN exists. Over 20 years ago, I invented HPFS2.
HPFS2 looks appealing. Did you implement it? And what were the design blunders in LEAN you decided not to go into in the footnote?
Given that normally UEFI only needs to read the filesystem, not write it, I think a more appropriate filesystem might be something like ZIP.
hmry 20 hours ago [-]
In the eternal words of the Microsoft Game Development Kit docs[0], "Windows operates natively in UTF-16 [...]. This is a unique burden that Windows places on code that targets multiple platforms."
I wonder when Microsoft will stop being a "UTF-16 house" adding UTF-16 to new projects... They did it again to LSP, and that was in 2016. Maybe by 2045 Microsoft will use UTF-8 for new projects, and then by 2100 we can switch to UTF-8 by default.
That one is explainable by the fact that it was developed for VS Code, a typescript/javascript project. Javascript uses UTF-16 for strings (for historical reasons unrelated to Microsoft, though they are the same reasons that made MS use UCS-2 during the same time period).
Someone 3 hours ago [-]
> Javascript uses UTF-16 for strings
I don’t think the spec requires that. charAt indexes on UTF-16 code points, but I don’t remember ever seeing that it has to do that in O(1) time, so that doesn’t imply the implementation has to use UTF-16 internally.
“Note: Avoid re-implementing the solutions above using charAt(). The detection of lone surrogates and their pairing is complex, and built-in APIs may be more performant as they directly use the internal representation of the string. Install a polyfill for the APIs mentioned above if necessary.”
Because of that, I would hope most modern implementations to at least have a variant internal representation that is similar to UTF-8.
> UTF-16 is used by the Windows API, and by many programming environments such as Java and Qt. The variable-length character of UTF-16, combined with the fact that most characters are not variable-length (so variable length is rarely tested), has led to many bugs in software, including in Windows itself.
tredre3 19 hours ago [-]
Absolutely, UTF-16 is bad and inexcusable in most contexts. Perhaps you misinterpreted my comment or I wasn't expressing myself properly.
I was trying to say: If all the components in your stack are javascript-based, it makes sense that your RPC-API would also use UTF-16. It wasn't Microsoft pushing it for historical Windows reasons as GP implied, it was dictated by a JS stack they chose but didn't create.
genxy 18 hours ago [-]
I understood, I was just providing context. Windows, JavaScript, Java are all UTF-16. 65k characters is all you need.
noosphr 3 hours ago [-]
I always thought the js libraries throwing emojies around was stupid.
Then I finally sat down to understand enough JS for LLM slop and the having rockets all over the place wasn't just cringe but the quickest way to show you handled utf 16.
skrellm 7 hours ago [-]
A simple solution for the lack of a C standard library:
- works on POSIX systems, with native tools (no special build env needed)
- provides a (limited) POSIX interface for your UEFI app
- transparently converts UTF-8 and UCS-16 strings between your app and the firmware
- unlike GNU-EFI, no "uefi_call_wrapper" trickery needed
- has a tool to create a bootable disk image (with GPT, ESP)
- example codes from a "Hello World" to booting an ELF executable
- 100% AI-free
bemtevi 3 hours ago [-]
Nice! How do you know it's 100% AI-free? I'm keeping an eye out for such projects and just want to know. Are you the developer?
kevin_thibedeau 20 hours ago [-]
> The linker won’t complain if your code calls functions that don’t exist – it will just mark them as external, expecting them to be provided by some other code. But they won’t be, and the program will just crash when it calls one of these missing functions.
You can verify no external symbols remain after linkage with: nm -D --undefined-only. This can be incorporated into a build script to verify the binary is valid.
JdeBP 14 hours ago [-]
Rod Smith and the OSDev Wiki went here, sometimes word for word, years before:
Of course, they both assume GCC on Linux. Change either one of those, and it is a wholly different kettle of fish. Both NetBSD and FreeBSD, for examples, come with an EFI development environment in base, squirreled away in /usr/src/boot in the case of FreeBSD. They have to, because they need to be able to build their own EFI boot loaders. NetBSD targets more than Intel processor architectures for EFI, moreover. (NetBSD can boot via EFI on ARM CPUs, for instance.)
edoceo 21 hours ago [-]
This guide is fantastic for getting rolling in the UEFI space. I used this as one of the references when building a bootloader with Zig. Has its own set of issue, especially that 16bit character situation.
Once you dig into those there are a bunch of sharp edges, or maybe it's just that that EFI environment is so weird compared to typical Linux system or application development.
Have noodled around with a side-project generating an entire system from boot loader via LLMs but haven't had energy for it given job is the same headspace that needs to be ignored once in a while to not burnout; ultimately want to boot a model of my Linux use (am using bpf to plan and model everything possible and convert it to a compute schedule for sched_ext) and just have a kernel <> model architecture
For security am considering how to embed in the model various authentication obligations to block access to certain blocks of memory without confirmation via webcam and key or something
marcosscriven 3 hours ago [-]
In a world of LLMs, is it realistic to port coreboot (or similar) to unsupported platforms.
mrlonglong 18 hours ago [-]
Yikes. UEFI is way worse than I thought it was.
Best thing to do with it is treat it as a bootloader and use something else a lot more sane than UEFI.
Dare I live in hope that a newer revision will use 8 bit UTF and better conventions.
kragen 11 hours ago [-]
Maybe coreboot is what you are looking for? Or DeviceTree? Or Open Firmware?
Or something for a specific board. UEFI or BIOS is just a compatibility layer, and its only advantage over saner ones is that it's already installed and working on certain cheap, fast hardware you can easily buy.
But maybe that's less of an advantage now than it was 28 years ago.
I was pleased last week that I could elicit enough of a UEFI environment from Opus 5.5 to be able to build an UEFI application without enormous, un-auditable dependencies like gnu-efi. Claude distilled the relevant parts of the UEFI interface into a 289-line header file. The example application just displays the keyboard and mouse events on a UEFI framebuffer using a vendored pixel font, thus the name "inputmon": http://canonical.org/~kragen/sw/inputmon-3.tar.gz
The Makefile includes a "run" target to boot it under QEMU with the OVMF implementation of UEFI.
(One fairly surprising feature of all this is that, not counting the time Claude was waiting for me, it took the model a total of about 7 minutes to write and test this. These 7 minutes were spread over almost 15 hours because I ran out of tokens and spent time thinking. This might be a good example of a case where an LLM is literally a million times more productive than a human programmer: the task is algorithmically trivial, and it doesn't involve difficult engineering tradeoffs, but involves deep knowledge of a pile of obfuscated recondite interfaces that are publicly documented and widely used by published open-source software. It is something I've wanted to do for 7 million minutes.)
I'm hoping I can get an in-browser demo of inputmon working next week, but that's probably going to involve doing some surgery on Bochs in order to get an amd64-compatible virtual machine that doesn't require multithreading the way QEMU does.
Inputmon does have the enormous, un-auditable dependency of LLVM and Clang, but that's a horror I'm already resigned to. But with clang, lld, and make, you can build the image from source, and with QEMU and OVMF you can run it in a virtual machine.
I think it's a little bit debatable to call UEFI "bare metal" (Boone responds: "this is a fair criticism"), and I'm particularly skeptical of Boone's claim that you can guarantee microsecond response times in the face of SMM, but whatever.
RetroTechie 18 hours ago [-]
> Inputmon does have the enormous, un-auditable dependency of LLVM and Clang
You mean build-time dependency? Not a run-time one.
If that bothers you, there's simpler/smaller compilers out there (TinyCC and the Portable C Compiler come to mind, but there's others). Or drop down to assembly?
kragen 13 hours ago [-]
Yes, build-time.
Coincidentally, I had Claude fix 18 bugs in PCC earlier this week actually. But PCC itself doesn't support the UEFI calling convention or PE32+ image format. Those can be provided by something much smaller and simpler than LLVM, of course, but I'm not there yet.
erminpour 19 hours ago [-]
More posts and projects like this please!
joeinfo888 22 hours ago [-]
Had been looking for this. Thank you
0c3ca83 18 hours ago [-]
It's like programming an overengineered DOS.
tremon 19 hours ago [-]
Is it real bare-metal if you're using UEFI, though?
RetroTechie 18 hours ago [-]
> Is it real bare-metal if you're using UEFI, though?
If I'm not mistaken, the "bare metal" part refers to how directly you can touch it once control passes to your code. So definitely qualifies imho.
Not whether a 'glorified bootloader' burned some CPU cycles before that.
The "bare metal" qualifier goes away if underlying OS prevents your code from touching the hardware directly.
akoboldfrying 10 hours ago [-]
I enjoyed this informative series (I skipped only the article on setting up on a DVD or USB flash drive). The tone is enjoyable too: that of a developer who has spent time working through many difficult corners and wants to share useful tips based on their experience, but makes no claims to omniscience. Needless to say, this is a refreshing change of pace from the AI-"enhanced" fare that's so common nowadays.
I did notice that the link in the main "menu" to part 5 actually goes to part 4, but you can still get to that final part via the "next part" link from the end of part 4.
SilentM68 19 hours ago [-]
Wish there was a noobie-friendly book e.g.,pdf, epub showing how to do this as is and assembly.
brcmthrowaway 19 hours ago [-]
Does anyone still use UEFI?
If I start looking into the latest and greatest Qualcomm Nuvia ARM Windows laptops, does it use UEFI? Or regular BIOS?
ranger207 16 hours ago [-]
BIOS was always heavily tied to x86 PCs, as it was a de facto standard in the first place by the fact that it was reverse engineered from the IBM PC. Of course, PC-compatible firmwares were never required for x86 PCs, but it made it convenient in the era when people would bring their own OS. When ARM started becoming popular, it was generally in embedded applications where the manufacturer was going to produce a single firmware to do a single task. It's only lately, since UEFI became the standard on x86-type computers, that anyone's bothered making a general-purpose enough ARM device where you might want to bring your own OS and that UEFI has been something that would be useful there
vel0city 19 hours ago [-]
> Does anyone still use UEFI?
Yes. It's extremely common.
> If I start looking into the latest and greatest Qualcomm Nuvia ARM Windows laptops, does it use UEFI?
Yes, those use UEFI.
> Or regular BIOS?
Almost nothing widely produced today uses old "regular BIOS". Even those which seem to use "regular BIOS" are largely UEFI systems acting like a legacy BIOS. Even things like Apple MacBooks which don't use EFI use an Apple custom similar firmware concept far removed from legacy BIOS.
Melatonic 10 hours ago [-]
What do you think will succeed UEFI ?
vel0city 1 hours ago [-]
I dunno. Probably some kind of firmware interface standard. Hopefully it'll be extensible so the same base design can adapt to a large range of hardware profiles and features. It sure would be nice if it was a unified concept as well so there could be wide ranges of compatibility.
Only kind of kidding. I imagine the future for a while will either be continued growth into proprietary firmware platforms (like Apple and how tons of other phones/tablets have done) or a reworking/adapting of the main concepts behind UEFI but maybe making it less like ancient Microsoft-like patterns. Potentially something like u-boot becoming more common, or things like LK (Little Kernel). I think we'll see more evolution instead of hard replacement of concepts.
brcmthrowaway 12 hours ago [-]
UEFI engineer found!
majorchord 2 hours ago [-]
> Does anyone still use UEFI?
Only 99% of all non-embedded computing products that are faster than a few hundred MHz.
And on "Be aware of the Windows-ness of EFI" commentary the resemblance to Windows coding style https://computernewb.com/~lily/files/Documents/NTDesignWorkb... is no accident. We leveraged this coding methodology as we evolved the original Intel Boot Initiative then EFI and then UEFI code and specification https://www.intel.com/content/dam/www/public/us/en/documents...
https://app.opencve.io/cve/CVE-2026-97631
To me, UEFI is like "leveraging the waste disposal methodology" of dumping your toxic waste in a lake. Yes, it's more convenient for you, but it does lasting damage and causes years of suffering for millions of people; and eventually somebody else has to clean up your mess, at far greater cost than if you'd just done something sensible to begin with.
I could probably say the same thing about X-Windows.
But, although FAT32 does indeed have the virtue of relative simplicity, that's no excuse for VFAT.
FAT32 is a variant of FAT introduced in the mid 90s with Windows 95 OSR2 that better supports large hard drives (beyond size limits, cluster sizes were getting too large on FAT16 drives etc.).
The reality, certainly in respect of the headlined subject, is that the bitness of the FAT and the style of the root directory (fixed location or variable length) are the only meaningful variants. In 2026, no-one aims not to support long filenames on FAT, and EFI understands them natively. EFI copes with all three bitnesses. And it does the conventional thing of variable length root directory on 32-bit and fixed-length root directory on 16-bit and 12-bit.
FAT is a very poor filesystem format, and no, it's not a minimum filesystem format if one is writing one's own operating system. It's a lazy filesystem format, inasmuch as the cross-development tooling for it exists. But if one were writing a minimum filesystem for one's own operating system, one could start from much better places. FAT is not minimal by any reasonable definition even if one is not writing one's own operating system, and requires an awful lot of hoops to be jumped through that are only there because one is being compatible with the cross-development tooling, several decades of historical changes, and whatnot.
One could use the original UFS, for example. LEAN exists. Over 20 years ago, I invented HPFS2.
* https://jdebp.uk/Proposals/hpfs2.html
Given that normally UEFI only needs to read the filesystem, not write it, I think a more appropriate filesystem might be something like ZIP.
I wonder when Microsoft will stop being a "UTF-16 house" adding UTF-16 to new projects... They did it again to LSP, and that was in 2016. Maybe by 2045 Microsoft will use UTF-8 for new projects, and then by 2100 we can switch to UTF-8 by default.
[0] https://learn.microsoft.com/en-us/gaming/gdk/docs/gdk-dev/ov...
That one is explainable by the fact that it was developed for VS Code, a typescript/javascript project. Javascript uses UTF-16 for strings (for historical reasons unrelated to Microsoft, though they are the same reasons that made MS use UCS-2 during the same time period).
I don’t think the spec requires that. charAt indexes on UTF-16 code points, but I don’t remember ever seeing that it has to do that in O(1) time, so that doesn’t imply the implementation has to use UTF-16 internally.
Also, for modern JavaScript, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... says:
“Note: Avoid re-implementing the solutions above using charAt(). The detection of lone surrogates and their pairing is complex, and built-in APIs may be more performant as they directly use the internal representation of the string. Install a polyfill for the APIs mentioned above if necessary.”
Because of that, I would hope most modern implementations to at least have a variant internal representation that is similar to UTF-8.
> UTF-16 is used by the Windows API, and by many programming environments such as Java and Qt. The variable-length character of UTF-16, combined with the fact that most characters are not variable-length (so variable length is rarely tested), has led to many bugs in software, including in Windows itself.
I was trying to say: If all the components in your stack are javascript-based, it makes sense that your RPC-API would also use UTF-16. It wasn't Microsoft pushing it for historical Windows reasons as GP implied, it was dictated by a JS stack they chose but didn't create.
Then I finally sat down to understand enough JS for LLM slop and the having rockets all over the place wasn't just cringe but the quickest way to show you handled utf 16.
https://gitlab.com/bztsrc/posix-uefi
Features:
- works on POSIX systems, with native tools (no special build env needed)
- provides a (limited) POSIX interface for your UEFI app
- transparently converts UTF-8 and UCS-16 strings between your app and the firmware
- unlike GNU-EFI, no "uefi_call_wrapper" trickery needed
- has a tool to create a bootable disk image (with GPT, ESP)
- example codes from a "Hello World" to booting an ELF executable
- 100% AI-free
You can verify no external symbols remain after linkage with: nm -D --undefined-only. This can be incorporated into a build script to verify the binary is valid.
* https://rodsbooks.com/efi-programming/
* https://wiki.osdev.org/GNU-EFI
Of course, they both assume GCC on Linux. Change either one of those, and it is a wholly different kettle of fish. Both NetBSD and FreeBSD, for examples, come with an EFI development environment in base, squirreled away in /usr/src/boot in the case of FreeBSD. They have to, because they need to be able to build their own EFI boot loaders. NetBSD targets more than Intel processor architectures for EFI, moreover. (NetBSD can boot via EFI on ARM CPUs, for instance.)
Once you dig into those there are a bunch of sharp edges, or maybe it's just that that EFI environment is so weird compared to typical Linux system or application development.
Irc client in uefi: https://github.com/codyd51/uefirc
UEFI library the irc client relies on: https://github.com/rust-osdev/uefi-rs
No more separate GRUB/boot loader code paths needed; boot Linux from UEFI by loading a kernel: https://pretalx.com/devconf-cz-2024/talk/W3AVCT/
Have noodled around with a side-project generating an entire system from boot loader via LLMs but haven't had energy for it given job is the same headspace that needs to be ignored once in a while to not burnout; ultimately want to boot a model of my Linux use (am using bpf to plan and model everything possible and convert it to a compute schedule for sched_ext) and just have a kernel <> model architecture
For security am considering how to embed in the model various authentication obligations to block access to certain blocks of memory without confirmation via webcam and key or something
Best thing to do with it is treat it as a bootloader and use something else a lot more sane than UEFI.
Dare I live in hope that a newer revision will use 8 bit UTF and better conventions.
Or something for a specific board. UEFI or BIOS is just a compatibility layer, and its only advantage over saner ones is that it's already installed and working on certain cheap, fast hardware you can easily buy.
But maybe that's less of an advantage now than it was 28 years ago.
https://github.com/MichalStrehovsky/zerosharp
https://github.com/MichalStrehovsky/uefimaze
Not my creation but on my list to poke at one day soon
It's probably worth pointing out that, unless you're writing a replacement for GRUB, Multiboot2 is a reasonable alternative to building a UEFI PE32+ image, and it permits you to still call UEFI services: https://www.gnu.org/software/grub/manual/multiboot2/multiboo... https://wiki.osdev.org/Multiboot
I was pleased last week that I could elicit enough of a UEFI environment from Opus 5.5 to be able to build an UEFI application without enormous, un-auditable dependencies like gnu-efi. Claude distilled the relevant parts of the UEFI interface into a 289-line header file. The example application just displays the keyboard and mouse events on a UEFI framebuffer using a vendored pixel font, thus the name "inputmon": http://canonical.org/~kragen/sw/inputmon-3.tar.gz
The Makefile includes a "run" target to boot it under QEMU with the OVMF implementation of UEFI.
(One fairly surprising feature of all this is that, not counting the time Claude was waiting for me, it took the model a total of about 7 minutes to write and test this. These 7 minutes were spread over almost 15 hours because I ran out of tokens and spent time thinking. This might be a good example of a case where an LLM is literally a million times more productive than a human programmer: the task is algorithmically trivial, and it doesn't involve difficult engineering tradeoffs, but involves deep knowledge of a pile of obfuscated recondite interfaces that are publicly documented and widely used by published open-source software. It is something I've wanted to do for 7 million minutes.)
I'm hoping I can get an in-browser demo of inputmon working next week, but that's probably going to involve doing some surgery on Bochs in order to get an amd64-compatible virtual machine that doesn't require multithreading the way QEMU does.
Inputmon does have the enormous, un-auditable dependency of LLVM and Clang, but that's a horror I'm already resigned to. But with clang, lld, and make, you can build the image from source, and with QEMU and OVMF you can run it in a virtual machine.
I think it's a little bit debatable to call UEFI "bare metal" (Boone responds: "this is a fair criticism"), and I'm particularly skeptical of Boone's claim that you can guarantee microsecond response times in the face of SMM, but whatever.
You mean build-time dependency? Not a run-time one.
If that bothers you, there's simpler/smaller compilers out there (TinyCC and the Portable C Compiler come to mind, but there's others). Or drop down to assembly?
Coincidentally, I had Claude fix 18 bugs in PCC earlier this week actually. But PCC itself doesn't support the UEFI calling convention or PE32+ image format. Those can be provided by something much smaller and simpler than LLVM, of course, but I'm not there yet.
If I'm not mistaken, the "bare metal" part refers to how directly you can touch it once control passes to your code. So definitely qualifies imho.
Not whether a 'glorified bootloader' burned some CPU cycles before that.
The "bare metal" qualifier goes away if underlying OS prevents your code from touching the hardware directly.
I did notice that the link in the main "menu" to part 5 actually goes to part 4, but you can still get to that final part via the "next part" link from the end of part 4.
If I start looking into the latest and greatest Qualcomm Nuvia ARM Windows laptops, does it use UEFI? Or regular BIOS?
Yes. It's extremely common.
> If I start looking into the latest and greatest Qualcomm Nuvia ARM Windows laptops, does it use UEFI?
Yes, those use UEFI.
> Or regular BIOS?
Almost nothing widely produced today uses old "regular BIOS". Even those which seem to use "regular BIOS" are largely UEFI systems acting like a legacy BIOS. Even things like Apple MacBooks which don't use EFI use an Apple custom similar firmware concept far removed from legacy BIOS.
Only kind of kidding. I imagine the future for a while will either be continued growth into proprietary firmware platforms (like Apple and how tons of other phones/tablets have done) or a reworking/adapting of the main concepts behind UEFI but maybe making it less like ancient Microsoft-like patterns. Potentially something like u-boot becoming more common, or things like LK (Little Kernel). I think we'll see more evolution instead of hard replacement of concepts.
Only 99% of all non-embedded computing products that are faster than a few hundred MHz.