2008-03-20 00:56:58 +01:00
|
|
|
/*
|
|
|
|
* This file is part of the libpayload project.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008 Advanced Micro Devices, Inc.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2008-09-01 00:10:35 +02:00
|
|
|
/**
|
|
|
|
* @mainpage
|
|
|
|
*
|
2008-08-28 18:53:24 +02:00
|
|
|
* @section intro Introduction
|
|
|
|
* libpayload is a small BSD-licensed static library (a lightweight
|
|
|
|
* implementation of common and useful functions) intended to be used
|
|
|
|
* as a basis for coreboot payloads.
|
|
|
|
*
|
|
|
|
* @section example Example
|
|
|
|
* Here is an example of a very simple payload:
|
|
|
|
* @include sample/hello.c
|
|
|
|
*/
|
|
|
|
|
2008-04-11 20:01:50 +02:00
|
|
|
#ifndef _LIBPAYLOAD_H
|
|
|
|
#define _LIBPAYLOAD_H
|
2008-03-20 00:56:58 +01:00
|
|
|
|
2010-03-25 23:15:19 +01:00
|
|
|
#include <libpayload-config.h>
|
Attached patch moves functions out of the huge libpayload.h into headers
according to libc/posix traditions, to simplify porting applications to
payloads.
It also adds a couple of functions:
strcasecmp, strncasecmp, strcat, strtol, strspn, strcspn, strtok_r,
strtok, perror, exit, getpagesize
Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
Acked-by: Stefan Reinauer <stepan@coresystems.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5643 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
2010-06-24 13:16:10 +02:00
|
|
|
#include <ctype.h>
|
2013-11-23 09:38:49 +01:00
|
|
|
#include <die.h>
|
2014-07-17 19:43:15 +02:00
|
|
|
#include <endian.h>
|
2012-08-29 01:31:09 +02:00
|
|
|
#include <ipchksum.h>
|
2008-03-20 00:56:58 +01:00
|
|
|
#include <stddef.h>
|
Attached patch moves functions out of the huge libpayload.h into headers
according to libc/posix traditions, to simplify porting applications to
payloads.
It also adds a couple of functions:
strcasecmp, strncasecmp, strcat, strtol, strspn, strcspn, strtok_r,
strtok, perror, exit, getpagesize
Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
Acked-by: Stefan Reinauer <stepan@coresystems.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5643 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
2010-06-24 13:16:10 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2008-03-20 00:56:58 +01:00
|
|
|
#include <arch/types.h>
|
|
|
|
#include <arch/io.h>
|
2008-08-19 19:49:53 +02:00
|
|
|
#include <arch/virtual.h>
|
2008-03-20 02:53:30 +01:00
|
|
|
#include <sysinfo.h>
|
2008-08-04 23:00:49 +02:00
|
|
|
#include <pci.h>
|
2013-08-09 13:27:35 +02:00
|
|
|
#ifdef CONFIG_LP_LAR
|
2010-03-25 23:15:19 +01:00
|
|
|
#include <lar.h>
|
|
|
|
#endif
|
2008-03-20 00:56:58 +01:00
|
|
|
|
|
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
|
|
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
|
|
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
|
|
|
|
2015-05-23 03:18:46 +02:00
|
|
|
static inline u32 div_round_up(u32 n, u32 d) { return n + d - 1 / d; }
|
|
|
|
|
2008-04-04 01:01:23 +02:00
|
|
|
#define LITTLE_ENDIAN 1234
|
|
|
|
#define BIG_ENDIAN 4321
|
|
|
|
|
2008-04-11 22:16:24 +02:00
|
|
|
#define EXIT_SUCCESS 0
|
|
|
|
#define EXIT_FAILURE 1
|
|
|
|
|
2008-04-08 01:33:50 +02:00
|
|
|
#define RAND_MAX 0x7fffffff
|
|
|
|
|
2008-10-20 18:51:43 +02:00
|
|
|
#define MAX_ARGC_COUNT 10
|
|
|
|
|
2008-09-01 00:10:35 +02:00
|
|
|
/*
|
|
|
|
* Payload information parameters - these are used to pass information
|
|
|
|
* to the entity loading the payload.
|
|
|
|
* Usage: PAYLOAD_INFO(key, value)
|
|
|
|
* Example: PAYLOAD_INFO(name, "CoreInfo!")
|
2008-05-27 22:06:54 +02:00
|
|
|
*/
|
|
|
|
#define _pstruct(key) __pinfo_ ##key
|
|
|
|
#define PAYLOAD_INFO(key, value) \
|
|
|
|
static const char _pstruct(key)[] \
|
|
|
|
__attribute__((__used__)) \
|
|
|
|
__attribute__((section(".note.pinfo"),unused)) = #key "=" value
|
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
|
|
|
* @defgroup nvram NVRAM and RTC functions
|
|
|
|
* @{
|
|
|
|
*/
|
2008-08-29 01:10:55 +02:00
|
|
|
|
|
|
|
#define NVRAM_RTC_SECONDS 0 /**< RTC Seconds offset in CMOS */
|
|
|
|
#define NVRAM_RTC_MINUTES 2 /**< RTC Minutes offset in CMOS */
|
|
|
|
#define NVRAM_RTC_HOURS 4 /**< RTC Hours offset in CMOS */
|
|
|
|
#define NVRAM_RTC_DAY 7 /**< RTC Days offset in CMOS */
|
|
|
|
#define NVRAM_RTC_MONTH 8 /**< RTC Month offset in CMOS */
|
|
|
|
#define NVRAM_RTC_YEAR 9 /**< RTC Year offset in CMOS */
|
|
|
|
#define NVRAM_RTC_FREQ_SELECT 10 /**< RTC Update Status Register */
|
|
|
|
#define NVRAM_RTC_UIP 0x80
|
|
|
|
|
2008-09-01 00:10:35 +02:00
|
|
|
/** Broken down time structure */
|
2008-04-26 01:11:02 +02:00
|
|
|
struct tm {
|
2008-08-29 01:10:55 +02:00
|
|
|
int tm_sec; /**< Number of seconds after the minute */
|
|
|
|
int tm_min; /**< Number of minutes after the hour */
|
|
|
|
int tm_hour; /**< Number of hours past midnight */
|
|
|
|
int tm_mday; /**< The day of the month */
|
|
|
|
int tm_mon; /**< The month of the year */
|
|
|
|
int tm_year; /**< The number of years since 1900 */
|
|
|
|
int tm_wday; /**< The day of the week */
|
|
|
|
int tm_yday; /**< The number of days since January 1 */
|
|
|
|
int tm_isdst; /**< A flag indicating daylight savings time */
|
2008-04-26 01:11:02 +02:00
|
|
|
};
|
2008-03-28 00:26:40 +01:00
|
|
|
|
2008-03-31 17:17:39 +02:00
|
|
|
u8 nvram_read(u8 addr);
|
|
|
|
void nvram_write(u8 val, u8 addr);
|
2008-04-26 01:11:02 +02:00
|
|
|
int nvram_updating(void);
|
|
|
|
void rtc_read_clock(struct tm *tm);
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
|
|
|
|
2012-08-30 15:36:57 +02:00
|
|
|
/**
|
|
|
|
* @defgroup storage driver functions
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
void storage_initialize(void);
|
|
|
|
/** @} */
|
|
|
|
|
2008-09-26 20:42:40 +02:00
|
|
|
/**
|
|
|
|
* @defgroup usb USB functions
|
|
|
|
* @{
|
|
|
|
*/
|
2010-04-27 08:56:47 +02:00
|
|
|
int usb_initialize(void);
|
2011-11-04 12:06:06 +01:00
|
|
|
int usb_exit (void);
|
2008-10-16 21:20:51 +02:00
|
|
|
int usbhid_havechar(void);
|
|
|
|
int usbhid_getchar(void);
|
2008-09-26 20:42:40 +02:00
|
|
|
/** @} */
|
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
|
|
|
* @defgroup input Device functions
|
|
|
|
* @{ @}
|
|
|
|
*/
|
2008-03-28 00:26:40 +01:00
|
|
|
|
2010-03-25 19:52:24 +01:00
|
|
|
extern void (*reset_handler)(void);
|
|
|
|
int add_reset_handler(void (*new_handler)(void));
|
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
|
|
|
* @defgroup keyboard Keyboard functions
|
|
|
|
* @ingroup input
|
|
|
|
* @{
|
|
|
|
*/
|
2008-04-26 01:09:39 +02:00
|
|
|
void keyboard_init(void);
|
2013-07-27 00:31:21 +02:00
|
|
|
void keyboard_disconnect(void);
|
2008-03-20 02:53:30 +01:00
|
|
|
int keyboard_havechar(void);
|
|
|
|
unsigned char keyboard_get_scancode(void);
|
|
|
|
int keyboard_getchar(void);
|
2008-09-26 20:37:26 +02:00
|
|
|
int keyboard_set_layout(char *country);
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2008-03-20 00:56:58 +01:00
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
|
|
|
* @defgroup serial Serial functions
|
|
|
|
* @ingroup input
|
|
|
|
* @{
|
|
|
|
*/
|
2008-03-20 02:53:30 +01:00
|
|
|
void serial_init(void);
|
2013-12-04 06:25:35 +01:00
|
|
|
void serial_console_init(void);
|
2008-10-21 17:08:18 +02:00
|
|
|
void serial_putchar(unsigned int c);
|
2008-03-20 02:53:30 +01:00
|
|
|
int serial_havechar(void);
|
|
|
|
int serial_getchar(void);
|
2008-06-20 02:01:42 +02:00
|
|
|
void serial_clear(void);
|
|
|
|
void serial_start_bold(void);
|
|
|
|
void serial_end_bold(void);
|
2008-09-26 20:36:26 +02:00
|
|
|
void serial_start_reverse(void);
|
|
|
|
void serial_end_reverse(void);
|
2008-08-11 22:34:28 +02:00
|
|
|
void serial_start_altcharset(void);
|
|
|
|
void serial_end_altcharset(void);
|
2008-09-03 21:59:44 +02:00
|
|
|
void serial_set_color(short fg, short bg);
|
2008-09-26 20:36:26 +02:00
|
|
|
void serial_cursor_enable(int state);
|
2008-06-20 02:01:42 +02:00
|
|
|
void serial_set_cursor(int y, int x);
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2008-06-20 02:01:42 +02:00
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
|
|
|
* @defgroup speaker Speaker functions
|
|
|
|
* @ingroup input
|
|
|
|
* @{
|
|
|
|
*/
|
2008-04-11 20:01:50 +02:00
|
|
|
void speaker_enable(u16 freq);
|
|
|
|
void speaker_disable(void);
|
|
|
|
void speaker_tone(u16 freq, unsigned int duration);
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2008-04-11 20:01:50 +02:00
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
|
|
|
* @defgroup video Video functions
|
|
|
|
* @ingroup input
|
|
|
|
* @{
|
|
|
|
*/
|
2012-10-06 08:35:04 +02:00
|
|
|
int video_init(void);
|
2008-04-11 00:49:02 +02:00
|
|
|
int video_console_init(void);
|
2012-10-06 08:43:37 +02:00
|
|
|
void video_get_rows_cols(unsigned int *rows, unsigned int *cols);
|
2008-04-11 00:49:02 +02:00
|
|
|
void video_console_putchar(unsigned int ch);
|
|
|
|
void video_console_putc(u8 row, u8 col, unsigned int ch);
|
|
|
|
void video_console_clear(void);
|
|
|
|
void video_console_cursor_enable(int state);
|
2008-08-19 19:44:49 +02:00
|
|
|
void video_console_get_cursor(unsigned int *x, unsigned int *y, unsigned int *en);
|
|
|
|
void video_console_set_cursor(unsigned int cursorx, unsigned int cursory);
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2008-08-19 19:44:49 +02:00
|
|
|
|
2012-09-29 09:21:27 +02:00
|
|
|
/**
|
|
|
|
* @defgroup cbmem_console CBMEM memory console.
|
|
|
|
* @ingroup input
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
void cbmem_console_init(void);
|
libpayload: console: Allow output drivers to print whole strings at once
The console output driver framework in libpayload is currently built on
the putchar primitive, meaning that every driver's function gets called
one character at a time. This becomes an issue when we add drivers that
could output multiple characters at a time, but have a high constant
overhead per invocation (such as the planned GDB stub, which needs to
wrap a special frame around output strings and wait for an
acknowledgement from the server).
This patch adds a new 'write' function pointer to the
console_output_driver structure as an alternative to 'putchar'. Output
drivers need to provide at least one of the two ('write' is preferred if
available). The CBMEM console driver is ported as a proof of concept
(since it's our most performace-critical driver and should in theory
benefit the most from less function pointer invocations, although it's
probably still negligible compared to the big sprawling mess that is
printf()).
Even with this fix, the problem remains that printf() was written with
the putchar primitive in mind. Even though normal text already contains
an optimization to allow multiple characters at a time, almost all
formatting directives cause their output (including things like
padding whitespace) to be putchar()ed one character at a time.
Therefore, this patch reworks parts of the output code (especially
number printing) to all but remove that inefficiency (directives still
invoke an extra write() call, but at least not one per character). Since
I'm touching printf() core code anyway, I also tried to salvage what I
could from that weird, broken "return negative on error" code path (not
that any of our current output drivers can trigger it anyway).
A final consequence of this patch is that the responsibility to prepend
line feeds with carriage returns is moved into the output driver
implementations. Doing this only makes sense for drivers with explicit
cursor position control (i.e. serial or video), and things like the
CBMEM console that appears like a normal file to the system really have
no business containing carriage returns (we don't want people to
accidentally associate us with Windows, now, do we?).
BUG=chrome-os-partner:18390
TEST=Made sure video and CBMEM console still look good, tried printf()
with as many weird edge-case strings as I could find and compared serial
output as well as sprintf() return value.
Original-Change-Id: Ie05ae489332a0103461620f5348774b6d4afd91a
Original-Signed-off-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/196384
Original-Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Original-Reviewed-by: David Hendricks <dhendrix@chromium.org>
(cherry picked from commit ab1ef0c07736fe1aa3e0baaf02d258731e6856c0)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I78f5aedf6d0c3665924995cdab691ee0162de404
Reviewed-on: http://review.coreboot.org/7880
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2014-04-18 05:00:20 +02:00
|
|
|
void cbmem_console_write(const void *buffer, size_t count);
|
2012-09-29 09:21:27 +02:00
|
|
|
/** @} */
|
|
|
|
|
2008-08-19 19:44:49 +02:00
|
|
|
/* drivers/option.c */
|
2012-01-16 10:14:24 +01:00
|
|
|
struct nvram_accessor {
|
|
|
|
u8 (*read)(u8 reg);
|
|
|
|
void (*write)(u8 val, u8 reg);
|
|
|
|
};
|
|
|
|
|
2012-02-02 15:51:29 +01:00
|
|
|
extern u8 *mem_accessor_base;
|
|
|
|
extern struct nvram_accessor *use_nvram, *use_mem;
|
2012-01-16 10:14:24 +01:00
|
|
|
|
|
|
|
struct cb_cmos_option_table *get_system_option_table(void);
|
2012-01-16 15:03:11 +01:00
|
|
|
int options_checksum_valid(const struct nvram_accessor *nvram);
|
2012-01-16 10:14:24 +01:00
|
|
|
void fix_options_checksum_with(const struct nvram_accessor *nvram);
|
2010-08-17 12:14:50 +02:00
|
|
|
void fix_options_checksum(void);
|
2012-09-24 20:06:27 +02:00
|
|
|
|
2012-01-16 15:39:57 +01:00
|
|
|
struct cb_cmos_entries *first_cmos_entry(struct cb_cmos_option_table *option_table);
|
|
|
|
struct cb_cmos_entries *next_cmos_entry(struct cb_cmos_entries *cur);
|
2012-09-24 20:06:27 +02:00
|
|
|
|
|
|
|
struct cb_cmos_enums *first_cmos_enum(struct cb_cmos_option_table *option_table);
|
|
|
|
struct cb_cmos_enums *next_cmos_enum(struct cb_cmos_enums *cmos_enum);
|
|
|
|
struct cb_cmos_enums *first_cmos_enum_of_id(struct cb_cmos_option_table *option_table, int id);
|
|
|
|
struct cb_cmos_enums *next_cmos_enum_of_id(struct cb_cmos_enums *cmos_enum, int id);
|
|
|
|
|
2012-02-17 12:02:47 +01:00
|
|
|
int get_option_with(const struct nvram_accessor *nvram, struct cb_cmos_option_table *option_table, void *dest, const char *name);
|
|
|
|
int get_option_from(struct cb_cmos_option_table *option_table, void *dest, const char *name);
|
|
|
|
int get_option(void *dest, const char *name);
|
|
|
|
int set_option_with(const struct nvram_accessor *nvram, struct cb_cmos_option_table *option_table, const void *value, const char *name);
|
|
|
|
int set_option(const void *value, const char *name);
|
|
|
|
int get_option_as_string(const struct nvram_accessor *nvram, struct cb_cmos_option_table *option_table, char **dest, const char *name);
|
|
|
|
int set_option_from_string(const struct nvram_accessor *nvram, struct cb_cmos_option_table *option_table, const char *value, const char *name);
|
2008-03-20 02:53:30 +01:00
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
|
|
|
* @defgroup console Console functions
|
|
|
|
* @{
|
|
|
|
*/
|
2014-01-14 02:45:54 +01:00
|
|
|
typedef enum {
|
|
|
|
CONSOLE_INPUT_TYPE_UNKNOWN = 0,
|
|
|
|
CONSOLE_INPUT_TYPE_USB,
|
|
|
|
} console_input_type;
|
|
|
|
|
2008-03-20 02:53:30 +01:00
|
|
|
void console_init(void);
|
libpayload: console: Allow output drivers to print whole strings at once
The console output driver framework in libpayload is currently built on
the putchar primitive, meaning that every driver's function gets called
one character at a time. This becomes an issue when we add drivers that
could output multiple characters at a time, but have a high constant
overhead per invocation (such as the planned GDB stub, which needs to
wrap a special frame around output strings and wait for an
acknowledgement from the server).
This patch adds a new 'write' function pointer to the
console_output_driver structure as an alternative to 'putchar'. Output
drivers need to provide at least one of the two ('write' is preferred if
available). The CBMEM console driver is ported as a proof of concept
(since it's our most performace-critical driver and should in theory
benefit the most from less function pointer invocations, although it's
probably still negligible compared to the big sprawling mess that is
printf()).
Even with this fix, the problem remains that printf() was written with
the putchar primitive in mind. Even though normal text already contains
an optimization to allow multiple characters at a time, almost all
formatting directives cause their output (including things like
padding whitespace) to be putchar()ed one character at a time.
Therefore, this patch reworks parts of the output code (especially
number printing) to all but remove that inefficiency (directives still
invoke an extra write() call, but at least not one per character). Since
I'm touching printf() core code anyway, I also tried to salvage what I
could from that weird, broken "return negative on error" code path (not
that any of our current output drivers can trigger it anyway).
A final consequence of this patch is that the responsibility to prepend
line feeds with carriage returns is moved into the output driver
implementations. Doing this only makes sense for drivers with explicit
cursor position control (i.e. serial or video), and things like the
CBMEM console that appears like a normal file to the system really have
no business containing carriage returns (we don't want people to
accidentally associate us with Windows, now, do we?).
BUG=chrome-os-partner:18390
TEST=Made sure video and CBMEM console still look good, tried printf()
with as many weird edge-case strings as I could find and compared serial
output as well as sprintf() return value.
Original-Change-Id: Ie05ae489332a0103461620f5348774b6d4afd91a
Original-Signed-off-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/196384
Original-Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Original-Reviewed-by: David Hendricks <dhendrix@chromium.org>
(cherry picked from commit ab1ef0c07736fe1aa3e0baaf02d258731e6856c0)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I78f5aedf6d0c3665924995cdab691ee0162de404
Reviewed-on: http://review.coreboot.org/7880
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2014-04-18 05:00:20 +02:00
|
|
|
void console_write(const void *buffer, size_t count);
|
2008-10-21 17:08:18 +02:00
|
|
|
int putchar(unsigned int c);
|
2008-03-20 02:53:30 +01:00
|
|
|
int puts(const char *s);
|
|
|
|
int havekey(void);
|
|
|
|
int getchar(void);
|
2008-04-09 01:21:33 +02:00
|
|
|
int getchar_timeout(int *ms);
|
2014-01-14 02:45:54 +01:00
|
|
|
console_input_type last_key_input_type(void);
|
2008-03-20 02:53:30 +01:00
|
|
|
|
2008-03-20 00:56:58 +01:00
|
|
|
extern int last_putchar;
|
|
|
|
|
2008-10-21 17:08:18 +02:00
|
|
|
struct console_input_driver;
|
|
|
|
struct console_input_driver {
|
|
|
|
struct console_input_driver *next;
|
|
|
|
int (*havekey) (void);
|
|
|
|
int (*getchar) (void);
|
2014-01-14 02:45:54 +01:00
|
|
|
console_input_type input_type;
|
2008-10-21 17:08:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct console_output_driver;
|
|
|
|
struct console_output_driver {
|
|
|
|
struct console_output_driver *next;
|
|
|
|
void (*putchar) (unsigned int);
|
libpayload: console: Allow output drivers to print whole strings at once
The console output driver framework in libpayload is currently built on
the putchar primitive, meaning that every driver's function gets called
one character at a time. This becomes an issue when we add drivers that
could output multiple characters at a time, but have a high constant
overhead per invocation (such as the planned GDB stub, which needs to
wrap a special frame around output strings and wait for an
acknowledgement from the server).
This patch adds a new 'write' function pointer to the
console_output_driver structure as an alternative to 'putchar'. Output
drivers need to provide at least one of the two ('write' is preferred if
available). The CBMEM console driver is ported as a proof of concept
(since it's our most performace-critical driver and should in theory
benefit the most from less function pointer invocations, although it's
probably still negligible compared to the big sprawling mess that is
printf()).
Even with this fix, the problem remains that printf() was written with
the putchar primitive in mind. Even though normal text already contains
an optimization to allow multiple characters at a time, almost all
formatting directives cause their output (including things like
padding whitespace) to be putchar()ed one character at a time.
Therefore, this patch reworks parts of the output code (especially
number printing) to all but remove that inefficiency (directives still
invoke an extra write() call, but at least not one per character). Since
I'm touching printf() core code anyway, I also tried to salvage what I
could from that weird, broken "return negative on error" code path (not
that any of our current output drivers can trigger it anyway).
A final consequence of this patch is that the responsibility to prepend
line feeds with carriage returns is moved into the output driver
implementations. Doing this only makes sense for drivers with explicit
cursor position control (i.e. serial or video), and things like the
CBMEM console that appears like a normal file to the system really have
no business containing carriage returns (we don't want people to
accidentally associate us with Windows, now, do we?).
BUG=chrome-os-partner:18390
TEST=Made sure video and CBMEM console still look good, tried printf()
with as many weird edge-case strings as I could find and compared serial
output as well as sprintf() return value.
Original-Change-Id: Ie05ae489332a0103461620f5348774b6d4afd91a
Original-Signed-off-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/196384
Original-Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Original-Reviewed-by: David Hendricks <dhendrix@chromium.org>
(cherry picked from commit ab1ef0c07736fe1aa3e0baaf02d258731e6856c0)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I78f5aedf6d0c3665924995cdab691ee0162de404
Reviewed-on: http://review.coreboot.org/7880
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2014-04-18 05:00:20 +02:00
|
|
|
void (*write) (const void *, size_t);
|
2008-10-21 17:08:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
void console_add_output_driver(struct console_output_driver *out);
|
|
|
|
void console_add_input_driver(struct console_input_driver *in);
|
2014-06-03 05:13:51 +02:00
|
|
|
int console_remove_output_driver(void *function);
|
2008-10-21 17:08:18 +02:00
|
|
|
|
2008-03-20 00:56:58 +01:00
|
|
|
#define havechar havekey
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2008-03-20 00:56:58 +01:00
|
|
|
|
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
2008-09-01 00:10:35 +02:00
|
|
|
* @defgroup exec Execution functions
|
2008-08-28 18:53:24 +02:00
|
|
|
* @{
|
|
|
|
*/
|
2008-05-20 22:10:49 +02:00
|
|
|
int exec(long addr, int argc, char **argv);
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2008-05-20 22:10:49 +02:00
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
2008-09-01 00:10:35 +02:00
|
|
|
* @defgroup misc Misc functions
|
2008-08-28 18:53:24 +02:00
|
|
|
* @{
|
|
|
|
*/
|
2008-03-28 00:26:40 +01:00
|
|
|
int bcd2dec(int b);
|
|
|
|
int dec2bcd(int d);
|
2008-04-11 20:38:04 +02:00
|
|
|
int abs(int j);
|
|
|
|
long int labs(long int j);
|
|
|
|
long long int llabs(long long int j);
|
|
|
|
u8 bin2hex(u8 b);
|
|
|
|
u8 hex2bin(u8 h);
|
2014-03-24 00:42:36 +01:00
|
|
|
void hexdump(const void *memory, size_t length);
|
2008-09-01 00:10:35 +02:00
|
|
|
void fatal(const char *msg) __attribute__ ((noreturn));
|
lib: Unify log2() and related functions
This patch adds a few bit counting functions that are commonly needed
for certain register calculations. We previously had a log2()
implementation already, but it was awkwardly split between some C code
that's only available in ramstage and an optimized x86-specific
implementation in pre-RAM that prevented other archs from pulling it
into earlier stages.
Using __builtin_clz() as the baseline allows GCC to inline optimized
assembly for most archs (including CLZ on ARM/ARM64 and BSR on x86), and
to perform constant-folding if possible. What was previously named log2f
on pre-RAM x86 is now ffs, since that's the standard name for that
operation and I honestly don't have the slightest idea how it could've
ever ended up being called log2f (which in POSIX is 'binary(2) LOGarithm
with Float result, whereas the Find First Set operation has no direct
correlation to logarithms that I know of). Make ffs result 0-based
instead of the POSIX standard's 1-based since that is consistent with
clz, log2 and the former log2f, and generally closer to what you want
for most applications (a value that can directly be used as a shift to
reach the found bit). Call it __ffs() instead of ffs() to avoid problems
when importing code, since that's what Linux uses for the 0-based
operation.
CQ-DEPEND=CL:273023
BRANCH=None
BUG=None
TEST=Built on Big, Falco, Jerry, Oak and Urara. Compared old and new
log2() and __ffs() results on Falco for a bunch of test values.
Change-Id: I599209b342059e17b3130621edb6b6bbeae26876
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 3701a16ae944ecff9c54fa9a50d28015690fcb2f
Original-Change-Id: I60f7cf893792508188fa04d088401a8bca4b4af6
Original-Signed-off-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/273008
Original-Reviewed-by: Patrick Georgi <pgeorgi@chromium.org>
Reviewed-on: http://review.coreboot.org/10394
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2015-05-23 01:26:40 +02:00
|
|
|
|
|
|
|
/* Count Leading Zeroes: clz(0) == 32, clz(0xf) == 28, clz(1 << 31) == 0 */
|
|
|
|
static inline int clz(u32 x) { return x ? __builtin_clz(x) : sizeof(x) * 8; }
|
|
|
|
/* Integer binary logarithm (rounding down): log2(0) == -1, log2(5) == 2 */
|
|
|
|
static inline int log2(u32 x) { return sizeof(x) * 8 - clz(x) - 1; }
|
|
|
|
/* Find First Set: __ffs(0xf) == 0, __ffs(0) == -1, __ffs(1 << 31) == 31 */
|
|
|
|
static inline int __ffs(u32 x) { return log2(x & (u32)(-(s32)x)); }
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2008-03-28 00:26:40 +01:00
|
|
|
|
2008-04-09 01:38:15 +02:00
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
2008-09-01 00:10:35 +02:00
|
|
|
* @defgroup hash Hashing functions
|
2008-08-28 18:53:24 +02:00
|
|
|
* @{
|
|
|
|
*/
|
2008-04-04 01:01:23 +02:00
|
|
|
#define SHA1_BLOCK_LENGTH 64
|
|
|
|
#define SHA1_DIGEST_LENGTH 20
|
|
|
|
typedef struct {
|
|
|
|
u32 state[5];
|
|
|
|
u64 count;
|
|
|
|
u8 buffer[SHA1_BLOCK_LENGTH];
|
|
|
|
} SHA1_CTX;
|
|
|
|
void SHA1Init(SHA1_CTX *context);
|
|
|
|
void SHA1Transform(u32 state[5], const u8 buffer[SHA1_BLOCK_LENGTH]);
|
|
|
|
void SHA1Update(SHA1_CTX *context, const u8 *data, size_t len);
|
2011-04-21 18:57:16 +02:00
|
|
|
void SHA1Pad(SHA1_CTX *context);
|
2008-04-04 01:01:23 +02:00
|
|
|
void SHA1Final(u8 digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context);
|
|
|
|
u8 *sha1(const u8 *data, size_t len, u8 *buf);
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2008-04-04 01:01:23 +02:00
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
2008-09-01 00:10:35 +02:00
|
|
|
* @defgroup time Time functions
|
2008-08-28 18:53:24 +02:00
|
|
|
* @{
|
|
|
|
*/
|
2008-08-29 01:10:55 +02:00
|
|
|
|
2008-09-01 00:10:35 +02:00
|
|
|
/** System time structure */
|
2008-04-26 01:11:02 +02:00
|
|
|
struct timeval {
|
2008-08-29 01:10:55 +02:00
|
|
|
time_t tv_sec; /**< Seconds */
|
|
|
|
suseconds_t tv_usec; /**< Microseconds */
|
2008-04-26 01:11:02 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
int gettimeofday(struct timeval *tv, void *tz);
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2008-04-26 01:11:02 +02:00
|
|
|
|
2013-08-09 13:27:35 +02:00
|
|
|
#ifdef CONFIG_LP_LAR
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
2008-09-01 00:10:35 +02:00
|
|
|
* @defgroup lar LAR functions
|
2008-08-28 18:53:24 +02:00
|
|
|
* @{
|
|
|
|
*/
|
2008-08-29 01:10:55 +02:00
|
|
|
|
2008-09-01 00:10:35 +02:00
|
|
|
/** LAR file header */
|
2008-05-07 22:34:02 +02:00
|
|
|
struct LAR {
|
2008-09-01 00:10:35 +02:00
|
|
|
void *start; /**< Location of the LAR in memory */
|
2008-08-29 01:10:55 +02:00
|
|
|
int cindex; /**< Next file to return in readlar() */
|
|
|
|
int count; /**< Number of entries in the header cache */
|
|
|
|
int alloc; /**< Number of slots in the header cache */
|
|
|
|
int eof; /**< Last entry in the header cache */
|
|
|
|
void **headers; /**< Pointer to the header cache */
|
2008-05-07 22:34:02 +02:00
|
|
|
};
|
|
|
|
|
2008-09-01 00:10:35 +02:00
|
|
|
/** A structure representing the next LAR entry */
|
2008-05-07 22:34:02 +02:00
|
|
|
struct larent {
|
2008-08-29 01:10:55 +02:00
|
|
|
u8 name[LAR_MAX_PATHLEN]; /**< The name of the next LAR entry */
|
2008-05-07 22:34:02 +02:00
|
|
|
};
|
|
|
|
|
2008-09-01 00:10:35 +02:00
|
|
|
/** A structure containing information about a LAR file */
|
2008-05-07 22:34:02 +02:00
|
|
|
struct larstat {
|
2008-08-29 01:10:55 +02:00
|
|
|
u32 len; /**< Length of the file in the LAR */
|
|
|
|
u32 reallen; /**< Length of the uncompressed file */
|
|
|
|
u32 checksum; /**< Checksum of the uncompressed file */
|
|
|
|
u32 compchecksum; /**< Checksum of the compressed file in the LAR */
|
|
|
|
u32 offset; /**< Offset of the file in the LAR */
|
|
|
|
u32 compression; /**< Compression type of the file */
|
|
|
|
u64 entry; /**< Entry point of the file for executables */
|
|
|
|
u64 loadaddress; /**< Address in memory to put the uncompressed file */
|
2008-05-07 22:34:02 +02:00
|
|
|
};
|
|
|
|
|
2008-09-01 00:10:35 +02:00
|
|
|
/** A structure representing a LAR file */
|
2008-05-07 22:34:02 +02:00
|
|
|
struct LFILE {
|
2008-08-29 01:10:55 +02:00
|
|
|
struct LAR *lar; /**< Pointer to the LAR struct */
|
|
|
|
struct lar_header *header; /**< Pointer to the header struct */
|
|
|
|
u32 size; /**< Size of the file */
|
|
|
|
void *start; /**< Start of the file in memory */
|
|
|
|
u32 offset; /**< Offset of the file in the LAR */
|
2008-05-07 22:34:02 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct LAR *openlar(void *addr);
|
|
|
|
int closelar(struct LAR *lar);
|
|
|
|
struct larent *readlar(struct LAR *lar);
|
|
|
|
void rewindlar(struct LAR *lar);
|
|
|
|
int larstat(struct LAR *lar, const char *path, struct larstat *buf);
|
2008-05-20 22:09:42 +02:00
|
|
|
void *larfptr(struct LAR *lar, const char *filename);
|
2008-05-27 21:57:53 +02:00
|
|
|
int lfverify(struct LAR *lar, const char *filename);
|
2008-09-01 00:10:35 +02:00
|
|
|
struct LFILE *lfopen(struct LAR *lar, const char *filename);
|
2008-05-07 22:34:02 +02:00
|
|
|
int lfread(void *ptr, size_t size, size_t nmemb, struct LFILE *stream);
|
|
|
|
|
|
|
|
int lfseek(struct LFILE *stream, long offset, int whence);
|
|
|
|
int lfclose(struct LFILE *file);
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2010-03-25 23:15:19 +01:00
|
|
|
#endif
|
2008-11-11 20:51:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @defgroup info System information functions
|
|
|
|
* This module contains functions that return information about the system
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
int sysinfo_have_multiboot(unsigned long *addr);
|
|
|
|
/** @} */
|
2008-05-07 22:34:02 +02:00
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
2008-09-01 00:10:35 +02:00
|
|
|
* @defgroup arch Architecture specific functions
|
|
|
|
* This module contains global architecture specific functions.
|
2008-08-29 01:12:22 +02:00
|
|
|
* All architectures are expected to define these functions.
|
2008-08-28 18:53:24 +02:00
|
|
|
* @{
|
|
|
|
*/
|
2008-03-20 02:53:30 +01:00
|
|
|
int get_coreboot_info(struct sysinfo_t *info);
|
2008-10-20 18:51:43 +02:00
|
|
|
int get_multiboot_info(struct sysinfo_t *info);
|
2014-09-11 23:20:35 +02:00
|
|
|
void *get_cb_header_ptr(void);
|
2008-03-20 00:56:58 +01:00
|
|
|
|
2011-12-24 02:33:05 +01:00
|
|
|
int lib_get_sysinfo(void);
|
2014-09-05 00:21:12 +02:00
|
|
|
void lib_sysinfo_get_memranges(struct memrange **ranges,
|
|
|
|
uint64_t *nranges);
|
2008-03-20 00:56:58 +01:00
|
|
|
|
2013-02-23 01:38:53 +01:00
|
|
|
/* Timer functions. */
|
|
|
|
/* Defined by each architecture. */
|
2008-03-20 02:53:30 +01:00
|
|
|
unsigned int get_cpu_speed(void);
|
2013-02-23 01:38:53 +01:00
|
|
|
uint64_t timer_hz(void);
|
|
|
|
uint64_t timer_raw_value(void);
|
2013-12-07 08:30:10 +01:00
|
|
|
uint64_t timer_us(uint64_t base);
|
2013-02-23 01:38:53 +01:00
|
|
|
/* Generic. */
|
2008-03-20 02:53:30 +01:00
|
|
|
void ndelay(unsigned int n);
|
2008-04-11 00:50:44 +02:00
|
|
|
void udelay(unsigned int n);
|
2008-03-20 02:53:30 +01:00
|
|
|
void mdelay(unsigned int n);
|
|
|
|
void delay(unsigned int n);
|
2008-03-20 00:56:58 +01:00
|
|
|
|
2008-08-28 18:53:24 +02:00
|
|
|
/**
|
2008-09-01 00:10:35 +02:00
|
|
|
* @defgroup readline Readline functions
|
|
|
|
* This interface provides a simple implementation of the standard readline()
|
|
|
|
* and getline() functions. They read a line of input from the console.
|
2008-08-28 18:53:24 +02:00
|
|
|
* @{
|
|
|
|
*/
|
2008-09-01 00:10:35 +02:00
|
|
|
char *readline(const char *prompt);
|
2008-08-23 14:17:46 +02:00
|
|
|
int getline(char *buffer, int len);
|
2008-08-28 18:53:24 +02:00
|
|
|
/** @} */
|
2008-03-20 00:56:58 +01:00
|
|
|
|
2014-05-23 23:37:10 +02:00
|
|
|
/* Defined in arch/${ARCH}/selfboot.c */
|
|
|
|
void selfboot(void *entry);
|
|
|
|
|
libpayload: Add remote GDB support
This patch adds the ability to attach a GDB host through the UART to a
running payload. Libpayload implements a small stub that can parse and
respond to the GDB remote protocol and provide the required primitives
(reading/writing registers/memory, etc.) to allow GDB to control
execution.
The goal of this implementation is to be as small and uninvasive as
possible. It implements only the minimum amount of primitives required,
and relies on GDB's impressive workaround capabilities (such as
emulating breakpoints by temporarily replacing instructions) for the
more complicated features. This way, a relatively tiny amount of code on
the firmware side opens a vast range of capabilities to the user, not
just in debugging but also in remote-controlling the firmware to change
its behavior (e.g. through GDBs ability to modify variables and call
functions).
By default, a system with the REMOTEGDB Kconfig will only trap into GDB
when executing halt() (including the calls from die_if(), assert(), and
exception handlers). In addition, payloads can manually call gdb_enter()
if desired. It will print a final "Ready for GDB connection." on the
serial, detach the normal serial output driver and wait for the commands
that GDB starts sending on attach.
Based on original implementation by Gabe Black <gabeblack@chromium.org>.
BUG=chrome-os-partner:18390
TEST=Boot a GDB enabled image in recovery mode (or get it to hit a
halt()), close your terminal, execute '<toolchain>-gdb --symbols
/build/<board>/firmware/depthcharge_gdb/depthcharge.elf --directory
~/trunk/src/third_party/coreboot/payloads/libpayload --directory
~/trunk/src/platform/depthcharge --directory
~/trunk/src/platform/vboot_reference --ex "target remote
<cpu_uart_pty>"' and behold the magic.
(You can also SIGSTOP your terminal's parent shell and the terminal
itself, and SIGCONT them in reverse order after GDB exits. More
convenient wrapper tools to do all this automatically coming soon.)
Original-Change-Id: Ib440d1804126cdfdac4a8801f5015b4487e25269
Original-Signed-off-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/202563
Original-Reviewed-by: Stefan Reinauer <reinauer@chromium.org>
(cherry picked from commit 9c4a642c7be2faf122fef39bdfaddd64aec68b77)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I9238b4eb19d3ab2c98e4e1c5946cd7d252ca3c3b
Reviewed-on: http://review.coreboot.org/8119
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2014-05-15 20:57:38 +02:00
|
|
|
/* Enter remote GDB mode. Will initialize connection if not already up. */
|
|
|
|
void gdb_enter(void);
|
|
|
|
/* Disconnect existing GDB connection if one exists. */
|
|
|
|
void gdb_exit(s8 exit_status);
|
|
|
|
|
2008-03-20 00:56:58 +01:00
|
|
|
#endif
|