Skip to content

Commit 429b438

Browse files
fix(onboarding): add explicit EFI loader path for flash entry (#1926)
## Summary - update API onboarding internal-boot BIOS update flow to create the flash UEFI entry with an explicit loader path - keep scope API-only (no webgui repo changes) - update onboarding internal-boot service spec to assert the new efibootmgr args ## Why Some motherboards fail to boot the USB entry in UEFI mode when the NVRAM boot entry is created without an explicit loader path, even when `EFI/BOOT/BOOTX64.EFI` exists. ## Change Details - flash boot entry command now includes `-l \EFI\BOOT\BOOTX64.EFI` - internal boot entry behavior is unchanged ## Testing - attempted: `pnpm --filter ./api test src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.spec.ts` - note: not executed in this fresh worktree because dependencies are not installed (`vitest: command not found`) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Boot entry creation now includes the EFI loader path, improving reliability of system boot setup. * Skips creating BIOS entries for disks that cannot be resolved from assignable disks and avoids adding invalid boot entries. * **Improvements** * Internal-boot UI now prefers disk serial number first (then disk ID, then device) for more consistent selection. * Expanded diagnostic and debug logging around boot device resolution and BIOS/boot update flows. * **Tests** * Tests updated to cover assignable-disk resolution, expected output messages for unresolved disks, and BIOS update paths. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent bae2e8b commit 429b438

File tree

4 files changed

+157
-60
lines changed

4 files changed

+157
-60
lines changed

api/src/unraid-api/graph/resolvers/onboarding/onboarding-internal-boot.service.spec.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,13 @@ describe('OnboardingInternalBootService', () => {
210210

211211
it('runs efibootmgr update flow when updateBios is requested', async () => {
212212
vi.mocked(emcmd).mockResolvedValue({ ok: true } as Awaited<ReturnType<typeof emcmd>>);
213+
disksService.getAssignableDisks.mockResolvedValue([
214+
{
215+
id: 'disk-1',
216+
serialNum: 'disk-1',
217+
device: '/dev/sdb',
218+
},
219+
]);
213220
vi.mocked(getters.emhttp).mockReturnValue({
214221
var: { mdState: 'STOPPED' },
215222
devices: [{ id: 'disk-1', device: 'sdb' }],
@@ -262,7 +269,10 @@ describe('OnboardingInternalBootService', () => {
262269
1
263270
);
264271
expect(vi.mocked(emcmd)).toHaveBeenCalledTimes(4);
265-
expect(vi.mocked(loadStateFileSync)).not.toHaveBeenCalled();
272+
expect(disksService.getAssignableDisks).toHaveBeenCalledTimes(1);
273+
expect(vi.mocked(loadStateFileSync)).toHaveBeenNthCalledWith(1, 'var');
274+
expect(vi.mocked(loadStateFileSync)).toHaveBeenNthCalledWith(2, 'devs');
275+
expect(vi.mocked(loadStateFileSync)).toHaveBeenNthCalledWith(3, 'disks');
266276
expect(vi.mocked(execa)).toHaveBeenNthCalledWith(1, 'efibootmgr', [], { reject: false });
267277
expect(vi.mocked(execa)).toHaveBeenNthCalledWith(2, 'efibootmgr', ['-b', '0001', '-B'], {
268278
reject: false,
@@ -286,7 +296,7 @@ describe('OnboardingInternalBootService', () => {
286296
expect(vi.mocked(execa)).toHaveBeenNthCalledWith(
287297
4,
288298
'efibootmgr',
289-
['-c', '-d', '/dev/sda', '-p', '1', '-L', 'Unraid Flash'],
299+
['-c', '-d', '/dev/sda', '-p', '1', '-L', 'Unraid Flash', '-l', '\\EFI\\BOOT\\BOOTX64.EFI'],
290300
{ reject: false }
291301
);
292302
expect(vi.mocked(execa)).toHaveBeenNthCalledWith(5, 'efibootmgr', [], { reject: false });
@@ -327,10 +337,18 @@ describe('OnboardingInternalBootService', () => {
327337

328338
expect(result.ok).toBe(true);
329339
expect(result.code).toBe(0);
330-
expect(result.output).toContain('efibootmgr failed for');
340+
expect(result.output).toContain(
341+
"Unable to resolve boot device for serial 'disk-1' from assignableDisks; skipping BIOS entry creation for this disk."
342+
);
343+
expect(result.output).not.toContain("efibootmgr failed for '/dev/disk-1'");
331344
expect(result.output).toContain(
332345
'BIOS boot entry updates completed with warnings; manual BIOS boot order changes may still be required.'
333346
);
347+
expect(vi.mocked(execa)).not.toHaveBeenCalledWith(
348+
'efibootmgr',
349+
expect.arrayContaining(['/dev/disk-1']),
350+
{ reject: false }
351+
);
334352
expect(internalBootStateService.invalidateCachedInternalBootDeviceState).toHaveBeenCalledTimes(
335353
1
336354
);

0 commit comments

Comments
 (0)