diff --git a/src/efibootmgr.service.test.ts b/src/efibootmgr.service.test.ts new file mode 100644 index 0000000..c6c297b --- /dev/null +++ b/src/efibootmgr.service.test.ts @@ -0,0 +1,41 @@ +import { describe, it } from "bun:test"; +import { EfiBootMgrService } from "./efibootmgr.service"; + +const EXAMPLE_EFI_BOOT_MGR_OUTPUT = `BootCurrent: 0001 +Timeout: 2 seconds +BootOrder: 0001,0004,0005,0002 +Boot0001* Fedora HD(1,GPT,) +Boot0002* Windows Boot Manager HD(1,GPT,) +Boot0004* Linux Boot Manager HD(1,GPT,) +Boot0005* UEFI OS HD(1,GPT,)`; + +const EXAMPLE_EFI_BOOT_MGR_OUTPUT_WITH_BOOT_NEXT = `BootNext: 0002 +BootCurrent: 0001 +Timeout: 2 seconds +BootOrder: 0001,0004,0005,0002 +Boot0001* Fedora HD(1,GPT,) +Boot0002* Windows Boot Manager HD(1,GPT,) +Boot0004* Linux Boot Manager HD(1,GPT,) +Boot0005* UEFI OS HD(1,GPT,)`; + +describe("EfiBootMgrService", () => { + it("parses the example efibootmgr output and returns boot entries", () => { + const efiBootMgrService = new EfiBootMgrService(); + + const result = efiBootMgrService.parseEfiBootMgrOutput( + EXAMPLE_EFI_BOOT_MGR_OUTPUT, + ); + + console.log(result); + }); + + it("parses the example efibootmgr output with boot next set and returns boot entries", () => { + const efiBootMgrService = new EfiBootMgrService(); + + const result = efiBootMgrService.parseEfiBootMgrOutput( + EXAMPLE_EFI_BOOT_MGR_OUTPUT_WITH_BOOT_NEXT, + ); + + console.log(result); + }); +}); diff --git a/src/efibootmgr.service.ts b/src/efibootmgr.service.ts index e391df3..6173ed9 100644 --- a/src/efibootmgr.service.ts +++ b/src/efibootmgr.service.ts @@ -11,11 +11,75 @@ export class EfiBootMgrService { await $`efibootmgr -n ${bootNum}`; } + parseEfiBootMgrOutput(output: string): z.output { + const lines = output.split("\n"); + + const isBootNextSet = output.includes("BootNext:"); + + if (lines.length < 4) { + throw new Error("Invalid output!"); + } + + let outputValues: { + bootNext?: string; + bootCurrent: string; + timeout: string; + bootOrder: string; + entries: Array; + }; + + if (isBootNextSet) { + const [bootNext, bootCurrent, timeout, bootOrder, ...entries] = lines; + + if (!bootNext || !bootCurrent || !timeout || !bootOrder) { + throw new Error("Invalid output!"); + } + + outputValues = { + bootNext, + bootCurrent, + timeout, + bootOrder, + entries, + }; + } else { + const [bootCurrent, timeout, bootOrder, ...entries] = lines; + + if (!bootCurrent || !timeout || !bootOrder) { + throw new Error("Invalid output!"); + } + + outputValues = { + bootCurrent, + timeout, + bootOrder, + entries, + }; + } + + return outputValues.entries.map((v) => { + const [bootStr, labelStr] = v.split("* "); + + if (!bootStr || !labelStr) throw new Error("Invalid output!"); + + const digits = bootStr.match(/\d/g); + + if (digits === null) throw new Error("invalid output!"); + + const [osName] = labelStr.split("\t"); + + if (!osName) throw new Error("Invalid output!"); + + return { + label: osName, + number: Number.parseInt(digits.join(""), 10), + }; + }); + } + async listBootEntries(): Promise> { const output = await $`efibootmgr`.text(); - console.log(output); - - return []; + return this.parseEfiBootMgrOutput(output); } }