blob: 1cd8960c666f1a2508f46c500963fe579734b441 [file] [log] [blame]
Lorenz Brun80deba52022-02-24 17:07:13 +01001// This assembles standalone microcode files into the format expected by the
2// Linux microcode loader. See
3// https://www.kernel.org/doc/html/latest/x86/microcode.html for further
4// information.
5package main
6
7import (
8 "flag"
9 "io"
10 "log"
11 "os"
12
13 "github.com/cavaliergopher/cpio"
14 "google.golang.org/protobuf/encoding/prototext"
15
16 "source.monogon.dev/metropolis/node/build/mkucode/spec"
17)
18
19var (
20 specPath = flag.String("spec", "", "Path to prototext specification (metropolis.node.build.mkucode.UCode)")
21 outPath = flag.String("out", "", "Output path for cpio to be prepend to initrd")
22)
23
24// Usage: -spec <ucode.prototxt> -out <ucode.cpio>
25func main() {
26 flag.Parse()
27 specRaw, err := os.ReadFile(*specPath)
28 if err != nil {
29 log.Fatalf("Failed to read spec: %v", err)
30 }
31 var ucodeSpec spec.UCode
32 if err := prototext.Unmarshal(specRaw, &ucodeSpec); err != nil {
33 log.Fatalf("Failed unmarshaling ucode spec: %v", err)
34 }
35 out, err := os.Create(*outPath)
36 if err != nil {
37 log.Fatalf("Failed to create cpio: %v", err)
38 }
39 defer out.Close()
40 cpioWriter := cpio.NewWriter(out)
41 for _, vendor := range ucodeSpec.Vendor {
42 var totalSize int64
43 for _, file := range vendor.File {
44 data, err := os.Stat(file)
45 if err != nil {
46 log.Fatalf("Failed to stat file for vendor %q: %v", vendor.Id, err)
47 }
48 totalSize += data.Size()
49 }
50 if err := cpioWriter.WriteHeader(&cpio.Header{
51 Mode: 0444,
52 Name: "kernel/x86/microcode/" + vendor.Id + ".bin",
53 Size: totalSize,
54 }); err != nil {
55 log.Fatalf("Failed to write cpio header for vendor %q: %v", vendor.Id, err)
56 }
57 for _, file := range vendor.File {
58 f, err := os.Open(file)
59 if err != nil {
60 log.Fatalf("Failed to open file for vendor %q: %v", vendor.Id, err)
61 }
62 if _, err := io.Copy(cpioWriter, f); err != nil {
63 log.Fatalf("Failed to copy data for file %q: %v", file, err)
64 }
65 f.Close()
66 }
67 }
68 if err := cpioWriter.Close(); err != nil {
69 log.Fatalf("Failed writing cpio: %v", err)
70 }
71}