blob: 60d2ebad776b2a721a3b6b76f147b9290e41a2fb [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <limits.h>
#include <stdint.h>
#include <arch/x86.h>
#include <platform/pc/bootbyte.h>
#define RTC_BASE_PORT (uint16_t)0x70
#define RTC_BOOT_BYTE 48 // CMOS register offset
// flags and fields in RTC_BOOT_BYTE
#define RTC_BOOT_NORMAL 0x1u // boot_option
#define RTC_BOOT_RECOVERY 0x2u // boot_option
#define RTC_BOOT_BOOTLOADER 0x4u // boot_option
#define RTC_BOOT_COUNT_MASK (0xf0u) // reboot_counter field mask
#define RTC_BOOT_COUNT_SHIFT (4) // reboot_counter shift amount
#define RTC_BOOT_COUNT_INITIAL (uint8_t)3 // reboot_counter initial value
static void cmos_write(uint8_t addr, uint8_t val) {
uint16_t ofs;
if (addr < 128) {
ofs = 0;
} else {
ofs = 2;
addr = (uint8_t)(addr - 128);
}
outp((uint16_t)(RTC_BASE_PORT + ofs), addr);
outp((uint16_t)(RTC_BASE_PORT + ofs + 1), val);
}
void bootbyte_set_reason(uint64_t reason) {
uint8_t val;
// set boot reason, clamp to be in range of a uint8_t, default to RTC_BOOT_NORMAL
if (reason <= 255) {
val = (uint8_t)reason;
} else {
val = RTC_BOOT_NORMAL;
}
// set default number of boot attempts
val |= (RTC_BOOT_COUNT_INITIAL << RTC_BOOT_COUNT_SHIFT);
cmos_write(RTC_BOOT_BYTE, val); // boot_option and reboot_counter
}