2 * This file is part of the coreboot project.
4 * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <console/console.h>
17 #include <ip_checksum.h>
18 #include <pc80/mc146818rtc.h>
24 * We need a region in CMOS to store the boot counter.
26 * This can either be declared as part of the option
27 * table or statically defined in the board config.
29 #if CONFIG_USE_OPTION_TABLE
30 # include "option_table.h"
31 # define BOOT_COUNT_CMOS_OFFSET (CMOS_VSTART_boot_count_offset >> 3)
33 # if defined(CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET) && CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET
34 # define BOOT_COUNT_CMOS_OFFSET CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET
36 # error "Must configure CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET"
40 #define BOOT_COUNT_SIGNATURE 0x4342 /* 'BC' */
46 } __attribute__ ((packed
));
48 /* Read and validate boot count structure from CMOS */
49 static int boot_count_cmos_read(struct boot_count
*bc
)
54 for (p
= (u8
*)bc
, i
= 0; i
< sizeof(*bc
); i
++, p
++)
55 *p
= cmos_read(BOOT_COUNT_CMOS_OFFSET
+ i
);
57 /* Verify signature */
58 if (bc
->signature
!= BOOT_COUNT_SIGNATURE
) {
59 printk(BIOS_DEBUG
, "Boot Count invalid signature\n");
63 /* Verify checksum over signature and counter only */
64 csum
= compute_ip_checksum(bc
, offsetof(struct boot_count
, checksum
));
66 if (csum
!= bc
->checksum
) {
67 printk(BIOS_DEBUG
, "Boot Count checksum mismatch\n");
74 /* Write boot count structure to CMOS */
75 static void boot_count_cmos_write(struct boot_count
*bc
)
79 /* Checksum over signature and counter only */
80 bc
->checksum
= compute_ip_checksum(
81 bc
, offsetof(struct boot_count
, checksum
));
83 for (p
= (u8
*)bc
, i
= 0; i
< sizeof(*bc
); i
++, p
++)
84 cmos_write(*p
, BOOT_COUNT_CMOS_OFFSET
+ i
);
87 /* Increment boot count and return the new value */
88 u32
boot_count_increment(void)
92 /* Read and increment boot count */
93 if (boot_count_cmos_read(&bc
) < 0) {
94 /* Structure invalid, re-initialize */
95 bc
.signature
= BOOT_COUNT_SIGNATURE
;
99 /* Increment boot counter */
102 /* Write the new count to CMOS */
103 boot_count_cmos_write(&bc
);
105 printk(BIOS_DEBUG
, "Boot Count incremented to %u\n", bc
.count
);
109 /* Return the current boot count */
110 u32
boot_count_read(void)
112 struct boot_count bc
;
114 if (boot_count_cmos_read(&bc
) < 0)