util/spd_tools: Add support for exclusive IDs
Currently memory parts that use the same SPD are assigned the same ID by spd_tools. This commit adds support for exclusive IDs. When given an exclusive ID a memory part will not share its ID with other parts unless they also have the same exclusive ID. BUG=b:225161910 TEST=Ran part_id_gen and checked that exclusive IDs work correctly and that the current behavior still works in their abscence. Signed-off-by: Robert Zieba <robertzieba@google.com> Change-Id: Ife5afe32337f69bc06451ce16238c7a83bc983c8 Reviewed-on: https://review.coreboot.org/c/coreboot/+/62905 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
This commit is contained in:
		
				
					committed by
					
						
						Karthik Ramasubramanian
					
				
			
			
				
	
			
			
			
						parent
						
							5d3b1bbce4
						
					
				
				
					commit
					a6425f170c
				
			@@ -459,10 +459,14 @@ 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 ID for each part. NOTE: Only assign a fixed ID if required
 | 
					*   optional fixed or exclusive ID for each part. A fixed ID is simply an integer
 | 
				
			||||||
    for legacy reasons.
 | 
					*   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.
 | 
				
			||||||
 | 
					*   NOTE: Only assign a fixed/exclusive ID if required for legacy reasons.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example of a CSV file using fixed IDs:
 | 
					Example of a CSV file using fixed and exclusive IDs:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
K4AAG165WA-BCWE,1
 | 
					K4AAG165WA-BCWE,1
 | 
				
			||||||
@@ -470,13 +474,15 @@ MT40A512M16TB-062E:J
 | 
				
			|||||||
MT40A1G16KD-062E:E
 | 
					MT40A1G16KD-062E:E
 | 
				
			||||||
K4A8G165WC-BCWE
 | 
					K4A8G165WC-BCWE
 | 
				
			||||||
H5AN8G6NDJR-XNC,8
 | 
					H5AN8G6NDJR-XNC,8
 | 
				
			||||||
H5ANAG6NCMR-XNC
 | 
					H5ANAG6NCMR-XNC,*9
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Explanation: This will ensure that the SPDs for K4AAG165WA-BCWE and
 | 
					Explanation: This will ensure that the SPDs for K4AAG165WA-BCWE and
 | 
				
			||||||
H5AN8G6NDJR-XNC are assigned to IDs 1 and 8 respectively. The SPDs for all other
 | 
					H5AN8G6NDJR-XNC are assigned to IDs 1 and 8 respectively. H5ANAG6NCMR-XNC
 | 
				
			||||||
memory parts will be assigned to the first compatible ID. Assigning fixed IDs
 | 
					will be assigned ID 9 and no other part will be assigned ID 9 even if it
 | 
				
			||||||
may result in duplicate SPD entries or gaps in the ID mapping.
 | 
					shares the same SPD. The SPDs for all other memory parts will be assigned to
 | 
				
			||||||
 | 
					the first compatible ID. Assigning fixed/exclusive IDs may result in duplicate
 | 
				
			||||||
 | 
					SPD entries or gaps in the ID mapping.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Output
 | 
					### Output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -93,9 +93,18 @@ func checkArgs(platform string, memTech string, makefileDir string, memPartsUsed
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type mappingType int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						Auto mappingType = iota
 | 
				
			||||||
 | 
						Fixed
 | 
				
			||||||
 | 
						Exclusive
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type usedPart struct {
 | 
					type usedPart struct {
 | 
				
			||||||
	partName string
 | 
						partName string
 | 
				
			||||||
	index    int
 | 
						index    int
 | 
				
			||||||
 | 
						mapping  mappingType
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func readPlatformsManifest(memTech string) (map[string]string, error) {
 | 
					func readPlatformsManifest(memTech string) (map[string]string, error) {
 | 
				
			||||||
@@ -174,16 +183,28 @@ func readParts(memPartsUsedFileName string) ([]usedPart, error) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if len(fields) == 1 {
 | 
							if len(fields) == 1 {
 | 
				
			||||||
			parts = append(parts, usedPart{fields[0], -1})
 | 
								parts = append(parts, usedPart{fields[0], -1, Auto})
 | 
				
			||||||
		} else if len(fields) == 2 {
 | 
							} else if len(fields) == 2 {
 | 
				
			||||||
			assignedId, err := strconv.Atoi(fields[1])
 | 
								var mapping = Auto
 | 
				
			||||||
 | 
								var assignedId = -1
 | 
				
			||||||
 | 
								var err error = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								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])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return nil, err
 | 
									return nil, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if assignedId > MaxMemoryId || assignedId < 0 {
 | 
								if assignedId > MaxMemoryId || assignedId < 0 {
 | 
				
			||||||
				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})
 | 
								parts = append(parts, usedPart{fields[0], assignedId, mapping})
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			return nil, fmt.Errorf("mem_parts_used_file file is incorrectly formatted")
 | 
								return nil, fmt.Errorf("mem_parts_used_file file is incorrectly formatted")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -245,7 +266,7 @@ type partIds struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getFileHeader() string {
 | 
					func getFileHeader() string {
 | 
				
			||||||
    return `# SPDX-License-Identifier: GPL-2.0-or-later
 | 
						return `# SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
# This is an auto-generated file. Do not edit!!
 | 
					# This is an auto-generated file. Do not edit!!
 | 
				
			||||||
# Generated by:
 | 
					# Generated by:
 | 
				
			||||||
` + fmt.Sprintf("# %s\n\n", strings.Join(os.Args[0:], " "))
 | 
					` + fmt.Sprintf("# %s\n\n", strings.Join(os.Args[0:], " "))
 | 
				
			||||||
@@ -262,6 +283,7 @@ func getFileHeader() string {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
func genPartIdInfo(parts []usedPart, partToSPDMap map[string]string, SPDToIndexMap map[string]int, makefileDirName string) ([]partIds, error) {
 | 
					func genPartIdInfo(parts []usedPart, partToSPDMap map[string]string, SPDToIndexMap map[string]int, makefileDirName string) ([]partIds, error) {
 | 
				
			||||||
	partIdList := []partIds{}
 | 
						partIdList := []partIds{}
 | 
				
			||||||
 | 
						assignedMapping := []mappingType{}
 | 
				
			||||||
	var s string
 | 
						var s string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Assign parts with fixed ids first
 | 
						// Assign parts with fixed ids first
 | 
				
			||||||
@@ -280,19 +302,34 @@ func genPartIdInfo(parts []usedPart, partToSPDMap map[string]string, SPDToIndexM
 | 
				
			|||||||
			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 ", p.partName, " in SPD Manifest. Please add the part to global part list and regenerate SPD Manifest")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Extend partIdList with empty entries if needed
 | 
							// Extend partIdList and assignedMapping with empty entries if needed
 | 
				
			||||||
		for i := len(partIdList) - 1; i < p.index; i++ {
 | 
							for i := len(partIdList) - 1; i < p.index; i++ {
 | 
				
			||||||
			partIdList = append(partIdList, partIds{})
 | 
								partIdList = append(partIdList, partIds{})
 | 
				
			||||||
 | 
								assignedMapping = append(assignedMapping, Auto)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if partIdList[p.index].SPDFileName != "" {
 | 
							// Only allow parts with the same index if they share the same SPD
 | 
				
			||||||
			return nil, fmt.Errorf("Part ", p.partName, " is assigned to an already assigned ID ", p.index)
 | 
							assignedSPD := partIdList[p.index].SPDFileName
 | 
				
			||||||
 | 
							if assignedSPD != "" && assignedSPD != partToSPDMap[p.partName] {
 | 
				
			||||||
 | 
								return nil, fmt.Errorf("ID %d is already assigned to %s, conflicting with %s(%s)", p.index, assignedSPD, p.partName, SPDFileName)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		partIdList[p.index] = partIds{SPDFileName: SPDFileName, memParts: p.partName}
 | 
							mapping := assignedMapping[p.index]
 | 
				
			||||||
 | 
							if (mapping == Fixed && p.mapping == Exclusive) || (mapping == Exclusive && p.mapping == Fixed) {
 | 
				
			||||||
 | 
								return nil, fmt.Errorf("Exclusive/non-exclusive conflict in assigning %s to ID %d", p.partName, p.index)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								assignedMapping[p.index] = p.mapping
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if partIdList[p.index].memParts == "" {
 | 
				
			||||||
 | 
								partIdList[p.index] = partIds{SPDFileName: SPDFileName, memParts: p.partName}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								partIdList[p.index].memParts += ", " + p.partName
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// SPDToIndexMap should point to first assigned index in the used part list
 | 
							// SPDToIndexMap should point to first assigned index in the used part list
 | 
				
			||||||
		if SPDToIndexMap[SPDFileName] < 0 {
 | 
							// Exclusive entries don't update the map because they're not valid for auto assigning
 | 
				
			||||||
 | 
							if SPDToIndexMap[SPDFileName] < 0 && p.mapping != Exclusive {
 | 
				
			||||||
			SPDToIndexMap[SPDFileName] = p.index
 | 
								SPDToIndexMap[SPDFileName] = p.index
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -317,7 +354,8 @@ func genPartIdInfo(parts []usedPart, partToSPDMap map[string]string, SPDToIndexM
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		index := SPDToIndexMap[SPDFileName]
 | 
							index := SPDToIndexMap[SPDFileName]
 | 
				
			||||||
		if index != -1 {
 | 
							// Only Exclusive mappings don't allow automatic assigning of parts
 | 
				
			||||||
 | 
							if index != -1 && assignedMapping[index] != Exclusive {
 | 
				
			||||||
			partIdList[index].memParts += ", " + p.partName
 | 
								partIdList[index].memParts += ", " + p.partName
 | 
				
			||||||
			appendPartIdInfo(&s, p.partName, index)
 | 
								appendPartIdInfo(&s, p.partName, index)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
@@ -338,6 +376,7 @@ func genPartIdInfo(parts []usedPart, partToSPDMap map[string]string, SPDToIndexM
 | 
				
			|||||||
				return nil, fmt.Errorf("Maximum part ID %d exceeded.", MaxMemoryId)
 | 
									return nil, fmt.Errorf("Maximum part ID %d exceeded.", MaxMemoryId)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			partIdList = append(partIdList, partIds{})
 | 
								partIdList = append(partIdList, partIds{})
 | 
				
			||||||
 | 
								assignedMapping = append(assignedMapping, Auto)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SPDToIndexMap[SPDFileName] = index
 | 
							SPDToIndexMap[SPDFileName] = index
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user