soc/intel/cmn/cse: Deprecate CONFIG_SOC_INTEL_CSE_RW_VERSION
[coreboot2.git] / util / docker / coreboot.org-status / board-status.html / boards.go
blob96e3be6a5cb372f635f270c7b40a69d40977dfb4
1 package main
3 import (
4 "fmt"
5 "io/fs"
6 "os"
7 "path/filepath"
8 "regexp"
9 "sort"
10 "strings"
13 func readBoardInfo(dir NamedFS) map[string]string {
14 result := make(map[string]string)
15 c, err := fs.ReadFile(dir.FS, filepath.Join(dir.Name, "board_info.txt"))
16 if err != nil {
17 return result
19 ls := strings.Split(string(c), "\n")
20 for _, l := range ls {
21 spl := strings.SplitN(l, ":", 2)
22 if len(spl) != 2 {
23 // This shouldn't ever happen, but let's try to
24 // extract as much information from erroneous
25 // board_info files (if they exist) as possible.
26 continue
28 result[strings.TrimSpace(spl[0])] = strings.TrimSpace(spl[1])
30 return result
33 func fetchBoards(dirs chan<- NamedFS) {
34 defer close(dirs)
35 ds, err := fs.Glob(cbdirFS, filepath.Join("src", "mainboard", "*", "*"))
36 if err != nil {
37 fmt.Fprintf(os.Stderr, "Could not find mainboard directories: %v\n", err)
38 return
40 for _, d := range ds {
41 if _, err := fs.ReadDir(cbdirFS, d); err != nil {
42 continue
44 dirs <- NamedFS{
45 FS: cbdirFS,
46 Name: d,
51 var niceVendors = make(map[string]string)
53 func getNiceVendor(dir string, vendor string) (string, error) {
54 if _, exists := niceVendors[vendor]; !exists {
55 c, err := fs.ReadFile(cbdirFS, filepath.Join(dir, "..", "Kconfig.name"))
56 if err != nil {
57 return "", err
59 re, err := regexp.Compile("(?i)config VENDOR_" + vendor)
60 if err != nil {
61 return "", err
63 ls := strings.Split(string(c), "\n")
64 next := false
65 for _, l := range ls {
66 if next {
67 niceVendors[vendor] = strings.Split(l, "\"")[1]
68 break
70 if re.Match([]byte(l)) {
71 next = true
75 return niceVendors[vendor], nil
78 func readKconfig(dir NamedFS) (string, string, string, string, string, error) {
79 var north, south, superio, cpu, partnum string
80 c, err := fs.ReadFile(dir.FS, filepath.Join(dir.Name, "Kconfig"))
81 if err != nil {
82 return north, south, superio, cpu, partnum, err
84 ls := strings.Split(string(c), "\n")
85 partoffset := 0
86 for _, l := range ls {
87 l = strings.TrimSpace(l)
88 if len(l) < 7 {
89 continue
91 // TODO: handling of MAINBOARD_PART_NUMBER is rather broken
92 // and fragile. Doesn't help that many boards use different
93 // part numbers for different models and this code can't
94 // figure it out.
95 if strings.Contains(strings.ToLower(l), "config mainboard_part_number") {
96 partoffset = 2
97 continue
99 if partoffset > 0 {
100 partoffset--
101 if strings.Contains(l, "default") {
102 partnum = strings.Split(l, "\"")[1]
103 continue
106 if l[0:7] != "select " {
107 continue
109 l = l[7:]
110 if len(l) > 12 && l[0:12] == "NORTHBRIDGE_" {
111 north = l[12:]
112 continue
114 if len(l) > 12 && l[0:12] == "SOUTHBRIDGE_" {
115 if strings.Contains(l, "SKIP_") ||
116 strings.Contains(l, "DISABLE_") {
117 continue
119 south = l[12:]
120 continue
122 if len(l) > 8 && l[0:8] == "SUPERIO_" {
123 superio = l[8:]
124 continue
126 if len(l) > 4 && (l[0:4] == "CPU_" || l[0:4] == "SOC_") {
127 if strings.Contains(l, "AMD_AGESA_FAMILY") ||
128 strings.Contains(l, "AMD_COMMON_") ||
129 strings.Contains(l, "INTEL_COMMON_") ||
130 strings.Contains(l, "INTEL_DISABLE_") ||
131 strings.Contains(l, "INTEL_CSE_") ||
132 strings.Contains(l, "CPU_MICROCODE_CBFS_NONE") {
133 continue
135 cpu = l[4:]
138 return north, south, superio, cpu, partnum, nil
141 type reReplace struct {
142 pattern *regexp.Regexp
143 replace string
146 func prettify(input string, rules *[]reReplace) string {
147 for _, rule := range *rules {
148 input = rule.pattern.ReplaceAllString(input, rule.replace)
150 return input
153 var northbridgeRules = []reReplace{
155 pattern: regexp.MustCompile("AMD_AGESA_FAMILY([0-9a-fA-F]*)(.*)"),
156 replace: "AMD Family ${1}h${2} (AGESA)",
159 pattern: regexp.MustCompile("AMD_PI_(.*)"),
160 replace: "AMD ${1} (PI)",
163 pattern: regexp.MustCompile("INTEL_FSP_(.*)"),
164 replace: "Intel® ${1} (FSP)",
167 pattern: regexp.MustCompile("AMD_FAMILY([0-9a-fA-F]*)"),
168 replace: "AMD Family ${1}h,",
171 pattern: regexp.MustCompile("AMD_AMDFAM([0-9a-fA-F]*)"),
172 replace: "AMD Family ${1}h",
175 pattern: regexp.MustCompile("_"),
176 replace: " ",
179 pattern: regexp.MustCompile("INTEL"),
180 replace: "Intel®",
184 func prettifyNorthbridge(northbridge string) string {
185 return prettify(northbridge, &northbridgeRules)
188 var southbridgeRules = []reReplace{
190 pattern: regexp.MustCompile("_"),
191 replace: " ",
194 pattern: regexp.MustCompile("INTEL"),
195 replace: "Intel®",
199 func prettifySouthbridge(southbridge string) string {
200 return prettify(southbridge, &southbridgeRules)
203 var superIORules = []reReplace{
205 pattern: regexp.MustCompile("_"),
206 replace: " ",
209 pattern: regexp.MustCompile("WINBOND"),
210 replace: "Winbond™,",
213 pattern: regexp.MustCompile("ITE"),
214 replace: "ITE™",
217 pattern: regexp.MustCompile("SMSC"),
218 replace: "SMSC®",
221 pattern: regexp.MustCompile("NUVOTON"),
222 replace: "Nuvoton ",
226 func prettifySuperIO(superio string) string {
227 return prettify(superio, &superIORules)
230 type cpuMapping struct {
231 cpu string
232 socket string
235 var cpuMappings = map[string]cpuMapping{
236 "ALLWINNER_A10": {
237 cpu: "Allwinner A10",
238 socket: "?",
240 "AMD_GEODE_LX": {
241 cpu: "AMD Geode™ LX",
242 socket: "—",
244 "AMD_SOCKET_754": {
245 cpu: "AMD Sempron™ / Athlon™ 64 / Turion™ 64",
246 socket: "Socket 754",
248 "AMD_SOCKET_ASB2": {
249 cpu: "AMD Turion™ II Neo/Athlon™ II Neo",
250 socket: "ASB2 (BGA812)",
252 "AMD_SOCKET_S1G1": {
253 cpu: "AMD Turion™ / X2 Sempron™",
254 socket: "Socket S1G1",
256 "AMD_SOCKET_G34": {
257 cpu: "AMD Opteron™ Magny-Cours/Interlagos",
258 socket: "Socket G34",
260 "AMD_SOCKET_G34_NON_AGESA": {
261 cpu: "AMD Opteron™ Magny-Cours/Interlagos",
262 socket: "Socket G34",
264 "AMD_SOCKET_C32": {
265 cpu: "AMD Opteron™ Magny-Cours/Interlagos",
266 socket: "Socket C32",
268 "AMD_SOCKET_C32_NON_AGESA": {
269 cpu: "AMD Opteron™ Magny-Cours/Interlagos",
270 socket: "Socket C32",
272 "AMD_SOCKET_AM2": {
273 cpu: "?",
274 socket: "Socket AM2",
276 "AMD_SOCKET_AM3": {
277 cpu: "AMD Athlon™ 64 / FX / X2",
278 socket: "Socket AM3",
280 "AMD_SOCKET_AM2R2": {
281 cpu: "AMD Athlon™ 64 / X2 / FX, Sempron™",
282 socket: "Socket AM2+",
284 "AMD_SOCKET_F": {
285 cpu: "AMD Opteron™",
286 socket: "Socket F",
288 "AMD_SOCKET_F_1207": {
289 cpu: "AMD Opteron™",
290 socket: "Socket F 1207",
292 "AMD_SOCKET_940": {
293 cpu: "AMD Opteron™",
294 socket: "Socket 940",
296 "AMD_SOCKET_939": {
297 cpu: "AMD Athlon™ 64 / FX / X2",
298 socket: "Socket 939",
300 "AMD_SC520": {
301 cpu: "AMD Élan™SC520",
302 socket: "—",
304 "AMD_STONEYRIDGE_FP4": {
305 cpu: "AMD Stoney Ridge",
306 socket: "FP4 BGA",
308 "ARMLTD_CORTEX_A9": {
309 cpu: "ARM Cortex A9",
310 socket: "?",
312 "DMP_VORTEX86EX": {
313 cpu: "DMP VORTEX86EX",
314 socket: "?",
316 "MEDIATEK_MT8173": {
317 cpu: "MediaTek MT8173",
318 socket: "—",
320 "NVIDIA_TEGRA124": {
321 cpu: "NVIDIA Tegra 124",
322 socket: "—",
324 "NVIDIA_TEGRA210": {
325 cpu: "NVIDIA Tegra 210",
326 socket: "—",
328 "SAMSUNG_EXYNOS5420": {
329 cpu: "Samsung Exynos 5420",
330 socket: "?",
332 "SAMSUNG_EXYNOS5250": {
333 cpu: "Samsung Exynos 5250",
334 socket: "?",
336 "TI_AM335X": {
337 cpu: "TI AM335X",
338 socket: "?",
340 "INTEL_APOLLOLAKE": {
341 cpu: "Intel® Apollo Lake",
342 socket: "—",
344 "INTEL_BAYTRAIL": {
345 cpu: "Intel® Bay Trail",
346 socket: "—",
348 "INTEL_BRASWELL": {
349 cpu: "Intel® Braswell",
350 socket: "—",
352 "INTEL_BROADWELL": {
353 cpu: "Intel® Broadwell",
354 socket: "—",
356 "INTEL_DENVERTON_NS": {
357 cpu: "Intel® Denverton-NS",
358 socket: "—",
360 "INTEL_FSP_BROADWELL_DE": {
361 cpu: "Intel® Broadwell-DE",
362 socket: "—",
364 "INTEL_GLK": {
365 cpu: "Intel® Gemini Lake",
366 socket: "—",
368 "INTEL_GEMINILAKE": {
369 cpu: "Intel® Gemini Lake",
370 socket: "—",
372 "INTEL_ICELAKE": {
373 cpu: "Intel® Ice Lake",
374 socket: "—",
376 "INTEL_KABYLAKE": {
377 cpu: "Intel® Kaby Lake",
378 socket: "—",
380 "INTEL_SANDYBRIDGE": {
381 cpu: "Intel® Sandy Bridge",
382 socket: "—",
384 "INTEL_SKYLAKE": {
385 cpu: "Intel® Skylake",
386 socket: "—",
388 "INTEL_SLOT_1": {
389 cpu: "Intel® Pentium® II/III, Celeron®",
390 socket: "Slot 1",
392 "INTEL_SOCKET_MPGA604": {
393 cpu: "Intel® Xeon®",
394 socket: "Socket 604",
396 "INTEL_SOCKET_M": {
397 cpu: "Intel® Core™ 2 Duo Mobile, Core™ Duo/Solo, Celeron® M",
398 socket: "Socket M (mPGA478MT)",
400 "INTEL_SOCKET_LGA771": {
401 cpu: "Intel Xeon™ 5000 series",
402 socket: "Socket LGA771",
404 "INTEL_SOCKET_LGA775": {
405 cpu: "Intel® Core 2, Pentium 4/D",
406 socket: "Socket LGA775",
408 "INTEL_SOCKET_PGA370": {
409 cpu: "Intel® Pentium® III-800, Celeron®",
410 socket: "Socket PGA370",
412 "INTEL_SOCKET_MPGA479M": {
413 cpu: "Intel® Mobile Celeron",
414 socket: "Socket 479",
416 "INTEL_HASWELL": {
417 cpu: "Intel® 4th Gen (Haswell) Core i3/i5/i7",
418 socket: "?",
420 "INTEL_FSP_RANGELEY": {
421 cpu: "Intel® Atom Rangeley (FSP)",
422 socket: "?",
424 "INTEL_SOCKET_441": {
425 cpu: "Intel® Atom™ 230",
426 socket: "Socket 441",
428 "INTEL_SOCKET_FC_PGA370": {
429 cpu: "Intel® Pentium® III, Celeron®",
430 socket: "Socket PGA370",
432 "INTEL_EP80579": {
433 cpu: "Intel® EP80579",
434 socket: "Intel® EP80579",
436 "INTEL_SOCKET_MFCBGA479": {
437 cpu: "Intel® Mobile Celeron",
438 socket: "Socket 479",
440 "INTEL_WHISKEYLAKE": {
441 cpu: "Intel® Whiskey Lake",
442 socket: "—",
444 "QC_IPQ806X": {
445 cpu: "Qualcomm IPQ806x",
446 socket: "—",
448 "QUALCOMM_QCS405": {
449 cpu: "Qualcomm QCS405",
450 socket: "—",
452 "ROCKCHIP_RK3288": {
453 cpu: "Rockchip RK3288",
454 socket: "—",
456 "ROCKCHIP_RK3399": {
457 cpu: "Rockchip RK3399",
458 socket: "—",
460 "VIA_C3": {
461 cpu: "VIA C3™",
462 socket: "?",
464 "VIA_C7": {
465 cpu: "VIA C7™",
466 socket: "?",
468 "VIA_NANO": {
469 cpu: "VIA NANO™",
470 socket: "?",
472 "QEMU_X86": {
473 cpu: "QEMU x86",
474 socket: "—",
478 func prettifyCPU(cpu, north string, northNice string) (string, string) {
479 if match, ok := cpuMappings[cpu]; ok {
480 return match.cpu, match.socket
482 if cpu == "" {
483 if match, ok := cpuMappings[north]; ok {
484 return match.cpu, match.socket
486 if north == "INTEL_IRONLAKE" {
487 return "Intel® 1st Gen (Westmere) Core i3/i5/i7", "?"
489 if north == "RDC_R8610" {
490 return "RDC R8610", "—"
492 if (len(north) > 10 && north[0:10] == "AMD_AGESA_") || (len(north) > 7 && north[0:7] == "AMD_PI_") {
493 return northNice, "?"
495 return north, north
497 if cpu == "INTEL_SOCKET_BGA956" {
498 if north == "INTEL_GM45" {
499 return "Intel® Core 2 Duo (Penryn)", "Socket P"
501 return "Intel® Pentium® M", "BGA956"
503 if cpu == "INTEL_SOCKET_RPGA989" || cpu == "INTEL_SOCKET_LGA1155" || cpu == "INTEL_SOCKET_RPGA988B" {
504 socket := "Socket " + cpu[13:]
505 if north == "INTEL_HASWELL" {
506 return "Intel® 4th Gen (Haswell) Core i3/i5/i7", socket
508 if north == "INTEL_IVYBRIDGE" || north == "INTEL_FSP_IVYBRIDGE" {
509 return "Intel® 3rd Gen (Ivybridge) Core i3/i5/i7", socket
511 if north == "INTEL_SANDYBRIDGE" {
512 return "Intel® 2nd Gen (Sandybridge) Core i3/i5/i7", socket
514 return north, socket
516 return cpu, cpu
519 func collectBoards(dirs <-chan NamedFS) {
520 for dir := range dirs {
521 path := strings.Split(dir.Name, string(filepath.Separator))
522 vendor, board := path[2], path[3]
523 vendorNice, err := getNiceVendor(dir.Name, vendor)
525 if err != nil {
526 fmt.Fprintf(os.Stderr, "Could not find nice vendor name for %s: %v\n", dir.Name, err)
527 continue
530 bi := readBoardInfo(dir)
531 cat := Category(bi["Category"])
532 if _, ok := data.CategoryNiceNames[cat]; !ok {
533 cat = "unclass"
535 if bi["Vendor cooperation score"] == "" {
536 bi["Vendor cooperation score"] = "—"
539 venboard := vendor + string(filepath.Separator) + board
540 if bi["Clone of"] != "" {
541 venboard = bi["Clone of"]
542 venboard = strings.ReplaceAll(venboard, "/", string(filepath.Separator))
543 newpath := filepath.Join(dir.Name, "..", "..", venboard)
544 dir.Name = newpath
547 north, south, superio, cpu, partnum, err := readKconfig(dir)
548 if err != nil {
549 fmt.Fprintf(os.Stderr, "'%s' is not a mainboard directory: %v\n", dir.Name, err)
550 // Continue with the path because that's what the
551 // shell script did. We might want to change semantics
552 // later.
554 northbridgeNice := prettifyNorthbridge(north)
555 southbridgeNice := prettifySouthbridge(south)
556 superIONice := prettifySuperIO(superio)
557 cpuNice, socketNice := prettifyCPU(cpu, north, northbridgeNice)
559 boardNice := bi["Board name"]
560 if boardNice == "" {
561 boardNice = partnum
563 if boardNice == "" {
564 boardNice = strings.ReplaceAll(boardNice, "_", " ")
565 boardNice = strings.ToUpper(boardNice)
568 b := Board{
569 Vendor: vendor,
570 Vendor2nd: bi["Vendor name"],
571 VendorNice: vendorNice,
572 VendorBoard: vendor + "/" + board,
573 Board: board,
574 BoardNice: boardNice,
575 BoardURL: bi["Board URL"],
576 NorthbridgeNice: northbridgeNice,
577 SouthbridgeNice: southbridgeNice,
578 SuperIONice: superIONice,
579 CPUNice: cpuNice,
580 SocketNice: socketNice,
581 ROMPackage: bi["ROM package"],
582 ROMProtocol: bi["ROM protocol"],
583 ROMSocketed: bi["ROM socketed"],
584 FlashromSupport: bi["Flashrom support"],
585 VendorCooperationScore: bi["Vendor cooperation score"],
586 VendorCooperationPage: bi["Vendor cooperation page"],
588 if b.ROMPackage == "" {
589 b.ROMPackage = "?"
591 if b.ROMProtocol == "" {
592 b.ROMProtocol = "?"
595 if data.BoardsByCategory[cat] == nil {
596 data.BoardsByCategory[cat] = []Board{}
598 data.BoardsByCategory[cat] = append(data.BoardsByCategory[cat], b)
600 for ci := range data.BoardsByCategory {
601 cat := data.BoardsByCategory[ci]
602 sort.Slice(data.BoardsByCategory[ci], func(i, j int) bool {
603 if cat[i].Vendor == cat[j].Vendor {
604 return cat[i].Board < cat[j].Board
606 return cat[i].Vendor < cat[j].Vendor