/* * This file is part of the coreboot project. * * Copyright (C) 2003 Eric Biederman * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; version 2 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA */ #include <arch/io.h> #include <console/console.h> #if CONFIG_CMOS_POST #include <pc80/mc146818rtc.h> #include <smp/spinlock.h> #endif #if CONFIG_CMOS_POST_EXTRA #include <device/device.h> #endif #include <elog.h> /* Write POST information */ /* someday romcc will be gone. */ #ifndef __ROMCC__ /* Some mainboards have very nice features beyond just a simple display. * They can override this function. */ void __attribute__((weak)) mainboard_post(uint8_t value) { } #else /* This just keeps the number of #ifs to a minimum */ #define mainboard_post(x) #endif #if CONFIG_CMOS_POST DECLARE_SPIN_LOCK(cmos_post_lock) #if !defined(__PRE_RAM__) void cmos_post_log(void) { u8 code = 0; #if CONFIG_CMOS_POST_EXTRA u32 extra = 0; #endif spin_lock(&cmos_post_lock); /* Get post code from other bank */ switch (cmos_read(CMOS_POST_BANK_OFFSET)) { case CMOS_POST_BANK_0_MAGIC: code = cmos_read(CMOS_POST_BANK_1_OFFSET); #if CONFIG_CMOS_POST_EXTRA extra = cmos_read32(CMOS_POST_BANK_1_EXTRA); #endif break; case CMOS_POST_BANK_1_MAGIC: code = cmos_read(CMOS_POST_BANK_0_OFFSET); #if CONFIG_CMOS_POST_EXTRA extra = cmos_read32(CMOS_POST_BANK_0_EXTRA); #endif break; } spin_unlock(&cmos_post_lock); /* Check last post code in previous boot against normal list */ switch (code) { case POST_OS_BOOT: case POST_OS_RESUME: case POST_ENTER_ELF_BOOT: case 0: break; default: printk(BIOS_WARNING, "POST: Unexpected post code " "in previous boot: 0x%02x\n", code); #if CONFIG_ELOG elog_add_event_word(ELOG_TYPE_LAST_POST_CODE, code); #if CONFIG_CMOS_POST_EXTRA if (extra) elog_add_event_dword(ELOG_TYPE_POST_EXTRA, extra); #endif #endif } } #if CONFIG_CMOS_POST_EXTRA void post_log_extra(u32 value) { spin_lock(&cmos_post_lock); switch (cmos_read(CMOS_POST_BANK_OFFSET)) { case CMOS_POST_BANK_0_MAGIC: cmos_write32(CMOS_POST_BANK_0_EXTRA, value); break; case CMOS_POST_BANK_1_MAGIC: cmos_write32(CMOS_POST_BANK_1_EXTRA, value); break; } spin_unlock(&cmos_post_lock); } void post_log_path(struct device *dev) { if (dev) { /* Encode path into lower 3 bytes */ u32 path = dev_path_encode(dev); /* Upper byte contains the log type */ path |= CMOS_POST_EXTRA_DEV_PATH << 24; post_log_extra(path); } } void post_log_clear(void) { post_log_extra(0); } #endif /* CONFIG_CMOS_POST_EXTRA */ #endif /* !__PRE_RAM__ */ static void cmos_post_code(u8 value) { spin_lock(&cmos_post_lock); switch (cmos_read(CMOS_POST_BANK_OFFSET)) { case CMOS_POST_BANK_0_MAGIC: cmos_write(value, CMOS_POST_BANK_0_OFFSET); break; case CMOS_POST_BANK_1_MAGIC: cmos_write(value, CMOS_POST_BANK_1_OFFSET); break; } spin_unlock(&cmos_post_lock); } #endif /* CONFIG_CMOS_POST */ void post_code(uint8_t value) { #if !CONFIG_NO_POST #if CONFIG_CONSOLE_POST print_emerg("POST: 0x"); print_emerg_hex8(value); print_emerg("\n"); #endif #if CONFIG_CMOS_POST cmos_post_code(value); #endif #if CONFIG_IO_POST outb(value, CONFIG_IO_POST_PORT); #endif #endif mainboard_post(value); }