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