blob: fe5582fbf511282cef3d628cb7697b3f0886407a [file] [log] [blame]
Simon Glasse25c34d2024-10-14 16:32:10 -06001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Support for booting from coreboot
4 *
5 * Copyright 2021 Google LLC
6 */
7
8#define LOG_CATEGORY UCLASS_RTC
9
10#include <command.h>
11#include <dm.h>
12#include <rtc.h>
13#include <asm/cb_sysinfo.h>
14#include <asm/global_data.h>
15
16DECLARE_GLOBAL_DATA_PTR;
17
18const struct sysinfo_t *get_table(void)
19{
20 if (!gd->arch.coreboot_table) {
21 printf("No coreboot sysinfo table found\n");
22 return NULL;
23 }
24
25 return &lib_sysinfo;
26}
27
28static int calc_sum(struct udevice *dev, uint start_bit, uint bit_count)
29{
30 uint start_byte = start_bit / 8;
31 uint byte_count = bit_count / 8;
32 int ret, i;
33 uint sum;
34
35 log_debug("Calc sum from %x: %x bytes\n", start_byte, byte_count);
36 sum = 0;
37 for (i = 0; i < bit_count / 8; i++) {
38 ret = rtc_read8(dev, start_bit / 8 + i);
39 if (ret < 0)
40 return ret;
41 sum += ret;
42 }
43
44 return (sum & 0xff) << 8 | (sum & 0xff00) >> 8;
45}
46
47/**
48 * prep_cbcmos() - Prepare for a CMOS-RAM command
49 *
50 * @tab: coreboot table
51 * @devnum: RTC device name to use, or NULL for the first one
52 * @dep: Returns RTC device on success
53 * Return: calculated checksum for CMOS RAM or -ve on error
54 */
55static int prep_cbcmos(const struct sysinfo_t *tab, const char *devname,
56 struct udevice **devp)
57{
58 struct udevice *dev;
59 int ret;
60
61 if (!tab)
62 return CMD_RET_FAILURE;
63 if (devname)
64 ret = uclass_get_device_by_name(UCLASS_RTC, devname, &dev);
65 else
66 ret = uclass_first_device_err(UCLASS_RTC, &dev);
67 if (ret) {
68 printf("Failed to get RTC device: %dE\n", ret);
69 return ret;
70 }
71
72 ret = calc_sum(dev, tab->cmos_range_start,
73 tab->cmos_range_end + 1 - tab->cmos_range_start);
74 if (ret < 0) {
75 printf("Failed to read RTC device: %dE\n", ret);
76 return ret;
77 }
78 *devp = dev;
79
80 return ret;
81}
82
83static int do_cbcmos_check(struct cmd_tbl *cmdtp, int flag, int argc,
84 char *const argv[])
85{
86 const struct sysinfo_t *tab = get_table();
87 struct udevice *dev;
88 u16 cur, sum;
89 int ret;
90
91 ret = prep_cbcmos(tab, argv[1], &dev);
92 if (ret < 0)
93 return CMD_RET_FAILURE;
94 sum = ret;
95
96 ret = rtc_read16(dev, tab->cmos_checksum_location / 8, &cur);
97 if (ret < 0) {
98 printf("Failed to read RTC device: %dE\n", ret);
99 return CMD_RET_FAILURE;
100 }
101 if (sum != cur) {
102 printf("Checksum %04x error: calculated %04x\n", cur, sum);
103 return CMD_RET_FAILURE;
104 }
105
106 return 0;
107}
108
109static int do_cbcmos_update(struct cmd_tbl *cmdtp, int flag, int argc,
110 char *const argv[])
111{
112 const struct sysinfo_t *tab = get_table();
113 struct udevice *dev;
114 u16 sum;
115 int ret;
116
117 ret = prep_cbcmos(tab, argv[1], &dev);
118 if (ret < 0)
119 return CMD_RET_FAILURE;
120 sum = ret;
121
122 ret = rtc_write16(dev, tab->cmos_checksum_location / 8, sum);
123 if (ret < 0) {
124 printf("Failed to read RTC device: %dE\n", ret);
125 return CMD_RET_FAILURE;
126 }
127 printf("Checksum %04x written\n", sum);
128
129 return 0;
130}
131
132U_BOOT_LONGHELP(cbcmos,
133 "check - check CMOS RAM\n"
134 "cbcmos update - Update CMOS-RAM checksum";
135);
136
137U_BOOT_CMD_WITH_SUBCMDS(cbcmos, "coreboot CMOS RAM", cbcmos_help_text,
138 U_BOOT_SUBCMD_MKENT(check, 2, 1, do_cbcmos_check),
139 U_BOOT_SUBCMD_MKENT(update, 2, 1, do_cbcmos_update));