| // This assembles standalone microcode files into the format expected by the | 
 | // Linux microcode loader. See | 
 | // https://www.kernel.org/doc/html/latest/x86/microcode.html for further | 
 | // information. | 
 | package main | 
 |  | 
 | import ( | 
 | 	"flag" | 
 | 	"io" | 
 | 	"log" | 
 | 	"os" | 
 |  | 
 | 	"github.com/cavaliergopher/cpio" | 
 | 	"google.golang.org/protobuf/encoding/prototext" | 
 |  | 
 | 	"source.monogon.dev/metropolis/node/build/mkucode/spec" | 
 | ) | 
 |  | 
 | var ( | 
 | 	specPath = flag.String("spec", "", "Path to prototext specification (metropolis.node.build.mkucode.UCode)") | 
 | 	outPath  = flag.String("out", "", "Output path for cpio to be prepend to initrd") | 
 | ) | 
 |  | 
 | // Usage: -spec <ucode.prototxt> -out <ucode.cpio> | 
 | func main() { | 
 | 	flag.Parse() | 
 | 	specRaw, err := os.ReadFile(*specPath) | 
 | 	if err != nil { | 
 | 		log.Fatalf("Failed to read spec: %v", err) | 
 | 	} | 
 | 	var ucodeSpec spec.UCode | 
 | 	if err := prototext.Unmarshal(specRaw, &ucodeSpec); err != nil { | 
 | 		log.Fatalf("Failed unmarshaling ucode spec: %v", err) | 
 | 	} | 
 | 	out, err := os.Create(*outPath) | 
 | 	if err != nil { | 
 | 		log.Fatalf("Failed to create cpio: %v", err) | 
 | 	} | 
 | 	defer out.Close() | 
 | 	cpioWriter := cpio.NewWriter(out) | 
 | 	for _, vendor := range ucodeSpec.Vendor { | 
 | 		var totalSize int64 | 
 | 		for _, file := range vendor.File { | 
 | 			data, err := os.Stat(file) | 
 | 			if err != nil { | 
 | 				log.Fatalf("Failed to stat file for vendor %q: %v", vendor.Id, err) | 
 | 			} | 
 | 			totalSize += data.Size() | 
 | 		} | 
 | 		if err := cpioWriter.WriteHeader(&cpio.Header{ | 
 | 			Mode: 0444, | 
 | 			Name: "kernel/x86/microcode/" + vendor.Id + ".bin", | 
 | 			Size: totalSize, | 
 | 		}); err != nil { | 
 | 			log.Fatalf("Failed to write cpio header for vendor %q: %v", vendor.Id, err) | 
 | 		} | 
 | 		for _, file := range vendor.File { | 
 | 			f, err := os.Open(file) | 
 | 			if err != nil { | 
 | 				log.Fatalf("Failed to open file for vendor %q: %v", vendor.Id, err) | 
 | 			} | 
 | 			if _, err := io.Copy(cpioWriter, f); err != nil { | 
 | 				log.Fatalf("Failed to copy data for file %q: %v", file, err) | 
 | 			} | 
 | 			f.Close() | 
 | 		} | 
 | 	} | 
 | 	if err := cpioWriter.Close(); err != nil { | 
 | 		log.Fatalf("Failed writing cpio: %v", err) | 
 | 	} | 
 | } |