github.com/linuxboot/fiano@v1.2.0/scripts/namecollect/namecollect.go (about) 1 // Copyright 2019 the LinuxBoot Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Run with `go run namecollect.go`. This updates the knownguids.go file with 6 // names from EDK2. 7 package main 8 9 import ( 10 "flag" 11 "go/build" 12 "log" 13 "os" 14 "os/exec" 15 "path/filepath" 16 "regexp" 17 "sort" 18 "strings" 19 "text/template" 20 "time" 21 22 "github.com/linuxboot/fiano/pkg/guid" 23 "github.com/linuxboot/fiano/pkg/knownguids" 24 ) 25 26 const knownGUIDsFile = "src/github.com/linuxboot/fiano/pkg/knownguids/guids.go" 27 28 var ( 29 debug = flag.Bool("d", false, "debug prints") 30 knownGUIDsTemplate = `// Copyright {{.Year}} the LinuxBoot Authors. All rights reserved 31 // Use of this source code is governed by a BSD-style 32 // license that can be found in the LICENSE file. 33 34 // Package knownguids contains a list of guids and their names. 35 // THIS FILE IS GENERATED! DO NOT MODIFY! 36 // To regenerate, run: go run scripts/namecollect/namecollect.go 37 package knownguids 38 39 import "github.com/linuxboot/fiano/pkg/guid" 40 41 // GUIDs is a mapping from a GUID to its name. 42 var GUIDs = map[guid.GUID]string { 43 {{- range .GUIDs}} 44 *guid.MustParse({{printf "%q" .GUID}}): {{printf "%q" .Name}}, 45 {{- end}} 46 } 47 ` 48 ) 49 50 func getGUIDsFile() string { 51 gopath := build.Default.GOPATH 52 if gopath == "" { 53 gopath = os.ExpandEnv("$HOME/go") 54 } 55 o := filepath.Join(gopath, knownGUIDsFile) 56 if *debug { 57 log.Printf("Writing to %s", o) 58 } 59 return o 60 } 61 62 func downloadEdk2() (tmpDir string, err error) { 63 tmpDir, err = os.MkdirTemp("", "namecollect") 64 if err != nil { 65 return "", err 66 } 67 github := "https://github.com/tianocore/edk2" 68 cmd := exec.Command("git", "clone", "--depth=1", github, tmpDir) 69 cmd.Stdin = os.Stdin 70 cmd.Stdout = os.Stdout 71 cmd.Stderr = os.Stderr 72 if err := cmd.Run(); err != nil { 73 os.RemoveAll(tmpDir) 74 return "", err 75 } 76 return tmpDir, nil 77 } 78 79 func findGUIDs(dir string) (map[guid.GUID]string, error) { 80 guids := map[guid.GUID]string{} 81 baseNameRegex := regexp.MustCompile(`[\t ]*BASE_NAME[\t ]*=([^\n#]+)`) 82 fileGUIDRegex := regexp.MustCompile(`[\t ]*FILE_GUID[\t ]*=([^\n#]+)`) 83 err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { 84 if err != nil { 85 log.Printf("skipping %q due to error: %v", path, err) 86 return nil 87 } 88 if info.Mode().IsRegular() && strings.HasSuffix(path, ".inf") { 89 if *debug { 90 log.Printf("Check %s", path) 91 } 92 contents, err := os.ReadFile(path) 93 if err != nil { 94 log.Printf("skipping %q due to error: %v", path, err) 95 return nil 96 } 97 baseNames := baseNameRegex.FindAllSubmatch(contents, -1) 98 fileGUIDs := fileGUIDRegex.FindAllSubmatch(contents, -1) 99 if len(baseNames) == 0 || len(fileGUIDs) == 0 { 100 log.Printf("skipping %q because is does not contain BASE_NAME or FILE_GUID", path) 101 return nil 102 } 103 if len(baseNames) != 1 || len(fileGUIDs) != 1 { 104 log.Printf("skipping %q because it contains multiple of BASE_NAME or FILE_GUID", path) 105 return nil 106 } 107 g, err := guid.Parse(strings.TrimSpace(string(fileGUIDs[0][1]))) 108 if err != nil { 109 log.Printf("skipping %q because the GUID %q cannot be parsed: %v", 110 path, fileGUIDs[0][1], err) 111 return nil 112 } 113 name := strings.TrimSpace(string(baseNames[0][1])) 114 if prevName, ok := guids[*g]; ok && prevName != name { 115 name = prevName + "/" + name 116 log.Printf("warning %v has two names %q and %q", *g, prevName, name) 117 } 118 guids[*g] = name 119 } 120 return nil 121 }) 122 return guids, err 123 } 124 125 func main() { 126 flag.Parse() 127 tmpl, err := template.New("knownguids").Parse(knownGUIDsTemplate) 128 if err != nil { 129 log.Fatal(err) 130 } 131 132 f, err := os.Create(getGUIDsFile()) 133 if err != nil { 134 log.Fatal(err) 135 } 136 137 tmpDir, err := downloadEdk2() 138 if err != nil { 139 log.Fatal(err) 140 } 141 defer os.RemoveAll(tmpDir) 142 143 newGUIDs, err := findGUIDs(tmpDir) 144 if err != nil { 145 log.Fatal(err) 146 } 147 148 previousGUIDs := knownguids.GUIDs 149 for guid, n := range previousGUIDs { 150 _, ok := newGUIDs[guid] 151 if !ok { 152 log.Printf("warning %v[%v] was in the old but not the new", n, guid) 153 newGUIDs[guid] = n 154 } 155 if newGUIDs[guid] != n { 156 log.Printf("warning %v name changed from %q to %q", guid, n, newGUIDs[guid]) 157 newGUIDs[guid] = n + "/" + newGUIDs[guid] 158 } 159 } 160 161 // Sort so the order is deterministic. 162 type guidNamePair struct { 163 GUID guid.GUID 164 Name string 165 } 166 sortedGUIDs := []guidNamePair{} 167 for k, v := range newGUIDs { 168 sortedGUIDs = append(sortedGUIDs, guidNamePair{k, v}) 169 } 170 sort.SliceStable(sortedGUIDs, func(i, j int) bool { 171 return strings.Compare(sortedGUIDs[i].Name, sortedGUIDs[j].Name) < 0 172 }) 173 174 err = tmpl.Execute(f, struct { 175 Year int 176 GUIDs []guidNamePair 177 }{ 178 Year: time.Now().Year(), 179 GUIDs: sortedGUIDs, 180 }) 181 if err != nil { 182 log.Fatal(err) 183 } 184 if err := f.Close(); err != nil { 185 log.Fatalln("error closing file:", err) 186 } 187 }