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  }