New commands cbmemc, lscoreboot, coreboot_boottime to inspect

coreboot tables content. Support for cbmemc.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-03-20 17:13:31 +01:00
parent ef8810e9f3
commit cc19857a2a
10 changed files with 446 additions and 5 deletions

View File

@ -1,3 +1,8 @@
2013-03-20 Vladimir Serbinenko <phcoder@gmail.com>
New commands cbmemc, lscoreboot, coreboot_boottime to inspect
coreboot tables content. Support for cbmemc.
2013-03-20 Vladimir Serbinenko <phcoder@gmail.com>
Fix a conflict between ports structures with 2 controllers of

View File

@ -110,6 +110,7 @@ endif
if COND_i386_coreboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/coreboot/lbio.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h
endif

View File

@ -518,6 +518,24 @@ module = {
enable = x86;
};
module = {
name = cbtime;
common = commands/i386/coreboot/cb_timestamps.c;
enable = i386_coreboot;
};
module = {
name = cbls;
common = commands/i386/coreboot/cbls.c;
enable = i386_coreboot;
};
module = {
name = cbmemc;
common = term/i386/coreboot/cbmemc.c;
enable = i386_coreboot;
};
module = {
name = regexp;
common = commands/regexp.c;

View File

@ -0,0 +1,118 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB 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, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/i386/coreboot/lbio.h>
#include <grub/i386/tsc.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint32_t
tsc2ms (grub_uint64_t tsc)
{
grub_uint64_t ah = tsc >> 32;
grub_uint64_t al = tsc & 0xffffffff;
return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate;
}
static const char *descs[] = {
[1] = "romstage",
[2] = "before RAM init",
[3] = "after RAM init",
[4] = "end of romstage",
[8] = "start of RAM copy",
[9] = "end of RAM copy",
[10] = "start of ramstage",
[30] = "device enumerate",
[40] = "device configure",
[50] = "device enable",
[60] = "device initialize",
[70] = "device done",
[75] = "CBMEM POST",
[80] = "writing tables",
[90] = "loading payload",
[98] = "wake jump",
[99] = "selfboot jump",
};
static int
iterate_linuxbios_table (grub_linuxbios_table_item_t table_item,
void *data)
{
int *available = data;
grub_uint64_t last_tsc = 0;
struct grub_linuxbios_timestamp_table *ts_table;
unsigned i;
if (table_item->tag != GRUB_LINUXBIOS_MEMBER_TIMESTAMPS)
return 0;
*available = 1;
ts_table = (struct grub_linuxbios_timestamp_table *) (grub_addr_t)
*(grub_uint64_t *) (table_item + 1);
for (i = 0; i < ts_table->used; i++)
{
grub_uint32_t tmabs = tsc2ms (ts_table->entries[i].tsc);
grub_uint32_t tmrel = tsc2ms (ts_table->entries[i].tsc - last_tsc);
last_tsc = ts_table->entries[i].tsc;
grub_printf ("%3d.%03ds %2d.%03ds %02d %s\n",
tmabs / 1000, tmabs % 1000, tmrel / 1000, tmrel % 1000,
ts_table->entries[i].id,
(ts_table->entries[i].id < ARRAY_SIZE (descs)
&& descs[ts_table->entries[i].id])
? descs[ts_table->entries[i].id] : "");
}
return 1;
}
static grub_err_t
grub_cmd_coreboot_boottime (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
int available = 0;
grub_linuxbios_table_iterate (iterate_linuxbios_table, &available);
if (!available)
{
grub_puts_ (N_("No boot time statistics is available\n"));
return 0;
}
return 0;
}
static grub_command_t cmd_boottime;
GRUB_MOD_INIT(cbtime)
{
cmd_boottime =
grub_register_command ("coreboot_boottime", grub_cmd_coreboot_boottime,
0, N_("Get coreboot boot time statistics."));
}
GRUB_MOD_FINI(cbtime)
{
grub_unregister_command (cmd_boottime);
}

View File

@ -0,0 +1,128 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB 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, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/i386/coreboot/lbio.h>
#include <grub/i386/tsc.h>
GRUB_MOD_LICENSE ("GPLv3+");
static const char *console_descs[] = {
"8250 UART",
"VGA",
"BTEXT",
"CBMEM console",
"SROM",
"EHCI debug",
"memory-mapped 8250 UART"
};
static const char *descs[] = {
[GRUB_LINUXBIOS_MEMBER_MEMORY] = "memory map (`lsmmap' to list)",
[GRUB_LINUXBIOS_MEMBER_MAINBOARD] = "mainboard",
[4] = "version",
[5] = "extra version",
[6] = "build",
[7] = "compile time",
[8] = "compile by",
[9] = "compile host",
[0xa] = "compile domain",
[0xb] = "compiler",
[0xc] = "linker",
[0xd] = "assembler",
[0xf] = "serial",
[GRUB_LINUXBIOS_MEMBER_CONSOLE] = "console",
[0x12] = "framebuffer",
[0x13] = "GPIO",
[0x15] = "VDAT",
[GRUB_LINUXBIOS_MEMBER_TIMESTAMPS] = "timestamps (`coreboot_boottime' to list)",
[GRUB_LINUXBIOS_MEMBER_CBMEMC] = "CBMEM console (`cbmem' to list)",
[0x18] = "MRC cache",
[0x19] = "VBNV",
[0xc8] = "CMOS option table",
[0xc9] = "CMOS option",
[0xca] = "CMOS option enum",
[0xcb] = "CMOS option defaults",
[0xcc] = "CMOS checksum",
};
static int
iterate_linuxbios_table (grub_linuxbios_table_item_t table_item,
void *data __attribute__ ((unused)))
{
if (table_item->tag < ARRAY_SIZE (descs) && descs[table_item->tag])
grub_printf ("tag=%02x size=%02x %s",
table_item->tag, table_item->size, descs[table_item->tag]);
else
grub_printf ("tag=%02x size=%02x",
table_item->tag, table_item->size);
switch (table_item->tag)
{
case GRUB_LINUXBIOS_MEMBER_MAINBOARD:
{
struct grub_linuxbios_mainboard *mb;
mb = (struct grub_linuxbios_mainboard *) (table_item + 1);
grub_printf (": vendor=`%s' part_number=`%s'",
mb->strings + mb->vendor,
mb->strings + mb->part_number);
break;
}
case 0x04 ... 0x0d:
grub_printf (": `%s'", (char *) (table_item + 1));
break;
case GRUB_LINUXBIOS_MEMBER_CONSOLE:
{
grub_uint16_t *val = (grub_uint16_t *) (table_item + 1);
grub_printf (": id=%d", *val);
if (*val < ARRAY_SIZE (console_descs)
&& console_descs[*val])
grub_printf (" %s", console_descs[*val]);
}
}
grub_printf ("\n");
return 0;
}
static grub_err_t
grub_cmd_lscoreboot (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
grub_linuxbios_table_iterate (iterate_linuxbios_table, 0);
return 0;
}
static grub_command_t cmd;
GRUB_MOD_INIT(cbls)
{
cmd =
grub_register_command ("lscoreboot", grub_cmd_lscoreboot,
0, N_("List coreboot tables."));
}
GRUB_MOD_FINI(cbls)
{
grub_unregister_command (cmd);
}

View File

@ -32,7 +32,7 @@ check_signature (grub_linuxbios_table_header_t tbl_header)
return 0;
}
static grub_err_t
grub_err_t
grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t,
void *),
void *hook_data)

View File

@ -979,20 +979,21 @@ grub_ucs4_count_lines (const grub_uint32_t * str,
}
void
grub_xputs_normal (const char *str)
grub_xnputs (const char *str, grub_size_t msg_len)
{
grub_uint32_t *unicode_str = NULL, *unicode_last_position;
int backlog = 0;
grub_term_output_t term;
grub_error_push ();
grub_utf8_to_ucs4_alloc (str, &unicode_str,
&unicode_last_position);
unicode_str = grub_malloc (msg_len * sizeof (grub_uint32_t));
grub_error_pop ();
if (!unicode_str)
{
for (; *str; str++)
for (; msg_len--; str++, msg_len++)
{
struct grub_unicode_glyph c =
{
@ -1021,6 +1022,10 @@ grub_xputs_normal (const char *str)
return;
}
msg_len = grub_utf8_to_ucs4 (unicode_str, msg_len,
(grub_uint8_t *) str, -1, 0);
unicode_last_position = unicode_str + msg_len;
FOR_ACTIVE_TERM_OUTPUTS(term)
{
int cur;
@ -1044,6 +1049,12 @@ grub_xputs_normal (const char *str)
grub_free (unicode_str);
}
void
grub_xputs_normal (const char *str)
{
grub_xnputs (str, grub_strlen (str));
}
void
grub_cls (void)
{

View File

@ -0,0 +1,127 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB 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, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/term.h>
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/terminfo.h>
#include <grub/dl.h>
#include <grub/machine/lbio.h>
#include <grub/command.h>
#include <grub/normal.h>
GRUB_MOD_LICENSE ("GPLv3+");
struct grub_linuxbios_cbmemc
{
grub_uint32_t size;
grub_uint32_t pointer;
char data[0];
};
static struct grub_linuxbios_cbmemc *cbmemc;
static void
put (struct grub_term_output *term __attribute__ ((unused)), const int c)
{
if (!cbmemc)
return;
if (cbmemc->pointer < cbmemc->size)
cbmemc->data[cbmemc->pointer] = c;
cbmemc->pointer++;
}
struct grub_terminfo_output_state grub_cbmemc_terminfo_output =
{
.put = put,
.width = 80,
.height = 24
};
static struct grub_term_output grub_cbmemc_term_output =
{
.name = "cbmemc",
.init = grub_terminfo_output_init,
.fini = 0,
.putchar = grub_terminfo_putchar,
.getxy = grub_terminfo_getxy,
.getwh = grub_terminfo_getwh,
.gotoxy = grub_terminfo_gotoxy,
.cls = grub_terminfo_cls,
.setcolorstate = grub_terminfo_setcolorstate,
.setcursor = grub_terminfo_setcursor,
.flags = GRUB_TERM_CODE_TYPE_ASCII,
.data = &grub_cbmemc_terminfo_output,
};
static int
iterate_linuxbios_table (grub_linuxbios_table_item_t table_item,
void *data __attribute__ ((unused)))
{
if (table_item->tag != GRUB_LINUXBIOS_MEMBER_CBMEMC)
return 0;
cbmemc = (struct grub_linuxbios_cbmemc *) (grub_addr_t)
*(grub_uint64_t *) (table_item + 1);
return 1;
}
static grub_err_t
grub_cmd_cbmemc (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
grub_size_t len;
char *str;
struct grub_linuxbios_cbmemc *cbmemc_saved;
if (!cbmemc)
return grub_error (GRUB_ERR_IO, "no CBMEM console found");
len = cbmemc->pointer;
if (len > cbmemc->size)
len = cbmemc->size;
str = cbmemc->data;
cbmemc_saved = cbmemc;
cbmemc = 0;
grub_xnputs (str, len);
cbmemc = cbmemc_saved;
return 0;
}
static grub_command_t cmd;
GRUB_MOD_INIT (cbmemc)
{
grub_linuxbios_table_iterate (iterate_linuxbios_table, 0);
if (cbmemc)
grub_term_register_output ("cbmemc", &grub_cbmemc_term_output);
cmd =
grub_register_command ("cbmemc", grub_cmd_cbmemc,
0, N_("Show CBMEM console content."));
}
GRUB_MOD_FINI (cbmemc)
{
grub_term_unregister_output (&grub_cbmemc_term_output);
grub_unregister_command (cmd);
}

View File

@ -31,11 +31,36 @@ struct grub_linuxbios_table_header
};
typedef struct grub_linuxbios_table_header *grub_linuxbios_table_header_t;
struct grub_linuxbios_timestamp_entry
{
grub_uint32_t id;
grub_uint64_t tsc;
} __attribute__((packed));
struct grub_linuxbios_timestamp_table
{
grub_uint64_t base_tsc;
grub_uint32_t capacity;
grub_uint32_t used;
struct grub_linuxbios_timestamp_entry entries[0];
} __attribute__((packed));
struct grub_linuxbios_mainboard
{
grub_uint8_t vendor;
grub_uint8_t part_number;
char strings[0];
};
struct grub_linuxbios_table_item
{
#define GRUB_LINUXBIOS_MEMBER_UNUSED 0x00
#define GRUB_LINUXBIOS_MEMBER_MEMORY 0x01
#define GRUB_LINUXBIOS_MEMBER_MAINBOARD 0x03
#define GRUB_LINUXBIOS_MEMBER_CONSOLE 0x10
#define GRUB_LINUXBIOS_MEMBER_LINK 0x11
#define GRUB_LINUXBIOS_MEMBER_TIMESTAMPS 0x16
#define GRUB_LINUXBIOS_MEMBER_CBMEMC 0x17
grub_uint32_t tag;
grub_uint32_t size;
};
@ -50,4 +75,9 @@ struct grub_linuxbios_mem_region
};
typedef struct grub_linuxbios_mem_region *mem_region_t;
grub_err_t
EXPORT_FUNC(grub_linuxbios_table_iterate) (int (*hook) (grub_linuxbios_table_item_t,
void *),
void *hook_data);
#endif

View File

@ -141,6 +141,9 @@ void grub_normal_free_menu (grub_menu_t menu);
void grub_normal_auth_init (void);
void grub_normal_auth_fini (void);
void
grub_xnputs (const char *str, grub_size_t msg_len);
grub_command_t
grub_dyncmd_get_cmd (grub_command_t cmd);