1 /* SPDX-License-Identifier: GPL-2.0-or-later */
17 /* ------------------------------------------------------------------------------------------ */
18 /* Program-defined types */
19 /* ------------------------------------------------------------------------------------------ */
20 type memParts
struct {
21 MemParts
[]memPart
`json:"parts"`
30 type memTech
interface {
32 * Returns the set -> platform mapping for the memory technology. Platforms with the
33 * same SPD requirements should be grouped together into a single set.
35 getSetMap() map[int][]int
38 * Takes the name and attributes of a part, as read from the memory_parts JSON file.
39 * Validates the attributes, returning an error if any attribute has an invalid value.
40 * Stores the name and attributes internally to be used later.
42 addNewPart(string, interface{}) error
45 * Takes the name of a part and a set number.
46 * Retrieves the part's attributes which were stored by addNewPart(). Updates them by
47 * setting any optional attributes which weren't specified in the JSON file to their
49 * Returns these updated attributes.
51 getSPDAttribs(string, int) (interface{}, error
)
54 * Returns the size of an SPD file for this memory technology.
59 * Takes an SPD byte index and the attributes of a part.
60 * Returns the value which that SPD byte should be set to based on the attributes.
62 getSPDByte(int, interface{}) byte
65 /* ------------------------------------------------------------------------------------------ */
67 /* ------------------------------------------------------------------------------------------ */
83 SPDManifestFileName
= "parts_spd_manifest.generated.txt"
84 PlatformManifestFileName
= "platforms_manifest.generated.txt"
87 /* ------------------------------------------------------------------------------------------ */
88 /* Global variables */
89 /* ------------------------------------------------------------------------------------------ */
91 var platformNames
= map[int]string{
103 var memTechMap
= map[string]memTech
{
109 /* ------------------------------------------------------------------------------------------ */
110 /* Conversion Helper Functions */
111 /* ------------------------------------------------------------------------------------------ */
113 func convNsToPs(timeNs
int) int {
117 func convMtbToPs(mtb
int) int {
121 func convPsToMtb(timePs
int) int {
122 return divRoundUp(timePs
, 125)
125 func convPsToMtbByte(timePs
int) byte {
126 return byte(convPsToMtb(timePs
) & 0xff)
129 func convPsToFtbByte(timePs
int) byte {
130 mtb
:= convPsToMtb(timePs
)
131 ftb
:= timePs
- convMtbToPs(mtb
)
136 func convNsToMtb(timeNs
int) int {
137 return convPsToMtb(convNsToPs(timeNs
))
140 func convNsToMtbByte(timeNs
int) byte {
141 return convPsToMtbByte(convNsToPs(timeNs
))
144 func convNsToFtbByte(timeNs
int) byte {
145 return convPsToFtbByte(convNsToPs(timeNs
))
148 func divRoundUp(dividend
int, divisor
int) int {
149 return (dividend
+ divisor
- 1) / divisor
152 /* ------------------------------------------------------------------------------------------ */
154 /* ------------------------------------------------------------------------------------------ */
156 func findIndex(dedupedAttribs
[]interface{}, newSPDAttribs
interface{}) int {
157 for i
:= 0; i
< len(dedupedAttribs
); i
++ {
158 if reflect
.DeepEqual(dedupedAttribs
[i
], newSPDAttribs
) {
166 func readMemParts(memPartsFilePath
string) (memParts
, error
) {
167 var memParts memParts
169 dataBytes
, err
:= ioutil
.ReadFile(memPartsFilePath
)
174 // Strip comments from json file
175 re
:= regexp
.MustCompile(`(?m)^\s*//.*`)
176 dataBytes
= re
.ReplaceAll(dataBytes
, []byte(""))
178 if err
:= json
.Unmarshal(dataBytes
, &memParts
); err
!= nil {
185 func createSPD(memAttribs
interface{}, t memTech
) string {
188 for i
:= 0; i
< t
.getSPDLen(); i
++ {
190 if memAttribs
!= nil {
191 b
= t
.getSPDByte(i
, memAttribs
)
195 s
+= fmt
.Sprintf("%02X\n", b
)
197 s
+= fmt
.Sprintf("%02X ", b
)
204 func writeSPD(memAttribs
interface{}, SPDId
int, SPDSetDirName
string, t memTech
) {
205 s
:= createSPD(memAttribs
, t
)
206 SPDFileName
:= fmt
.Sprintf("spd-%d.hex", SPDId
)
207 ioutil
.WriteFile(filepath
.Join(SPDSetDirName
, SPDFileName
), []byte(s
), 0644)
210 func writeEmptySPD(SPDSetDirName
string, t memTech
) {
211 s
:= createSPD(nil, t
)
212 SPDFileName
:= "spd-empty.hex"
213 ioutil
.WriteFile(filepath
.Join(SPDSetDirName
, SPDFileName
), []byte(s
), 0644)
216 func getGeneratedString() string {
217 return fmt
.Sprintf("# Generated by:\n# %s\n\n", strings
.Join(os
.Args
[0:], " "))
220 func writeSPDManifest(memPartArray
[]memPart
, SPDSetDirName
string) {
223 s
+= getGeneratedString()
224 for i
:= 0; i
< len(memPartArray
); i
++ {
225 s
+= fmt
.Sprintf("%s,spd-%d.hex\n", memPartArray
[i
].Name
, memPartArray
[i
].SPDId
)
228 ioutil
.WriteFile(filepath
.Join(SPDSetDirName
, SPDManifestFileName
), []byte(s
), 0644)
231 func writeSetMap(setMap
map[int][]int, SPDDirName
string) {
234 s
+= getGeneratedString()
237 for k
, _
:= range setMap
{
238 setNumbers
= append(setNumbers
, k
)
240 sort
.Ints(setNumbers
)
242 for _
, num
:= range setNumbers
{
243 for _
, item
:= range setMap
[num
] {
244 s
+= fmt
.Sprintf("%s,set-%d\n", platformNames
[item
], num
)
248 ioutil
.WriteFile(filepath
.Join(SPDDirName
, PlatformManifestFileName
), []byte(s
), 0644)
252 fmt
.Printf("\nUsage: %s <mem_parts_list_json> <mem_technology>\n\n", os
.Args
[0])
253 fmt
.Printf(" where,\n")
254 fmt
.Printf(" mem_parts_list_json = JSON File containing list of memory parts and attributes\n")
255 fmt
.Printf(" mem_technology = Memory technology for which to generate SPDs\n")
256 fmt
.Printf(" supported technologies: %v\n\n\n",
257 reflect
.ValueOf(memTechMap
).MapKeys())
261 if len(os
.Args
) != 3 {
263 log
.Fatal("Incorrect number of arguments")
267 memPartsFilePath
, memTechnology
:= os
.Args
[1], os
.Args
[2]
269 t
, ok
:= memTechMap
[strings
.ToLower(memTechnology
)]
271 log
.Fatal("Unsupported memory technology ", memTechnology
)
274 SPDDir
, err
:= filepath
.Abs(filepath
.Dir(memPartsFilePath
))
279 memParts
, err
:= readMemParts(memPartsFilePath
)
284 memPartExists
:= make(map[string]bool)
285 for i
:= 0; i
< len(memParts
.MemParts
); i
++ {
286 if memPartExists
[memParts
.MemParts
[i
].Name
] {
287 log
.Fatalf("%s is duplicated in mem_parts_list_json", memParts
.MemParts
[i
].Name
)
289 memPartExists
[memParts
.MemParts
[i
].Name
] = true
291 if err
:= t
.addNewPart(memParts
.MemParts
[i
].Name
, memParts
.MemParts
[i
].Attribs
); err
!= nil {
296 setMap
:= t
.getSetMap()
298 for i
:= 0; i
< len(setMap
); i
++ {
299 var dedupedAttribs
[]interface{}
301 for j
:= 0; j
< len(memParts
.MemParts
); j
++ {
302 spdAttribs
, _
:= t
.getSPDAttribs(memParts
.MemParts
[j
].Name
, i
)
305 if index
= findIndex(dedupedAttribs
, spdAttribs
); index
== -1 {
306 dedupedAttribs
= append(dedupedAttribs
, spdAttribs
)
307 index
= len(dedupedAttribs
) - 1
310 memParts
.MemParts
[j
].SPDId
= index
+ 1
313 SPDSetDir
:= fmt
.Sprintf("%s/set-%d", SPDDir
, i
)
314 os
.MkdirAll(SPDSetDir
, os
.ModePerm
)
316 for j
:= 0; j
< len(dedupedAttribs
); j
++ {
317 writeSPD(dedupedAttribs
[j
], j
+1, SPDSetDir
, t
)
320 writeEmptySPD(SPDSetDir
, t
)
322 writeSPDManifest(memParts
.MemParts
, SPDSetDir
)
325 writeSetMap(setMap
, SPDDir
)