From 35cdaf24fa1b3f4fd4816726d45c750212b83daf Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Wed, 13 Aug 2014 15:28:13 -0500 Subject: Support for serial console. Change-Id: Ia1b11f68cc4be175076562b7daf0291b14df498b Origin: Google Shared Technology RTC: 97495 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/13250 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell Reviewed-by: A. Patrick Williams III --- src/usr/console/HBconfig | 4 + src/usr/console/console.C | 109 +++++++++++ src/usr/console/daemon.C | 116 ++++++++++++ src/usr/console/daemon.H | 39 ++++ src/usr/console/makefile | 33 ++++ src/usr/console/uart.C | 220 +++++++++++++++++++++++ src/usr/console/uart.H | 163 +++++++++++++++++ src/usr/console/uartconfig.C | 44 +++++ src/usr/initservice/extinitsvc/extinitsvctasks.H | 16 +- src/usr/lpc/HBconfig | 4 - src/usr/makefile | 1 + src/usr/trace/HBconfig | 5 + src/usr/trace/daemon/daemon.C | 8 + src/usr/trace/makefile | 12 +- src/usr/trace/service.C | 97 +++++++++- 15 files changed, 864 insertions(+), 7 deletions(-) create mode 100644 src/usr/console/HBconfig create mode 100644 src/usr/console/console.C create mode 100644 src/usr/console/daemon.C create mode 100644 src/usr/console/daemon.H create mode 100644 src/usr/console/makefile create mode 100644 src/usr/console/uart.C create mode 100644 src/usr/console/uart.H create mode 100644 src/usr/console/uartconfig.C delete mode 100644 src/usr/lpc/HBconfig create mode 100644 src/usr/trace/HBconfig (limited to 'src/usr') diff --git a/src/usr/console/HBconfig b/src/usr/console/HBconfig new file mode 100644 index 000000000..ee8885cbf --- /dev/null +++ b/src/usr/console/HBconfig @@ -0,0 +1,4 @@ +config CONSOLE + default n + help + Enable console support. diff --git a/src/usr/console/console.C b/src/usr/console/console.C new file mode 100644 index 000000000..74f496f93 --- /dev/null +++ b/src/usr/console/console.C @@ -0,0 +1,109 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/console/console.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] International Business Machines Corp. */ +/* [+] Google Inc. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include +#include +#include +#include +#include +#include +#include +#include "daemon.H" + +namespace CONSOLE +{ + msg_q_t g_msgq = msg_q_create(); + + void display(const char* str) + { + timespec_t time; + clock_gettime(CLOCK_MONOTONIC, &time); + + msg_t* msg = msg_allocate(); + msg->type = DISPLAY; + msg->data[0] = time.tv_sec; + msg->data[1] = time.tv_nsec; + msg->extra_data = strdup(str); + msg_send(g_msgq, msg); + } + + void displayf(const char* header, const char* format, ...) + { + va_list args; + va_start(args, format); + + vdisplayf(header, format, args); + + va_end(args); + } + + void vdisplayf(const char* header, const char* format, va_list args) + { + using Util::vasprintf; + + class OutputBuffer : public Util::ConsoleBufferInterface + { + public: + int putc(int c) + { + str.push_back(c); + return c; + } + + size_t operator()(int c) { return putc(c); } + + std::vector str; + }; + + OutputBuffer b; + + if (header) + { + while(*header) + { + b.putc(*header); + header++; + } + b.putc('|'); + } + + vasprintf(b, format, args); + b.putc('\n'); + b.putc('\0'); + + if (b.str.size()) + { + display(&b.str[0]); + } + } + + void flush() + { + msg_t* msg = msg_allocate(); + msg->type = SYNC; + msg_sendrecv(g_msgq, msg); + } + +} diff --git a/src/usr/console/daemon.C b/src/usr/console/daemon.C new file mode 100644 index 000000000..a501920ff --- /dev/null +++ b/src/usr/console/daemon.C @@ -0,0 +1,116 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/console/daemon.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] International Business Machines Corp. */ +/* [+] Google Inc. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include +#include +#include +#include +#include +#include +#include "uart.H" +#include "daemon.H" + +namespace CONSOLE +{ + extern msg_q_t g_msgq; + + /* Display characters one at a time from string. */ + void _display(const char* str) + { + + while(*str) + { + // UART uses DOS-style new lines. "\r\n" + if (*str == '\n') + { + Uart::g_device->putc('\r'); + } + + Uart::g_device->putc(*str); + + str++; + } + } + + void* consoleDaemon(void* unused) + { + // Detach and register daemon with shutdown path. + task_detach(); + INITSERVICE::registerShutdownEvent(g_msgq, SYNC, + INITSERVICE::CONSOLE_PRIORITY); + + // Create a default output UART device if there isn't already one. + // - Some devices are registered via the CONSOLE_UART_DEFINE_DEVICE + // macro and therefore don't need this. + if (NULL == Uart::g_device) + { + Uart::g_device = new Uart(); + Uart::g_device->initialize(); + } + + while(1) + { + msg_t* msg = msg_wait(g_msgq); + + switch (msg->type) + { + case DISPLAY: + { + if (NULL != msg->extra_data) + { + char timestamp[11]; + sprintf(timestamp, "%3d.%05d|", + msg->data[0], + // 5 Digits worth of ns. + (msg->data[1]*100000)/NS_PER_SEC); + _display(timestamp); + + _display( + static_cast(msg->extra_data)); + free(msg->extra_data); + } + msg_free(msg); + break; + } + + case SYNC: + { + msg_respond(g_msgq, msg); + break; + } + } + + } + + return NULL; + } + + void consoleEntryPoint(errlHndl_t& o_errl) + { + task_create(&consoleDaemon, NULL); + } +} + +TASK_ENTRY_MACRO(CONSOLE::consoleEntryPoint); diff --git a/src/usr/console/daemon.H b/src/usr/console/daemon.H new file mode 100644 index 000000000..02453a879 --- /dev/null +++ b/src/usr/console/daemon.H @@ -0,0 +1,39 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/console/daemon.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] International Business Machines Corp. */ +/* [+] Google Inc. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __CONSOLE_DAEMON_H +#define __CONSOLE_DAEMON_H + +namespace CONSOLE +{ + /** Enumeration of IPC message types to daemon. */ + enum ConsoleDaemonMessages + { + DISPLAY, //< Display a string to console. + SYNC //< Synchronization point to ensure console is flushed. + }; +} + +#endif diff --git a/src/usr/console/makefile b/src/usr/console/makefile new file mode 100644 index 000000000..8252fb17a --- /dev/null +++ b/src/usr/console/makefile @@ -0,0 +1,33 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/console/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2014 +# [+] Google Inc. +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +ROOTPATH = ../../.. +MODULE = console + +OBJS += daemon.o +OBJS += uart.o +OBJS += uartconfig.o + +include $(ROOTPATH)/config.mk diff --git a/src/usr/console/uart.C b/src/usr/console/uart.C new file mode 100644 index 000000000..385a05cd9 --- /dev/null +++ b/src/usr/console/uart.C @@ -0,0 +1,220 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/console/uart.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] International Business Machines Corp. */ +/* [+] Google Inc. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include "uart.H" +#include +#include +#include +#include +#include +#include +#include + +namespace CONSOLE +{ + void Uart::initialize() + { + using namespace UARTREGS; + + errlHndl_t l_errl = NULL; + + do + { + // Check for failure from superclass initalize call. + if (iv_failed) { break; } + + // Clear line control reg. + l_errl = writeReg(LCR, 0x00); + if (l_errl) { break; } + + // Check for existence of scratch register (and thus UART device). + { + const uint8_t value = 'h'; + uint8_t data = 0; + l_errl = writeReg(SCR, value); + if (l_errl) { break; } + l_errl = readReg(SCR, data); + if (l_errl) { break; } + + if (data != value) + { + printk("UART: Device not found.\n"); + break; + } + } + + // Reset interrupt register. + l_errl = writeReg(IER, 0); + if (l_errl) { break; } + + + // Set baud rate. + uint64_t divisor = (g_uartClock / 16) / g_uartBaud; + l_errl = writeReg(LCR, LCR_DLAB); + if (l_errl) { break; } + l_errl = writeReg(DLL, divisor & 0xff); + if (l_errl) { break; } + l_errl = writeReg(DLM, divisor >> 8); + if (l_errl) { break; } + + // Set 8N1 mode. + l_errl = writeReg(LCR, LCR_DWL8 | LCR_NOP | LCR_STP1); + if (l_errl) { break; } + + // Enable Request-to-send/Data-terminal-ready + l_errl = writeReg(MCR, MCR_RTS | MCR_DTR); + if (l_errl) { break; } + + // Clear and enable FIFOs. + l_errl = writeReg(FCR, FCR_ENF | FCR_CLFR | FCR_CLFT); + if (l_errl) { break; } + + // Found device. + printk("UART: Device initialized.\n"); + iv_initialized = true; + + } while(0); + + if (l_errl) + { + iv_failed = true; + errlCommit(l_errl, CONSOLE_COMP_ID); + } + } + + void Uart::putc(char c) + { + using namespace UARTREGS; + + errlHndl_t l_errl = NULL; + do + { + if (iv_failed || !iv_initialized) { break; } + + // Wait for transmit FIFO to have space. + { + const uint64_t DELAY_NS = 100; + const uint64_t DELAY_LOOPS = 10000; + + uint8_t data = 0; + uint64_t loops = 0; + + do + { + l_errl = readReg(LSR, data); + if (l_errl) { break; } + + // Wait for idle or error status. + if (data == LSR_BAD || (data & LSR_THRE)) + { + break; + } + nanosleep(0, DELAY_NS); + + loops++; + } while( loops < DELAY_LOOPS); + + if (l_errl) + { + printk("UART: Error state in xmit - LPC error.\n"); + iv_failed = true; + break; + } + else if (data == LSR_BAD) + { + printk("UART: Error state in xmit - bad data.\n"); + iv_failed = true; + /*@ + * @errortype + * @moduleid CONSOLE::MOD_CONSOLE_UART_PUTC + * @reasoncode CONSOLE::RC_INVALID_DATA + * @devdesc Unexpected data from LPC-UART interface. + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + CONSOLE::MOD_CONSOLE_UART_PUTC, + CONSOLE::RC_INVALID_DATA); + //@TODO: RTC:116090 - Should be BMC hardware. + l_errl->addProcedureCallout(HWAS::EPUB_PRC_LVL_SUPP, + HWAS::SRCI_PRIORITY_MED); + break; + } + else if (loops >= DELAY_LOOPS) + { + printk("UART: FIFO timeout.\n"); + iv_failed = true; + /*@ + * @errortype + * @moduleid CONSOLE::MOD_CONSOLE_UART_PUTC + * @reasoncode CONSOLE::RC_TIMEOUT + * @devdesc Timeout from LPC-UART interface. + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + CONSOLE::MOD_CONSOLE_UART_PUTC, + CONSOLE::RC_TIMEOUT); + //@TODO: RTC:116090 - Should be BMC hardware. + l_errl->addProcedureCallout(HWAS::EPUB_PRC_LVL_SUPP, + HWAS::SRCI_PRIORITY_MED); + break; + } + } + + // Write character to FIFO. + l_errl = writeReg(THR, c); + + } while(0); + + if (l_errl) + { + iv_failed = true; + errlCommit(l_errl, CONSOLE_COMP_ID); + } + return; + } + + errlHndl_t Uart::writeReg(uint64_t i_addr, uint8_t i_byte) + { + size_t len = sizeof(i_byte); + return deviceWrite(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL, + &i_byte, + len, + DEVICE_LPC_ADDRESS(LPC::TRANS_IO, + i_addr + g_uartBase)); + } + + errlHndl_t Uart::readReg(uint64_t i_addr, uint8_t& o_byte) + { + size_t len = sizeof(o_byte); + return deviceRead(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL, + static_cast(&o_byte), + len, + DEVICE_LPC_ADDRESS(LPC::TRANS_IO, + i_addr + g_uartBase)); + } + + Uart* Uart::g_device = NULL; + +} diff --git a/src/usr/console/uart.H b/src/usr/console/uart.H new file mode 100644 index 000000000..b892ec45d --- /dev/null +++ b/src/usr/console/uart.H @@ -0,0 +1,163 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/console/uart.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] International Business Machines Corp. */ +/* [+] Google Inc. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __CONSOLE_UART_H +#define __CONSOLE_UART_H + +#include + +namespace CONSOLE +{ + namespace UARTREGS + { + /** UART Register Offsets */ + enum + { + RBR = 0, ///< Recv Buffer + THR = 0, ///< Tran Holding + DLL = 0, ///< Divisor Latch LSB + IER = 1, ///< Interrupt Enable + DLM = 1, ///< Divisor Latch MSB + FCR = 2, ///< FIFO Control + IIR = 2, ///< Interrupt Identification + LCR = 3, ///< Line Control + MCR = 4, ///< Modem Control + LSR = 5, ///< Line Status + MSR = 6, ///< Modem Status + SCR = 7, ///< Scratch + }; + + /** Line Status Register (LSR) bit definitions */ + enum + { + LSR_DR = 0x01, ///< Data ready + LSR_OE = 0x02, ///< Overrun + LSR_PE = 0x04, ///< Parity error + LSR_FE = 0x08, ///< Framing error + LSR_BI = 0x10, ///< Break + LSR_THRE = 0x20, ///< Xmit holding register empty + LSR_TEMT = 0x40, ///< Xmitter empty + LSR_ERR = 0x80, ///< Error + LSR_BAD = 0xff, ///< Invalid value for LSR + }; + + /** Line Control Register (LCR) bit definitions */ + enum + { + LCR_DWL5 = 0x00, ///< Data word length: 5 bits + LCR_DWL6 = 0x01, ///< Data word length: 6 bits + LCR_DWL7 = 0x02, ///< Data word length: 7 bits + LCR_DWL8 = 0x03, ///< Data word length: 8 bits + + LCR_STP1 = 0x00, ///< 1 stop bits + LCR_STP2 = 0x04, ///< 1.5(5) or 2(6,7,8) stop bits + + LCR_NOP = 0x00, ///< No Parity + LCR_ODDP = 0x08, ///< Odd Parity + LCR_EVEP = 0x18, ///< Even Parity + LCR_HIP = 0x28, ///< High Parity + LCR_LOP = 0x38, ///< Low Parity + + LCR_DLAB = 0x80, ///< DLL access + }; + + /** Modem Control Register (MCR) bit definitions */ + enum + { + MCR_DTR = 0x01, ///< Data terminal ready + MCR_RTS = 0x02, ///< Request to send + }; + + /** FIFO Control Register (FCR) bit definitions */ + enum + { + FCR_ENF = 0x01, ///< Enable FIFOs. + FCR_CLFR = 0x02, ///< Clear Receive FIFO. + FCR_CLFT = 0x04, ///< Clear Transmit FIFO + }; + } + + /** @class Uart + * @brief Abstraction class for UART-based console operations. + */ + class Uart + { + public: + Uart() : iv_initialized(false), iv_failed(false) {}; + virtual ~Uart() {}; + + /** Display character to console. */ + virtual void putc(char c); + + /** Get character from console. */ + //virtual void getc(char& c); + + /** Perform UART-specific initialization. */ + virtual void initialize(); + + /** Pointer to console UART singleton. + * + * Should be initalized using the CONSOLE_UART_DEFINE_DEVICE macro. + */ + static Uart* g_device; + + protected: + + /** Perform write operation to UART engine. */ + virtual errlHndl_t writeReg(uint64_t i_addr, uint8_t i_byte); + /** Perform read operation to UART engine. */ + virtual errlHndl_t readReg(uint64_t i_addr, uint8_t& o_byte); + + void setFailed() { iv_failed = true; } + + private: + bool iv_initialized; + bool iv_failed; + + // Prohibit copy constructors. + Uart(const Uart&); + Uart& operator=(const Uart&); + }; + + // Static configuration constants. See uartconfig.C. + extern const uint64_t g_uartBase; + extern const uint64_t g_uartBaud; + extern const uint64_t g_uartClock; +} + +/** Helper macro to associate inherited UART device with the singleton. */ +#define CONSOLE_UART_DEFINE_DEVICE(Type) \ + class ConsoleInit##Type \ + { \ + public: \ + ConsoleInit##Type() \ + { \ + Uart::g_device = new Type(); \ + Uart::g_device->initialize(); \ + } \ + }; \ + ConsoleInit##Type __console_init_##Type; + +#endif diff --git a/src/usr/console/uartconfig.C b/src/usr/console/uartconfig.C new file mode 100644 index 000000000..e0c88f40a --- /dev/null +++ b/src/usr/console/uartconfig.C @@ -0,0 +1,44 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/console/uartconfig.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] Google Inc. */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include "uart.H" + +const uint64_t CONSOLE::g_uartBase = 0x3f8; +const uint64_t CONSOLE::g_uartBaud = 115200; +const uint64_t CONSOLE::g_uartClock = 1843200; + +/* Someone could decide to make these attributes that are accessed like: + * TARGETING::Target *sys; + * TARGETING::targetService().getTopLevelTarget(sys); + * + * g_uartBase = sys->getAttr(); + * g_uartBaud = sys->getAttr(); + * + * ( though the variables would need to be initialized via a function call + * indirection ) + * + * In order to do this, we'd have to remove this file from the object + * list and insert a new file via a config option. + */ diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H index e51865af6..19fe70a84 100644 --- a/src/usr/initservice/extinitsvc/extinitsvctasks.H +++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H @@ -68,6 +68,20 @@ const TaskInfo g_exttaskinfolist[] = { } }, + /** + * @brief console library + */ +#ifdef CONFIG_CONSOLE + { + "libconsole.so", // library name + NULL, // no function to run + { + START_TASK, // task type + EXT_IMAGE, // extended image module + } + }, +#endif + /** * @brief FSI Device Driver */ @@ -76,7 +90,7 @@ const TaskInfo g_exttaskinfolist[] = { "libfsi.so" , // taskname NULL, // no pointer to fn { - INIT_TASK, // task type + INIT_TASK, // init only EXT_IMAGE, // Extended Module } }, diff --git a/src/usr/lpc/HBconfig b/src/usr/lpc/HBconfig deleted file mode 100644 index b273a29ac..000000000 --- a/src/usr/lpc/HBconfig +++ /dev/null @@ -1,4 +0,0 @@ -config LPC_CONSOLE - default n - help - Enable the Hostboot console over the LPC bus. diff --git a/src/usr/makefile b/src/usr/makefile index 34d64fbdf..746868f18 100644 --- a/src/usr/makefile +++ b/src/usr/makefile @@ -61,5 +61,6 @@ SUBDIRS += devtree.d SUBDIRS += sbe.d SUBDIRS += gpio.d SUBDIRS += lpc.d +SUBDIRS += console.d include ${ROOTPATH}/config.mk diff --git a/src/usr/trace/HBconfig b/src/usr/trace/HBconfig new file mode 100644 index 000000000..a39695a57 --- /dev/null +++ b/src/usr/trace/HBconfig @@ -0,0 +1,5 @@ +config CONSOLE_OUTPUT_TRACE + default y if CONSOLE + depends on CONSOLE + help + Enables output of trace to console. diff --git a/src/usr/trace/daemon/daemon.C b/src/usr/trace/daemon/daemon.C index a51048128..de438b2f4 100644 --- a/src/usr/trace/daemon/daemon.C +++ b/src/usr/trace/daemon/daemon.C @@ -6,6 +6,7 @@ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2012,2014 */ +/* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -45,6 +46,8 @@ #include #include +#include +#include namespace TRACE { @@ -129,6 +132,11 @@ namespace TRACEDAEMON pruneTraceEntries(); coalescePages(); +#ifdef CONFIG_CONSOLE_OUTPUT_TRACE + // Flush console. + CONSOLE::flush(); +#endif + msg->data[0] = msg->data[1] = 0; break; } diff --git a/src/usr/trace/makefile b/src/usr/trace/makefile index 98d224201..c8df1cf38 100644 --- a/src/usr/trace/makefile +++ b/src/usr/trace/makefile @@ -5,7 +5,10 @@ # # OpenPOWER HostBoot Project # -# COPYRIGHT International Business Machines Corp. 2011,2014 +# Contributors Listed Below - COPYRIGHT 2011,2014 +# [+] Google Inc. +# [+] International Business Machines Corp. +# # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,6 +35,13 @@ OBJS += daemonif.o OBJS += debug.o OBJS += assert.o +# We need the client interfaces for console available in the base image, +# similar to the client interfaces for trace. Putting 'console.o' from the +# console component into libtrace.so instead of creating a whole new library +# for that purpose. +VPATH += ../console +OBJS += $(if $(CONFIG_CONSOLE),console.o) + SUBDIRS += daemon.d SUBDIRS += test.d SUBDIRS += runtime.d diff --git a/src/usr/trace/service.C b/src/usr/trace/service.C index 28beac950..db5ea8590 100644 --- a/src/usr/trace/service.C +++ b/src/usr/trace/service.C @@ -5,7 +5,10 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ +/* Contributors Listed Below - COPYRIGHT 2012,2014 */ +/* [+] Google Inc. */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -34,6 +37,10 @@ #include #include #include +#include +#include +#include +#include namespace TRACE { @@ -68,6 +75,15 @@ namespace TRACE } } + #ifdef CONFIG_CONSOLE_OUTPUT_TRACE + { + va_list args; + va_copy(args, i_args); + CONSOLE::vdisplayf(i_td->iv_compName, i_fmt, i_args); + va_end(args); + } + #endif + do { // Get the right buffer for this component. @@ -224,6 +240,85 @@ namespace TRACE } } + #ifdef CONFIG_CONSOLE_OUTPUT_TRACE + { + // Output binary data. + // Format is: + // ~[0x0000] 01234567 01234567 01234567 01234567 *012345689abcdef* + static size_t BINARY_FORMAT_LENGTH = 69; + + size_t pos = 0; + char* output = strdup(i_fmt); + size_t output_size = strlen(output)+1; + while(pos < i_size) + { + char bin_output[BINARY_FORMAT_LENGTH]; + + // Create length header. + size_t bin_pos = sprintf(bin_output, + "~[0x%04hx]", (uint16_t) pos); + + // Create hex representation. + for (int i =0 ; i < 16; ++i) + { + if ((i % 4) == 0) + { + bin_output[bin_pos++] = ' '; + } + if ((pos + i) < i_size) + { + sprintf(&bin_output[bin_pos], + "%02x", ((const char*)i_ptr)[pos+i]); + bin_pos += 2; + } + else + { + bin_output[bin_pos++] = ' '; + bin_output[bin_pos++] = ' '; + } + } + + for (int i = 0; i < 4; ++i) + { + bin_output[bin_pos++] = ' '; + } + bin_output[bin_pos++] = '*'; + + // Create ascii representation. + for(int i = 0; i< 16; ++i) + { + char ch = ' '; + if ((pos + i) < i_size) + { + ch = ((const char*) i_ptr)[pos+i]; + if (!isprint(ch)) + { + ch = '.'; + } + } + bin_output[bin_pos++] = ch; + } + bin_output[bin_pos++] = '*'; + bin_output[bin_pos++] = '\0'; + + // Append to output string. + output = static_cast( + realloc(output, output_size + BINARY_FORMAT_LENGTH)); + strcat(output, "\n"); + strcat(output, bin_output); + output_size += BINARY_FORMAT_LENGTH; + + pos += 16; + } + + // Output full binary dump. + CONSOLE::displayf(i_td->iv_compName, output); + free(output); + + } + #endif + + do { // Get the right buffer for this component. -- cgit v1.2.1