Loading...
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)); |