119 lines
3.1 KiB
C
119 lines
3.1 KiB
C
/*
|
|
* 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);
|
|
}
|