util/spd_tools: Add ability to override SPD file for parts
This commit adds the ability to override the SPD file that is used for a
specific part.
BUG=b:224884904
TEST=Verified that generated makefile uses specified SPD file and that
it remains unchanged when this capability is not used
Signed-off-by: Robert Zieba <robertzieba@google.com>
Change-Id: I078dd04fead2bf19f53bc6ca8295187d439adc20
Reviewed-on: https://review.coreboot.org/c/coreboot/+/63281
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Rob Barnes <robbarnes@google.com>
diff --git a/util/spd_tools/README.md b/util/spd_tools/README.md
index 01bc417..6f09f56 100644
--- a/util/spd_tools/README.md
+++ b/util/spd_tools/README.md
@@ -459,14 +459,16 @@
* The memory technology used by the board, e.g. lp4x.
* The path to the directory where the generated Makefile.inc should be placed.
* A CSV file containing a list of the memory parts used by the board, with an
-* optional fixed or exclusive ID for each part. A fixed ID is simply an integer
-* and it ensure that part (and any that share the same SPD) will be assigned
-* that ID. An exclusive ID is prefixed with `*` and ensures that only parts with
-* the same exclusive ID will be assigned that ID, even if they would otherwise
-* share the same ID.
+* optional fixed or exclusive ID for each part and an optional SPD override file.
+* A fixed ID is simply an integer and it ensure that part (and any that share the same SPD)
+* will be assigned that ID. An exclusive ID is prefixed with `*` and ensures that
+* only parts with the same exclusive ID will be assigned that ID, even if they would
+* otherwise share the same ID. When using an SPD override file, the file will be searched
+* for in the directory where mem_parts_used is located, if it is not found there then it
+* will be searched for in the appropriate default spd directory.
* NOTE: Only assign a fixed/exclusive ID if required for legacy reasons.
-Example of a CSV file using fixed and exclusive IDs:
+Example of a CSV file using fixed and exclusive IDs, and SPD file overrides:
```
K4AAG165WA-BCWE,1
@@ -475,6 +477,8 @@
K4A8G165WC-BCWE
H5AN8G6NDJR-XNC,8
H5ANAG6NCMR-XNC,*9
+H9HCNNNCPMMLXR-NEE,,H9HCNNNCPMMLXR-NEE.hex
+H54G56CYRBX247,4,H54G56CYRBX247.hex
```
Explanation: This will ensure that the SPDs for K4AAG165WA-BCWE and
diff --git a/util/spd_tools/src/part_id_gen/part_id_gen.go b/util/spd_tools/src/part_id_gen/part_id_gen.go
index 65e07f4..edbad9c 100644
--- a/util/spd_tools/src/part_id_gen/part_id_gen.go
+++ b/util/spd_tools/src/part_id_gen/part_id_gen.go
@@ -102,9 +102,10 @@
)
type usedPart struct {
- partName string
- index int
- mapping mappingType
+ partName string
+ index int
+ mapping mappingType
+ SPDOverride string
}
func readPlatformsManifest(memTech string) (map[string]string, error) {
@@ -183,30 +184,44 @@
}
if len(fields) == 1 {
- parts = append(parts, usedPart{fields[0], -1, Auto})
- } else if len(fields) == 2 {
+ parts = append(parts, usedPart{fields[0], -1, Auto, ""})
+ } else {
var mapping = Auto
var assignedId = -1
var err error = nil
+ var spdOverride string = ""
- if len(fields[1]) >= 2 && fields[1][0] == '*' {
- // Exclusive mapping
- mapping = Exclusive
- assignedId, err = strconv.Atoi(fields[1][1:])
- } else {
- mapping = Fixed
- assignedId, err = strconv.Atoi(fields[1])
+ // Second column, ID override
+ if len(fields) >= 2 {
+ if len(fields[1]) >= 2 && fields[1][0] == '*' {
+ // Exclusive mapping
+ mapping = Exclusive
+ assignedId, err = strconv.Atoi(fields[1][1:])
+ } else if fields[1] != "" {
+ // Fixed mapping
+ mapping = Fixed
+ assignedId, err = strconv.Atoi(fields[1])
+ }
+ }
+
+ // Third column, SPD file override
+ if len(fields) >= 3 {
+ if len(fields[2]) == 0 {
+ err = fmt.Errorf("mem_parts_used_file file is incorrectly formatted, SPD file column is empty")
+ } else {
+ spdOverride = fields[2]
+ }
}
if err != nil {
return nil, err
}
- if assignedId > MaxMemoryId || assignedId < 0 {
+
+ if assignedId > MaxMemoryId {
return nil, fmt.Errorf("Out of bounds assigned id %d for part %s", assignedId, fields[0])
}
- parts = append(parts, usedPart{fields[0], assignedId, mapping})
- } else {
- return nil, fmt.Errorf("mem_parts_used_file file is incorrectly formatted")
+
+ parts = append(parts, usedPart{fields[0], assignedId, mapping, spdOverride})
}
}
@@ -288,7 +303,6 @@
// Assign parts with fixed ids first
for _, p := range parts {
-
if p.index == -1 {
continue
}
@@ -299,7 +313,7 @@
SPDFileName, ok := partToSPDMap[p.partName]
if !ok {
- return nil, fmt.Errorf("Failed to find part ", p.partName, " in SPD Manifest. Please add the part to global part list and regenerate SPD Manifest")
+ return nil, fmt.Errorf("Failed to find part %s in SPD Manifest. Please add the part to global part list and regenerate SPD Manifest", p.partName)
}
// Extend partIdList and assignedMapping with empty entries if needed
@@ -396,7 +410,7 @@
* This function generates Makefile.inc under the variant directory path and adds assigned SPDs
* to SPD_SOURCES.
*/
-func genMakefile(partIdList []partIds, makefileDirName string, SPDDir string) error {
+func genMakefile(partIdList []partIds, makefileDirName string, SPDDir string, partsDir string) error {
s := getFileHeader()
s += fmt.Sprintf("SPD_SOURCES =\n")
@@ -405,7 +419,18 @@
s += fmt.Sprintf("SPD_SOURCES += %v ", filepath.Join(SPDDir, SPDEmptyFileName))
s += fmt.Sprintf(" # ID = %d(0b%04b)\n", i, int64(i))
} else {
- s += fmt.Sprintf("SPD_SOURCES += %v ", filepath.Join(SPDDir, partIdList[i].SPDFileName))
+ SPDFileName := partIdList[i].SPDFileName
+ path := filepath.Join(partsDir, SPDFileName)
+
+ // Check if the file exists in the directory of the parts file
+ if _, err := os.Stat(path); err != nil {
+ // File doesn't exist, check spd directory
+ path = filepath.Join(SPDDir, SPDFileName)
+ if _, err = os.Stat(path); err != nil {
+ return fmt.Errorf("Failed to write Makefile, SPD file '%s' doesn't exist", SPDFileName)
+ }
+ }
+ s += fmt.Sprintf("SPD_SOURCES += %v ", path)
s += fmt.Sprintf(" # ID = %d(0b%04b) ", i, int64(i))
s += fmt.Sprintf(" Parts = %04s\n", partIdList[i].memParts)
}
@@ -442,12 +467,20 @@
log.Fatal(err)
}
+ // Update our SPD maps with part specific overrides
+ for _, p := range parts {
+ if p.SPDOverride != "" {
+ partToSPDMap[p.partName] = p.SPDOverride
+ SPDToIndexMap[p.SPDOverride] = -1
+ }
+ }
+
partIdList, err := genPartIdInfo(parts, partToSPDMap, SPDToIndexMap, makefileDir)
if err != nil {
log.Fatal(err)
}
- if err := genMakefile(partIdList, makefileDir, SPDDir); err != nil {
+ if err := genMakefile(partIdList, makefileDir, SPDDir, filepath.Dir(memPartsUsedFile)); err != nil {
log.Fatal(err)
}
}