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>
This commit is contained in:
@ -459,14 +459,16 @@ This program takes the following inputs:
|
|||||||
* The memory technology used by the board, e.g. lp4x.
|
* The memory technology used by the board, e.g. lp4x.
|
||||||
* The path to the directory where the generated Makefile.inc should be placed.
|
* 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
|
* 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
|
* optional fixed or exclusive ID for each part and an optional SPD override file.
|
||||||
* and it ensure that part (and any that share the same SPD) will be assigned
|
* A fixed ID is simply an integer and it ensure that part (and any that share the same SPD)
|
||||||
* that ID. An exclusive ID is prefixed with `*` and ensures that only parts with
|
* will be assigned that ID. An exclusive ID is prefixed with `*` and ensures that
|
||||||
* the same exclusive ID will be assigned that ID, even if they would otherwise
|
* only parts with the same exclusive ID will be assigned that ID, even if they would
|
||||||
* share the same ID.
|
* 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.
|
* 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
|
K4AAG165WA-BCWE,1
|
||||||
@ -475,6 +477,8 @@ MT40A1G16KD-062E:E
|
|||||||
K4A8G165WC-BCWE
|
K4A8G165WC-BCWE
|
||||||
H5AN8G6NDJR-XNC,8
|
H5AN8G6NDJR-XNC,8
|
||||||
H5ANAG6NCMR-XNC,*9
|
H5ANAG6NCMR-XNC,*9
|
||||||
|
H9HCNNNCPMMLXR-NEE,,H9HCNNNCPMMLXR-NEE.hex
|
||||||
|
H54G56CYRBX247,4,H54G56CYRBX247.hex
|
||||||
```
|
```
|
||||||
|
|
||||||
Explanation: This will ensure that the SPDs for K4AAG165WA-BCWE and
|
Explanation: This will ensure that the SPDs for K4AAG165WA-BCWE and
|
||||||
|
@ -102,9 +102,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type usedPart struct {
|
type usedPart struct {
|
||||||
partName string
|
partName string
|
||||||
index int
|
index int
|
||||||
mapping mappingType
|
mapping mappingType
|
||||||
|
SPDOverride string
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPlatformsManifest(memTech string) (map[string]string, error) {
|
func readPlatformsManifest(memTech string) (map[string]string, error) {
|
||||||
@ -183,30 +184,44 @@ func readParts(memPartsUsedFileName string) ([]usedPart, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(fields) == 1 {
|
if len(fields) == 1 {
|
||||||
parts = append(parts, usedPart{fields[0], -1, Auto})
|
parts = append(parts, usedPart{fields[0], -1, Auto, ""})
|
||||||
} else if len(fields) == 2 {
|
} else {
|
||||||
var mapping = Auto
|
var mapping = Auto
|
||||||
var assignedId = -1
|
var assignedId = -1
|
||||||
var err error = nil
|
var err error = nil
|
||||||
|
var spdOverride string = ""
|
||||||
|
|
||||||
if len(fields[1]) >= 2 && fields[1][0] == '*' {
|
// Second column, ID override
|
||||||
// Exclusive mapping
|
if len(fields) >= 2 {
|
||||||
mapping = Exclusive
|
if len(fields[1]) >= 2 && fields[1][0] == '*' {
|
||||||
assignedId, err = strconv.Atoi(fields[1][1:])
|
// Exclusive mapping
|
||||||
} else {
|
mapping = Exclusive
|
||||||
mapping = Fixed
|
assignedId, err = strconv.Atoi(fields[1][1:])
|
||||||
assignedId, err = strconv.Atoi(fields[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 {
|
if err != nil {
|
||||||
return nil, err
|
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])
|
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 {
|
parts = append(parts, usedPart{fields[0], assignedId, mapping, spdOverride})
|
||||||
return nil, fmt.Errorf("mem_parts_used_file file is incorrectly formatted")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +303,6 @@ func genPartIdInfo(parts []usedPart, partToSPDMap map[string]string, SPDToIndexM
|
|||||||
|
|
||||||
// Assign parts with fixed ids first
|
// Assign parts with fixed ids first
|
||||||
for _, p := range parts {
|
for _, p := range parts {
|
||||||
|
|
||||||
if p.index == -1 {
|
if p.index == -1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -299,7 +313,7 @@ func genPartIdInfo(parts []usedPart, partToSPDMap map[string]string, SPDToIndexM
|
|||||||
|
|
||||||
SPDFileName, ok := partToSPDMap[p.partName]
|
SPDFileName, ok := partToSPDMap[p.partName]
|
||||||
if !ok {
|
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
|
// Extend partIdList and assignedMapping with empty entries if needed
|
||||||
@ -396,7 +410,7 @@ func genPartIdInfo(parts []usedPart, partToSPDMap map[string]string, SPDToIndexM
|
|||||||
* This function generates Makefile.inc under the variant directory path and adds assigned SPDs
|
* This function generates Makefile.inc under the variant directory path and adds assigned SPDs
|
||||||
* to SPD_SOURCES.
|
* 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 := getFileHeader()
|
||||||
s += fmt.Sprintf("SPD_SOURCES =\n")
|
s += fmt.Sprintf("SPD_SOURCES =\n")
|
||||||
|
|
||||||
@ -405,7 +419,18 @@ func genMakefile(partIdList []partIds, makefileDirName string, SPDDir string) er
|
|||||||
s += fmt.Sprintf("SPD_SOURCES += %v ", filepath.Join(SPDDir, SPDEmptyFileName))
|
s += fmt.Sprintf("SPD_SOURCES += %v ", filepath.Join(SPDDir, SPDEmptyFileName))
|
||||||
s += fmt.Sprintf(" # ID = %d(0b%04b)\n", i, int64(i))
|
s += fmt.Sprintf(" # ID = %d(0b%04b)\n", i, int64(i))
|
||||||
} else {
|
} 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(" # ID = %d(0b%04b) ", i, int64(i))
|
||||||
s += fmt.Sprintf(" Parts = %04s\n", partIdList[i].memParts)
|
s += fmt.Sprintf(" Parts = %04s\n", partIdList[i].memParts)
|
||||||
}
|
}
|
||||||
@ -442,12 +467,20 @@ func main() {
|
|||||||
log.Fatal(err)
|
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)
|
partIdList, err := genPartIdInfo(parts, partToSPDMap, SPDToIndexMap, makefileDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
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)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user