Resync with trunk
This commit is contained in:
commit
e68d3b243f
706 changed files with 157184 additions and 45875 deletions
774
commands/acpi.c
Normal file
774
commands/acpi.c
Normal file
|
@ -0,0 +1,774 @@
|
|||
/* acpi.c - modify acpi tables. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/extcmd.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/memory.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/api.h>
|
||||
#endif
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"exclude", 'x', 0,
|
||||
N_("Don't load host tables specified by comma-separated list."),
|
||||
0, ARG_TYPE_STRING},
|
||||
{"load-only", 'n', 0,
|
||||
N_("Load only tables specified by comma-separated list."), 0, ARG_TYPE_STRING},
|
||||
{"v1", '1', 0, N_("Expose v1 tables."), 0, ARG_TYPE_NONE},
|
||||
{"v2", '2', 0, N_("Expose v2 and v3 tables."), 0, ARG_TYPE_NONE},
|
||||
{"oemid", 'o', 0, N_("Set OEMID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING},
|
||||
{"oemtable", 't', 0,
|
||||
N_("Set OEMTABLE ID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING},
|
||||
{"oemtablerev", 'r', 0,
|
||||
N_("Set OEMTABLE revision of RSDP, XSDT and RSDT."), 0, ARG_TYPE_INT},
|
||||
{"oemtablecreator", 'c', 0,
|
||||
N_("Set creator field of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING},
|
||||
{"oemtablecreatorrev", 'd', 0,
|
||||
N_("Set creator revision of RSDP, XSDT and RSDT."), 0, ARG_TYPE_INT},
|
||||
{"no-ebda", 'e', 0, N_("Don't update EBDA. May fix failures or hangs on some."
|
||||
" BIOSes but makes it ineffective with OS not receiving RSDP from GRUB."),
|
||||
0, ARG_TYPE_NONE},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
|
||||
grub_uint8_t
|
||||
grub_byte_checksum (void *base, grub_size_t size)
|
||||
{
|
||||
grub_uint8_t *ptr;
|
||||
grub_uint8_t ret = 0;
|
||||
for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size;
|
||||
ptr++)
|
||||
ret += *ptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* rev1 is 1 if ACPIv1 is to be generated, 0 otherwise.
|
||||
rev2 contains the revision of ACPIv2+ to generate or 0 if none. */
|
||||
static int rev1, rev2;
|
||||
/* OEMID of RSDP, RSDT and XSDT. */
|
||||
static char root_oemid[6];
|
||||
/* OEMTABLE of the same tables. */
|
||||
static char root_oemtable[8];
|
||||
/* OEMREVISION of the same tables. */
|
||||
static grub_uint32_t root_oemrev;
|
||||
/* CreatorID of the same tables. */
|
||||
static char root_creator_id[4];
|
||||
/* CreatorRevision of the same tables. */
|
||||
static grub_uint32_t root_creator_rev;
|
||||
static struct grub_acpi_rsdp_v10 *rsdpv1_new = 0;
|
||||
static struct grub_acpi_rsdp_v20 *rsdpv2_new = 0;
|
||||
static char *playground = 0, *playground_ptr = 0;
|
||||
static int playground_size = 0;
|
||||
|
||||
/* Linked list of ACPI tables. */
|
||||
struct efiemu_acpi_table
|
||||
{
|
||||
void *addr;
|
||||
grub_size_t size;
|
||||
struct efiemu_acpi_table *next;
|
||||
};
|
||||
static struct efiemu_acpi_table *acpi_tables = 0;
|
||||
|
||||
/* DSDT isn't in RSDT. So treat it specially. */
|
||||
static void *table_dsdt = 0;
|
||||
/* Pointer to recreated RSDT. */
|
||||
static void *rsdt_addr = 0;
|
||||
|
||||
/* Allocation handles for different tables. */
|
||||
static grub_size_t dsdt_size = 0;
|
||||
|
||||
/* Address of original FACS. */
|
||||
static grub_uint32_t facs_addr = 0;
|
||||
|
||||
struct grub_acpi_rsdp_v20 *
|
||||
grub_acpi_get_rsdpv2 (void)
|
||||
{
|
||||
if (rsdpv2_new)
|
||||
return rsdpv2_new;
|
||||
if (rsdpv1_new)
|
||||
return 0;
|
||||
return grub_machine_acpi_get_rsdpv2 ();
|
||||
}
|
||||
|
||||
struct grub_acpi_rsdp_v10 *
|
||||
grub_acpi_get_rsdpv1 (void)
|
||||
{
|
||||
if (rsdpv1_new)
|
||||
return rsdpv1_new;
|
||||
if (rsdpv2_new)
|
||||
return 0;
|
||||
return grub_machine_acpi_get_rsdpv1 ();
|
||||
}
|
||||
|
||||
static inline int
|
||||
iszero (grub_uint8_t *reg, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
if (reg[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_acpi_create_ebda (void)
|
||||
{
|
||||
int ebda_kb_len;
|
||||
int ebda_len;
|
||||
int mmapregion = 0;
|
||||
grub_uint8_t *ebda, *v1inebda = 0, *v2inebda = 0;
|
||||
grub_uint64_t highestlow = 0;
|
||||
grub_uint8_t *targetebda, *target;
|
||||
struct grub_acpi_rsdp_v10 *v1;
|
||||
struct grub_acpi_rsdp_v20 *v2;
|
||||
auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t,
|
||||
grub_uint32_t);
|
||||
int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t size,
|
||||
grub_uint32_t type)
|
||||
{
|
||||
grub_uint64_t end = start + size;
|
||||
if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
|
||||
return 0;
|
||||
if (end > 0x100000)
|
||||
end = 0x100000;
|
||||
if (end > start + ebda_len
|
||||
&& highestlow < ((end - ebda_len) & (~0xf)) )
|
||||
highestlow = (end - ebda_len) & (~0xf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ebda = (grub_uint8_t *) UINT_TO_PTR ((*((grub_uint16_t *)0x40e)) << 4);
|
||||
ebda_kb_len = *(grub_uint16_t *) ebda;
|
||||
if (! ebda || ebda_kb_len > 16)
|
||||
ebda_kb_len = 0;
|
||||
ebda_len = (ebda_kb_len + 1) << 10;
|
||||
|
||||
/* FIXME: use low-memory mm allocation once it's available. */
|
||||
grub_mmap_iterate (find_hook);
|
||||
targetebda = (grub_uint8_t *) UINT_TO_PTR (highestlow);
|
||||
grub_dprintf ("acpi", "creating ebda @%llx\n",
|
||||
(unsigned long long) highestlow);
|
||||
if (! highestlow)
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't find space for the new EBDA");
|
||||
|
||||
mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len,
|
||||
GRUB_MACHINE_MEMORY_RESERVED);
|
||||
if (! mmapregion)
|
||||
return grub_errno;
|
||||
|
||||
/* XXX: EBDA is unstandardized, so this implementation is heuristical. */
|
||||
if (ebda_kb_len)
|
||||
grub_memcpy (targetebda, ebda, 0x400);
|
||||
else
|
||||
grub_memset (targetebda, 0, 0x400);
|
||||
*((grub_uint16_t *) targetebda) = ebda_kb_len + 1;
|
||||
target = targetebda;
|
||||
|
||||
v1 = grub_acpi_get_rsdpv1 ();
|
||||
v2 = grub_acpi_get_rsdpv2 ();
|
||||
if (v2 && v2->length > 40)
|
||||
v2 = 0;
|
||||
|
||||
/* First try to replace already existing rsdp. */
|
||||
if (v2)
|
||||
{
|
||||
grub_dprintf ("acpi", "Scanning EBDA for old rsdpv2\n");
|
||||
for (; target < targetebda + 0x400 - v2->length; target += 0x10)
|
||||
if (grub_memcmp (target, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (target,
|
||||
sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& ((struct grub_acpi_rsdp_v10 *) target)->revision != 0
|
||||
&& ((struct grub_acpi_rsdp_v20 *) target)->length <= v2->length)
|
||||
{
|
||||
grub_memcpy (target, v2, v2->length);
|
||||
grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
|
||||
v2inebda = target;
|
||||
target += v2->length;
|
||||
target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
|
||||
v2 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (v1)
|
||||
{
|
||||
grub_dprintf ("acpi", "Scanning EBDA for old rsdpv1\n");
|
||||
for (; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10);
|
||||
target += 0x10)
|
||||
if (grub_memcmp (target, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (target,
|
||||
sizeof (struct grub_acpi_rsdp_v10)) == 0)
|
||||
{
|
||||
grub_memcpy (target, v1, sizeof (struct grub_acpi_rsdp_v10));
|
||||
grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target);
|
||||
v1inebda = target;
|
||||
target += sizeof (struct grub_acpi_rsdp_v10);
|
||||
target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
|
||||
v1 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
target = targetebda + 0x100;
|
||||
|
||||
/* Try contiguous zeros. */
|
||||
if (v2)
|
||||
{
|
||||
grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
|
||||
for (; target < targetebda + 0x400 - v2->length; target += 0x10)
|
||||
if (iszero (target, v2->length))
|
||||
{
|
||||
grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
|
||||
grub_memcpy (target, v2, v2->length);
|
||||
v2inebda = target;
|
||||
target += v2->length;
|
||||
target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
|
||||
v2 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (v1)
|
||||
{
|
||||
grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
|
||||
for (; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10);
|
||||
target += 0x10)
|
||||
if (iszero (target, sizeof (struct grub_acpi_rsdp_v10)))
|
||||
{
|
||||
grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target);
|
||||
grub_memcpy (target, v1, sizeof (struct grub_acpi_rsdp_v10));
|
||||
v1inebda = target;
|
||||
target += sizeof (struct grub_acpi_rsdp_v10);
|
||||
target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
|
||||
v1 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (v1 || v2)
|
||||
{
|
||||
grub_mmap_unregister (mmapregion);
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't find suitable spot in EBDA");
|
||||
}
|
||||
|
||||
/* Remove any other RSDT. */
|
||||
for (target = targetebda;
|
||||
target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10);
|
||||
target += 0x10)
|
||||
if (grub_memcmp (target, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (target,
|
||||
sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& target != v1inebda && target != v2inebda)
|
||||
*target = 0;
|
||||
|
||||
grub_dprintf ("acpi", "Switching EBDA\n");
|
||||
(*((grub_uint16_t *) 0x40e)) = ((long)targetebda) >> 4;
|
||||
grub_dprintf ("acpi", "EBDA switched\n");
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Create tables common to ACPIv1 and ACPIv2+ */
|
||||
static void
|
||||
setup_common_tables (void)
|
||||
{
|
||||
struct efiemu_acpi_table *cur;
|
||||
struct grub_acpi_table_header *rsdt;
|
||||
grub_uint32_t *rsdt_entry;
|
||||
int numoftables;
|
||||
|
||||
/* Treat DSDT. */
|
||||
grub_memcpy (playground_ptr, table_dsdt, dsdt_size);
|
||||
grub_free (table_dsdt);
|
||||
table_dsdt = playground_ptr;
|
||||
playground_ptr += dsdt_size;
|
||||
|
||||
/* Treat other tables. */
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
{
|
||||
struct grub_acpi_fadt *fadt;
|
||||
|
||||
grub_memcpy (playground_ptr, cur->addr, cur->size);
|
||||
grub_free (cur->addr);
|
||||
cur->addr = playground_ptr;
|
||||
playground_ptr += cur->size;
|
||||
|
||||
/* If it's FADT correct DSDT and FACS addresses. */
|
||||
fadt = (struct grub_acpi_fadt *) cur->addr;
|
||||
if (grub_memcmp (fadt->hdr.signature, "FACP", 4) == 0)
|
||||
{
|
||||
fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt);
|
||||
fadt->facs_addr = facs_addr;
|
||||
|
||||
/* Does a revision 2 exist at all? */
|
||||
if (fadt->hdr.revision >= 3)
|
||||
{
|
||||
fadt->dsdt_xaddr = PTR_TO_UINT64 (table_dsdt);
|
||||
fadt->facs_xaddr = facs_addr;
|
||||
}
|
||||
|
||||
/* Recompute checksum. */
|
||||
fadt->hdr.checksum = 0;
|
||||
fadt->hdr.checksum = 1 + ~grub_byte_checksum (fadt, fadt->hdr.length);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill RSDT entries. */
|
||||
numoftables = 0;
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
numoftables++;
|
||||
|
||||
rsdt_addr = rsdt = (struct grub_acpi_table_header *) playground_ptr;
|
||||
playground_ptr += sizeof (struct grub_acpi_table_header) + 4 * numoftables;
|
||||
|
||||
rsdt_entry = (grub_uint32_t *)(rsdt + 1);
|
||||
|
||||
/* Fill RSDT header. */
|
||||
grub_memcpy (&(rsdt->signature), "RSDT", 4);
|
||||
rsdt->length = sizeof (struct grub_acpi_table_header) + 4 * numoftables;
|
||||
rsdt->revision = 1;
|
||||
grub_memcpy (&(rsdt->oemid), root_oemid, 6);
|
||||
grub_memcpy (&(rsdt->oemtable), root_oemtable, 4);
|
||||
rsdt->oemrev = root_oemrev;
|
||||
grub_memcpy (&(rsdt->creator_id), root_creator_id, 6);
|
||||
rsdt->creator_rev = root_creator_rev;
|
||||
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
*(rsdt_entry++) = PTR_TO_UINT32 (cur->addr);
|
||||
|
||||
/* Recompute checksum. */
|
||||
rsdt->checksum = 0;
|
||||
rsdt->checksum = 1 + ~grub_byte_checksum (rsdt, rsdt->length);
|
||||
}
|
||||
|
||||
/* Regenerate ACPIv1 RSDP */
|
||||
static void
|
||||
setv1table (void)
|
||||
{
|
||||
/* Create RSDP. */
|
||||
rsdpv1_new = (struct grub_acpi_rsdp_v10 *) playground_ptr;
|
||||
playground_ptr += sizeof (struct grub_acpi_rsdp_v10);
|
||||
grub_memcpy (&(rsdpv1_new->signature), "RSD PTR ", 8);
|
||||
grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
|
||||
rsdpv1_new->revision = 0;
|
||||
rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
|
||||
rsdpv1_new->checksum = 0;
|
||||
rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new,
|
||||
sizeof (*rsdpv1_new));
|
||||
grub_dprintf ("acpi", "Generated ACPIv1 tables\n");
|
||||
}
|
||||
|
||||
static void
|
||||
setv2table (void)
|
||||
{
|
||||
struct grub_acpi_table_header *xsdt;
|
||||
struct efiemu_acpi_table *cur;
|
||||
grub_uint64_t *xsdt_entry;
|
||||
int numoftables;
|
||||
|
||||
numoftables = 0;
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
numoftables++;
|
||||
|
||||
/* Create XSDT. */
|
||||
xsdt = (struct grub_acpi_table_header *) playground_ptr;
|
||||
playground_ptr += sizeof (struct grub_acpi_table_header) + 8 * numoftables;
|
||||
|
||||
xsdt_entry = (grub_uint64_t *)(xsdt + 1);
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
*(xsdt_entry++) = PTR_TO_UINT64 (cur->addr);
|
||||
grub_memcpy (&(xsdt->signature), "XSDT", 4);
|
||||
xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables;
|
||||
xsdt->revision = 1;
|
||||
grub_memcpy (&(xsdt->oemid), root_oemid, sizeof (xsdt->oemid));
|
||||
grub_memcpy (&(xsdt->oemtable), root_oemtable, sizeof (xsdt->oemtable));
|
||||
xsdt->oemrev = root_oemrev;
|
||||
grub_memcpy (&(xsdt->creator_id), root_creator_id, sizeof (xsdt->creator_id));
|
||||
xsdt->creator_rev = root_creator_rev;
|
||||
xsdt->checksum = 0;
|
||||
xsdt->checksum = 1 + ~grub_byte_checksum (xsdt, xsdt->length);
|
||||
|
||||
/* Create RSDPv2. */
|
||||
rsdpv2_new = (struct grub_acpi_rsdp_v20 *) playground_ptr;
|
||||
playground_ptr += sizeof (struct grub_acpi_rsdp_v20);
|
||||
grub_memcpy (&(rsdpv2_new->rsdpv1.signature), "RSD PTR ",
|
||||
sizeof (rsdpv2_new->rsdpv1.signature));
|
||||
grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid,
|
||||
sizeof (rsdpv2_new->rsdpv1.oemid));
|
||||
rsdpv2_new->rsdpv1.revision = rev2;
|
||||
rsdpv2_new->rsdpv1.rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
|
||||
rsdpv2_new->rsdpv1.checksum = 0;
|
||||
rsdpv2_new->rsdpv1.checksum = 1 + ~grub_byte_checksum
|
||||
(&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1));
|
||||
rsdpv2_new->length = sizeof (*rsdpv2_new);
|
||||
rsdpv2_new->xsdt_addr = PTR_TO_UINT64 (xsdt);
|
||||
rsdpv2_new->checksum = 0;
|
||||
rsdpv2_new->checksum = 1 + ~grub_byte_checksum (rsdpv2_new,
|
||||
rsdpv2_new->length);
|
||||
grub_dprintf ("acpi", "Generated ACPIv2 tables\n");
|
||||
}
|
||||
|
||||
static void
|
||||
free_tables (void)
|
||||
{
|
||||
struct efiemu_acpi_table *cur, *t;
|
||||
if (table_dsdt)
|
||||
grub_free (table_dsdt);
|
||||
for (cur = acpi_tables; cur;)
|
||||
{
|
||||
t = cur;
|
||||
grub_free (cur->addr);
|
||||
cur = cur->next;
|
||||
grub_free (t);
|
||||
}
|
||||
acpi_tables = 0;
|
||||
table_dsdt = 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_acpi (struct grub_extcmd *cmd,
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_acpi_rsdp_v10 *rsdp;
|
||||
struct efiemu_acpi_table *cur, *t;
|
||||
grub_err_t err;
|
||||
int i, mmapregion;
|
||||
int numoftables;
|
||||
|
||||
/* Default values if no RSDP is found. */
|
||||
rev1 = 1;
|
||||
rev2 = 3;
|
||||
|
||||
facs_addr = 0;
|
||||
playground = playground_ptr = 0;
|
||||
playground_size = 0;
|
||||
|
||||
rsdp = (struct grub_acpi_rsdp_v10 *) grub_machine_acpi_get_rsdpv2 ();
|
||||
|
||||
if (! rsdp)
|
||||
rsdp = grub_machine_acpi_get_rsdpv1 ();
|
||||
|
||||
if (rsdp)
|
||||
{
|
||||
grub_uint32_t *entry_ptr;
|
||||
char *exclude = 0;
|
||||
char *load_only = 0;
|
||||
char *ptr;
|
||||
/* RSDT consists of header and an array of 32-bit pointers. */
|
||||
struct grub_acpi_table_header *rsdt;
|
||||
|
||||
exclude = state[0].set ? grub_strdup (state[0].arg) : 0;
|
||||
if (exclude)
|
||||
{
|
||||
for (ptr = exclude; *ptr; ptr++)
|
||||
*ptr = grub_tolower (*ptr);
|
||||
}
|
||||
|
||||
load_only = state[1].set ? grub_strdup (state[1].arg) : 0;
|
||||
if (load_only)
|
||||
{
|
||||
for (ptr = load_only; *ptr; ptr++)
|
||||
*ptr = grub_tolower (*ptr);
|
||||
}
|
||||
|
||||
/* Set revision variables to replicate the same version as host. */
|
||||
rev1 = ! rsdp->revision;
|
||||
rev2 = rsdp->revision;
|
||||
rsdt = (struct grub_acpi_table_header *) UINT_TO_PTR (rsdp->rsdt_addr);
|
||||
/* Load host tables. */
|
||||
for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
|
||||
entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
|
||||
+ rsdt->length);
|
||||
entry_ptr++)
|
||||
{
|
||||
char signature[5];
|
||||
struct efiemu_acpi_table *table;
|
||||
struct grub_acpi_table_header *curtable
|
||||
= (struct grub_acpi_table_header *) UINT_TO_PTR (*entry_ptr);
|
||||
signature[4] = 0;
|
||||
for (i = 0; i < 4;i++)
|
||||
signature[i] = grub_tolower (curtable->signature[i]);
|
||||
|
||||
/* If it's FADT it contains addresses of DSDT and FACS. */
|
||||
if (grub_strcmp (signature, "facp") == 0)
|
||||
{
|
||||
struct grub_acpi_table_header *dsdt;
|
||||
struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *) curtable;
|
||||
|
||||
/* Set root header variables to the same values
|
||||
as FACP by default. */
|
||||
grub_memcpy (&root_oemid, &(fadt->hdr.oemid),
|
||||
sizeof (root_oemid));
|
||||
grub_memcpy (&root_oemtable, &(fadt->hdr.oemtable),
|
||||
sizeof (root_oemtable));
|
||||
root_oemrev = fadt->hdr.oemrev;
|
||||
grub_memcpy (&root_creator_id, &(fadt->hdr.creator_id),
|
||||
sizeof (root_creator_id));
|
||||
root_creator_rev = fadt->hdr.creator_rev;
|
||||
|
||||
/* Load DSDT if not excluded. */
|
||||
dsdt = (struct grub_acpi_table_header *)
|
||||
UINT_TO_PTR (fadt->dsdt_addr);
|
||||
if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt"))
|
||||
&& (! load_only || grub_strword (load_only, "dsdt"))
|
||||
&& dsdt->length >= sizeof (*dsdt))
|
||||
{
|
||||
dsdt_size = dsdt->length;
|
||||
table_dsdt = grub_malloc (dsdt->length);
|
||||
if (! table_dsdt)
|
||||
{
|
||||
free_tables ();
|
||||
grub_free (exclude);
|
||||
grub_free (load_only);
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't allocate table");
|
||||
}
|
||||
grub_memcpy (table_dsdt, dsdt, dsdt->length);
|
||||
}
|
||||
|
||||
/* Save FACS address. FACS shouldn't be overridden. */
|
||||
facs_addr = fadt->facs_addr;
|
||||
}
|
||||
|
||||
/* Skip excluded tables. */
|
||||
if (exclude && grub_strword (exclude, signature))
|
||||
continue;
|
||||
if (load_only && ! grub_strword (load_only, signature))
|
||||
continue;
|
||||
|
||||
/* Sanity check. */
|
||||
if (curtable->length < sizeof (*curtable))
|
||||
continue;
|
||||
|
||||
table = (struct efiemu_acpi_table *) grub_malloc
|
||||
(sizeof (struct efiemu_acpi_table));
|
||||
if (! table)
|
||||
{
|
||||
free_tables ();
|
||||
grub_free (exclude);
|
||||
grub_free (load_only);
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't allocate table structure");
|
||||
}
|
||||
table->size = curtable->length;
|
||||
table->addr = grub_malloc (table->size);
|
||||
playground_size += table->size;
|
||||
if (! table->addr)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't allocate table");
|
||||
}
|
||||
table->next = acpi_tables;
|
||||
acpi_tables = table;
|
||||
grub_memcpy (table->addr, curtable, table->size);
|
||||
}
|
||||
grub_free (exclude);
|
||||
grub_free (load_only);
|
||||
}
|
||||
|
||||
/* Does user specify versions to generate? */
|
||||
if (state[2].set || state[3].set)
|
||||
{
|
||||
rev1 = state[2].set;
|
||||
if (state[3].set)
|
||||
rev2 = rev2 ? : 2;
|
||||
else
|
||||
rev2 = 0;
|
||||
}
|
||||
|
||||
/* Does user override root header information? */
|
||||
if (state[4].set)
|
||||
grub_strncpy (root_oemid, state[4].arg, sizeof (root_oemid));
|
||||
if (state[5].set)
|
||||
grub_strncpy (root_oemtable, state[5].arg, sizeof (root_oemtable));
|
||||
if (state[6].set)
|
||||
root_oemrev = grub_strtoul (state[6].arg, 0, 0);
|
||||
if (state[7].set)
|
||||
grub_strncpy (root_creator_id, state[7].arg, sizeof (root_creator_id));
|
||||
if (state[8].set)
|
||||
root_creator_rev = grub_strtoul (state[8].arg, 0, 0);
|
||||
|
||||
/* Load user tables */
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
grub_file_t file;
|
||||
grub_size_t size;
|
||||
char *buf;
|
||||
|
||||
file = grub_gzfile_open (args[i], 1);
|
||||
if (! file)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't open file %s", args[i]);
|
||||
}
|
||||
|
||||
size = grub_file_size (file);
|
||||
if (size < sizeof (struct grub_acpi_table_header))
|
||||
{
|
||||
grub_file_close (file);
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_BAD_OS, "file %s is too small", args[i]);
|
||||
}
|
||||
|
||||
buf = (char *) grub_malloc (size);
|
||||
if (! buf)
|
||||
{
|
||||
grub_file_close (file);
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't read file %s", args[i]);
|
||||
}
|
||||
|
||||
if (grub_file_read (file, buf, size) != (int) size)
|
||||
{
|
||||
grub_file_close (file);
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[i]);
|
||||
}
|
||||
grub_file_close (file);
|
||||
|
||||
if (grub_memcmp (((struct grub_acpi_table_header *) buf)->signature,
|
||||
"DSDT", 4) == 0)
|
||||
{
|
||||
grub_free (table_dsdt);
|
||||
table_dsdt = buf;
|
||||
dsdt_size = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct efiemu_acpi_table *table;
|
||||
table = (struct efiemu_acpi_table *) grub_malloc
|
||||
(sizeof (struct efiemu_acpi_table));
|
||||
if (! table)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't allocate table structure");
|
||||
}
|
||||
|
||||
table->size = size;
|
||||
table->addr = buf;
|
||||
playground_size += table->size;
|
||||
|
||||
table->next = acpi_tables;
|
||||
acpi_tables = table;
|
||||
}
|
||||
}
|
||||
|
||||
numoftables = 0;
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
numoftables++;
|
||||
|
||||
/* DSDT. */
|
||||
playground_size += dsdt_size;
|
||||
/* RSDT. */
|
||||
playground_size += sizeof (struct grub_acpi_table_header) + 4 * numoftables;
|
||||
/* RSDPv1. */
|
||||
playground_size += sizeof (struct grub_acpi_rsdp_v10);
|
||||
/* XSDT. */
|
||||
playground_size += sizeof (struct grub_acpi_table_header) + 8 * numoftables;
|
||||
/* RSDPv2. */
|
||||
playground_size += sizeof (struct grub_acpi_rsdp_v20);
|
||||
|
||||
playground = playground_ptr
|
||||
= grub_mmap_malign_and_register (1, playground_size, &mmapregion,
|
||||
GRUB_MACHINE_MEMORY_ACPI, 0);
|
||||
|
||||
if (! playground)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't allocate space for ACPI tables");
|
||||
}
|
||||
|
||||
setup_common_tables ();
|
||||
|
||||
/* Request space for RSDPv1. */
|
||||
if (rev1)
|
||||
setv1table ();
|
||||
|
||||
/* Request space for RSDPv2+ and XSDT. */
|
||||
if (rev2)
|
||||
setv2table ();
|
||||
|
||||
for (cur = acpi_tables; cur;)
|
||||
{
|
||||
t = cur;
|
||||
cur = cur->next;
|
||||
grub_free (t);
|
||||
}
|
||||
acpi_tables = 0;
|
||||
|
||||
if (! state[9].set && (err = grub_acpi_create_ebda ()))
|
||||
{
|
||||
rsdpv1_new = 0;
|
||||
rsdpv2_new = 0;
|
||||
grub_mmap_free_and_unregister (mmapregion);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
{
|
||||
struct grub_efi_guid acpi = GRUB_EFI_ACPI_TABLE_GUID;
|
||||
struct grub_efi_guid acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID;
|
||||
|
||||
grub_efi_system_table->boot_services->install_configuration_table
|
||||
(&acpi20, grub_acpi_get_rsdpv2 ());
|
||||
grub_efi_system_table->boot_services->install_configuration_table
|
||||
(&acpi, grub_acpi_get_rsdpv1 ());
|
||||
}
|
||||
#endif
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(acpi)
|
||||
{
|
||||
cmd = grub_register_extcmd ("acpi", grub_cmd_acpi,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
|
||||
"--load-only=table1,table2] FILE1"
|
||||
" [FILE2] [...]"),
|
||||
N_("Load host ACPI tables and tables "
|
||||
"specified by arguments."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(acpi)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
|
@ -17,17 +17,17 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_file_t file;
|
||||
|
@ -40,7 +40,7 @@ grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
unsigned length);
|
||||
auto void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
|
||||
unsigned offset, unsigned length);
|
||||
|
||||
|
||||
void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
|
||||
unsigned length)
|
||||
{
|
||||
|
@ -52,7 +52,7 @@ grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
num_sectors++;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
print_blocklist (start_sector, num_sectors, 0, 0);
|
||||
num_sectors = 0;
|
||||
}
|
||||
|
@ -65,20 +65,20 @@ grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
else
|
||||
print_blocklist (sector, 0, offset, length);
|
||||
}
|
||||
|
||||
|
||||
void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
|
||||
unsigned offset, unsigned length)
|
||||
{
|
||||
if (num_entries++)
|
||||
grub_printf (",");
|
||||
|
||||
grub_printf ("%llu", sector - part_start);
|
||||
grub_printf ("%llu", (unsigned long long) (sector - part_start));
|
||||
if (num > 0)
|
||||
grub_printf ("+%u", num);
|
||||
if (offset != 0 || length != 0)
|
||||
grub_printf ("[%u-%u]", offset, offset + length);
|
||||
}
|
||||
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||
|
||||
|
@ -88,11 +88,11 @@ grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
|
||||
if (! file->device->disk)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
"this command is available only for disk devices.");
|
||||
"this command is available only for disk devices");
|
||||
|
||||
if (file->device->disk->partition)
|
||||
part_start = grub_partition_get_start (file->device->disk->partition);
|
||||
|
||||
|
||||
file->read_hook = read_blocklist;
|
||||
|
||||
while (grub_file_read (file, buf, sizeof (buf)) > 0)
|
||||
|
@ -100,23 +100,21 @@ grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
|
||||
if (num_sectors > 0)
|
||||
print_blocklist (start_sector, num_sectors, 0, 0);
|
||||
|
||||
|
||||
grub_file_close (file);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(blocklist)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
grub_register_command ("blocklist", grub_cmd_blocklist,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"blocklist FILE",
|
||||
"Print a block list.", 0);
|
||||
cmd = grub_register_command ("blocklist", grub_cmd_blocklist,
|
||||
N_("FILE"), N_("Print a block list."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(blocklist)
|
||||
{
|
||||
grub_unregister_command ("blocklist");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
|
|
176
commands/boot.c
176
commands/boot.c
|
@ -1,7 +1,7 @@
|
|||
/* boot.c - command to boot an operating system */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,2003,2004,2005,2007,2009 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
|
||||
|
@ -19,32 +19,178 @@
|
|||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_boot (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
int argc, char **args __attribute__ ((unused)))
|
||||
static grub_err_t (*grub_loader_boot_func) (void);
|
||||
static grub_err_t (*grub_loader_unload_func) (void);
|
||||
static int grub_loader_noreturn;
|
||||
|
||||
struct grub_preboot_t
|
||||
{
|
||||
if (argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many arguments");
|
||||
|
||||
grub_loader_boot ();
|
||||
|
||||
return 0;
|
||||
grub_err_t (*preboot_func) (int);
|
||||
grub_err_t (*preboot_rest_func) (void);
|
||||
grub_loader_preboot_hook_prio_t prio;
|
||||
struct grub_preboot_t *next;
|
||||
struct grub_preboot_t *prev;
|
||||
};
|
||||
|
||||
static int grub_loader_loaded;
|
||||
static struct grub_preboot_t *preboots_head = 0,
|
||||
*preboots_tail = 0;
|
||||
|
||||
int
|
||||
grub_loader_is_loaded (void)
|
||||
{
|
||||
return grub_loader_loaded;
|
||||
}
|
||||
|
||||
/* Register a preboot hook. */
|
||||
void *
|
||||
grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
|
||||
grub_err_t (*preboot_rest_func) (void),
|
||||
grub_loader_preboot_hook_prio_t prio)
|
||||
{
|
||||
struct grub_preboot_t *cur, *new_preboot;
|
||||
|
||||
if (! preboot_func && ! preboot_rest_func)
|
||||
return 0;
|
||||
|
||||
new_preboot = (struct grub_preboot_t *)
|
||||
grub_malloc (sizeof (struct grub_preboot_t));
|
||||
if (! new_preboot)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added");
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_preboot->preboot_func = preboot_func;
|
||||
new_preboot->preboot_rest_func = preboot_rest_func;
|
||||
new_preboot->prio = prio;
|
||||
|
||||
for (cur = preboots_head; cur && cur->prio > prio; cur = cur->next);
|
||||
|
||||
if (cur)
|
||||
{
|
||||
new_preboot->next = cur;
|
||||
new_preboot->prev = cur->prev;
|
||||
cur->prev = new_preboot;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_preboot->next = 0;
|
||||
new_preboot->prev = preboots_tail;
|
||||
preboots_tail = new_preboot;
|
||||
}
|
||||
if (new_preboot->prev)
|
||||
new_preboot->prev->next = new_preboot;
|
||||
else
|
||||
preboots_head = new_preboot;
|
||||
|
||||
return new_preboot;
|
||||
}
|
||||
|
||||
void
|
||||
grub_loader_unregister_preboot_hook (void *hnd)
|
||||
{
|
||||
struct grub_preboot_t *preb = hnd;
|
||||
|
||||
if (preb->next)
|
||||
preb->next->prev = preb->prev;
|
||||
else
|
||||
preboots_tail = preb->prev;
|
||||
if (preb->prev)
|
||||
preb->prev->next = preb->next;
|
||||
else
|
||||
preboots_head = preb->next;
|
||||
|
||||
grub_free (preb);
|
||||
}
|
||||
|
||||
void
|
||||
grub_loader_set (grub_err_t (*boot) (void),
|
||||
grub_err_t (*unload) (void),
|
||||
int noreturn)
|
||||
{
|
||||
if (grub_loader_loaded && grub_loader_unload_func)
|
||||
grub_loader_unload_func ();
|
||||
|
||||
grub_loader_boot_func = boot;
|
||||
grub_loader_unload_func = unload;
|
||||
grub_loader_noreturn = noreturn;
|
||||
|
||||
grub_loader_loaded = 1;
|
||||
}
|
||||
|
||||
void
|
||||
grub_loader_unset(void)
|
||||
{
|
||||
if (grub_loader_loaded && grub_loader_unload_func)
|
||||
grub_loader_unload_func ();
|
||||
|
||||
grub_loader_boot_func = 0;
|
||||
grub_loader_unload_func = 0;
|
||||
|
||||
grub_loader_loaded = 0;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_loader_boot (void)
|
||||
{
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
struct grub_preboot_t *cur;
|
||||
|
||||
if (! grub_loader_loaded)
|
||||
return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");
|
||||
|
||||
if (grub_loader_noreturn)
|
||||
grub_machine_fini ();
|
||||
|
||||
for (cur = preboots_head; cur; cur = cur->next)
|
||||
{
|
||||
err = cur->preboot_func (grub_loader_noreturn);
|
||||
if (err)
|
||||
{
|
||||
for (cur = cur->prev; cur; cur = cur->prev)
|
||||
cur->preboot_rest_func ();
|
||||
return err;
|
||||
}
|
||||
}
|
||||
err = (grub_loader_boot_func) ();
|
||||
|
||||
for (cur = preboots_tail; cur; cur = cur->prev)
|
||||
if (! err)
|
||||
err = cur->preboot_rest_func ();
|
||||
else
|
||||
cur->preboot_rest_func ();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* boot */
|
||||
static grub_err_t
|
||||
grub_cmd_boot (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
return grub_loader_boot ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static grub_command_t cmd_boot;
|
||||
|
||||
GRUB_MOD_INIT(boot)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
grub_register_command ("boot", grub_cmd_boot, GRUB_COMMAND_FLAG_BOTH,
|
||||
"boot", "Boot an operating system.", 0);
|
||||
cmd_boot =
|
||||
grub_register_command ("boot", grub_cmd_boot,
|
||||
0, N_("Boot an operating system."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(boot)
|
||||
{
|
||||
grub_unregister_command ("boot");
|
||||
grub_unregister_command (cmd_boot);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* cat.c - command to show the contents of a file */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003,2005,2007,2008 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
|
||||
|
@ -17,23 +17,24 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_cat (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
grub_cmd_cat (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
|
||||
{
|
||||
grub_file_t file;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
grub_ssize_t size;
|
||||
int key = 0;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
@ -41,16 +42,17 @@ grub_cmd_cat (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
file = grub_gzfile_open (args[0], 1);
|
||||
if (! file)
|
||||
return 0;
|
||||
|
||||
while ((size = grub_file_read (file, buf, sizeof (buf))) > 0)
|
||||
|
||||
while ((size = grub_file_read (file, buf, sizeof (buf))) > 0
|
||||
&& key != GRUB_TERM_ESC)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
unsigned char c = buf[i];
|
||||
|
||||
if (grub_isprint (c) || grub_isspace (c))
|
||||
|
||||
if ((grub_isprint (c) || grub_isspace (c)) && c != '\r')
|
||||
grub_putchar (c);
|
||||
else
|
||||
{
|
||||
|
@ -59,24 +61,28 @@ grub_cmd_cat (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
|
||||
}
|
||||
}
|
||||
|
||||
while (grub_checkkey () >= 0 &&
|
||||
(key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != GRUB_TERM_ESC)
|
||||
;
|
||||
}
|
||||
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
grub_file_close (file);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(cat)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
grub_register_command ("cat", grub_cmd_cat, GRUB_COMMAND_FLAG_BOTH,
|
||||
"cat FILE", "Show the contents of a file.", 0);
|
||||
cmd = grub_register_command_p1 ("cat", grub_cmd_cat,
|
||||
N_("FILE"), N_("Show the contents of a file."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(cat)
|
||||
{
|
||||
grub_unregister_command ("cat");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* cmd.c - command to cmp an operating system */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2005,2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003,2005,2006,2007,2009 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
|
||||
|
@ -17,18 +17,18 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#define BUFFER_SIZE 512
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_cmp (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_ssize_t rd1, rd2;
|
||||
|
@ -41,7 +41,7 @@ grub_cmd_cmp (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
|
||||
|
||||
grub_printf ("Compare `%s' and `%s':\n", args[0],
|
||||
grub_printf ("Compare file `%s' with `%s':\n", args[0],
|
||||
args[1]);
|
||||
|
||||
file1 = grub_gzfile_open (args[0], 1);
|
||||
|
@ -50,23 +50,23 @@ grub_cmd_cmp (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
goto cleanup;
|
||||
|
||||
if (grub_file_size (file1) != grub_file_size (file2))
|
||||
grub_printf ("Differ in size: %llu [%s], %llu [%s]\n",
|
||||
grub_file_size (file1), args[0],
|
||||
grub_file_size (file2), args[1]);
|
||||
grub_printf ("Files differ in size: %llu [%s], %llu [%s]\n",
|
||||
(unsigned long long) grub_file_size (file1), args[0],
|
||||
(unsigned long long) grub_file_size (file2), args[1]);
|
||||
else
|
||||
{
|
||||
pos = 0;
|
||||
|
||||
buf1 = grub_malloc (BUFFER_SIZE);
|
||||
buf2 = grub_malloc (BUFFER_SIZE);
|
||||
|
||||
|
||||
if (! buf1 || ! buf2)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
rd1 = grub_file_read (file1, buf1, BUFFER_SIZE);
|
||||
rd2 = grub_file_read (file2, buf2, BUFFER_SIZE);
|
||||
|
||||
|
@ -77,22 +77,22 @@ grub_cmd_cmp (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
{
|
||||
if (buf1[i] != buf2[i])
|
||||
{
|
||||
grub_printf ("Differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n",
|
||||
i + pos, buf1[i], args[0],
|
||||
grub_printf ("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n",
|
||||
(unsigned long long) (i + pos), buf1[i], args[0],
|
||||
buf2[i], args[1]);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
pos += BUFFER_SIZE;
|
||||
|
||||
|
||||
}
|
||||
while (rd2);
|
||||
|
||||
|
||||
grub_printf ("The files are identical.\n");
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
|
||||
if (buf1)
|
||||
grub_free (buf1);
|
||||
if (buf2)
|
||||
|
@ -105,15 +105,15 @@ cleanup:
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(cmp)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
grub_register_command ("cmp", grub_cmd_cmp, GRUB_COMMAND_FLAG_BOTH,
|
||||
"cmp FILE1 FILE2", "Compare two files.", 0);
|
||||
cmd = grub_register_command ("cmp", grub_cmd_cmp,
|
||||
N_("FILE1 FILE2"), N_("Compare two files."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(cmp)
|
||||
{
|
||||
grub_unregister_command ("cmp");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* configfile.c - command to manually load config file */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2006,2007,2009 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
|
||||
|
@ -17,62 +17,59 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_configfile (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
|
||||
grub_cmd_source (grub_command_t cmd, int argc, char **args)
|
||||
{
|
||||
int new_env;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
grub_cls ();
|
||||
grub_env_context_open ();
|
||||
grub_normal_execute (args[0], 1);
|
||||
grub_env_context_close ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_source (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
|
||||
{
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
grub_normal_execute (args[0], 1);
|
||||
new_env = (cmd->name[0] == 'c');
|
||||
|
||||
if (new_env)
|
||||
{
|
||||
grub_cls ();
|
||||
grub_env_context_open (1);
|
||||
}
|
||||
|
||||
grub_normal_execute (args[0], 1, ! new_env);
|
||||
|
||||
if (new_env)
|
||||
grub_env_context_close ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_configfile, cmd_source, cmd_dot;
|
||||
|
||||
GRUB_MOD_INIT(configfile)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
grub_register_command ("configfile", grub_cmd_configfile,
|
||||
GRUB_COMMAND_FLAG_BOTH, "configfile FILE",
|
||||
"Load another config file.", 0);
|
||||
grub_register_command ("source", grub_cmd_source,
|
||||
GRUB_COMMAND_FLAG_BOTH, "source FILE",
|
||||
"Load another config file without changing context.",
|
||||
0);
|
||||
grub_register_command (".", grub_cmd_source,
|
||||
GRUB_COMMAND_FLAG_BOTH, ". FILE",
|
||||
"Load another config file without changing context.",
|
||||
0);
|
||||
cmd_configfile =
|
||||
grub_register_command ("configfile", grub_cmd_source,
|
||||
N_("FILE"), N_("Load another config file."));
|
||||
cmd_source =
|
||||
grub_register_command ("source", grub_cmd_source,
|
||||
N_("FILE"),
|
||||
N_("Load another config file without changing context.")
|
||||
);
|
||||
cmd_dot =
|
||||
grub_register_command (".", grub_cmd_source,
|
||||
N_("FILE"),
|
||||
N_("Load another config file without changing context.")
|
||||
);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(configfile)
|
||||
{
|
||||
grub_unregister_command ("configfile");
|
||||
grub_unregister_command ("source");
|
||||
grub_unregister_command (".");
|
||||
grub_unregister_command (cmd_configfile);
|
||||
grub_unregister_command (cmd_source);
|
||||
grub_unregister_command (cmd_dot);
|
||||
}
|
||||
|
|
71
commands/crc.c
Normal file
71
commands/crc.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* crc.c - command to calculate the crc32 checksum of a file */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2010 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/disk.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/lib/crc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_crc (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
|
||||
{
|
||||
grub_file_t file;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
grub_ssize_t size;
|
||||
grub_uint32_t crc;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
file = grub_file_open (args[0]);
|
||||
if (! file)
|
||||
return 0;
|
||||
|
||||
crc = 0;
|
||||
while ((size = grub_file_read (file, buf, sizeof (buf))) > 0)
|
||||
crc = grub_getcrc32 (crc, buf, size);
|
||||
|
||||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
grub_printf ("%08x\n", crc);
|
||||
|
||||
fail:
|
||||
grub_file_close (file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(crc)
|
||||
{
|
||||
cmd = grub_register_command ("crc", grub_cmd_crc,
|
||||
N_("FILE"),
|
||||
N_("Calculate the crc32 checksum of a file."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(crc)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
146
commands/date.c
Normal file
146
commands/date.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
/* date.c - command to display/set current datetime. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 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/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#define GRUB_DATETIME_SET_YEAR 1
|
||||
#define GRUB_DATETIME_SET_MONTH 2
|
||||
#define GRUB_DATETIME_SET_DAY 4
|
||||
#define GRUB_DATETIME_SET_HOUR 8
|
||||
#define GRUB_DATETIME_SET_MINUTE 16
|
||||
#define GRUB_DATETIME_SET_SECOND 32
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_date (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_datetime datetime;
|
||||
int limit[6][2] = {{1980, 2079}, {1, 12}, {1, 31}, {0, 23}, {0, 59}, {0, 59}};
|
||||
int value[6], mask;
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
if (grub_get_datetime (&datetime))
|
||||
return grub_errno;
|
||||
|
||||
grub_printf ("%d-%02d-%02d %02d:%02d:%02d %s\n",
|
||||
datetime.year, datetime.month, datetime.day,
|
||||
datetime.hour, datetime.minute, datetime.second,
|
||||
grub_get_weekday_name (&datetime));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_memset (&value, 0, sizeof (value));
|
||||
mask = 0;
|
||||
|
||||
for (; argc; argc--, args++)
|
||||
{
|
||||
char *p, c;
|
||||
int m1, ofs, n, cur_mask;
|
||||
|
||||
p = args[0];
|
||||
m1 = grub_strtoul (p, &p, 10);
|
||||
|
||||
c = *p;
|
||||
if (c == '-')
|
||||
ofs = 0;
|
||||
else if (c == ':')
|
||||
ofs = 3;
|
||||
else
|
||||
goto fail;
|
||||
|
||||
value[ofs] = m1;
|
||||
cur_mask = (1 << ofs);
|
||||
mask &= ~(cur_mask * (1 + 2 + 4));
|
||||
|
||||
for (n = 1; (n < 3) && (*p); n++)
|
||||
{
|
||||
if (*p != c)
|
||||
goto fail;
|
||||
|
||||
value[ofs + n] = grub_strtoul (p + 1, &p, 10);
|
||||
cur_mask |= (1 << (ofs + n));
|
||||
}
|
||||
|
||||
if (*p)
|
||||
goto fail;
|
||||
|
||||
if ((ofs == 0) && (n == 2))
|
||||
{
|
||||
value[ofs + 2] = value[ofs + 1];
|
||||
value[ofs + 1] = value[ofs];
|
||||
ofs++;
|
||||
cur_mask <<= 1;
|
||||
}
|
||||
|
||||
for (; n; n--, ofs++)
|
||||
if ((value [ofs] < limit[ofs][0]) ||
|
||||
(value [ofs] > limit[ofs][1]))
|
||||
goto fail;
|
||||
|
||||
mask |= cur_mask;
|
||||
}
|
||||
|
||||
if (grub_get_datetime (&datetime))
|
||||
return grub_errno;
|
||||
|
||||
if (mask & GRUB_DATETIME_SET_YEAR)
|
||||
datetime.year = value[0];
|
||||
|
||||
if (mask & GRUB_DATETIME_SET_MONTH)
|
||||
datetime.month = value[1];
|
||||
|
||||
if (mask & GRUB_DATETIME_SET_DAY)
|
||||
datetime.day = value[2];
|
||||
|
||||
if (mask & GRUB_DATETIME_SET_HOUR)
|
||||
datetime.hour = value[3];
|
||||
|
||||
if (mask & GRUB_DATETIME_SET_MINUTE)
|
||||
datetime.minute = value[4];
|
||||
|
||||
if (mask & GRUB_DATETIME_SET_SECOND)
|
||||
datetime.second = value[5];
|
||||
|
||||
return grub_set_datetime (&datetime);
|
||||
|
||||
fail:
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid datetime");
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(date)
|
||||
{
|
||||
cmd =
|
||||
grub_register_command ("date", grub_cmd_date,
|
||||
N_("[[year-]month-day] [hour:minute[:second]]"),
|
||||
N_("Command to display/set current datetime."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(date)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -17,22 +17,22 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{0, 'n', 0, "do not output the trailing newline", 0, 0},
|
||||
{0, 'e', 0, "enable interpretation of backslash escapes", 0, 0},
|
||||
{0, 'n', 0, N_("Do not output the trailing newline."), 0, 0},
|
||||
{0, 'e', 0, N_("Enable interpretation of backslash escapes."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_echo (struct grub_arg_list *state, int argc, char **args)
|
||||
grub_cmd_echo (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
int newline = 1;
|
||||
int i;
|
||||
|
||||
|
@ -91,7 +91,7 @@ grub_cmd_echo (struct grub_arg_list *state, int argc, char **args)
|
|||
arg++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* This was not an escaped character, or escaping is not
|
||||
enabled. */
|
||||
grub_printf ("%c", *arg);
|
||||
|
@ -109,16 +109,16 @@ grub_cmd_echo (struct grub_arg_list *state, int argc, char **args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(echo)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
grub_register_command ("echo", grub_cmd_echo, GRUB_COMMAND_FLAG_BOTH,
|
||||
"echo [-e|-n] FILE", "Display a line of text.",
|
||||
options);
|
||||
cmd = grub_register_extcmd ("echo", grub_cmd_echo, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[-e|-n] STRING"), N_("Display a line of text."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(echo)
|
||||
{
|
||||
grub_unregister_command ("echo");
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* acpi.c - Display acpi tables. */
|
||||
/* acpi.c - get acpi tables. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2009 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
|
||||
|
@ -16,175 +16,44 @@
|
|||
* 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/types.h>
|
||||
#include <grub/mm.h>
|
||||
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/api.h>
|
||||
|
||||
static grub_uint32_t read16 (grub_uint8_t *p)
|
||||
struct grub_acpi_rsdp_v10 *
|
||||
grub_machine_acpi_get_rsdpv1 (void)
|
||||
{
|
||||
return grub_le_to_cpu16 (*(grub_uint16_t *)p);
|
||||
}
|
||||
unsigned i;
|
||||
static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
|
||||
|
||||
static grub_uint32_t read32 (grub_uint8_t *p)
|
||||
{
|
||||
return grub_le_to_cpu32 (*(grub_uint32_t *)p);
|
||||
}
|
||||
|
||||
static grub_uint64_t read64 (grub_uint8_t *p)
|
||||
{
|
||||
return grub_le_to_cpu64 (*(grub_uint64_t *)p);
|
||||
}
|
||||
|
||||
static void
|
||||
disp_acpi_table (grub_uint8_t *t)
|
||||
{
|
||||
int i;
|
||||
grub_printf ("%c%c%c%c %4dB rev=%d OEM=", t[0], t[1], t[2], t[3],
|
||||
read32 (t + 4), t[8]);
|
||||
for (i = 0; i < 6; i++)
|
||||
grub_printf ("%c", t[10 + i]);
|
||||
grub_printf (" ");
|
||||
for (i = 0; i < 8; i++)
|
||||
grub_printf ("%c", t[16 + i]);
|
||||
grub_printf (" V=%08lx ", read32 (t + 24));
|
||||
for (i = 0; i < 4; i++)
|
||||
grub_printf ("%c", t[28 + i]);
|
||||
grub_printf (" %08lx\n", read32 (t + 32));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
disp_acpi_apic_table (grub_uint8_t *t)
|
||||
{
|
||||
grub_uint8_t *d;
|
||||
grub_uint32_t len;
|
||||
grub_uint32_t flags;
|
||||
|
||||
disp_acpi_table (t);
|
||||
grub_printf ("Local APIC=%08lx Flags=%08lx\n",
|
||||
read32 (t + 36), read32 (t + 40));
|
||||
len = read32 (t + 4);
|
||||
len -= 44;
|
||||
d = t + 44;
|
||||
while (len > 0)
|
||||
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
|
||||
{
|
||||
grub_uint32_t l = d[1];
|
||||
grub_printf (" type=%x l=%d ", d[0], l);
|
||||
grub_efi_guid_t *guid =
|
||||
&grub_efi_system_table->configuration_table[i].vendor_guid;
|
||||
|
||||
switch (d[0])
|
||||
{
|
||||
case 2:
|
||||
grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x",
|
||||
d[2], d[3], read32 (d + 4), read16 (d + 8));
|
||||
break;
|
||||
case 6:
|
||||
grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016llx",
|
||||
d[2], read32 (d + 4), read64 (d + 8));
|
||||
break;
|
||||
case 7:
|
||||
flags = read32 (d + 8);
|
||||
grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x",
|
||||
d[2], d[3], d[4], flags);
|
||||
if (flags & 1)
|
||||
grub_printf (" Enabled");
|
||||
else
|
||||
grub_printf (" Disabled");
|
||||
if (l >= 17)
|
||||
grub_printf ("\n"
|
||||
" UID val=%08x, Str=%s", read32 (d + 12), d + 16);
|
||||
break;
|
||||
case 8:
|
||||
grub_printf ("Platform INT flags=%04x type=%02x (",
|
||||
read16 (d + 2), d[4]);
|
||||
if (d[4] <= 3)
|
||||
{
|
||||
static const char * const platint_type[4] =
|
||||
{"Nul", "PMI", "INIT", "CPEI"};
|
||||
grub_printf ("%s", platint_type[d[4]]);
|
||||
}
|
||||
else
|
||||
grub_printf ("??");
|
||||
grub_printf (") ID=%02x EID=%02x\n", d[5], d[6]);
|
||||
grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x",
|
||||
d[7], read32 (d + 8), read32 (d + 12));
|
||||
break;
|
||||
default:
|
||||
grub_printf (" ??");
|
||||
}
|
||||
grub_printf ("\n");
|
||||
d += l;
|
||||
len -= l;
|
||||
if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t)))
|
||||
return (struct grub_acpi_rsdp_v10 *)
|
||||
grub_efi_system_table->configuration_table[i].vendor_table;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
disp_acpi_xsdt_table (grub_uint8_t *t)
|
||||
struct grub_acpi_rsdp_v20 *
|
||||
grub_machine_acpi_get_rsdpv2 (void)
|
||||
{
|
||||
grub_uint32_t len;
|
||||
grub_uint8_t *desc;
|
||||
unsigned i;
|
||||
static grub_efi_guid_t acpi20_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
|
||||
|
||||
disp_acpi_table (t);
|
||||
len = read32 (t + 4) - 36;
|
||||
desc = t + 36;
|
||||
while (len > 0)
|
||||
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
|
||||
{
|
||||
t = read64 (desc);
|
||||
|
||||
if (t[0] == 'A' && t[1] == 'P' && t[2] == 'I' && t[3] == 'C')
|
||||
disp_acpi_apic_table (t);
|
||||
else
|
||||
disp_acpi_table (t);
|
||||
desc += 8;
|
||||
len -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
disp_acpi_rsdt_table (grub_uint8_t *t)
|
||||
{
|
||||
grub_uint32_t len;
|
||||
grub_uint8_t *desc;
|
||||
|
||||
disp_acpi_table (t);
|
||||
len = read32 (t + 4) - 36;
|
||||
desc = t + 36;
|
||||
while (len > 0)
|
||||
{
|
||||
t = read32 (desc);
|
||||
|
||||
if (t != NULL)
|
||||
disp_acpi_table (t);
|
||||
desc += 4;
|
||||
len -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
disp_acpi_rsdp_table (grub_uint8_t *rsdp)
|
||||
{
|
||||
grub_uint8_t *t = rsdp;
|
||||
int i;
|
||||
grub_uint8_t *xsdt;
|
||||
|
||||
grub_printf ("RSDP signature:");
|
||||
for (i = 0; i < 8; i++)
|
||||
grub_printf ("%c", t[i]);
|
||||
grub_printf (" chksum:%02x, OEM-ID: ", t[8]);
|
||||
for (i = 0; i < 6; i++)
|
||||
grub_printf ("%c", t[9 + i]);
|
||||
grub_printf (" rev=%d\n", t[15]);
|
||||
grub_printf ("RSDT=%08lx", read32 (t + 16));
|
||||
if (t[15] == 2)
|
||||
{
|
||||
xsdt = read64 (t + 24);
|
||||
grub_printf (" len=%d XSDT=%016llx\n", read32 (t + 20), xsdt);
|
||||
grub_printf ("\n");
|
||||
disp_acpi_xsdt_table (xsdt);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_printf ("\n");
|
||||
disp_acpi_rsdt_table (read32 (t + 16));
|
||||
grub_efi_guid_t *guid =
|
||||
&grub_efi_system_table->configuration_table[i].vendor_guid;
|
||||
|
||||
if (! grub_memcmp (guid, &acpi20_guid, sizeof (grub_efi_guid_t)))
|
||||
return (struct grub_acpi_rsdp_v20 *)
|
||||
grub_efi_system_table->configuration_table[i].vendor_table;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
190
commands/efi/acpi2.c
Normal file
190
commands/efi/acpi2.c
Normal file
|
@ -0,0 +1,190 @@
|
|||
/* acpi.c - Display acpi tables. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 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/types.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/normal.h>
|
||||
|
||||
static grub_uint32_t read16 (grub_uint8_t *p)
|
||||
{
|
||||
return grub_le_to_cpu16 (*(grub_uint16_t *)p);
|
||||
}
|
||||
|
||||
static grub_uint32_t read32 (grub_uint8_t *p)
|
||||
{
|
||||
return grub_le_to_cpu32 (*(grub_uint32_t *)p);
|
||||
}
|
||||
|
||||
static grub_uint64_t read64 (grub_uint8_t *p)
|
||||
{
|
||||
return grub_le_to_cpu64 (*(grub_uint64_t *)p);
|
||||
}
|
||||
|
||||
static void
|
||||
disp_acpi_table (grub_uint8_t *t)
|
||||
{
|
||||
int i;
|
||||
grub_printf ("%c%c%c%c %4dB rev=%d OEM=", t[0], t[1], t[2], t[3],
|
||||
read32 (t + 4), t[8]);
|
||||
for (i = 0; i < 6; i++)
|
||||
grub_printf ("%c", t[10 + i]);
|
||||
grub_printf (" ");
|
||||
for (i = 0; i < 8; i++)
|
||||
grub_printf ("%c", t[16 + i]);
|
||||
grub_printf (" V=%08lx ", read32 (t + 24));
|
||||
for (i = 0; i < 4; i++)
|
||||
grub_printf ("%c", t[28 + i]);
|
||||
grub_printf (" %08lx\n", read32 (t + 32));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
disp_acpi_apic_table (grub_uint8_t *t)
|
||||
{
|
||||
grub_uint8_t *d;
|
||||
grub_uint32_t len;
|
||||
grub_uint32_t flags;
|
||||
|
||||
disp_acpi_table (t);
|
||||
grub_printf ("Local APIC=%08lx Flags=%08lx\n",
|
||||
read32 (t + 36), read32 (t + 40));
|
||||
len = read32 (t + 4);
|
||||
len -= 44;
|
||||
d = t + 44;
|
||||
while (len > 0)
|
||||
{
|
||||
grub_uint32_t l = d[1];
|
||||
grub_printf (" type=%x l=%d ", d[0], l);
|
||||
|
||||
switch (d[0])
|
||||
{
|
||||
case 2:
|
||||
grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x",
|
||||
d[2], d[3], read32 (d + 4), read16 (d + 8));
|
||||
break;
|
||||
case 6:
|
||||
grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016llx",
|
||||
d[2], read32 (d + 4), read64 (d + 8));
|
||||
break;
|
||||
case 7:
|
||||
flags = read32 (d + 8);
|
||||
grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x",
|
||||
d[2], d[3], d[4], flags);
|
||||
if (flags & 1)
|
||||
grub_printf (" Enabled");
|
||||
else
|
||||
grub_printf (" Disabled");
|
||||
if (l >= 17)
|
||||
grub_printf ("\n"
|
||||
" UID val=%08x, Str=%s", read32 (d + 12), d + 16);
|
||||
break;
|
||||
case 8:
|
||||
grub_printf ("Platform INT flags=%04x type=%02x (",
|
||||
read16 (d + 2), d[4]);
|
||||
if (d[4] <= 3)
|
||||
{
|
||||
static const char * const platint_type[4] =
|
||||
{"Nul", "PMI", "INIT", "CPEI"};
|
||||
grub_printf ("%s", platint_type[d[4]]);
|
||||
}
|
||||
else
|
||||
grub_printf ("??");
|
||||
grub_printf (") ID=%02x EID=%02x\n", d[5], d[6]);
|
||||
grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x",
|
||||
d[7], read32 (d + 8), read32 (d + 12));
|
||||
break;
|
||||
default:
|
||||
grub_printf (" ??");
|
||||
}
|
||||
grub_printf ("\n");
|
||||
d += l;
|
||||
len -= l;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
disp_acpi_xsdt_table (grub_uint8_t *t)
|
||||
{
|
||||
grub_uint32_t len;
|
||||
grub_uint8_t *desc;
|
||||
|
||||
disp_acpi_table (t);
|
||||
len = read32 (t + 4) - 36;
|
||||
desc = t + 36;
|
||||
while (len > 0)
|
||||
{
|
||||
t = read64 (desc);
|
||||
|
||||
if (t[0] == 'A' && t[1] == 'P' && t[2] == 'I' && t[3] == 'C')
|
||||
disp_acpi_apic_table (t);
|
||||
else
|
||||
disp_acpi_table (t);
|
||||
desc += 8;
|
||||
len -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
disp_acpi_rsdt_table (grub_uint8_t *t)
|
||||
{
|
||||
grub_uint32_t len;
|
||||
grub_uint8_t *desc;
|
||||
|
||||
disp_acpi_table (t);
|
||||
len = read32 (t + 4) - 36;
|
||||
desc = t + 36;
|
||||
while (len > 0)
|
||||
{
|
||||
t = read32 (desc);
|
||||
|
||||
if (t != NULL)
|
||||
disp_acpi_table (t);
|
||||
desc += 4;
|
||||
len -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
disp_acpi_rsdp_table (grub_uint8_t *rsdp)
|
||||
{
|
||||
grub_uint8_t *t = rsdp;
|
||||
int i;
|
||||
grub_uint8_t *xsdt;
|
||||
|
||||
grub_printf ("RSDP signature:");
|
||||
for (i = 0; i < 8; i++)
|
||||
grub_printf ("%c", t[i]);
|
||||
grub_printf (" chksum:%02x, OEM-ID: ", t[8]);
|
||||
for (i = 0; i < 6; i++)
|
||||
grub_printf ("%c", t[9 + i]);
|
||||
grub_printf (" rev=%d\n", t[15]);
|
||||
grub_printf ("RSDT=%08lx", read32 (t + 16));
|
||||
if (t[15] == 2)
|
||||
{
|
||||
xsdt = read64 (t + 24);
|
||||
grub_printf (" len=%d XSDT=%016llx\n", read32 (t + 20), xsdt);
|
||||
grub_printf ("\n");
|
||||
disp_acpi_xsdt_table (xsdt);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_printf ("\n");
|
||||
disp_acpi_rsdt_table (read32 (t + 16));
|
||||
}
|
||||
}
|
110
commands/efi/fixvideo.c
Normal file
110
commands/efi/fixvideo.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
/* fixvideo.c - fix video problem in efi */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/file.h>
|
||||
#include <grub/pci.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static struct grub_video_patch
|
||||
{
|
||||
const char *name;
|
||||
grub_uint32_t pci_id;
|
||||
grub_uint32_t mmio_bar;
|
||||
grub_uint32_t mmio_reg;
|
||||
grub_uint32_t mmio_old;
|
||||
} video_patches[] =
|
||||
{
|
||||
{"Intel 945GM", 0x27a28086, 0, 0x71184, 0x1000000}, /* DSPBBASE */
|
||||
{"Intel 965GM", 0x2a028086, 0, 0x7119C, 0x1000000}, /* DSPBSURF */
|
||||
{0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static int NESTED_FUNC_ATTR
|
||||
scan_card (grub_pci_device_t dev, grub_pci_id_t pciid)
|
||||
{
|
||||
grub_pci_address_t addr;
|
||||
|
||||
addr = grub_pci_make_address (dev, 2);
|
||||
if (grub_pci_read_byte (addr + 3) == 0x3)
|
||||
{
|
||||
struct grub_video_patch *p = video_patches;
|
||||
|
||||
while (p->name)
|
||||
{
|
||||
if (p->pci_id == pciid)
|
||||
{
|
||||
grub_target_addr_t base;
|
||||
|
||||
grub_printf ("Found graphic card: %s\n", p->name);
|
||||
addr += 8 + p->mmio_bar * 4;
|
||||
base = grub_pci_read (addr);
|
||||
if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) ||
|
||||
(base & GRUB_PCI_ADDR_MEM_PREFETCH))
|
||||
grub_printf ("Invalid MMIO bar %d\n", p->mmio_bar);
|
||||
else
|
||||
{
|
||||
base &= GRUB_PCI_ADDR_MEM_MASK;
|
||||
base += p->mmio_reg;
|
||||
|
||||
if (*((volatile grub_uint32_t *) base) != p->mmio_old)
|
||||
grub_printf ("Old value don't match\n");
|
||||
else
|
||||
{
|
||||
*((volatile grub_uint32_t *) base) = 0;
|
||||
if (*((volatile grub_uint32_t *) base))
|
||||
grub_printf ("Set MMIO fails\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
grub_printf ("Unknown graphic card: %x\n", pciid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_fixvideo (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_pci_iterate (scan_card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_fixvideo;
|
||||
|
||||
GRUB_MOD_INIT(fixvideo)
|
||||
{
|
||||
cmd_fixvideo = grub_register_command ("fix_video", grub_cmd_fixvideo,
|
||||
0, N_("Fix video problem."));
|
||||
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(fixvideo)
|
||||
{
|
||||
grub_unregister_command (cmd_fixvideo);
|
||||
}
|
216
commands/efi/loadbios.c
Normal file
216
commands/efi/loadbios.c
Normal file
|
@ -0,0 +1,216 @@
|
|||
/* loadbios.c - command to load a bios dump */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/file.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/pci.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
|
||||
static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
|
||||
static grub_efi_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID;
|
||||
|
||||
#define EBDA_SEG_ADDR 0x40e
|
||||
#define LOW_MEM_ADDR 0x413
|
||||
#define FAKE_EBDA_SEG 0x9fc0
|
||||
|
||||
#define BLANK_MEM 0xffffffff
|
||||
#define VBIOS_ADDR 0xc0000
|
||||
#define SBIOS_ADDR 0xf0000
|
||||
|
||||
static int
|
||||
enable_rom_area (void)
|
||||
{
|
||||
grub_pci_address_t addr;
|
||||
grub_uint32_t *rom_ptr;
|
||||
grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
|
||||
|
||||
rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
|
||||
if (*rom_ptr != BLANK_MEM)
|
||||
{
|
||||
grub_printf ("ROM image is present.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr = grub_pci_make_address (dev, 36);
|
||||
grub_pci_write_byte (addr++, 0x30);
|
||||
grub_pci_write_byte (addr++, 0x33);
|
||||
grub_pci_write_byte (addr++, 0x33);
|
||||
grub_pci_write_byte (addr++, 0x33);
|
||||
grub_pci_write_byte (addr++, 0x33);
|
||||
grub_pci_write_byte (addr++, 0x33);
|
||||
grub_pci_write_byte (addr++, 0x33);
|
||||
grub_pci_write_byte (addr, 0);
|
||||
|
||||
*rom_ptr = 0;
|
||||
if (*rom_ptr != 0)
|
||||
{
|
||||
grub_printf ("Can\'t enable ROM area.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
lock_rom_area (void)
|
||||
{
|
||||
grub_pci_address_t addr;
|
||||
grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
|
||||
|
||||
addr = grub_pci_make_address (dev, 36);
|
||||
grub_pci_write_byte (addr++, 0x10);
|
||||
grub_pci_write_byte (addr++, 0x11);
|
||||
grub_pci_write_byte (addr++, 0x11);
|
||||
grub_pci_write_byte (addr++, 0x11);
|
||||
grub_pci_write_byte (addr, 0x11);
|
||||
}
|
||||
|
||||
static void
|
||||
fake_bios_data (int use_rom)
|
||||
{
|
||||
unsigned i;
|
||||
void *acpi, *smbios;
|
||||
grub_uint16_t *ebda_seg_ptr, *low_mem_ptr;
|
||||
|
||||
ebda_seg_ptr = (grub_uint16_t *) EBDA_SEG_ADDR;
|
||||
low_mem_ptr = (grub_uint16_t *) LOW_MEM_ADDR;
|
||||
if ((*ebda_seg_ptr) || (*low_mem_ptr))
|
||||
return;
|
||||
|
||||
acpi = 0;
|
||||
smbios = 0;
|
||||
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
|
||||
{
|
||||
grub_efi_guid_t *guid =
|
||||
&grub_efi_system_table->configuration_table[i].vendor_guid;
|
||||
|
||||
if (! grub_memcmp (guid, &acpi2_guid, sizeof (grub_efi_guid_t)))
|
||||
{
|
||||
acpi = grub_efi_system_table->configuration_table[i].vendor_table;
|
||||
grub_dprintf ("efi", "ACPI2: %p\n", acpi);
|
||||
}
|
||||
else if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t)))
|
||||
{
|
||||
void *t;
|
||||
|
||||
t = grub_efi_system_table->configuration_table[i].vendor_table;
|
||||
if (! acpi)
|
||||
acpi = t;
|
||||
grub_dprintf ("efi", "ACPI: %p\n", t);
|
||||
}
|
||||
else if (! grub_memcmp (guid, &smbios_guid, sizeof (grub_efi_guid_t)))
|
||||
{
|
||||
smbios = grub_efi_system_table->configuration_table[i].vendor_table;
|
||||
grub_dprintf ("efi", "SMBIOS: %p\n", smbios);
|
||||
}
|
||||
}
|
||||
|
||||
*ebda_seg_ptr = FAKE_EBDA_SEG;
|
||||
*low_mem_ptr = (FAKE_EBDA_SEG >> 6);
|
||||
|
||||
*((grub_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr;
|
||||
|
||||
if (acpi)
|
||||
grub_memcpy ((char *) ((FAKE_EBDA_SEG << 4) + 16), acpi, 1024 - 16);
|
||||
|
||||
if ((use_rom) && (smbios))
|
||||
grub_memcpy ((char *) SBIOS_ADDR, (char *) smbios + 16, 16);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_fakebios (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
if (enable_rom_area ())
|
||||
{
|
||||
fake_bios_data (1);
|
||||
lock_rom_area ();
|
||||
}
|
||||
else
|
||||
fake_bios_data (0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
grub_file_t file;
|
||||
int size;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no ROM image specified");
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
file = grub_file_open (argv[1]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
if (file->size != 4)
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid int10 dump size");
|
||||
else
|
||||
grub_file_read (file, (void *) 0x40, 4);
|
||||
|
||||
grub_file_close (file);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
size = file->size;
|
||||
if ((size < 0x10000) || (size > 0x40000))
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid bios dump size");
|
||||
else if (enable_rom_area ())
|
||||
{
|
||||
grub_file_read (file, (void *) VBIOS_ADDR, size);
|
||||
fake_bios_data (size <= 0x40000);
|
||||
lock_rom_area ();
|
||||
}
|
||||
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_fakebios, cmd_loadbios;
|
||||
|
||||
GRUB_MOD_INIT(loadbios)
|
||||
{
|
||||
cmd_fakebios = grub_register_command ("fakebios", grub_cmd_fakebios,
|
||||
0, N_("Fake BIOS."));
|
||||
|
||||
cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
|
||||
"BIOS_DUMP [INT10_DUMP]",
|
||||
N_("Load BIOS dump."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(loadbios)
|
||||
{
|
||||
grub_unregister_command (cmd_fakebios);
|
||||
grub_unregister_command (cmd_loadbios);
|
||||
}
|
96
commands/extcmd.c
Normal file
96
commands/extcmd.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* extcmd.c - support extended command */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/mm.h>
|
||||
#include <grub/list.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/extcmd.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_extcmd_dispatcher (struct grub_command *cmd,
|
||||
int argc, char **args)
|
||||
{
|
||||
int new_argc;
|
||||
char **new_args;
|
||||
struct grub_arg_option *parser;
|
||||
struct grub_arg_list *state;
|
||||
int maxargs = 0;
|
||||
grub_err_t ret;
|
||||
grub_extcmd_t ext;
|
||||
|
||||
ext = cmd->data;
|
||||
parser = (struct grub_arg_option *) ext->options;
|
||||
while (parser && (parser++)->doc)
|
||||
maxargs++;
|
||||
|
||||
/* Set up the option state. */
|
||||
state = grub_zalloc (sizeof (struct grub_arg_list) * maxargs);
|
||||
|
||||
if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc))
|
||||
{
|
||||
ext->state = state;
|
||||
ret = (ext->func) (ext, new_argc, new_args);
|
||||
grub_free (new_args);
|
||||
}
|
||||
else
|
||||
ret = grub_errno;
|
||||
|
||||
grub_free (state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
grub_extcmd_t
|
||||
grub_register_extcmd (const char *name, grub_extcmd_func_t func,
|
||||
unsigned flags, const char *summary,
|
||||
const char *description,
|
||||
const struct grub_arg_option *parser)
|
||||
{
|
||||
grub_extcmd_t ext;
|
||||
grub_command_t cmd;
|
||||
|
||||
ext = (grub_extcmd_t) grub_malloc (sizeof (*ext));
|
||||
if (! ext)
|
||||
return 0;
|
||||
|
||||
cmd = grub_register_command_prio (name, grub_extcmd_dispatcher,
|
||||
summary, description, 1);
|
||||
if (! cmd)
|
||||
{
|
||||
grub_free (ext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd->flags = (flags | GRUB_COMMAND_FLAG_EXTCMD);
|
||||
cmd->data = ext;
|
||||
|
||||
ext->cmd = cmd;
|
||||
ext->func = func;
|
||||
ext->options = parser;
|
||||
ext->data = 0;
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
void
|
||||
grub_unregister_extcmd (grub_extcmd_t ext)
|
||||
{
|
||||
grub_unregister_command (ext->cmd);
|
||||
grub_free (ext);
|
||||
}
|
256
commands/gptsync.c
Normal file
256
commands/gptsync.c
Normal file
|
@ -0,0 +1,256 @@
|
|||
/* gptsync.c - fill the mbr based on gpt entries */
|
||||
/* XXX: I don't know what to do if sector size isn't 512 bytes */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/command.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/msdos_partition.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
/* Convert a LBA address to a CHS address in the INT 13 format. */
|
||||
/* Taken from grub1. */
|
||||
/* XXX: use hardcoded geometry of C = 1024, H = 255, S = 63.
|
||||
Is it a problem?
|
||||
*/
|
||||
static void
|
||||
lba_to_chs (int lba, grub_uint8_t *cl, grub_uint8_t *ch,
|
||||
grub_uint8_t *dh)
|
||||
{
|
||||
int cylinder, head, sector;
|
||||
int sectors = 63, heads = 255, cylinders = 1024;
|
||||
|
||||
sector = lba % sectors + 1;
|
||||
head = (lba / sectors) % heads;
|
||||
cylinder = lba / (sectors * heads);
|
||||
|
||||
if (cylinder >= cylinders)
|
||||
{
|
||||
*cl = *ch = *dh = 0xff;
|
||||
return;
|
||||
}
|
||||
|
||||
*cl = sector | ((cylinder & 0x300) >> 2);
|
||||
*ch = cylinder & 0xFF;
|
||||
*dh = head;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_device_t dev;
|
||||
struct grub_msdos_partition_mbr mbr;
|
||||
struct grub_partition *partition;
|
||||
grub_disk_addr_t first_sector;
|
||||
int numactive = 0;
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
||||
if (argc > 4)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "only 3 partitions can be "
|
||||
"in hybrid MBR");
|
||||
|
||||
if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
|
||||
{
|
||||
args[0][grub_strlen (args[0]) - 1] = 0;
|
||||
dev = grub_device_open (args[0] + 1);
|
||||
args[0][grub_strlen (args[0])] = ')';
|
||||
}
|
||||
else
|
||||
dev = grub_device_open (args[0]);
|
||||
|
||||
if (! dev)
|
||||
return grub_errno;
|
||||
|
||||
if (! dev->disk)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a disk");
|
||||
}
|
||||
|
||||
/* Read the protective MBR. */
|
||||
if (grub_disk_read (dev->disk, 0, 0, sizeof (mbr), &mbr))
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Check if it is valid. */
|
||||
if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
|
||||
}
|
||||
|
||||
/* Make sure the MBR is a protective MBR and not a normal MBR. */
|
||||
if (mbr.entries[0].type != GRUB_PC_PARTITION_TYPE_GPT_DISK)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no GPT partition map found");
|
||||
}
|
||||
|
||||
int i;
|
||||
first_sector = dev->disk->total_sectors;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
char *separator, csep = 0;
|
||||
grub_uint8_t type;
|
||||
separator = grub_strchr (args[i], '+');
|
||||
if (! separator)
|
||||
separator = grub_strchr (args[i], '-');
|
||||
if (separator)
|
||||
{
|
||||
csep = *separator;
|
||||
*separator = 0;
|
||||
}
|
||||
partition = grub_partition_probe (dev->disk, args[i]);
|
||||
if (separator)
|
||||
*separator = csep;
|
||||
if (! partition)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such partition");
|
||||
}
|
||||
|
||||
if (partition->start + partition->len > 0xffffffff)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"only partitions resding in the first 2TB "
|
||||
"can be presen in hybrid MBR");
|
||||
}
|
||||
|
||||
|
||||
if (first_sector > partition->start)
|
||||
first_sector = partition->start;
|
||||
|
||||
if (separator && *(separator + 1))
|
||||
type = grub_strtoul (separator + 1, 0, 0);
|
||||
else
|
||||
{
|
||||
grub_fs_t fs = 0;
|
||||
dev->disk->partition = partition;
|
||||
fs = grub_fs_probe (dev);
|
||||
|
||||
/* Unknown filesystem isn't fatal. */
|
||||
if (grub_errno == GRUB_ERR_UNKNOWN_FS)
|
||||
{
|
||||
fs = 0;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (fs && grub_strcmp (fs->name, "ntfs") == 0)
|
||||
type = GRUB_PC_PARTITION_TYPE_NTFS;
|
||||
else if (fs && grub_strcmp (fs->name, "fat") == 0)
|
||||
/* FIXME: detect FAT16. */
|
||||
type = GRUB_PC_PARTITION_TYPE_FAT32_LBA;
|
||||
else if (fs && (grub_strcmp (fs->name, "hfsplus") == 0
|
||||
|| grub_strcmp (fs->name, "hfs") == 0))
|
||||
type = GRUB_PC_PARTITION_TYPE_HFS;
|
||||
else
|
||||
/* FIXME: detect more types. */
|
||||
type = GRUB_PC_PARTITION_TYPE_EXT2FS;
|
||||
|
||||
dev->disk->partition = 0;
|
||||
}
|
||||
|
||||
mbr.entries[i].flag = (csep == '+') ? 0x80 : 0;
|
||||
if (csep == '+')
|
||||
{
|
||||
numactive++;
|
||||
if (numactive == 2)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"only one partition can be active");
|
||||
}
|
||||
}
|
||||
mbr.entries[i].type = type;
|
||||
mbr.entries[i].start = grub_cpu_to_le32 (partition->start);
|
||||
lba_to_chs (partition->start,
|
||||
&(mbr.entries[i].start_sector),
|
||||
&(mbr.entries[i].start_cylinder),
|
||||
&(mbr.entries[i].start_head));
|
||||
lba_to_chs (partition->start + partition->len - 1,
|
||||
&(mbr.entries[i].end_sector),
|
||||
&(mbr.entries[i].end_cylinder),
|
||||
&(mbr.entries[i].end_head));
|
||||
mbr.entries[i].length = grub_cpu_to_le32 (partition->len);
|
||||
grub_free (partition);
|
||||
}
|
||||
for (; i < 4; i++)
|
||||
grub_memset (&(mbr.entries[i]), 0, sizeof (mbr.entries[i]));
|
||||
|
||||
/* The protective partition. */
|
||||
if (first_sector > 0xffffffff)
|
||||
first_sector = 0xffffffff;
|
||||
else
|
||||
first_sector--;
|
||||
mbr.entries[0].flag = 0;
|
||||
mbr.entries[0].type = GRUB_PC_PARTITION_TYPE_GPT_DISK;
|
||||
mbr.entries[0].start = grub_cpu_to_le32 (1);
|
||||
lba_to_chs (1,
|
||||
&(mbr.entries[0].start_sector),
|
||||
&(mbr.entries[0].start_cylinder),
|
||||
&(mbr.entries[0].start_head));
|
||||
lba_to_chs (first_sector,
|
||||
&(mbr.entries[0].end_sector),
|
||||
&(mbr.entries[0].end_cylinder),
|
||||
&(mbr.entries[0].end_head));
|
||||
mbr.entries[0].length = grub_cpu_to_le32 (first_sector);
|
||||
|
||||
mbr.signature = grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE);
|
||||
|
||||
if (grub_disk_write (dev->disk, 0, 0, sizeof (mbr), &mbr))
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_printf ("New MBR is written to '%s'\n", args[0]);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(gptsync)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
cmd = grub_register_command ("gptsync", grub_cmd_gptsync,
|
||||
N_("DEVICE [PARTITION[+/-[TYPE]]] ..."),
|
||||
N_("Fill hybrid MBR of GPT drive DEVICE. "
|
||||
"specified partitions will be a part "
|
||||
"of hybrid mbr. Up to 3 partitions are "
|
||||
"allowed. TYPE is an MBR type. "
|
||||
"+ means that partition is active. "
|
||||
"Only one partition can be active."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(gptsync)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* halt.c - command to halt the computer. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2008 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
|
||||
|
@ -17,13 +17,13 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_halt (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
|
@ -31,16 +31,16 @@ grub_cmd_halt (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(ieee1275_halt)
|
||||
GRUB_MOD_INIT(halt)
|
||||
{
|
||||
(void)mod; /* To stop warning. */
|
||||
grub_register_command ("halt", grub_cmd_halt, GRUB_COMMAND_FLAG_BOTH,
|
||||
"halt", "halts the computer. This command does not"
|
||||
" work on all firmware.", 0);
|
||||
cmd = grub_register_command ("halt", grub_cmd_halt,
|
||||
0, N_("Halts the computer. This command does"
|
||||
" not work on all firmware implementations."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(ieee1275_halt)
|
||||
GRUB_MOD_FINI(halt)
|
||||
{
|
||||
grub_unregister_command ("halt");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
101
commands/handler.c
Normal file
101
commands/handler.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* handler.c - commands to list or select handlers */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/handler.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_handler (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
void *curr_item = 0;
|
||||
grub_handler_class_t head;
|
||||
|
||||
auto int list_item (grub_named_list_t item);
|
||||
int list_item (grub_named_list_t item)
|
||||
{
|
||||
if (item == curr_item)
|
||||
grub_putchar ('*');
|
||||
|
||||
grub_printf ("%s\n", item->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
head = grub_handler_class_list;
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *class_name;
|
||||
grub_handler_class_t class;
|
||||
|
||||
class_name = args[0];
|
||||
argc--;
|
||||
args++;
|
||||
|
||||
class = grub_named_list_find (GRUB_AS_NAMED_LIST (head), class_name);
|
||||
if (! class)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "class not found");
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
curr_item = class->cur_handler;
|
||||
grub_list_iterate (GRUB_AS_LIST (class->handler_list),
|
||||
(grub_list_hook_t) list_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_handler_t handler;
|
||||
|
||||
handler =
|
||||
grub_named_list_find (GRUB_AS_NAMED_LIST (class->handler_list),
|
||||
args[0]);
|
||||
|
||||
if (! handler)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "handler not found");
|
||||
|
||||
grub_handler_set_current (class, handler);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_handler;
|
||||
|
||||
GRUB_MOD_INIT(handler)
|
||||
{
|
||||
cmd_handler =
|
||||
grub_register_command ("handler", grub_cmd_handler,
|
||||
N_("[class [handler]]"),
|
||||
N_("List or select a handler."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(handler)
|
||||
{
|
||||
grub_unregister_command (cmd_handler);
|
||||
}
|
278
commands/hashsum.c
Normal file
278
commands/hashsum.c
Normal file
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/extcmd.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/normal.h>
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"hash", 'h', 0, "Specify hash to use.", "HASH", ARG_TYPE_STRING},
|
||||
{"check", 'c', 0, "Check hash list file.", "FILE", ARG_TYPE_STRING},
|
||||
{"prefix", 'p', 0, "Base directory for hash list.", "DIRECTORY",
|
||||
ARG_TYPE_STRING},
|
||||
{"keep-going", 'k', 0, "Don't stop after first error.", 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
struct { const char *name; const char *hashname; } aliases[] =
|
||||
{
|
||||
{"sha256sum", "sha256"},
|
||||
{"sha512sum", "sha512"},
|
||||
{"md5sum", "md5"},
|
||||
};
|
||||
|
||||
static inline int
|
||||
hextoval (char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result)
|
||||
{
|
||||
grub_uint8_t context[hash->contextsize];
|
||||
char *readbuf[4096];
|
||||
|
||||
grub_memset (context, 0, sizeof (context));
|
||||
hash->init (context);
|
||||
while (1)
|
||||
{
|
||||
grub_ssize_t r;
|
||||
r = grub_file_read (file, readbuf, sizeof (readbuf));
|
||||
if (r < 0)
|
||||
return grub_errno;
|
||||
if (r == 0)
|
||||
break;
|
||||
hash->write (context, readbuf, r);
|
||||
}
|
||||
hash->final (context);
|
||||
grub_memcpy (result, hash->read (context), hash->mdlen);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
||||
const char *prefix, int keep)
|
||||
{
|
||||
grub_file_t hashlist, file;
|
||||
char *buf = NULL;
|
||||
grub_uint8_t expected[hash->mdlen];
|
||||
grub_uint8_t actual[hash->mdlen];
|
||||
grub_err_t err;
|
||||
unsigned i;
|
||||
unsigned unread = 0, mismatch = 0;
|
||||
|
||||
hashlist = grub_file_open (hashfilename);
|
||||
if (!hashlist)
|
||||
return grub_errno;
|
||||
|
||||
while (grub_free (buf), (buf = grub_file_getline (hashlist)))
|
||||
{
|
||||
const char *p = buf;
|
||||
for (i = 0; i < hash->mdlen; i++)
|
||||
{
|
||||
int high, low;
|
||||
high = hextoval (*p++);
|
||||
low = hextoval (*p++);
|
||||
if (high < 0 || low < 0)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list");
|
||||
expected[i] = (high << 4) | low;
|
||||
}
|
||||
if (*p++ != ' ' || *p++ != ' ')
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list");
|
||||
if (prefix)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = grub_malloc (grub_strlen (prefix)
|
||||
+ grub_strlen (p) + 2);
|
||||
if (!filename)
|
||||
return grub_errno;
|
||||
grub_sprintf (filename, "%s/%s", prefix, p);
|
||||
file = grub_file_open (filename);
|
||||
grub_free (filename);
|
||||
}
|
||||
else
|
||||
file = grub_file_open (p);
|
||||
if (!file)
|
||||
{
|
||||
grub_file_close (hashlist);
|
||||
grub_free (buf);
|
||||
return grub_errno;
|
||||
}
|
||||
err = hash_file (file, hash, actual);
|
||||
grub_file_close (file);
|
||||
if (err)
|
||||
{
|
||||
grub_printf ("%s: READ ERROR\n", p);
|
||||
if (!keep)
|
||||
{
|
||||
grub_file_close (hashlist);
|
||||
grub_free (buf);
|
||||
return err;
|
||||
}
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
unread++;
|
||||
continue;
|
||||
}
|
||||
if (grub_crypto_memcmp (expected, actual, hash->mdlen) != 0)
|
||||
{
|
||||
grub_printf ("%s: HASH MISMATCH\n", p);
|
||||
if (!keep)
|
||||
{
|
||||
grub_file_close (hashlist);
|
||||
grub_free (buf);
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE,
|
||||
"hash of '%s' mismatches", p);
|
||||
}
|
||||
mismatch++;
|
||||
continue;
|
||||
}
|
||||
grub_printf ("%s: OK\n", p);
|
||||
}
|
||||
if (mismatch || unread)
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE,
|
||||
"%d files couldn't be read and hash "
|
||||
"of %d files mismatches", unread, mismatch);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hashsum (struct grub_extcmd *cmd,
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
const char *hashname = NULL;
|
||||
const char *prefix = NULL;
|
||||
const gcry_md_spec_t *hash;
|
||||
unsigned i;
|
||||
int keep = state[3].set;
|
||||
unsigned unread = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (aliases); i++)
|
||||
if (grub_strcmp (cmd->cmd->name, aliases[i].name) == 0)
|
||||
hashname = aliases[i].hashname;
|
||||
if (state[0].set)
|
||||
hashname = state[0].arg;
|
||||
|
||||
if (!hashname)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no hash specified");
|
||||
|
||||
hash = grub_crypto_lookup_md_by_name (hashname);
|
||||
if (!hash)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown hash");
|
||||
|
||||
if (state[2].set)
|
||||
prefix = state[2].arg;
|
||||
|
||||
if (state[1].set)
|
||||
{
|
||||
if (argc != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"--check is incompatible with file list");
|
||||
return check_list (hash, state[1].arg, prefix, keep);
|
||||
}
|
||||
|
||||
for (i = 0; i < (unsigned) argc; i++)
|
||||
{
|
||||
grub_uint8_t result[hash->mdlen];
|
||||
grub_file_t file;
|
||||
grub_err_t err;
|
||||
unsigned j;
|
||||
file = grub_file_open (args[i]);
|
||||
if (!file)
|
||||
{
|
||||
if (!keep)
|
||||
return grub_errno;
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
unread++;
|
||||
continue;
|
||||
}
|
||||
err = hash_file (file, hash, result);
|
||||
grub_file_close (file);
|
||||
if (err)
|
||||
{
|
||||
if (!keep)
|
||||
return err;
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
unread++;
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < hash->mdlen; j++)
|
||||
grub_printf ("%02x", result[j]);
|
||||
grub_printf (" %s\n", args[i]);
|
||||
}
|
||||
|
||||
if (unread)
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "%d files couldn't be read.",
|
||||
unread);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd, cmd_md5, cmd_sha256, cmd_sha512;
|
||||
|
||||
GRUB_MOD_INIT(hashsum)
|
||||
{
|
||||
cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"hashsum -h HASH [-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]",
|
||||
"Compute or check hash checksum.",
|
||||
options);
|
||||
cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"md5sum [-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]",
|
||||
"Compute or check hash checksum.",
|
||||
options);
|
||||
cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"sha256sum [-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]",
|
||||
"Compute or check hash checksum.",
|
||||
options);
|
||||
cmd_sha512 = grub_register_extcmd ("sha512sum", grub_cmd_hashsum,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"sha512sum [-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]",
|
||||
"Compute or check hash checksum.",
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(hashsum)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_unregister_extcmd (cmd_md5);
|
||||
grub_unregister_extcmd (cmd_sha256);
|
||||
grub_unregister_extcmd (cmd_sha512);
|
||||
}
|
421
commands/hdparm.c
Normal file
421
commands/hdparm.c
Normal file
|
@ -0,0 +1,421 @@
|
|||
/* hdparm.c - command to get/set ATA disk parameters. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/ata.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/lib/hexdump.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"apm", 'B', 0, N_("Set Advanced Power Management\n"
|
||||
"(1=low, ..., 254=high, 255=off)."),
|
||||
0, ARG_TYPE_INT},
|
||||
{"power", 'C', 0, N_("Check power mode."), 0, ARG_TYPE_NONE},
|
||||
{"security-freeze", 'F', 0, N_("Freeze ATA security settings until reset."),
|
||||
0, ARG_TYPE_NONE},
|
||||
{"health", 'H', 0, N_("Check SMART health status."), 0, ARG_TYPE_NONE},
|
||||
{"aam", 'M', 0, N_("Set Automatic Acoustic Management\n"
|
||||
"(0=off, 128=quiet, ..., 254=fast)."),
|
||||
0, ARG_TYPE_INT},
|
||||
{"standby-timeout", 'S', 0, N_("Set standby timeout\n"
|
||||
"(0=off, 1=5s, 2=10s, ..., 240=20m, 241=30m, ...)."),
|
||||
0, ARG_TYPE_INT},
|
||||
{"standby", 'y', 0, N_("Set drive to standby mode."), 0, ARG_TYPE_NONE},
|
||||
{"sleep", 'Y', 0, N_("Set drive to sleep mode."), 0, ARG_TYPE_NONE},
|
||||
{"identify", 'i', 0, N_("Print drive identity and settings."),
|
||||
0, ARG_TYPE_NONE},
|
||||
{"dumpid", 'I', 0, N_("Dump contents of ATA IDENTIFY sector."),
|
||||
0, ARG_TYPE_NONE},
|
||||
{"smart", -1, 0, N_("Disable/enable SMART (0/1)."), 0, ARG_TYPE_INT},
|
||||
{"quiet", 'q', 0, N_("Do not print messages."), 0, ARG_TYPE_NONE},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
enum grub_ata_smart_commands
|
||||
{
|
||||
GRUB_ATA_FEAT_SMART_ENABLE = 0xd8,
|
||||
GRUB_ATA_FEAT_SMART_DISABLE = 0xd9,
|
||||
GRUB_ATA_FEAT_SMART_STATUS = 0xda,
|
||||
};
|
||||
|
||||
static int quiet = 0;
|
||||
|
||||
static grub_err_t
|
||||
grub_hdparm_do_ata_cmd (grub_disk_t disk, grub_uint8_t cmd,
|
||||
grub_uint8_t features, grub_uint8_t sectors,
|
||||
void * buffer, int size)
|
||||
{
|
||||
struct grub_disk_ata_pass_through_parms apt;
|
||||
grub_memset (&apt, 0, sizeof (apt));
|
||||
|
||||
apt.taskfile[GRUB_ATA_REG_CMD] = cmd;
|
||||
apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
|
||||
apt.taskfile[GRUB_ATA_REG_SECTORS] = sectors;
|
||||
apt.buffer = buffer;
|
||||
apt.size = size;
|
||||
|
||||
if (grub_disk_ata_pass_through (disk, &apt))
|
||||
return grub_errno;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_hdparm_do_check_powermode_cmd (grub_disk_t disk)
|
||||
{
|
||||
struct grub_disk_ata_pass_through_parms apt;
|
||||
grub_memset (&apt, 0, sizeof (apt));
|
||||
|
||||
apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_CHECK_POWER_MODE;
|
||||
|
||||
if (grub_disk_ata_pass_through (disk, &apt))
|
||||
return -1;
|
||||
|
||||
return apt.taskfile[GRUB_ATA_REG_SECTORS];
|
||||
}
|
||||
|
||||
static int
|
||||
grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features)
|
||||
{
|
||||
struct grub_disk_ata_pass_through_parms apt;
|
||||
grub_memset (&apt, 0, sizeof (apt));
|
||||
|
||||
apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_SMART;
|
||||
apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
|
||||
apt.taskfile[GRUB_ATA_REG_LBAMID] = 0x4f;
|
||||
apt.taskfile[GRUB_ATA_REG_LBAHIGH] = 0xc2;
|
||||
|
||||
if (grub_disk_ata_pass_through (disk, &apt))
|
||||
return -1;
|
||||
|
||||
if (features == GRUB_ATA_FEAT_SMART_STATUS)
|
||||
{
|
||||
if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0x4f
|
||||
&& apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0xc2)
|
||||
return 0; /* Good SMART status. */
|
||||
else if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0xf4
|
||||
&& apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0x2c)
|
||||
return 1; /* Bad SMART status. */
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_hdparm_simple_cmd (const char * msg,
|
||||
grub_disk_t disk, grub_uint8_t cmd)
|
||||
{
|
||||
if (! quiet && msg)
|
||||
grub_printf ("%s", msg);
|
||||
|
||||
grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, 0, 0, NULL, 0);
|
||||
|
||||
if (! quiet && msg)
|
||||
grub_printf ("%s\n", ! err ? "" : ": not supported");
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_hdparm_set_val_cmd (const char * msg, int val,
|
||||
grub_disk_t disk, grub_uint8_t cmd,
|
||||
grub_uint8_t features, grub_uint8_t sectors)
|
||||
{
|
||||
if (! quiet && msg && *msg)
|
||||
{
|
||||
if (val >= 0)
|
||||
grub_printf ("Set %s to %d", msg, val);
|
||||
else
|
||||
grub_printf ("Disable %s", msg);
|
||||
}
|
||||
|
||||
grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, features, sectors,
|
||||
NULL, 0);
|
||||
|
||||
if (! quiet && msg)
|
||||
grub_printf ("%s\n", ! err ? "" : ": not supported");
|
||||
return err;
|
||||
}
|
||||
|
||||
static const char *
|
||||
le16_to_char (char *dest, const grub_uint16_t * src16, unsigned bytes)
|
||||
{
|
||||
grub_uint16_t * dest16 = (grub_uint16_t *) dest;
|
||||
unsigned i;
|
||||
for (i = 0; i < bytes / 2; i++)
|
||||
dest16[i] = grub_be_to_cpu16 (src16[i]);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_hdparm_print_identify (const char * idbuf)
|
||||
{
|
||||
const grub_uint16_t * idw = (const grub_uint16_t *) idbuf;
|
||||
|
||||
/* Print identity strings. */
|
||||
char tmp[40];
|
||||
grub_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40));
|
||||
grub_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8));
|
||||
grub_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
|
||||
|
||||
/* Print AAM, APM and SMART settings. */
|
||||
grub_uint16_t features1 = grub_le_to_cpu16 (idw[82]);
|
||||
grub_uint16_t features2 = grub_le_to_cpu16 (idw[83]);
|
||||
grub_uint16_t enabled1 = grub_le_to_cpu16 (idw[85]);
|
||||
grub_uint16_t enabled2 = grub_le_to_cpu16 (idw[86]);
|
||||
|
||||
grub_printf ("Automatic Acoustic Management: ");
|
||||
if (features2 & 0x0200)
|
||||
{
|
||||
if (enabled2 & 0x0200)
|
||||
{
|
||||
grub_uint16_t aam = grub_le_to_cpu16 (idw[94]);
|
||||
grub_printf ("%u (128=quiet, ..., 254=fast, recommended=%u)\n",
|
||||
aam & 0xff, (aam >> 8) & 0xff);
|
||||
}
|
||||
else
|
||||
grub_printf ("disabled\n");
|
||||
}
|
||||
else
|
||||
grub_printf ("not supported\n");
|
||||
|
||||
grub_printf ("Advanced Power Management: ");
|
||||
if (features2 & 0x0008)
|
||||
{
|
||||
if (enabled2 & 0x0008)
|
||||
grub_printf ("%u (1=low, ..., 254=high)\n",
|
||||
grub_le_to_cpu16 (idw[91]) & 0xff);
|
||||
else
|
||||
grub_printf ("disabled\n");
|
||||
}
|
||||
else
|
||||
grub_printf ("not supported\n");
|
||||
|
||||
grub_printf ("SMART Feature Set: ");
|
||||
if (features1 & 0x0001)
|
||||
grub_printf ("%sabled\n", (enabled1 & 0x0001 ? "en" : "dis"));
|
||||
else
|
||||
grub_printf ("not supported\n");
|
||||
|
||||
/* Print security settings. */
|
||||
grub_uint16_t security = grub_le_to_cpu16 (idw[128]);
|
||||
|
||||
grub_printf ("ATA Security: ");
|
||||
if (security & 0x0001)
|
||||
grub_printf ("%s, %s, %s, %s\n",
|
||||
(security & 0x0002 ? "ENABLED" : "disabled"),
|
||||
(security & 0x0004 ? "**LOCKED**" : "not locked"),
|
||||
(security & 0x0008 ? "frozen" : "NOT FROZEN"),
|
||||
(security & 0x0010 ? "COUNT EXPIRED" : "count not expired"));
|
||||
else
|
||||
grub_printf ("not supported\n");
|
||||
}
|
||||
|
||||
static void
|
||||
grub_hdparm_print_standby_tout (int timeout)
|
||||
{
|
||||
if (timeout == 0)
|
||||
grub_printf ("off");
|
||||
else if (timeout <= 252 || timeout == 255)
|
||||
{
|
||||
int h = 0, m = 0 , s = 0;
|
||||
if (timeout == 255)
|
||||
{
|
||||
m = 21;
|
||||
s = 15;
|
||||
}
|
||||
else if (timeout == 252)
|
||||
m = 21;
|
||||
else if (timeout <= 240)
|
||||
{
|
||||
s = timeout * 5;
|
||||
m = s / 60;
|
||||
s %= 60;
|
||||
}
|
||||
else
|
||||
{
|
||||
m = (timeout - 240) * 30;
|
||||
h = m / 60;
|
||||
m %= 60;
|
||||
}
|
||||
grub_printf ("%02d:%02d:%02d", h, m, s);
|
||||
}
|
||||
else
|
||||
grub_printf ("invalid or vendor-specific");
|
||||
}
|
||||
|
||||
static int get_int_arg (const struct grub_arg_list *state)
|
||||
{
|
||||
return (state->set ? (int)grub_strtoul (state->arg, 0, 0) : -1);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state????
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
|
||||
/* Check command line. */
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing device name argument");
|
||||
|
||||
grub_size_t len = grub_strlen (args[0]);
|
||||
if (! (args[0][0] == '(' && args[0][len - 1] == ')'))
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name");
|
||||
args[0][len - 1] = 0;
|
||||
|
||||
if (! grub_disk_ata_pass_through)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "ATA pass through not available");
|
||||
|
||||
int i = 0;
|
||||
int apm = get_int_arg (&state[i++]);
|
||||
int power = state[i++].set;
|
||||
int sec_freeze = state[i++].set;
|
||||
int health = state[i++].set;
|
||||
int aam = get_int_arg (&state[i++]);
|
||||
int standby_tout = get_int_arg (&state[i++]);
|
||||
int standby_now = state[i++].set;
|
||||
int sleep_now = state[i++].set;
|
||||
int ident = state[i++].set;
|
||||
int dumpid = state[i++].set;
|
||||
int enable_smart = get_int_arg (&state[i++]);
|
||||
quiet = state[i++].set;
|
||||
|
||||
/* Open disk. */
|
||||
grub_disk_t disk = grub_disk_open (&args[0][1]);
|
||||
if (! disk)
|
||||
return grub_errno;
|
||||
|
||||
if (disk->partition)
|
||||
{
|
||||
grub_disk_close (disk);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed");
|
||||
}
|
||||
|
||||
/* Change settings. */
|
||||
if (aam >= 0)
|
||||
grub_hdparm_set_val_cmd ("Automatic Acoustic Management", (aam ? aam : -1),
|
||||
disk, GRUB_ATA_CMD_SET_FEATURES, (aam ? 0x42 : 0xc2), aam);
|
||||
|
||||
if (apm >= 0)
|
||||
grub_hdparm_set_val_cmd ("Advanced Power Management",
|
||||
(apm != 255 ? apm : -1), disk, GRUB_ATA_CMD_SET_FEATURES,
|
||||
(apm != 255 ? 0x05 : 0x85), (apm != 255 ? apm : 0));
|
||||
|
||||
if (standby_tout >= 0)
|
||||
{
|
||||
if (! quiet)
|
||||
{
|
||||
grub_printf ("Set standby timeout to %d (", standby_tout);
|
||||
grub_hdparm_print_standby_tout (standby_tout);
|
||||
grub_printf (")");
|
||||
}
|
||||
/* The IDLE cmd sets disk to idle mode and configures standby timer. */
|
||||
grub_hdparm_set_val_cmd ("", -1, disk, GRUB_ATA_CMD_IDLE, 0, standby_tout);
|
||||
}
|
||||
|
||||
if (enable_smart >= 0)
|
||||
{
|
||||
if (! quiet)
|
||||
grub_printf ("%sable SMART operations", (enable_smart ? "En" : "Dis"));
|
||||
int err = grub_hdparm_do_smart_cmd (disk, (enable_smart ?
|
||||
GRUB_ATA_FEAT_SMART_ENABLE : GRUB_ATA_FEAT_SMART_DISABLE));
|
||||
if (! quiet)
|
||||
grub_printf ("%s\n", err ? ": not supported" : "");
|
||||
}
|
||||
|
||||
if (sec_freeze)
|
||||
grub_hdparm_simple_cmd ("Freeze security settings", disk,
|
||||
GRUB_ATA_CMD_SECURITY_FREEZE_LOCK);
|
||||
|
||||
/* Print/dump IDENTIFY. */
|
||||
if (ident || dumpid)
|
||||
{
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
if (grub_hdparm_do_ata_cmd (disk, GRUB_ATA_CMD_IDENTIFY_DEVICE,
|
||||
0, 0, buf, sizeof (buf)))
|
||||
grub_printf ("Cannot read ATA IDENTIFY data\n");
|
||||
else
|
||||
{
|
||||
if (ident)
|
||||
grub_hdparm_print_identify (buf);
|
||||
if (dumpid)
|
||||
hexdump (0, buf, sizeof (buf));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check power mode. */
|
||||
if (power)
|
||||
{
|
||||
grub_printf ("Disk power mode is: ");
|
||||
int mode = grub_hdparm_do_check_powermode_cmd (disk);
|
||||
if (mode < 0)
|
||||
grub_printf ("unknown\n");
|
||||
else
|
||||
grub_printf ("%s (0x%02x)\n",
|
||||
(mode == 0xff ? "active/idle" :
|
||||
mode == 0x80 ? "idle" :
|
||||
mode == 0x00 ? "standby" : "unknown"), mode);
|
||||
}
|
||||
|
||||
/* Check health. */
|
||||
int status = 0;
|
||||
if (health)
|
||||
{
|
||||
if (! quiet)
|
||||
grub_printf ("SMART status is: ");
|
||||
int err = grub_hdparm_do_smart_cmd (disk, GRUB_ATA_FEAT_SMART_STATUS);
|
||||
if (! quiet)
|
||||
grub_printf ("%s\n", (err < 0 ? "unknown" :
|
||||
err == 0 ? "OK" : "*BAD*"));
|
||||
status = (err > 0);
|
||||
}
|
||||
|
||||
/* Change power mode. */
|
||||
if (standby_now)
|
||||
grub_hdparm_simple_cmd ("Set disk to standby mode", disk,
|
||||
GRUB_ATA_CMD_STANDBY_IMMEDIATE);
|
||||
|
||||
if (sleep_now)
|
||||
grub_hdparm_simple_cmd ("Set disk to sleep mode", disk,
|
||||
GRUB_ATA_CMD_SLEEP);
|
||||
|
||||
grub_disk_close (disk);
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return status;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(hdparm)
|
||||
{
|
||||
cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[OPTIONS] DISK"),
|
||||
N_("Get/set ATA disk parameters."), options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(hdparm)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
117
commands/help.c
117
commands/help.c
|
@ -1,7 +1,7 @@
|
|||
/* help.c - command to show a help text. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2008,2009 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
|
||||
|
@ -17,90 +17,129 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
/* XXX: This has to be changed into a function so the screen can be
|
||||
optimally used. */
|
||||
#define TERM_WIDTH 80
|
||||
#include <grub/term.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/charset.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_help (struct grub_arg_list *state __attribute__ ((unused)), int argc,
|
||||
grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
|
||||
char **args)
|
||||
|
||||
{
|
||||
int cnt = 0;
|
||||
char *currarg;
|
||||
|
||||
|
||||
auto int print_command_info (grub_command_t cmd);
|
||||
auto int print_command_help (grub_command_t cmd);
|
||||
|
||||
int print_command_info (grub_command_t cmd)
|
||||
{
|
||||
if (grub_command_find (cmd->name))
|
||||
if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) &&
|
||||
(cmd->flags & GRUB_COMMAND_FLAG_CMDLINE))
|
||||
{
|
||||
if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)
|
||||
{
|
||||
char description[TERM_WIDTH / 2];
|
||||
int desclen = grub_strlen (cmd->summary);
|
||||
|
||||
/* Make a string with a length of TERM_WIDTH / 2 - 1 filled
|
||||
with the description followed by spaces. */
|
||||
grub_memset (description, ' ', TERM_WIDTH / 2 - 1);
|
||||
description[TERM_WIDTH / 2 - 1] = '\0';
|
||||
grub_memcpy (description, cmd->summary,
|
||||
(desclen < TERM_WIDTH / 2 - 1
|
||||
? desclen : TERM_WIDTH / 2 - 1));
|
||||
|
||||
grub_printf ("%s%s", description, (cnt++) % 2 ? "\n" : " ");
|
||||
}
|
||||
struct grub_term_output *term;
|
||||
const char *summary_translated = _(cmd->summary);
|
||||
char *command_help;
|
||||
grub_uint32_t *unicode_command_help;
|
||||
grub_uint32_t *unicode_last_position;
|
||||
|
||||
command_help = grub_malloc (grub_strlen (cmd->name) +
|
||||
sizeof (" ") - 1 +
|
||||
grub_strlen (summary_translated));
|
||||
|
||||
grub_sprintf(command_help, "%s %s", cmd->name, summary_translated);
|
||||
|
||||
grub_utf8_to_ucs4_alloc (command_help, &unicode_command_help,
|
||||
&unicode_last_position);
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
{
|
||||
unsigned stringwidth;
|
||||
grub_uint32_t *unicode_last_screen_position;
|
||||
|
||||
unicode_last_screen_position = unicode_command_help;
|
||||
|
||||
stringwidth = 0;
|
||||
|
||||
while (unicode_last_screen_position < unicode_last_position &&
|
||||
stringwidth < ((grub_term_width (term) / 2) - 2))
|
||||
{
|
||||
stringwidth
|
||||
+= grub_term_getcharwidth (term,
|
||||
*unicode_last_screen_position);
|
||||
unicode_last_screen_position++;
|
||||
}
|
||||
|
||||
grub_print_ucs4 (unicode_command_help,
|
||||
unicode_last_screen_position, term);
|
||||
if (!(cnt % 2))
|
||||
grub_print_spaces (term, grub_term_width (term) / 2
|
||||
- stringwidth);
|
||||
}
|
||||
if (cnt % 2)
|
||||
grub_printf ("\n");
|
||||
cnt++;
|
||||
|
||||
grub_free (command_help);
|
||||
grub_free (unicode_command_help);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_command_help (grub_command_t cmd)
|
||||
{
|
||||
if (grub_command_find (cmd->name))
|
||||
if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE)
|
||||
{
|
||||
if (! grub_strncmp (cmd->name, currarg, grub_strlen (currarg)))
|
||||
{
|
||||
if (cnt++ > 0)
|
||||
grub_printf ("\n\n");
|
||||
|
||||
grub_arg_show_help (cmd);
|
||||
|
||||
if (cmd->flags & GRUB_COMMAND_FLAG_EXTCMD)
|
||||
grub_arg_show_help ((grub_extcmd_t) cmd->data);
|
||||
else
|
||||
grub_printf ("%s %s %s\n%s\b", _("Usage:"), cmd->name, _(cmd->summary),
|
||||
_(cmd->description));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (argc == 0)
|
||||
grub_iterate_commands (print_command_info);
|
||||
{
|
||||
grub_command_iterate (print_command_info);
|
||||
if (!(cnt % 2))
|
||||
grub_printf ("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
currarg = args[i];
|
||||
grub_iterate_commands (print_command_help);
|
||||
grub_command_iterate (print_command_help);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(help)
|
||||
{
|
||||
(void)mod; /* To stop warning. */
|
||||
grub_register_command ("help", grub_cmd_help, GRUB_COMMAND_FLAG_CMDLINE,
|
||||
"help [PATTERN ...]", "Show a help message.", 0);
|
||||
cmd = grub_register_extcmd ("help", grub_cmd_help,
|
||||
GRUB_COMMAND_FLAG_CMDLINE,
|
||||
N_("[PATTERN ...]"),
|
||||
N_("Show a help message."), 0);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(help)
|
||||
{
|
||||
grub_unregister_command ("help");
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* hexdump.c - command to dump the contents of a file or memory */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2007,2008,2009 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
|
||||
|
@ -17,91 +17,80 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/hexdump.h>
|
||||
#include <grub/lib/hexdump.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"skip", 's', 0, "skip offset bytes from the beginning of file.", 0,
|
||||
{"skip", 's', 0, N_("Skip offset bytes from the beginning of file."), 0,
|
||||
ARG_TYPE_INT},
|
||||
{"length", 'n', 0, "read only length bytes", 0, ARG_TYPE_INT},
|
||||
{"length", 'n', 0, N_("Read only LENGTH bytes."), 0, ARG_TYPE_INT},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
void
|
||||
hexdump (unsigned long bse, char *buf, int len)
|
||||
{
|
||||
int pos;
|
||||
char line[80];
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
int cnt, i;
|
||||
|
||||
pos = grub_sprintf (line, "%08lx ", bse);
|
||||
cnt = 16;
|
||||
if (cnt > len)
|
||||
cnt = len;
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
pos += grub_sprintf (&line[pos], "%02x ", (unsigned char) buf[i]);
|
||||
if ((i & 7) == 7)
|
||||
line[pos++] = ' ';
|
||||
}
|
||||
|
||||
for (; i < 16; i++)
|
||||
{
|
||||
pos += grub_sprintf (&line[pos], " ");
|
||||
if ((i & 7) == 7)
|
||||
line[pos++] = ' ';
|
||||
}
|
||||
|
||||
line[pos++] = '|';
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
line[pos++] = ((buf[i] >= 32) && (buf[i] < 127)) ? buf[i] : '.';
|
||||
|
||||
line[pos++] = '|';
|
||||
|
||||
line[pos] = 0;
|
||||
|
||||
grub_printf ("%s\n", line);
|
||||
|
||||
bse += 16;
|
||||
buf += 16;
|
||||
len -= cnt;
|
||||
}
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hexdump (struct grub_arg_list *state, int argc, char **args)
|
||||
grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
grub_file_t file;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE * 4];
|
||||
grub_ssize_t size, length;
|
||||
unsigned long skip;
|
||||
int is_file;
|
||||
grub_disk_addr_t skip;
|
||||
int namelen;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
skip = (state[0].set) ? grub_strtoul (state[0].arg, 0, 0) : 0;
|
||||
length = (state[1].set) ? grub_strtoul (state[1].arg, 0, 0) : 0;
|
||||
namelen = grub_strlen (args[0]);
|
||||
skip = (state[0].set) ? grub_strtoull (state[0].arg, 0, 0) : 0;
|
||||
length = (state[1].set) ? grub_strtoul (state[1].arg, 0, 0) : 256;
|
||||
|
||||
is_file = (grub_strcmp (args[0], "(mem)"));
|
||||
if ((!is_file) && (!length))
|
||||
length = 256;
|
||||
|
||||
if (is_file)
|
||||
if (!grub_strcmp (args[0], "(mem)"))
|
||||
hexdump (skip, (char *) (grub_addr_t) skip, length);
|
||||
else if ((args[0][0] == '(') && (args[0][namelen - 1] == ')'))
|
||||
{
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t sector;
|
||||
grub_size_t ofs;
|
||||
|
||||
args[0][namelen - 1] = 0;
|
||||
disk = grub_disk_open (&args[0][1]);
|
||||
if (! disk)
|
||||
return 0;
|
||||
|
||||
sector = (skip >> (GRUB_DISK_SECTOR_BITS + 2)) * 4;
|
||||
ofs = skip & (GRUB_DISK_SECTOR_SIZE * 4 - 1);
|
||||
while (length)
|
||||
{
|
||||
grub_size_t len;
|
||||
|
||||
len = length;
|
||||
if (len > sizeof (buf))
|
||||
len = sizeof (buf);
|
||||
|
||||
if (grub_disk_read (disk, sector, ofs, len, buf))
|
||||
break;
|
||||
|
||||
hexdump (skip, buf, len);
|
||||
|
||||
ofs = 0;
|
||||
skip += len;
|
||||
length -= len;
|
||||
sector += 4;
|
||||
}
|
||||
|
||||
grub_disk_close (disk);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_file_t file;
|
||||
|
||||
file = grub_gzfile_open (args[0], 1);
|
||||
if (!file)
|
||||
if (! file)
|
||||
return 0;
|
||||
|
||||
file->offset = skip;
|
||||
|
@ -123,22 +112,22 @@ grub_cmd_hexdump (struct grub_arg_list *state, int argc, char **args)
|
|||
|
||||
grub_file_close (file);
|
||||
}
|
||||
else
|
||||
hexdump (skip, (char *) skip, length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT (hexdump)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
grub_register_command ("hexdump", grub_cmd_hexdump, GRUB_COMMAND_FLAG_BOTH,
|
||||
"hexdump [ -s offset ] [-n length] { FILE | (mem) }",
|
||||
"Dump the contents of a file or memory.", options);
|
||||
cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[OPTIONS] FILE_OR_DEVICE"),
|
||||
N_("Dump the contents of a file or memory."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (hexdump)
|
||||
{
|
||||
grub_unregister_command ("hexdump");
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* cpuid.c - test for CPU features */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006, 2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
|
||||
* Based on gcc/gcc/config/i386/driver-i386.c
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
|
@ -18,41 +18,46 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i386/cpuid.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#define cpuid(num,a,b,c,d) \
|
||||
asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
|
||||
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
|
||||
: "0" (num))
|
||||
|
||||
#define bit_LM (1 << 29)
|
||||
|
||||
unsigned char has_longmode = 0;
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"long-mode", 'l', 0, "check for long mode flag (default)", 0, 0},
|
||||
{"long-mode", 'l', 0, N_("Check for long mode flag (default)."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#define bit_LM (1 << 29)
|
||||
|
||||
unsigned char grub_cpuid_has_longmode = 0;
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_cpuid (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
grub_cmd_cpuid (grub_extcmd_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
return !has_longmode;
|
||||
return grub_cpuid_has_longmode ? GRUB_ERR_NONE
|
||||
: grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(cpuid)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
/* grub-emu */
|
||||
has_longmode = 1;
|
||||
grub_cpuid_has_longmode = 1;
|
||||
#else
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
unsigned int max_level;
|
||||
|
@ -79,15 +84,15 @@ GRUB_MOD_INIT(cpuid)
|
|||
goto done;
|
||||
|
||||
cpuid (0x80000001, eax, ebx, ecx, edx);
|
||||
has_longmode = !!(edx & bit_LM);
|
||||
grub_cpuid_has_longmode = !!(edx & bit_LM);
|
||||
done:
|
||||
#endif
|
||||
|
||||
grub_register_command ("cpuid", grub_cmd_cpuid, GRUB_COMMAND_FLAG_CMDLINE,
|
||||
"cpuid", "Check for CPU features", options);
|
||||
cmd = grub_register_extcmd ("cpuid", grub_cmd_cpuid, GRUB_COMMAND_FLAG_BOTH,
|
||||
"[-l]", N_("Check for CPU features."), options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(cpuid)
|
||||
{
|
||||
grub_unregister_command ("cpuid");
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
||||
|
|
81
commands/i386/pc/acpi.c
Normal file
81
commands/i386/pc/acpi.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* acpi.c - get acpi tables. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/acpi.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
struct grub_acpi_rsdp_v10 *
|
||||
grub_machine_acpi_get_rsdpv1 (void)
|
||||
{
|
||||
int ebda_len;
|
||||
grub_uint8_t *ebda, *ptr;
|
||||
|
||||
grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n");
|
||||
ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4);
|
||||
ebda_len = * (grub_uint16_t *) ebda;
|
||||
if (! ebda_len)
|
||||
return 0;
|
||||
for (ptr = ebda; ptr < ebda + 0x400; ptr += 16)
|
||||
if (grub_memcmp (ptr, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0)
|
||||
return (struct grub_acpi_rsdp_v10 *) ptr;
|
||||
|
||||
grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n");
|
||||
for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000;
|
||||
ptr += 16)
|
||||
if (grub_memcmp (ptr, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0)
|
||||
return (struct grub_acpi_rsdp_v10 *) ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct grub_acpi_rsdp_v20 *
|
||||
grub_machine_acpi_get_rsdpv2 (void)
|
||||
{
|
||||
int ebda_len;
|
||||
grub_uint8_t *ebda, *ptr;
|
||||
|
||||
grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n");
|
||||
ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4);
|
||||
ebda_len = * (grub_uint16_t *) ebda;
|
||||
if (! ebda_len)
|
||||
return 0;
|
||||
for (ptr = ebda; ptr < ebda + 0x400; ptr += 16)
|
||||
if (grub_memcmp (ptr, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& ((struct grub_acpi_rsdp_v10 *) ptr)->revision != 0
|
||||
&& ((struct grub_acpi_rsdp_v20 *) ptr)->length < 1024
|
||||
&& grub_byte_checksum (ptr, ((struct grub_acpi_rsdp_v20 *) ptr)->length)
|
||||
== 0)
|
||||
return (struct grub_acpi_rsdp_v20 *) ptr;
|
||||
|
||||
grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n");
|
||||
for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000;
|
||||
ptr += 16)
|
||||
if (grub_memcmp (ptr, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& ((struct grub_acpi_rsdp_v10 *) ptr)->revision != 0
|
||||
&& ((struct grub_acpi_rsdp_v20 *) ptr)->length < 1024
|
||||
&& grub_byte_checksum (ptr, ((struct grub_acpi_rsdp_v20 *) ptr)->length)
|
||||
== 0)
|
||||
return (struct grub_acpi_rsdp_v20 *) ptr;
|
||||
return 0;
|
||||
}
|
422
commands/i386/pc/drivemap.c
Normal file
422
commands/i386/pc/drivemap.c
Normal file
|
@ -0,0 +1,422 @@
|
|||
/* drivemap.c - command to manage the BIOS drive mappings. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008, 2009 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/extcmd.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/biosnum.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
|
||||
/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
|
||||
static grub_uint32_t *const int13slot = UINT_TO_PTR (4 * 0x13);
|
||||
|
||||
/* Remember to update enum opt_idxs accordingly. */
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"list", 'l', 0, N_("Show the current mappings."), 0, 0},
|
||||
{"reset", 'r', 0, N_("Reset all mappings to the default values."), 0, 0},
|
||||
{"swap", 's', 0, N_("Perform both direct and reverse mappings."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Remember to update options[] accordingly. */
|
||||
enum opt_idxs
|
||||
{
|
||||
OPTIDX_LIST = 0,
|
||||
OPTIDX_RESET,
|
||||
OPTIDX_SWAP,
|
||||
};
|
||||
|
||||
/* Realmode far ptr (2 * 16b) to the previous INT13h handler. */
|
||||
extern grub_uint32_t grub_drivemap_oldhandler;
|
||||
|
||||
/* The type "void" is used for imported assembly labels, takes no storage and
|
||||
serves just to take the address with &label. */
|
||||
|
||||
/* The assembly function to replace the old INT13h handler. It does not follow
|
||||
any C callspecs and returns with IRET. */
|
||||
extern const void grub_drivemap_handler;
|
||||
|
||||
/* Start of the drive mappings area (space reserved at runtime). */
|
||||
extern const void grub_drivemap_mapstart;
|
||||
|
||||
typedef struct drivemap_node
|
||||
{
|
||||
struct drivemap_node *next;
|
||||
grub_uint8_t newdrive;
|
||||
grub_uint8_t redirto;
|
||||
} drivemap_node_t;
|
||||
|
||||
typedef struct __attribute__ ((packed)) int13map_node
|
||||
{
|
||||
grub_uint8_t disknum;
|
||||
grub_uint8_t mapto;
|
||||
} int13map_node_t;
|
||||
|
||||
#define INT13H_OFFSET(x) \
|
||||
(((grub_uint8_t *)(x)) - ((grub_uint8_t *)&grub_drivemap_handler))
|
||||
|
||||
static drivemap_node_t *map_head;
|
||||
static void *drivemap_hook;
|
||||
static int drivemap_mmap;
|
||||
|
||||
/* Puts the specified mapping into the table, replacing an existing mapping
|
||||
for newdrive or adding a new one if required. */
|
||||
static grub_err_t
|
||||
drivemap_set (grub_uint8_t newdrive, grub_uint8_t redirto)
|
||||
{
|
||||
drivemap_node_t *mapping = 0;
|
||||
drivemap_node_t *search = map_head;
|
||||
while (search)
|
||||
{
|
||||
if (search->newdrive == newdrive)
|
||||
{
|
||||
mapping = search;
|
||||
break;
|
||||
}
|
||||
search = search->next;
|
||||
}
|
||||
|
||||
/* Check for pre-existing mappings to modify before creating a new one. */
|
||||
if (mapping)
|
||||
mapping->redirto = redirto;
|
||||
else
|
||||
{
|
||||
mapping = grub_malloc (sizeof (drivemap_node_t));
|
||||
if (! mapping)
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"cannot allocate map entry, not enough memory");
|
||||
mapping->newdrive = newdrive;
|
||||
mapping->redirto = redirto;
|
||||
mapping->next = map_head;
|
||||
map_head = mapping;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Removes the mapping for newdrive from the table. If there is no mapping,
|
||||
then this function behaves like a no-op on the map. */
|
||||
static void
|
||||
drivemap_remove (grub_uint8_t newdrive)
|
||||
{
|
||||
drivemap_node_t *mapping = 0;
|
||||
drivemap_node_t *search = map_head;
|
||||
drivemap_node_t *previous = 0;
|
||||
|
||||
while (search)
|
||||
{
|
||||
if (search->newdrive == newdrive)
|
||||
{
|
||||
mapping = search;
|
||||
break;
|
||||
}
|
||||
previous = search;
|
||||
search = search->next;
|
||||
}
|
||||
|
||||
if (mapping)
|
||||
{
|
||||
if (previous)
|
||||
previous->next = mapping->next;
|
||||
else
|
||||
map_head = mapping->next;
|
||||
grub_free (mapping);
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a GRUB-like device name and a convenient location, stores the
|
||||
related BIOS disk number. Accepts devices like \((f|h)dN\), with
|
||||
0 <= N < 128. */
|
||||
static grub_err_t
|
||||
tryparse_diskstring (const char *str, grub_uint8_t *output)
|
||||
{
|
||||
/* Skip opening paren in order to allow both (hd0) and hd0. */
|
||||
if (*str == '(')
|
||||
str++;
|
||||
if ((str[0] == 'f' || str[0] == 'h') && str[1] == 'd')
|
||||
{
|
||||
grub_uint8_t bios_num = (str[0] == 'h') ? 0x80 : 0x00;
|
||||
unsigned long drivenum = grub_strtoul (str + 2, 0, 0);
|
||||
if (grub_errno == GRUB_ERR_NONE && drivenum < 128)
|
||||
{
|
||||
bios_num |= drivenum;
|
||||
if (output)
|
||||
*output = bios_num;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device format \"%s\" "
|
||||
"invalid: must be (f|h)dN, with 0 <= N < 128", str);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
list_mappings (void)
|
||||
{
|
||||
/* Show: list mappings. */
|
||||
if (! map_head)
|
||||
{
|
||||
grub_printf ("No drives have been remapped\n");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_printf ("OS disk #num ------> GRUB/BIOS device\n");
|
||||
drivemap_node_t *curnode = map_head;
|
||||
while (curnode)
|
||||
{
|
||||
grub_printf ("%cD #%-3u (0x%02x) %cd%d\n",
|
||||
(curnode->newdrive & 0x80) ? 'H' : 'F',
|
||||
curnode->newdrive & 0x7F, curnode->newdrive,
|
||||
(curnode->redirto & 0x80) ? 'h' : 'f',
|
||||
curnode->redirto & 0x7F
|
||||
);
|
||||
curnode = curnode->next;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args)
|
||||
{
|
||||
if (cmd->state[OPTIDX_LIST].set)
|
||||
{
|
||||
return list_mappings ();
|
||||
}
|
||||
else if (cmd->state[OPTIDX_RESET].set)
|
||||
{
|
||||
/* Reset: just delete all mappings, freeing their memory. */
|
||||
drivemap_node_t *curnode = map_head;
|
||||
drivemap_node_t *prevnode = 0;
|
||||
while (curnode)
|
||||
{
|
||||
prevnode = curnode;
|
||||
curnode = curnode->next;
|
||||
grub_free (prevnode);
|
||||
}
|
||||
map_head = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
else if (!cmd->state[OPTIDX_SWAP].set && argc == 0)
|
||||
{
|
||||
/* No arguments */
|
||||
return list_mappings ();
|
||||
}
|
||||
|
||||
/* Neither flag: put mapping. */
|
||||
grub_uint8_t mapfrom = 0;
|
||||
grub_uint8_t mapto = 0xFF;
|
||||
grub_err_t err;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
|
||||
|
||||
err = tryparse_diskstring (args[0], &mapfrom);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
||||
err = tryparse_diskstring (args[1], &mapto);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
||||
if (mapto == mapfrom)
|
||||
{
|
||||
/* Reset to default. */
|
||||
grub_dprintf ("drivemap", "Removing mapping for %s (%02x)\n",
|
||||
args[0], mapfrom);
|
||||
drivemap_remove (mapfrom);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
/* Set the mapping for the disk (overwrites any existing mapping). */
|
||||
grub_dprintf ("drivemap", "%s %s (%02x) = %s (%02x)\n",
|
||||
cmd->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping",
|
||||
args[1], mapto, args[0], mapfrom);
|
||||
err = drivemap_set (mapto, mapfrom);
|
||||
/* If -s, perform the reverse mapping too (only if the first was OK). */
|
||||
if (cmd->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE)
|
||||
err = drivemap_set (mapfrom, mapto);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Int13h handler installer - reserves conventional memory for the handler,
|
||||
copies it over and sets the IVT entry for int13h.
|
||||
This code rests on the assumption that GRUB does not activate any kind
|
||||
of memory mapping apart from identity paging, since it accesses
|
||||
realmode structures by their absolute addresses, like the IVT at 0;
|
||||
and transforms a pmode pointer into a rmode seg:off far ptr. */
|
||||
static grub_err_t
|
||||
install_int13_handler (int noret __attribute__ ((unused)))
|
||||
{
|
||||
/* Size of the full int13 handler "bundle", including code and map. */
|
||||
grub_uint32_t total_size;
|
||||
/* Base address of the space reserved for the handler bundle. */
|
||||
grub_uint8_t *handler_base = 0;
|
||||
/* Address of the map within the deployed bundle. */
|
||||
int13map_node_t *handler_map;
|
||||
|
||||
int i;
|
||||
int entries = 0;
|
||||
drivemap_node_t *curentry = map_head;
|
||||
|
||||
/* Count entries to prepare a contiguous map block. */
|
||||
while (curentry)
|
||||
{
|
||||
entries++;
|
||||
curentry = curentry->next;
|
||||
}
|
||||
if (entries == 0)
|
||||
{
|
||||
/* No need to install the int13h handler. */
|
||||
grub_dprintf ("drivemap", "No drives marked as remapped, not installing "
|
||||
"our int13h handler.\n");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_dprintf ("drivemap", "Installing our int13h handler\n");
|
||||
|
||||
/* Save the pointer to the old handler. */
|
||||
grub_drivemap_oldhandler = *int13slot;
|
||||
grub_dprintf ("drivemap", "Original int13 handler: %04x:%04x\n",
|
||||
(grub_drivemap_oldhandler >> 16) & 0x0ffff,
|
||||
grub_drivemap_oldhandler & 0x0ffff);
|
||||
|
||||
/* Find a rmode-segment-aligned zone in conventional memory big
|
||||
enough to hold the handler and its data. */
|
||||
total_size = INT13H_OFFSET (&grub_drivemap_mapstart)
|
||||
+ (entries + 1) * sizeof (int13map_node_t);
|
||||
grub_dprintf ("drivemap", "Payload is %u bytes long\n", total_size);
|
||||
handler_base = grub_mmap_malign_and_register (16, total_size,
|
||||
&drivemap_mmap,
|
||||
GRUB_MACHINE_MEMORY_RESERVED,
|
||||
GRUB_MMAP_MALLOC_LOW);
|
||||
if (! handler_base)
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't reserve "
|
||||
"memory for the int13h handler");
|
||||
|
||||
/* Copy int13h handler bundle to reserved area. */
|
||||
grub_dprintf ("drivemap", "Reserved memory at %p, copying handler\n",
|
||||
handler_base);
|
||||
grub_memcpy (handler_base, &grub_drivemap_handler,
|
||||
INT13H_OFFSET (&grub_drivemap_mapstart));
|
||||
|
||||
/* Copy the mappings to the reserved area. */
|
||||
curentry = map_head;
|
||||
handler_map = (int13map_node_t *) (handler_base +
|
||||
INT13H_OFFSET (&grub_drivemap_mapstart));
|
||||
grub_dprintf ("drivemap", "Target map at %p, copying mappings\n", handler_map);
|
||||
for (i = 0; i < entries; ++i, curentry = curentry->next)
|
||||
{
|
||||
handler_map[i].disknum = curentry->newdrive;
|
||||
handler_map[i].mapto = curentry->redirto;
|
||||
grub_dprintf ("drivemap", "\t#%d: 0x%02x <- 0x%02x\n", i,
|
||||
handler_map[i].disknum, handler_map[i].mapto);
|
||||
}
|
||||
/* Signal end-of-map. */
|
||||
handler_map[i].disknum = 0;
|
||||
handler_map[i].mapto = 0;
|
||||
grub_dprintf ("drivemap", "\t#%d: 0x00 <- 0x00 (end)\n", i);
|
||||
|
||||
/* Install our function as the int13h handler in the IVT. */
|
||||
*int13slot = ((grub_uint32_t) handler_base) << 12; /* Segment address. */
|
||||
grub_dprintf ("drivemap", "New int13 handler: %04x:%04x\n",
|
||||
(*int13slot >> 16) & 0x0ffff, *int13slot & 0x0ffff);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
uninstall_int13_handler (void)
|
||||
{
|
||||
if (! grub_drivemap_oldhandler)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
*int13slot = grub_drivemap_oldhandler;
|
||||
grub_mmap_free_and_unregister (drivemap_mmap);
|
||||
grub_drivemap_oldhandler = 0;
|
||||
grub_dprintf ("drivemap", "Restored int13 handler: %04x:%04x\n",
|
||||
(*int13slot >> 16) & 0x0ffff, *int13slot & 0x0ffff);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_get_root_biosnumber_drivemap (void)
|
||||
{
|
||||
char *biosnum;
|
||||
int ret = -1;
|
||||
grub_device_t dev;
|
||||
|
||||
biosnum = grub_env_get ("biosnum");
|
||||
|
||||
if (biosnum)
|
||||
return grub_strtoul (biosnum, 0, 0);
|
||||
|
||||
dev = grub_device_open (0);
|
||||
if (dev && dev->disk && dev->disk->dev
|
||||
&& dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID)
|
||||
{
|
||||
drivemap_node_t *curnode = map_head;
|
||||
ret = (int) dev->disk->id;
|
||||
while (curnode)
|
||||
{
|
||||
if (curnode->redirto == ret)
|
||||
{
|
||||
ret = curnode->newdrive;
|
||||
break;
|
||||
}
|
||||
curnode = curnode->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
static int (*grub_get_root_biosnumber_saved) (void);
|
||||
|
||||
GRUB_MOD_INIT (drivemap)
|
||||
{
|
||||
grub_get_root_biosnumber_saved = grub_get_root_biosnumber;
|
||||
grub_get_root_biosnumber = grub_get_root_biosnumber_drivemap;
|
||||
cmd = grub_register_extcmd ("drivemap", grub_cmd_drivemap,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"drivemap"
|
||||
N_("-l | -r | [-s] grubdev osdisk."),
|
||||
N_("Manage the BIOS drive mappings."),
|
||||
options);
|
||||
drivemap_hook =
|
||||
grub_loader_register_preboot_hook (&install_int13_handler,
|
||||
&uninstall_int13_handler,
|
||||
GRUB_LOADER_PREBOOT_HOOK_PRIO_NORMAL);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (drivemap)
|
||||
{
|
||||
grub_get_root_biosnumber = grub_get_root_biosnumber_saved;
|
||||
grub_loader_unregister_preboot_hook (drivemap_hook);
|
||||
drivemap_hook = 0;
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
119
commands/i386/pc/drivemap_int13h.S
Normal file
119
commands/i386/pc/drivemap_int13h.S
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* drivemap_int13h.S - interrupt handler for the BIOS drive remapper */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008, 2009 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/symbol.h>
|
||||
|
||||
#define INT13H_OFFSET(x) ((x) - EXT_C(grub_drivemap_handler))
|
||||
|
||||
.code16
|
||||
|
||||
/* Copy starts here. When deployed, this code must be segment-aligned. */
|
||||
|
||||
/* The replacement int13 handler. Preserve all registers. */
|
||||
FUNCTION(grub_drivemap_handler)
|
||||
/* Save %dx for future restore. */
|
||||
push %dx
|
||||
/* Push flags. Used to simulate interrupt with original flags. */
|
||||
pushf
|
||||
|
||||
/* Map the drive number (always in DL). */
|
||||
push %ax
|
||||
push %bx
|
||||
#ifdef APPLE_CC
|
||||
grub_drivemap_mapstart_ofs = INT13H_OFFSET(EXT_C(grub_drivemap_mapstart))
|
||||
movw $grub_drivemap_mapstart_ofs, %bx
|
||||
#else
|
||||
movw $INT13H_OFFSET(EXT_C(grub_drivemap_mapstart)), %bx
|
||||
#endif
|
||||
|
||||
more_remaining:
|
||||
movw %cs:(%bx), %ax
|
||||
cmpb %ah, %al
|
||||
jz not_found /* DRV=DST => map end - drive not remapped, keep DL. */
|
||||
inc %bx
|
||||
inc %bx
|
||||
cmpb %dl, %al
|
||||
jnz more_remaining /* Not found, but more remaining, loop. */
|
||||
movb %ah, %dl /* Found - drive remapped, modify DL. */
|
||||
|
||||
not_found:
|
||||
pop %bx
|
||||
pop %ax
|
||||
|
||||
/* If the call isn't ah=0x8 or ah=0x15 we must restore %dx. */
|
||||
cmpb $0x8, %ah
|
||||
jz norestore
|
||||
cmpb $0x15, %ah
|
||||
jz norestore
|
||||
|
||||
/* Restore flags. */
|
||||
popf
|
||||
pushf
|
||||
|
||||
#ifdef APPLE_CC
|
||||
grub_drivemap_oldhandler_ofs = INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
|
||||
lcall *%cs:grub_drivemap_oldhandler_ofs
|
||||
#else
|
||||
lcall *%cs:INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
|
||||
#endif
|
||||
|
||||
push %bp
|
||||
mov %sp, %bp
|
||||
|
||||
tail:
|
||||
/* Save new flags below %esp so the caller will recieve new flags. */
|
||||
pushf
|
||||
pop %dx
|
||||
mov %dx, 8(%bp)
|
||||
|
||||
pop %bp
|
||||
|
||||
/* Restore %dx. */
|
||||
pop %dx
|
||||
iret
|
||||
|
||||
norestore:
|
||||
|
||||
/* Restore flags. */
|
||||
popf
|
||||
pushf
|
||||
|
||||
#ifdef APPLE_CC
|
||||
lcall *%cs:grub_drivemap_oldhandler_ofs
|
||||
#else
|
||||
lcall *%cs:INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
|
||||
#endif
|
||||
|
||||
push %bp
|
||||
mov %sp, %bp
|
||||
|
||||
/* Save %dx. So it won't be restored to original value. */
|
||||
mov %dx, 2(%bp)
|
||||
|
||||
jmp tail
|
||||
|
||||
/* Far pointer to the old handler. Stored as a CS:IP in the style of real-mode
|
||||
IVT entries (thus PI:SC in mem). */
|
||||
VARIABLE(grub_drivemap_oldhandler)
|
||||
.word 0x0, 0x0
|
||||
|
||||
/* This label MUST be at the end of the copied block, since the installer code
|
||||
reserves additional space for mappings at runtime and copies them over it. */
|
||||
.align 2
|
||||
VARIABLE(grub_drivemap_mapstart)
|
|
@ -1,7 +1,7 @@
|
|||
/* halt.c - command to halt the computer. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2009 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
|
||||
|
@ -17,23 +17,24 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/machine/init.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"no-apm", 'n', 0, "do not use APM to halt the computer", 0, 0},
|
||||
{"no-apm", 'n', 0, N_("Do not use APM to halt the computer."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_halt (struct grub_arg_list *state,
|
||||
grub_cmd_halt (grub_extcmd_t cmd,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
int no_apm = 0;
|
||||
if (state[0].set)
|
||||
no_apm = 1;
|
||||
|
@ -41,17 +42,17 @@ grub_cmd_halt (struct grub_arg_list *state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(halt)
|
||||
{
|
||||
(void)mod; /* To stop warning. */
|
||||
grub_register_command ("halt", grub_cmd_halt, GRUB_COMMAND_FLAG_BOTH,
|
||||
"halt [-n]",
|
||||
"Halt the system, if possible using APM", options);
|
||||
cmd = grub_register_extcmd ("halt", grub_cmd_halt, GRUB_COMMAND_FLAG_BOTH,
|
||||
"[-n]",
|
||||
N_("Halt the system, if possible using APM."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(halt)
|
||||
{
|
||||
grub_unregister_command ("halt");
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* play.c - command to play a tune */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2009 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
|
||||
|
@ -19,15 +19,15 @@
|
|||
|
||||
/* Lots of this file is borrowed from GNU/Hurd generic-speaker driver. */
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/machine/time.h>
|
||||
#include <grub/cpu/io.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#define BASE_TEMPO 120
|
||||
|
||||
|
@ -144,7 +144,7 @@ beep_on (short pitch)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_play (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_file_t file;
|
||||
|
@ -159,7 +159,7 @@ grub_cmd_play (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
if (! file)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
|
||||
|
||||
if (grub_file_read (file, (void *) &tempo, sizeof(tempo)) != sizeof(tempo))
|
||||
if (grub_file_read (file, &tempo, sizeof(tempo)) != sizeof(tempo))
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_error (GRUB_ERR_FILE_READ_ERROR,
|
||||
|
@ -168,11 +168,11 @@ grub_cmd_play (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
|
||||
grub_dprintf ("play","tempo = %d\n", tempo);
|
||||
|
||||
while (grub_file_read (file, (void *) &buf,
|
||||
while (grub_file_read (file, &buf,
|
||||
sizeof (struct note)) == sizeof (struct note)
|
||||
&& buf.pitch != T_FINE && grub_checkkey () < 0)
|
||||
{
|
||||
|
||||
|
||||
grub_dprintf ("play", "pitch = %d, duration = %d\n", buf.pitch,
|
||||
buf.duration);
|
||||
|
||||
|
@ -203,15 +203,15 @@ grub_cmd_play (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(play)
|
||||
{
|
||||
(void)mod; /* To stop warning. */
|
||||
grub_register_command ("play", grub_cmd_play, GRUB_COMMAND_FLAG_BOTH,
|
||||
"play FILE", "Play a tune", 0);
|
||||
cmd = grub_register_command ("play", grub_cmd_play,
|
||||
N_("FILE"), N_("Play a tune."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(play)
|
||||
{
|
||||
grub_unregister_command ("play");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* reboot.c - command to reboot the computer. */
|
||||
/* pxe.c - command to control the pxe driver */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2008,2009 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
|
||||
|
@ -17,29 +17,36 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/machine/pxe.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_reboot (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
grub_reboot ();
|
||||
if (! grub_pxe_pxenv)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment");
|
||||
|
||||
grub_pxe_unload ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
GRUB_MOD_INIT(ieee1275_reboot)
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(pxecmd)
|
||||
{
|
||||
(void)mod; /* To stop warning. */
|
||||
grub_register_command ("reboot", grub_cmd_reboot, GRUB_COMMAND_FLAG_BOTH,
|
||||
"reboot", "Reboot the computer", 0);
|
||||
cmd = grub_register_command ("pxe_unload", grub_cmd_pxe_unload,
|
||||
0,
|
||||
N_("Unload PXE environment."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(ieee1275_reboot)
|
||||
GRUB_MOD_FINI(pxecmd)
|
||||
{
|
||||
grub_unregister_command ("reboot");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* vbeinfo.c - command to list compatible VBE video modes. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2008,2009 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
|
||||
|
@ -17,14 +17,14 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/machine/init.h>
|
||||
#include <grub/machine/vbe.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static void *
|
||||
real2pm (grub_vbe_farptr_t ptr)
|
||||
|
@ -34,7 +34,7 @@ real2pm (grub_vbe_farptr_t ptr)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_vbeinfo (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
grub_cmd_vbeinfo (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
|
@ -48,31 +48,43 @@ grub_cmd_vbeinfo (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
grub_err_t err;
|
||||
char *modevar;
|
||||
|
||||
grub_printf ("List of compatible video modes:\n");
|
||||
|
||||
err = grub_vbe_probe (&controller_info);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
||||
grub_printf ("VBE info: version: %d.%d OEM software rev: %d.%d\n",
|
||||
controller_info.version >> 8,
|
||||
controller_info.version & 0xFF,
|
||||
controller_info.oem_software_rev >> 8,
|
||||
controller_info.oem_software_rev & 0xFF);
|
||||
|
||||
/* The total_memory field is in 64 KiB units. */
|
||||
grub_printf (" total memory: %d KiB\n",
|
||||
(controller_info.total_memory << 16) / 1024);
|
||||
|
||||
/* Because the information on video modes is stored in a temporary place,
|
||||
it is better to copy it to somewhere safe. */
|
||||
p = video_mode_list = real2pm (controller_info.video_mode_ptr);
|
||||
while (*p++ != 0xFFFF)
|
||||
;
|
||||
|
||||
|
||||
video_mode_list_size = (grub_addr_t) p - (grub_addr_t) video_mode_list;
|
||||
saved_video_mode_list = grub_malloc (video_mode_list_size);
|
||||
if (! saved_video_mode_list)
|
||||
return grub_errno;
|
||||
|
||||
grub_memcpy (saved_video_mode_list, video_mode_list, video_mode_list_size);
|
||||
|
||||
|
||||
grub_printf ("List of compatible video modes:\n");
|
||||
grub_printf ("Legend: P=Packed pixel, D=Direct color, "
|
||||
"mask/pos=R/G/B/reserved\n");
|
||||
|
||||
/* Walk through all video modes listed. */
|
||||
for (p = saved_video_mode_list; *p != 0xFFFF; p++)
|
||||
{
|
||||
const char *memory_model = 0;
|
||||
grub_uint32_t mode = (grub_uint32_t) *p;
|
||||
|
||||
|
||||
err = grub_vbe_get_video_mode_info (mode, &mode_info_tmp);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
{
|
||||
|
@ -80,33 +92,33 @@ grub_cmd_vbeinfo (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((mode_info_tmp.mode_attributes & 0x001) == 0)
|
||||
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_SUPPORTED) == 0)
|
||||
/* If not available, skip it. */
|
||||
continue;
|
||||
|
||||
if ((mode_info_tmp.mode_attributes & 0x002) == 0)
|
||||
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_RESERVED_1) == 0)
|
||||
/* Not enough information. */
|
||||
continue;
|
||||
|
||||
if ((mode_info_tmp.mode_attributes & 0x008) == 0)
|
||||
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_COLOR) == 0)
|
||||
/* Monochrome is unusable. */
|
||||
continue;
|
||||
|
||||
if ((mode_info_tmp.mode_attributes & 0x080) == 0)
|
||||
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_LFB_AVAIL) == 0)
|
||||
/* We support only linear frame buffer modes. */
|
||||
continue;
|
||||
|
||||
if ((mode_info_tmp.mode_attributes & 0x010) == 0)
|
||||
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_GRAPHICS) == 0)
|
||||
/* We allow only graphical modes. */
|
||||
continue;
|
||||
|
||||
switch (mode_info_tmp.memory_model)
|
||||
{
|
||||
case 0x04:
|
||||
memory_model = "Packed Pixel";
|
||||
case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
|
||||
memory_model = "Packed";
|
||||
break;
|
||||
case 0x06:
|
||||
memory_model = "Direct Color";
|
||||
case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
|
||||
memory_model = "Direct";
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -116,16 +128,29 @@ grub_cmd_vbeinfo (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
if (! memory_model)
|
||||
continue;
|
||||
|
||||
grub_printf ("0x%03x: %d x %d x %d bpp (%s)\n",
|
||||
mode,
|
||||
grub_printf ("0x%03x: %4d x %4d x %2d %s",
|
||||
mode,
|
||||
mode_info_tmp.x_resolution,
|
||||
mode_info_tmp.y_resolution,
|
||||
mode_info_tmp.bits_per_pixel,
|
||||
memory_model);
|
||||
memory_model);
|
||||
|
||||
/* Show mask and position details for direct color modes. */
|
||||
if (mode_info_tmp.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR)
|
||||
grub_printf (", mask: %d/%d/%d/%d pos: %d/%d/%d/%d",
|
||||
mode_info_tmp.red_mask_size,
|
||||
mode_info_tmp.green_mask_size,
|
||||
mode_info_tmp.blue_mask_size,
|
||||
mode_info_tmp.rsvd_mask_size,
|
||||
mode_info_tmp.red_field_position,
|
||||
mode_info_tmp.green_field_position,
|
||||
mode_info_tmp.blue_field_position,
|
||||
mode_info_tmp.rsvd_field_position);
|
||||
grub_printf ("\n");
|
||||
}
|
||||
|
||||
grub_free (saved_video_mode_list);
|
||||
|
||||
|
||||
/* Check existence of vbe_mode environment variable. */
|
||||
modevar = grub_env_get ("vbe_mode");
|
||||
|
||||
|
@ -145,18 +170,16 @@ grub_cmd_vbeinfo (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(vbeinfo)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
grub_register_command ("vbeinfo",
|
||||
grub_cmd_vbeinfo,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"vbeinfo",
|
||||
"List compatible VESA BIOS extension video modes.",
|
||||
0);
|
||||
cmd =
|
||||
grub_register_command ("vbeinfo", grub_cmd_vbeinfo, 0,
|
||||
N_("List compatible VESA BIOS extension video modes."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(vbeinfo)
|
||||
{
|
||||
grub_unregister_command ("vbeinfo");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
|
|
|
@ -19,16 +19,16 @@
|
|||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/machine/init.h>
|
||||
#include <grub/machine/vbe.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_vbetest (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
grub_cmd_vbetest (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
|
@ -74,7 +74,7 @@ grub_cmd_vbetest (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
grub_printf ("Old video mode = %04x\n", old_mode);
|
||||
else
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
|
||||
/* Check existence of vbe_mode environment variable. */
|
||||
modevar = grub_env_get ("vbe_mode");
|
||||
if (modevar != 0)
|
||||
|
@ -91,7 +91,7 @@ grub_cmd_vbetest (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
err = grub_vbe_get_video_mode_info (use_mode, &mode_info);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
||||
|
||||
/* Dump out details about the mode being tested. */
|
||||
grub_printf ("mode: 0x%03x\n",
|
||||
use_mode);
|
||||
|
@ -156,24 +156,23 @@ grub_cmd_vbetest (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
|
||||
grub_getkey ();
|
||||
|
||||
grub_video_restore ();
|
||||
|
||||
/* Restore old video mode. */
|
||||
grub_vbe_set_video_mode (old_mode, 0);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(vbetest)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
grub_register_command ("vbetest",
|
||||
grub_cmd_vbetest,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"vbetest",
|
||||
"Test VESA BIOS Extension 2.0+ support",
|
||||
0);
|
||||
cmd = grub_register_command ("vbetest", grub_cmd_vbetest,
|
||||
0, N_("Test VESA BIOS Extension 2.0+ support."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(vbetest)
|
||||
{
|
||||
grub_unregister_command ("vbetest");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
|
|
|
@ -17,14 +17,15 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_suspend (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
grub_cmd_suspend (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
|
@ -34,15 +35,15 @@ grub_cmd_suspend (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(ieee1275_suspend)
|
||||
{
|
||||
(void)mod; /* To stop warning. */
|
||||
grub_register_command ("suspend", grub_cmd_suspend, GRUB_COMMAND_FLAG_BOTH,
|
||||
"suspend", "Return to Open Firmware prompt", 0);
|
||||
cmd = grub_register_command ("suspend", grub_cmd_suspend,
|
||||
0, N_("Return to Open Firmware prompt."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(ieee1275_suspend)
|
||||
{
|
||||
grub_unregister_command ("suspend");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
|
|
93
commands/keystatus.c
Normal file
93
commands/keystatus.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
/* keystatus.c - Command to check key modifier status. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/extcmd.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"shift", 's', 0, N_("Check Shift key."), 0, 0},
|
||||
{"ctrl", 'c', 0, N_("Check Control key."), 0, 0},
|
||||
{"alt", 'a', 0, N_("Check Alt key."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#define grub_cur_term_input grub_term_get_current_input ()
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_keystatus (grub_extcmd_t cmd,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
int expect_mods = 0;
|
||||
int mods;
|
||||
|
||||
if (state[0].set)
|
||||
expect_mods |= GRUB_TERM_STATUS_SHIFT;
|
||||
if (state[1].set)
|
||||
expect_mods |= GRUB_TERM_STATUS_CTRL;
|
||||
if (state[2].set)
|
||||
expect_mods |= GRUB_TERM_STATUS_ALT;
|
||||
|
||||
grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods);
|
||||
|
||||
/* Without arguments, just check whether getkeystatus is supported at
|
||||
all. */
|
||||
if (expect_mods == 0)
|
||||
{
|
||||
grub_term_input_t term;
|
||||
int nterms = 0;
|
||||
|
||||
FOR_ACTIVE_TERM_INPUTS (term)
|
||||
if (!term->getkeystatus)
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
else
|
||||
nterms++;
|
||||
if (!nterms)
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mods = grub_getkeystatus ();
|
||||
grub_dprintf ("keystatus", "mods: %d\n", mods);
|
||||
if (mods >= 0 && (mods & expect_mods) != 0)
|
||||
return 0;
|
||||
else
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(keystatus)
|
||||
{
|
||||
cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[--shift] [--ctrl] [--alt]"),
|
||||
N_("Check key modifier status."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(keystatus)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
410
commands/loadenv.c
Normal file
410
commands/loadenv.c
Normal file
|
@ -0,0 +1,410 @@
|
|||
/* loadenv.c - command to load/save environment variable. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009 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/mm.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/lib/envblk.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static grub_file_t
|
||||
open_envblk_file (char *filename)
|
||||
{
|
||||
grub_file_t file;
|
||||
|
||||
if (! filename)
|
||||
{
|
||||
char *prefix;
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (prefix)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = grub_strlen (prefix);
|
||||
filename = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG));
|
||||
if (! filename)
|
||||
return 0;
|
||||
|
||||
grub_strcpy (filename, prefix);
|
||||
filename[len] = '/';
|
||||
grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG);
|
||||
file = grub_file_open (filename);
|
||||
grub_free (filename);
|
||||
return file;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, "prefix is not found");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return grub_file_open (filename);
|
||||
}
|
||||
|
||||
static grub_envblk_t
|
||||
read_envblk_file (grub_file_t file)
|
||||
{
|
||||
grub_off_t offset = 0;
|
||||
char *buf;
|
||||
grub_size_t size = grub_file_size (file);
|
||||
grub_envblk_t envblk;
|
||||
|
||||
buf = grub_malloc (size);
|
||||
if (! buf)
|
||||
return 0;
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
grub_ssize_t ret;
|
||||
|
||||
ret = grub_file_read (file, buf + offset, size);
|
||||
if (ret <= 0)
|
||||
{
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
grub_error (GRUB_ERR_FILE_READ_ERROR, "cannot read");
|
||||
grub_free (buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size -= ret;
|
||||
offset += ret;
|
||||
}
|
||||
|
||||
envblk = grub_envblk_open (buf, offset);
|
||||
if (! envblk)
|
||||
{
|
||||
grub_free (buf);
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return envblk;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_load_env (grub_extcmd_t cmd,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
|
||||
auto int set_var (const char *name, const char *value);
|
||||
int set_var (const char *name, const char *value)
|
||||
{
|
||||
grub_env_set (name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
envblk = read_envblk_file (file);
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
grub_envblk_iterate (envblk, set_var);
|
||||
grub_envblk_close (envblk);
|
||||
|
||||
fail:
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_list_env (grub_extcmd_t cmd,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
|
||||
/* Print all variables in current context. */
|
||||
auto int print_var (const char *name, const char *value);
|
||||
int print_var (const char *name, const char *value)
|
||||
{
|
||||
grub_printf ("%s=%s\n", name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
envblk = read_envblk_file (file);
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
grub_envblk_iterate (envblk, print_var);
|
||||
grub_envblk_close (envblk);
|
||||
|
||||
fail:
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Used to maintain a variable length of blocklists internally. */
|
||||
struct blocklist
|
||||
{
|
||||
grub_disk_addr_t sector;
|
||||
unsigned offset;
|
||||
unsigned length;
|
||||
struct blocklist *next;
|
||||
};
|
||||
|
||||
static void
|
||||
free_blocklists (struct blocklist *p)
|
||||
{
|
||||
struct blocklist *q;
|
||||
|
||||
for (; p; p = q)
|
||||
{
|
||||
q = p->next;
|
||||
grub_free (p);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
||||
grub_file_t file)
|
||||
{
|
||||
grub_size_t total_length;
|
||||
grub_size_t index;
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t part_start;
|
||||
struct blocklist *p;
|
||||
char *buf;
|
||||
|
||||
/* Sanity checks. */
|
||||
total_length = 0;
|
||||
for (p = blocklists; p; p = p->next)
|
||||
{
|
||||
struct blocklist *q;
|
||||
for (q = p->next; q; q = q->next)
|
||||
{
|
||||
/* Check if any pair of blocks overlap. */
|
||||
if (p->sector == q->sector)
|
||||
{
|
||||
/* This might be actually valid, but it is unbelievable that
|
||||
any filesystem makes such a silly allocation. */
|
||||
grub_error (GRUB_ERR_BAD_FS, "malformed file");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
total_length += p->length;
|
||||
}
|
||||
|
||||
if (total_length != grub_file_size (file))
|
||||
{
|
||||
/* Maybe sparse, unallocated sectors. No way in GRUB. */
|
||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, "sparse file not allowed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* One more sanity check. Re-read all sectors by blocklists, and compare
|
||||
those with the data read via a file. */
|
||||
disk = file->device->disk;
|
||||
if (disk->partition)
|
||||
part_start = grub_partition_get_start (disk->partition);
|
||||
else
|
||||
part_start = 0;
|
||||
|
||||
buf = grub_envblk_buffer (envblk);
|
||||
for (p = blocklists, index = 0; p; index += p->length, p = p->next)
|
||||
{
|
||||
char blockbuf[GRUB_DISK_SECTOR_SIZE];
|
||||
|
||||
if (grub_disk_read (disk, p->sector - part_start,
|
||||
p->offset, p->length, blockbuf))
|
||||
return 0;
|
||||
|
||||
if (grub_memcmp (buf + index, blockbuf, p->length) != 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_FILE_READ_ERROR, "invalid blocklist");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
|
||||
grub_file_t file)
|
||||
{
|
||||
char *buf;
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t part_start;
|
||||
struct blocklist *p;
|
||||
grub_size_t index;
|
||||
|
||||
buf = grub_envblk_buffer (envblk);
|
||||
disk = file->device->disk;
|
||||
if (disk->partition)
|
||||
part_start = grub_partition_get_start (disk->partition);
|
||||
else
|
||||
part_start = 0;
|
||||
|
||||
index = 0;
|
||||
for (p = blocklists; p; index += p->length, p = p->next)
|
||||
{
|
||||
if (grub_disk_write (disk, p->sector - part_start,
|
||||
p->offset, p->length, buf + index))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_save_env (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
grub_file_t file;
|
||||
grub_envblk_t envblk;
|
||||
struct blocklist *head = 0;
|
||||
struct blocklist *tail = 0;
|
||||
|
||||
/* Store blocklists in a linked list. */
|
||||
auto void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector,
|
||||
unsigned offset,
|
||||
unsigned length);
|
||||
void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector,
|
||||
unsigned offset, unsigned length)
|
||||
{
|
||||
struct blocklist *block;
|
||||
|
||||
if (offset + length > GRUB_DISK_SECTOR_SIZE)
|
||||
/* Seemingly a bug. */
|
||||
return;
|
||||
|
||||
block = grub_malloc (sizeof (*block));
|
||||
if (! block)
|
||||
return;
|
||||
|
||||
block->sector = sector;
|
||||
block->offset = offset;
|
||||
block->length = length;
|
||||
|
||||
/* Slightly complicated, because the list should be FIFO. */
|
||||
block->next = 0;
|
||||
if (tail)
|
||||
tail->next = block;
|
||||
tail = block;
|
||||
if (! head)
|
||||
head = block;
|
||||
}
|
||||
|
||||
if (! argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
|
||||
|
||||
file = open_envblk_file ((state[0].set) ? state[0].arg : 0);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
if (! file->device->disk)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
|
||||
}
|
||||
|
||||
file->read_hook = read_hook;
|
||||
envblk = read_envblk_file (file);
|
||||
file->read_hook = 0;
|
||||
if (! envblk)
|
||||
goto fail;
|
||||
|
||||
if (! check_blocklists (envblk, head, file))
|
||||
goto fail;
|
||||
|
||||
while (argc)
|
||||
{
|
||||
char *value;
|
||||
|
||||
value = grub_env_get (args[0]);
|
||||
if (value)
|
||||
{
|
||||
if (! grub_envblk_set (envblk, args[0], value))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "environment block too small");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
argc--;
|
||||
args++;
|
||||
}
|
||||
|
||||
write_blocklists (envblk, head, file);
|
||||
|
||||
fail:
|
||||
if (envblk)
|
||||
grub_envblk_close (envblk);
|
||||
free_blocklists (head);
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd_load, cmd_list, cmd_save;
|
||||
|
||||
GRUB_MOD_INIT(loadenv)
|
||||
{
|
||||
cmd_load =
|
||||
grub_register_extcmd ("load_env", grub_cmd_load_env,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[-f FILE]"),
|
||||
N_("Load variables from environment block file."),
|
||||
options);
|
||||
cmd_list =
|
||||
grub_register_extcmd ("list_env", grub_cmd_list_env,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[-f FILE]"),
|
||||
N_("List variables from environment block file."),
|
||||
options);
|
||||
cmd_save =
|
||||
grub_register_extcmd ("save_env", grub_cmd_save_env,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[-f FILE] variable_name [...]"),
|
||||
N_("Save variables to environment block file."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(loadenv)
|
||||
{
|
||||
grub_unregister_extcmd (cmd_load);
|
||||
grub_unregister_extcmd (cmd_list);
|
||||
grub_unregister_extcmd (cmd_save);
|
||||
}
|
116
commands/ls.c
116
commands/ls.c
|
@ -1,7 +1,7 @@
|
|||
/* ls.c - command to list files and devices */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003,2005,2007,2008,2009 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
|
||||
|
@ -22,19 +22,21 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"long", 'l', 0, "show a long list with more detailed information", 0, 0},
|
||||
{"human-readable", 'h', 0, "print sizes in a human readable format", 0, 0},
|
||||
{"all", 'a', 0, "list all files", 0, 0},
|
||||
{"long", 'l', 0, N_("Show a long list with more detailed information."), 0, 0},
|
||||
{"human-readable", 'h', 0, N_("Print sizes in a human readable format."), 0, 0},
|
||||
{"all", 'a', 0, N_("List all files."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -50,10 +52,10 @@ grub_ls_list_devices (int longlist)
|
|||
grub_normal_print_device_info (name);
|
||||
else
|
||||
grub_printf ("(%s) ", name);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
grub_device_iterate (grub_ls_print_devices);
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
|
@ -68,28 +70,32 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
grub_fs_t fs;
|
||||
const char *path;
|
||||
grub_device_t dev;
|
||||
auto int print_files (const char *filename, int dir);
|
||||
auto int print_files_long (const char *filename, int dir);
|
||||
|
||||
int print_files (const char *filename, int dir)
|
||||
|
||||
auto int print_files (const char *filename,
|
||||
const struct grub_dirhook_info *info);
|
||||
auto int print_files_long (const char *filename,
|
||||
const struct grub_dirhook_info *info);
|
||||
|
||||
int print_files (const char *filename, const struct grub_dirhook_info *info)
|
||||
{
|
||||
if (all || filename[0] != '.')
|
||||
grub_printf ("%s%s ", filename, dir ? "/" : "");
|
||||
|
||||
grub_printf ("%s%s ", filename, info->dir ? "/" : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_files_long (const char *filename, int dir)
|
||||
|
||||
int print_files_long (const char *filename,
|
||||
const struct grub_dirhook_info *info)
|
||||
{
|
||||
char pathname[grub_strlen (dirname) + grub_strlen (filename) + 1];
|
||||
|
||||
if ((! all) && (filename[0] == '.'))
|
||||
return 0;
|
||||
|
||||
if (! dir)
|
||||
if (! info->dir)
|
||||
{
|
||||
grub_file_t file;
|
||||
|
||||
|
||||
if (dirname[grub_strlen (dirname) - 1] == '/')
|
||||
grub_sprintf (pathname, "%s%s", dirname, filename);
|
||||
else
|
||||
|
@ -105,36 +111,56 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
}
|
||||
|
||||
if (! human)
|
||||
grub_printf ("%-12llu", file->size);
|
||||
grub_printf ("%-12llu", (unsigned long long) file->size);
|
||||
else
|
||||
{
|
||||
float fsize = file->size;
|
||||
grub_uint64_t fsize = file->size * 100ULL;
|
||||
int fsz = file->size;
|
||||
int units = 0;
|
||||
char buf[20];
|
||||
|
||||
|
||||
while (fsz / 1024)
|
||||
{
|
||||
fsize /= 1024;
|
||||
fsize = (fsize + 512) / 1024;
|
||||
fsz /= 1024;
|
||||
units++;
|
||||
}
|
||||
|
||||
if (units)
|
||||
{
|
||||
grub_sprintf (buf, "%0.2f%c", fsize, grub_human_sizes[units]);
|
||||
grub_uint32_t whole, fraction;
|
||||
|
||||
whole = grub_divmod64 (fsize, 100, &fraction);
|
||||
grub_sprintf (buf, "%u.%02u%c", whole, fraction,
|
||||
grub_human_sizes[units]);
|
||||
grub_printf ("%-12s", buf);
|
||||
}
|
||||
else
|
||||
grub_printf ("%-12llu", file->size);
|
||||
|
||||
grub_printf ("%-12llu", (unsigned long long) file->size);
|
||||
|
||||
}
|
||||
grub_file_close (file);
|
||||
}
|
||||
}
|
||||
else
|
||||
grub_printf ("%-12s", "DIR");
|
||||
|
||||
grub_printf ("%s%s\n", filename, dir ? "/" : "");
|
||||
if (info->mtimeset)
|
||||
{
|
||||
struct grub_datetime datetime;
|
||||
grub_unixtime2datetime (info->mtime, &datetime);
|
||||
if (human)
|
||||
grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ",
|
||||
datetime.year, datetime.month, datetime.day,
|
||||
datetime.hour, datetime.minute,
|
||||
datetime.second,
|
||||
grub_get_weekday_name (&datetime));
|
||||
else
|
||||
grub_printf (" %04d%02d%02d%02d%02d%02d ",
|
||||
datetime.year, datetime.month,
|
||||
datetime.day, datetime.hour,
|
||||
datetime.minute, datetime.second);
|
||||
}
|
||||
grub_printf ("%s%s\n", filename, info->dir ? "/" : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -150,13 +176,13 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
path = dirname;
|
||||
else
|
||||
path++;
|
||||
|
||||
|
||||
if (! path && ! device_name)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (! *path)
|
||||
{
|
||||
if (grub_errno == GRUB_ERR_UNKNOWN_FS)
|
||||
|
@ -177,47 +203,50 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
/* PATH might be a regular file. */
|
||||
char *p;
|
||||
grub_file_t file;
|
||||
|
||||
struct grub_dirhook_info info;
|
||||
grub_errno = 0;
|
||||
|
||||
|
||||
file = grub_file_open (dirname);
|
||||
if (! file)
|
||||
goto fail;
|
||||
|
||||
|
||||
grub_file_close (file);
|
||||
|
||||
|
||||
p = grub_strrchr (dirname, '/') + 1;
|
||||
dirname = grub_strndup (dirname, p - dirname);
|
||||
if (! dirname)
|
||||
goto fail;
|
||||
|
||||
all = 1;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
if (longlist)
|
||||
print_files_long (p, 0);
|
||||
print_files_long (p, &info);
|
||||
else
|
||||
print_files (p, 0);
|
||||
print_files (p, &info);
|
||||
|
||||
grub_free (dirname);
|
||||
}
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
grub_putchar ('\n');
|
||||
|
||||
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
fail:
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
|
||||
grub_free (device_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_ls (struct grub_arg_list *state, int argc, char **args)
|
||||
grub_cmd_ls (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
|
||||
if (argc == 0)
|
||||
grub_ls_list_devices (state[0].set);
|
||||
else
|
||||
|
@ -227,15 +256,16 @@ grub_cmd_ls (struct grub_arg_list *state, int argc, char **args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(ls)
|
||||
{
|
||||
(void)mod; /* To stop warning. */
|
||||
grub_register_command ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH,
|
||||
"ls [-l|-h|-a] [FILE]",
|
||||
"List devices and files.", options);
|
||||
cmd = grub_register_extcmd ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[-l|-h|-a] [FILE]"),
|
||||
N_("List devices and files."), options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(ls)
|
||||
{
|
||||
grub_unregister_command ("ls");
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
||||
|
|
53
commands/lsmmap.c
Normal file
53
commands/lsmmap.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 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/machine/memory.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)), char **args __attribute__ ((unused)))
|
||||
|
||||
{
|
||||
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
|
||||
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
|
||||
{
|
||||
grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n",
|
||||
(long long) addr, (long long) size, type);
|
||||
return 0;
|
||||
}
|
||||
grub_machine_mmap_iterate (hook);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(lsmmap)
|
||||
{
|
||||
cmd = grub_register_command ("lsmmap", grub_cmd_lsmmap,
|
||||
0, N_("List memory map provided by firmware."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(lsmmap)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
228
commands/lspci.c
Normal file
228
commands/lspci.c
Normal file
|
@ -0,0 +1,228 @@
|
|||
/* lspci.c - List PCI devices. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008, 2009 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/pci.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
struct grub_pci_classname
|
||||
{
|
||||
int class;
|
||||
int subclass;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
static const struct grub_pci_classname grub_pci_classes[] =
|
||||
{
|
||||
{ 0, 0, "" },
|
||||
{ 1, 0, "SCSI Controller" },
|
||||
{ 1, 1, "IDE Controller" },
|
||||
{ 1, 2, "Floppy Controller" },
|
||||
{ 1, 3, "IPI Controller" },
|
||||
{ 1, 4, "RAID Controller" },
|
||||
{ 1, 6, "SATA Controller" },
|
||||
{ 1, 0x80, "Mass storage Controller" },
|
||||
{ 2, 0, "Ethernet Controller" },
|
||||
{ 2, 1, "Token Ring Controller" },
|
||||
{ 2, 2, "FDDI Controller" },
|
||||
{ 2, 3, "ATM Controller" },
|
||||
{ 2, 4, "ISDN Controller" },
|
||||
{ 2, 0x80, "Network controller" },
|
||||
{ 3, 0, "VGA Controller" },
|
||||
{ 3, 1, "XGA Controller" },
|
||||
{ 3, 2, "3D Controller" },
|
||||
{ 3, 0x80, "Display Controller" },
|
||||
{ 4, 0, "Multimedia Video Device" },
|
||||
{ 4, 1, "Multimedia Audio Device" },
|
||||
{ 4, 2, "Multimedia Telephony Device" },
|
||||
{ 4, 0x80, "Multimedia device" },
|
||||
{ 5, 0, "RAM Controller" },
|
||||
{ 5, 1, "Flash Memory Controller" },
|
||||
{ 5, 0x80, "Memory Controller" },
|
||||
{ 6, 0, "Host Bridge" },
|
||||
{ 6, 1, "ISA Bridge" },
|
||||
{ 6, 2, "EISA Bride" },
|
||||
{ 6, 3, "MCA Bridge" },
|
||||
{ 6, 4, "PCI-PCI Bridge" },
|
||||
{ 6, 5, "PCMCIA Bridge" },
|
||||
{ 6, 6, "NuBus Bridge" },
|
||||
{ 6, 7, "CardBus Bridge" },
|
||||
{ 6, 8, "Raceway Bridge" },
|
||||
{ 6, 0x80, "Unknown Bridge" },
|
||||
{ 7, 0x80, "Communication controller" },
|
||||
{ 8, 0x80, "System hardware" },
|
||||
{ 9, 0, "Keyboard Controller" },
|
||||
{ 9, 1, "Digitizer" },
|
||||
{ 9, 2, "Mouse Controller" },
|
||||
{ 9, 3, "Scanner Controller" },
|
||||
{ 9, 4, "Gameport Controller" },
|
||||
{ 9, 0x80, "Unknown Input Device" },
|
||||
{ 10, 0, "Generic Docking Station" },
|
||||
{ 10, 0x80, "Unknown Docking Station" },
|
||||
{ 11, 0, "80386 Processor" },
|
||||
{ 11, 1, "80486 Processor" },
|
||||
{ 11, 2, "Pentium Processor" },
|
||||
{ 11, 0x10, "Alpha Processor" },
|
||||
{ 11, 0x20, "PowerPC Processor" },
|
||||
{ 11, 0x30, "MIPS Processor" },
|
||||
{ 11, 0x40, "Co-Processor" },
|
||||
{ 11, 0x80, "Unknown Processor" },
|
||||
{ 12, 3, "USB Controller" },
|
||||
{ 12, 0x80, "Serial Bus Controller" },
|
||||
{ 13, 0x80, "Wireless Controller" },
|
||||
{ 14, 0, "I2O" },
|
||||
{ 15, 0, "IrDA Controller" },
|
||||
{ 15, 1, "Consumer IR" },
|
||||
{ 15, 0x10, "RF-Controller" },
|
||||
{ 15, 0x80, "Satellite Communication Controller" },
|
||||
{ 16, 0, "Network Decryption" },
|
||||
{ 16, 1, "Entertainment Decryption" },
|
||||
{ 16, 0x80, "Unknown Decryption Controller" },
|
||||
{ 17, 0, "Digital IO Module" },
|
||||
{ 17, 0x80, "Unknown Data Input System" },
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
static const char *
|
||||
grub_pci_get_class (int class, int subclass)
|
||||
{
|
||||
const struct grub_pci_classname *curr = grub_pci_classes;
|
||||
|
||||
while (curr->desc)
|
||||
{
|
||||
if (curr->class == class && curr->subclass == subclass)
|
||||
return curr->desc;
|
||||
curr++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"iospace", 'i', 0, "show I/O spaces", 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static int iospace;
|
||||
|
||||
static int NESTED_FUNC_ATTR
|
||||
grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
|
||||
{
|
||||
grub_uint32_t class;
|
||||
const char *sclass;
|
||||
grub_pci_address_t addr;
|
||||
int reg;
|
||||
|
||||
grub_printf ("%02x:%02x.%x %04x:%04x", grub_pci_get_bus (dev),
|
||||
grub_pci_get_device (dev), grub_pci_get_function (dev),
|
||||
pciid & 0xFFFF, pciid >> 16);
|
||||
addr = grub_pci_make_address (dev, 2);
|
||||
class = grub_pci_read (addr);
|
||||
|
||||
/* Lookup the class name, if there isn't a specific one,
|
||||
retry with 0x80 to get the generic class name. */
|
||||
sclass = grub_pci_get_class (class >> 24, (class >> 16) & 0xFF);
|
||||
if (! sclass)
|
||||
sclass = grub_pci_get_class (class >> 24, 0x80);
|
||||
if (! sclass)
|
||||
sclass = "";
|
||||
|
||||
grub_printf (" [%04x] %s", (class >> 16) & 0xffff, sclass);
|
||||
|
||||
grub_uint8_t pi = (class >> 8) & 0xff;
|
||||
if (pi)
|
||||
grub_printf (" [PI %02x]", pi);
|
||||
|
||||
grub_printf ("\n");
|
||||
|
||||
if (iospace)
|
||||
{
|
||||
reg = 4;
|
||||
while (reg < 10)
|
||||
{
|
||||
grub_uint64_t space;
|
||||
addr = grub_pci_make_address (dev, reg);
|
||||
space = grub_pci_read (addr);
|
||||
|
||||
reg++;
|
||||
|
||||
if (space == 0)
|
||||
continue;
|
||||
|
||||
switch (space & GRUB_PCI_ADDR_SPACE_MASK)
|
||||
{
|
||||
case GRUB_PCI_ADDR_SPACE_IO:
|
||||
grub_printf ("\tIO space %d at 0x%llx\n", (reg - 1) - 4,
|
||||
(unsigned long long)
|
||||
(space & GRUB_PCI_ADDR_IO_MASK));
|
||||
break;
|
||||
case GRUB_PCI_ADDR_SPACE_MEMORY:
|
||||
if ((space & GRUB_PCI_ADDR_MEM_TYPE_MASK)
|
||||
== GRUB_PCI_ADDR_MEM_TYPE_64)
|
||||
{
|
||||
addr = grub_pci_make_address (dev, reg);
|
||||
space |= ((grub_uint64_t) grub_pci_read (addr)) << 32;
|
||||
reg++;
|
||||
grub_printf ("\t64-bit memory space %d at 0x%016llx [%s]\n",
|
||||
(reg - 2) - 4, (unsigned long long)
|
||||
(space & GRUB_PCI_ADDR_MEM_MASK),
|
||||
space & GRUB_PCI_ADDR_MEM_PREFETCH
|
||||
? "prefetchable" : "non-prefetchable");
|
||||
|
||||
}
|
||||
else
|
||||
grub_printf ("\t32-bit memory space %d at 0x%016llx [%s]\n",
|
||||
(reg - 1) - 4, (unsigned long long)
|
||||
(space & GRUB_PCI_ADDR_MEM_MASK),
|
||||
space & GRUB_PCI_ADDR_MEM_PREFETCH
|
||||
? "prefetchable" : "non-prefetchable");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_lspci (grub_extcmd_t cmd,
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
iospace = cmd->state[0].set;
|
||||
grub_pci_iterate (grub_lspci_iter);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(lspci)
|
||||
{
|
||||
cmd = grub_register_extcmd ("lspci", grub_cmd_lspci, GRUB_COMMAND_FLAG_BOTH,
|
||||
"[-i]", N_("List PCI devices."), options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(lspci)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
149
commands/memrw.c
Normal file
149
commands/memrw.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/* memrw.c - command to read / write physical memory */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/extcmd.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_extcmd_t cmd_read_byte, cmd_read_word, cmd_read_dword;
|
||||
static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword;
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{0, 'v', 0, N_("Save read value into variable VARNAME."),
|
||||
"VARNAME", ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
|
||||
{
|
||||
grub_target_addr_t addr;
|
||||
grub_uint32_t value = 0;
|
||||
char buf[sizeof ("XXXXXXXX")];
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments");
|
||||
|
||||
addr = grub_strtoul (argv[0], 0, 0);
|
||||
switch (cmd->cmd->name[sizeof ("read_") - 1])
|
||||
{
|
||||
case 'd':
|
||||
value = *((volatile grub_uint32_t *) addr);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
value = *((volatile grub_uint16_t *) addr);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
value = *((volatile grub_uint8_t *) addr);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd->state[0].set)
|
||||
{
|
||||
grub_sprintf (buf, "%x", value);
|
||||
grub_env_set (cmd->state[0].arg, buf);
|
||||
}
|
||||
else
|
||||
grub_printf ("0x%x\n", value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_write (grub_command_t cmd, int argc, char **argv)
|
||||
{
|
||||
grub_target_addr_t addr;
|
||||
grub_uint32_t value;
|
||||
grub_uint32_t mask = 0xffffffff;
|
||||
|
||||
if (argc != 2 && argc != 3)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments");
|
||||
|
||||
addr = grub_strtoul (argv[0], 0, 0);
|
||||
value = grub_strtoul (argv[1], 0, 0);
|
||||
if (argc == 3)
|
||||
mask = grub_strtoul (argv[2], 0, 0);
|
||||
value &= mask;
|
||||
switch (cmd->name[sizeof ("write_") - 1])
|
||||
{
|
||||
case 'd':
|
||||
if (mask != 0xffffffff)
|
||||
*((volatile grub_uint32_t *) addr)
|
||||
= (*((volatile grub_uint32_t *) addr) & ~mask) | value;
|
||||
else
|
||||
*((volatile grub_uint32_t *) addr) = value;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if ((mask & 0xffff) != 0xffff)
|
||||
*((volatile grub_uint16_t *) addr)
|
||||
= (*((volatile grub_uint16_t *) addr) & ~mask) | value;
|
||||
else
|
||||
*((volatile grub_uint16_t *) addr) = value;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
if ((mask & 0xff) != 0xff)
|
||||
*((volatile grub_uint8_t *) addr)
|
||||
= (*((volatile grub_uint8_t *) addr) & ~mask) | value;
|
||||
else
|
||||
*((volatile grub_uint8_t *) addr) = value;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT(memrw)
|
||||
{
|
||||
cmd_read_byte =
|
||||
grub_register_extcmd ("read_byte", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("ADDR"), N_("Read byte from ADDR."), options);
|
||||
cmd_read_word =
|
||||
grub_register_extcmd ("read_word", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("ADDR"), N_("Read word from ADDR."), options);
|
||||
cmd_read_dword =
|
||||
grub_register_extcmd ("read_dword", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("ADDR"), N_("Read dword from ADDR."), options);
|
||||
cmd_write_byte =
|
||||
grub_register_command ("write_byte", grub_cmd_write,
|
||||
N_("ADDR VALUE [MASK]"), N_("Write byte VALUE to ADDR."));
|
||||
cmd_write_word =
|
||||
grub_register_command ("write_word", grub_cmd_write,
|
||||
N_("ADDR VALUE [MASK]"), N_("Write word VALUE to ADDR."));
|
||||
cmd_write_dword =
|
||||
grub_register_command ("write_dword", grub_cmd_write,
|
||||
N_("ADDR VALUE [MASK]"), N_("Write dword VALUE to ADDR."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(memrw)
|
||||
{
|
||||
grub_unregister_extcmd (cmd_read_byte);
|
||||
grub_unregister_extcmd (cmd_read_word);
|
||||
grub_unregister_extcmd (cmd_read_dword);
|
||||
grub_unregister_command (cmd_write_byte);
|
||||
grub_unregister_command (cmd_write_word);
|
||||
grub_unregister_command (cmd_write_dword);
|
||||
}
|
392
commands/minicmd.c
Normal file
392
commands/minicmd.c
Normal file
|
@ -0,0 +1,392 @@
|
|||
/* minicmd.c - commands for the rescue mode */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2005,2006,2007,2009 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/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
/* cat FILE */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_cat (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
grub_file_t file;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
grub_ssize_t size;
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
while ((size = grub_file_read (file, buf, sizeof (buf))) > 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
unsigned char c = buf[i];
|
||||
|
||||
if ((grub_isprint (c) || grub_isspace (c)) && c != '\r')
|
||||
grub_putchar (c);
|
||||
else
|
||||
{
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
|
||||
grub_printf ("<%x>", (int) c);
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
grub_file_close (file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* help */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_help (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_command_t p;
|
||||
|
||||
for (p = grub_command_list; p; p = p->next)
|
||||
grub_printf ("%s (%d%c)\t%s\n", p->name,
|
||||
p->prio & GRUB_PRIO_LIST_PRIO_MASK,
|
||||
(p->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) ? '+' : '-',
|
||||
p->description);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
grub_rescue_cmd_info (void)
|
||||
{
|
||||
extern void grub_disk_cache_get_performance (unsigned long *,
|
||||
unsigned long *);
|
||||
unsigned long hits, misses;
|
||||
|
||||
grub_disk_cache_get_performance (&hits, &misses);
|
||||
grub_printf ("Disk cache: hits = %u, misses = %u ", hits, misses);
|
||||
if (hits + misses)
|
||||
{
|
||||
unsigned long ratio = hits * 10000 / (hits + misses);
|
||||
grub_printf ("(%u.%u%%)\n", ratio / 100, ratio % 100);
|
||||
}
|
||||
else
|
||||
grub_printf ("(N/A)\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* root [DEVICE] */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_root (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
grub_device_t dev;
|
||||
grub_fs_t fs;
|
||||
|
||||
if (argc > 0)
|
||||
{
|
||||
char *device_name = grub_file_get_device_name (argv[0]);
|
||||
if (! device_name)
|
||||
return grub_errno;
|
||||
|
||||
grub_env_set ("root", device_name);
|
||||
grub_free (device_name);
|
||||
}
|
||||
|
||||
dev = grub_device_open (0);
|
||||
if (! dev)
|
||||
return grub_errno;
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
if (grub_errno == GRUB_ERR_UNKNOWN_FS)
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
grub_printf ("(%s): Filesystem is %s.\n",
|
||||
grub_env_get ("root"), fs ? fs->name : "unknown");
|
||||
|
||||
grub_device_close (dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
grub_rescue_cmd_testload (int argc, char *argv[])
|
||||
{
|
||||
grub_file_t file;
|
||||
char *buf;
|
||||
grub_ssize_t size;
|
||||
grub_ssize_t pos;
|
||||
auto void read_func (unsigned long sector, unsigned offset, unsigned len);
|
||||
|
||||
void read_func (unsigned long sector __attribute__ ((unused)),
|
||||
unsigned offset __attribute__ ((unused)),
|
||||
unsigned len __attribute__ ((unused)))
|
||||
{
|
||||
grub_putchar ('.');
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||
return;
|
||||
}
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return;
|
||||
|
||||
size = grub_file_size (file) & ~(GRUB_DISK_SECTOR_SIZE - 1);
|
||||
if (size == 0)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return;
|
||||
}
|
||||
|
||||
buf = grub_malloc (size);
|
||||
if (! buf)
|
||||
goto fail;
|
||||
|
||||
grub_printf ("Reading %s sequentially", argv[0]);
|
||||
file->read_hook = read_func;
|
||||
if (grub_file_read (file, buf, size) != size)
|
||||
goto fail;
|
||||
grub_printf (" Done.\n");
|
||||
|
||||
/* Read sequentially again. */
|
||||
grub_printf ("Reading %s sequentially again", argv[0]);
|
||||
if (grub_file_seek (file, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
for (pos = 0; pos < size; pos += GRUB_DISK_SECTOR_SIZE)
|
||||
{
|
||||
char sector[GRUB_DISK_SECTOR_SIZE];
|
||||
|
||||
if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
|
||||
!= GRUB_DISK_SECTOR_SIZE)
|
||||
goto fail;
|
||||
|
||||
if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
|
||||
{
|
||||
grub_printf ("\nDiffers in %d\n", pos);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
grub_printf (" Done.\n");
|
||||
|
||||
/* Read backwards and compare. */
|
||||
grub_printf ("Reading %s backwards", argv[0]);
|
||||
pos = size;
|
||||
while (pos > 0)
|
||||
{
|
||||
char sector[GRUB_DISK_SECTOR_SIZE];
|
||||
|
||||
pos -= GRUB_DISK_SECTOR_SIZE;
|
||||
|
||||
if (grub_file_seek (file, pos) < 0)
|
||||
goto fail;
|
||||
|
||||
if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
|
||||
!= GRUB_DISK_SECTOR_SIZE)
|
||||
goto fail;
|
||||
|
||||
if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
grub_printf ("\nDiffers in %d\n", pos);
|
||||
|
||||
for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i++)
|
||||
grub_putchar (buf[pos + i]);
|
||||
|
||||
if (i)
|
||||
grub_refresh ();
|
||||
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
grub_printf (" Done.\n");
|
||||
|
||||
fail:
|
||||
|
||||
grub_file_close (file);
|
||||
grub_free (buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* dump ADDRESS [SIZE] */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
grub_uint8_t *addr;
|
||||
grub_size_t size = 4;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no address specified");
|
||||
|
||||
addr = (grub_uint8_t *) grub_strtoul (argv[0], 0, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
if (argc > 1)
|
||||
size = (grub_size_t) grub_strtoul (argv[1], 0, 0);
|
||||
|
||||
while (size--)
|
||||
{
|
||||
grub_printf ("%x%x ", *addr >> 4, *addr & 0xf);
|
||||
addr++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* rmmod MODULE */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_rmmod (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
grub_dl_t mod;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
|
||||
|
||||
mod = grub_dl_get (argv[0]);
|
||||
if (! mod)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such module");
|
||||
|
||||
if (grub_dl_unref (mod) <= 0)
|
||||
grub_dl_unload (mod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* lsmod */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
auto int print_module (grub_dl_t mod);
|
||||
|
||||
int print_module (grub_dl_t mod)
|
||||
{
|
||||
grub_dl_dep_t dep;
|
||||
|
||||
grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count);
|
||||
for (dep = mod->dep; dep; dep = dep->next)
|
||||
{
|
||||
if (dep != mod->dep)
|
||||
grub_putchar (',');
|
||||
|
||||
grub_printf ("%s", dep->mod->name);
|
||||
}
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_printf ("Name\tRef Count\tDependencies\n");
|
||||
grub_dl_iterate (print_module);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* exit */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_exit ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* clear */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_cls ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_cat, cmd_help, cmd_root;
|
||||
static grub_command_t cmd_dump, cmd_rmmod, cmd_lsmod, cmd_exit;
|
||||
static grub_command_t cmd_clear;
|
||||
|
||||
GRUB_MOD_INIT(minicmd)
|
||||
{
|
||||
cmd_cat =
|
||||
grub_register_command ("cat", grub_mini_cmd_cat,
|
||||
N_("FILE"), N_("Show the contents of a file."));
|
||||
cmd_help =
|
||||
grub_register_command ("help", grub_mini_cmd_help,
|
||||
0, N_("Show this message."));
|
||||
cmd_root =
|
||||
grub_register_command ("root", grub_mini_cmd_root,
|
||||
N_("[DEVICE]"), N_("Set the root device."));
|
||||
cmd_dump =
|
||||
grub_register_command ("dump", grub_mini_cmd_dump,
|
||||
N_("ADDR"), N_("Dump memory."));
|
||||
cmd_rmmod =
|
||||
grub_register_command ("rmmod", grub_mini_cmd_rmmod,
|
||||
N_("MODULE"), N_("Remove a module."));
|
||||
cmd_lsmod =
|
||||
grub_register_command ("lsmod", grub_mini_cmd_lsmod,
|
||||
0, N_("Show loaded modules."));
|
||||
cmd_exit =
|
||||
grub_register_command ("exit", grub_mini_cmd_exit,
|
||||
0, N_("Exit from GRUB."));
|
||||
cmd_clear =
|
||||
grub_register_command ("clear", grub_mini_cmd_clear,
|
||||
0, N_("Clear the screen."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(minicmd)
|
||||
{
|
||||
grub_unregister_command (cmd_cat);
|
||||
grub_unregister_command (cmd_help);
|
||||
grub_unregister_command (cmd_root);
|
||||
grub_unregister_command (cmd_dump);
|
||||
grub_unregister_command (cmd_rmmod);
|
||||
grub_unregister_command (cmd_lsmod);
|
||||
grub_unregister_command (cmd_exit);
|
||||
grub_unregister_command (cmd_clear);
|
||||
}
|
333
commands/parttool.c
Normal file
333
commands/parttool.c
Normal file
|
@ -0,0 +1,333 @@
|
|||
/* parttool.c - common dispatcher and parser for partition operations */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/parttool.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static struct grub_parttool *parts = 0;
|
||||
static int curhandle = 0;
|
||||
static grub_dl_t mymod;
|
||||
static char helpmsg[] =
|
||||
"Perform COMMANDS on partition.\n"
|
||||
"Use \"parttool PARTITION help\" for the list "
|
||||
"of available commands.";
|
||||
|
||||
int
|
||||
grub_parttool_register(const char *part_name,
|
||||
const grub_parttool_function_t func,
|
||||
const struct grub_parttool_argdesc *args)
|
||||
{
|
||||
struct grub_parttool *cur;
|
||||
int nargs = 0;
|
||||
|
||||
if (! parts)
|
||||
grub_dl_ref (mymod);
|
||||
|
||||
cur = (struct grub_parttool *) grub_malloc (sizeof (struct grub_parttool));
|
||||
cur->next = parts;
|
||||
cur->name = grub_strdup (part_name);
|
||||
cur->handle = curhandle++;
|
||||
for (nargs = 0; args[nargs].name != 0; nargs++);
|
||||
cur->nargs = nargs;
|
||||
cur->args = (struct grub_parttool_argdesc *)
|
||||
grub_malloc ((nargs + 1) * sizeof (struct grub_parttool_argdesc));
|
||||
grub_memcpy (cur->args, args,
|
||||
(nargs + 1) * sizeof (struct grub_parttool_argdesc));
|
||||
|
||||
cur->func = func;
|
||||
parts = cur;
|
||||
return cur->handle;
|
||||
}
|
||||
|
||||
void
|
||||
grub_parttool_unregister (int handle)
|
||||
{
|
||||
struct grub_parttool *prev = 0, *cur, *t;
|
||||
for (cur = parts; cur; )
|
||||
if (cur->handle == handle)
|
||||
{
|
||||
grub_free (cur->args);
|
||||
grub_free (cur->name);
|
||||
if (prev)
|
||||
prev->next = cur->next;
|
||||
else
|
||||
parts = cur->next;
|
||||
t = cur;
|
||||
cur = cur->next;
|
||||
grub_free (t);
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
if (! parts)
|
||||
grub_dl_unref (mymod);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_device_t dev;
|
||||
struct grub_parttool *cur, *ptool;
|
||||
int *parsed;
|
||||
int i, j;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
auto grub_err_t show_help (void);
|
||||
grub_err_t show_help (void)
|
||||
{
|
||||
int found = 0;
|
||||
for (cur = parts; cur; cur = cur->next)
|
||||
if (grub_strcmp (dev->disk->partition->partmap->name, cur->name) == 0)
|
||||
{
|
||||
struct grub_parttool_argdesc *curarg;
|
||||
found = 1;
|
||||
for (curarg = cur->args; curarg->name; curarg++)
|
||||
{
|
||||
int spacing = 20;
|
||||
|
||||
spacing -= grub_strlen (curarg->name);
|
||||
grub_printf ("%s", curarg->name);
|
||||
|
||||
switch (curarg->type)
|
||||
{
|
||||
case GRUB_PARTTOOL_ARG_BOOL:
|
||||
grub_printf ("+/-");
|
||||
spacing -= 3;
|
||||
break;
|
||||
|
||||
case GRUB_PARTTOOL_ARG_VAL:
|
||||
grub_printf ("=VAL");
|
||||
spacing -= 4;
|
||||
break;
|
||||
|
||||
case GRUB_PARTTOOL_ARG_END:
|
||||
break;
|
||||
}
|
||||
while (spacing-- > 0)
|
||||
grub_printf (" ");
|
||||
grub_printf ("%s\n", curarg->desc);
|
||||
}
|
||||
}
|
||||
if (! found)
|
||||
grub_printf ("Sorry no parttool is available for %s\n",
|
||||
dev->disk->partition->partmap->name);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
grub_printf ("%s\n", helpmsg);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments");
|
||||
}
|
||||
|
||||
if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
|
||||
{
|
||||
args[0][grub_strlen (args[0]) - 1] = 0;
|
||||
dev = grub_device_open (args[0] + 1);
|
||||
args[0][grub_strlen (args[0]) - 1] = ')';
|
||||
}
|
||||
else
|
||||
dev = grub_device_open (args[0]);
|
||||
|
||||
if (! dev)
|
||||
return grub_errno;
|
||||
|
||||
if (! dev->disk)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a disk");
|
||||
}
|
||||
|
||||
if (! dev->disk->partition)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a partition");
|
||||
}
|
||||
|
||||
/* Load modules. */
|
||||
#ifndef GRUB_UTIL
|
||||
{
|
||||
const char *prefix;
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (prefix)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = grub_malloc (grub_strlen (prefix) + sizeof ("/parttool.lst"));
|
||||
if (filename)
|
||||
{
|
||||
grub_file_t file;
|
||||
|
||||
grub_sprintf (filename, "%s/parttool.lst", prefix);
|
||||
file = grub_file_open (filename);
|
||||
if (file)
|
||||
{
|
||||
char *buf = 0;
|
||||
for (;; grub_free(buf))
|
||||
{
|
||||
char *p, *name;
|
||||
|
||||
buf = grub_file_getline (file);
|
||||
|
||||
if (! buf)
|
||||
break;
|
||||
|
||||
name = buf;
|
||||
|
||||
if (! grub_isgraph (name[0]))
|
||||
continue;
|
||||
|
||||
p = grub_strchr (name, ':');
|
||||
if (! p)
|
||||
continue;
|
||||
|
||||
*p = '\0';
|
||||
while (*++p == ' ')
|
||||
;
|
||||
|
||||
if (! grub_isgraph (*p))
|
||||
continue;
|
||||
|
||||
if (grub_strcmp (name, dev->disk->partition->partmap->name)
|
||||
!= 0)
|
||||
continue;
|
||||
|
||||
grub_dl_load (p);
|
||||
}
|
||||
|
||||
grub_file_close (file);
|
||||
}
|
||||
|
||||
grub_free (filename);
|
||||
}
|
||||
}
|
||||
/* Ignore errors. */
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (argc == 1)
|
||||
return show_help ();
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
if (grub_strcmp (args[i], "help") == 0)
|
||||
return show_help ();
|
||||
|
||||
parsed = (int *) grub_zalloc (argc * sizeof (int));
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
if (! parsed[i])
|
||||
{
|
||||
struct grub_parttool_argdesc *curarg;
|
||||
struct grub_parttool_args *pargs;
|
||||
for (cur = parts; cur; cur = cur->next)
|
||||
if (grub_strcmp (dev->disk->partition->partmap->name, cur->name) == 0)
|
||||
{
|
||||
for (curarg = cur->args; curarg->name; curarg++)
|
||||
if (grub_strncmp (curarg->name, args[i],
|
||||
grub_strlen (curarg->name)) == 0
|
||||
&& ((curarg->type == GRUB_PARTTOOL_ARG_BOOL
|
||||
&& (args[i][grub_strlen (curarg->name)] == '+'
|
||||
|| args[i][grub_strlen (curarg->name)] == '-'
|
||||
|| args[i][grub_strlen (curarg->name)] == 0))
|
||||
|| (curarg->type == GRUB_PARTTOOL_ARG_VAL
|
||||
&& args[i][grub_strlen (curarg->name)] == '=')))
|
||||
|
||||
break;
|
||||
if (curarg->name)
|
||||
break;
|
||||
}
|
||||
if (! cur)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unrecognised argument %s",
|
||||
args[i]);
|
||||
ptool = cur;
|
||||
pargs = (struct grub_parttool_args *)
|
||||
grub_zalloc (ptool->nargs * sizeof (struct grub_parttool_args));
|
||||
for (j = i; j < argc; j++)
|
||||
if (! parsed[j])
|
||||
{
|
||||
for (curarg = ptool->args; curarg->name; curarg++)
|
||||
if (grub_strncmp (curarg->name, args[i],
|
||||
grub_strlen (curarg->name)) == 0
|
||||
&& ((curarg->type == GRUB_PARTTOOL_ARG_BOOL
|
||||
&& (args[j][grub_strlen (curarg->name)] == '+'
|
||||
|| args[j][grub_strlen (curarg->name)] == '-'
|
||||
|| args[j][grub_strlen (curarg->name)] == 0))
|
||||
|| (curarg->type == GRUB_PARTTOOL_ARG_VAL
|
||||
&& args[j][grub_strlen (curarg->name)] == '=')))
|
||||
{
|
||||
parsed[j] = 1;
|
||||
pargs[curarg - ptool->args].set = 1;
|
||||
switch (curarg->type)
|
||||
{
|
||||
case GRUB_PARTTOOL_ARG_BOOL:
|
||||
pargs[curarg - ptool->args].bool
|
||||
= (args[j][grub_strlen (curarg->name)] != '-');
|
||||
break;
|
||||
|
||||
case GRUB_PARTTOOL_ARG_VAL:
|
||||
pargs[curarg - ptool->args].str
|
||||
= (args[j] + grub_strlen (curarg->name) + 1);
|
||||
break;
|
||||
|
||||
case GRUB_PARTTOOL_ARG_END:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = ptool->func (dev, pargs);
|
||||
grub_free (pargs);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
grub_free (parsed);
|
||||
grub_device_close (dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(parttool)
|
||||
{
|
||||
mymod = mod;
|
||||
cmd = grub_register_command ("parttool", grub_cmd_parttool,
|
||||
N_("PARTITION COMMANDS"),
|
||||
helpmsg);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(parttool)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
86
commands/password.c
Normal file
86
commands/password.c
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/auth.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/list.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
|
||||
static grub_err_t
|
||||
check_password (const char *user, const char *entered,
|
||||
void *password)
|
||||
{
|
||||
if (grub_crypto_memcmp (entered, password, GRUB_AUTH_MAX_PASSLEN) != 0)
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
grub_auth_authenticate (user);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_err_t err;
|
||||
char *pass;
|
||||
int copylen;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments expected");
|
||||
|
||||
pass = grub_zalloc (GRUB_AUTH_MAX_PASSLEN);
|
||||
if (!pass)
|
||||
return grub_errno;
|
||||
copylen = grub_strlen (args[1]);
|
||||
if (copylen >= GRUB_AUTH_MAX_PASSLEN)
|
||||
copylen = GRUB_AUTH_MAX_PASSLEN - 1;
|
||||
grub_memcpy (pass, args[1], copylen);
|
||||
|
||||
err = grub_auth_register_authentication (args[0], check_password, pass);
|
||||
if (err)
|
||||
{
|
||||
grub_free (pass);
|
||||
return err;
|
||||
}
|
||||
grub_dl_ref (my_mod);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(password)
|
||||
{
|
||||
my_mod = mod;
|
||||
cmd = grub_register_command ("password", grub_cmd_password,
|
||||
N_("USER PASSWORD"),
|
||||
N_("Set user password (plaintext). "
|
||||
"Unrecommended and insecure."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(password)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
196
commands/password_pbkdf2.c
Normal file
196
commands/password_pbkdf2.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/auth.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/list.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
|
||||
struct pbkdf2_password
|
||||
{
|
||||
grub_uint8_t *salt;
|
||||
grub_size_t saltlen;
|
||||
unsigned int c;
|
||||
grub_uint8_t *expected;
|
||||
grub_size_t buflen;
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
check_password (const char *user, const char *entered, void *pin)
|
||||
{
|
||||
grub_uint8_t *buf;
|
||||
struct pbkdf2_password *pass = pin;
|
||||
gcry_err_code_t err;
|
||||
|
||||
buf = grub_malloc (pass->buflen);
|
||||
if (!buf)
|
||||
return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
|
||||
|
||||
err = grub_crypto_pbkdf2 (GRUB_MD_SHA512, (grub_uint8_t *) entered,
|
||||
grub_strlen (entered),
|
||||
pass->salt, pass->saltlen, pass->c,
|
||||
buf, pass->buflen);
|
||||
if (err)
|
||||
{
|
||||
grub_free (buf);
|
||||
return grub_crypto_gcry_error (err);
|
||||
}
|
||||
|
||||
if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0)
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
grub_auth_authenticate (user);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static inline int
|
||||
hex2val (char hex)
|
||||
{
|
||||
if ('0' <= hex && hex <= '9')
|
||||
return hex - '0';
|
||||
if ('a' <= hex && hex <= 'f')
|
||||
return hex - 'a' + 10;
|
||||
if ('A' <= hex && hex <= 'F')
|
||||
return hex - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_err_t err;
|
||||
char *ptr, *ptr2;
|
||||
grub_uint8_t *ptro;
|
||||
struct pbkdf2_password *pass;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected.");
|
||||
|
||||
if (grub_memcmp (args[1], "grub.pbkdf2.sha512.",
|
||||
sizeof ("grub.pbkdf2.sha512.") - 1) != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
|
||||
|
||||
ptr = args[1] + sizeof ("grub.pbkdf2.sha512.") - 1;
|
||||
|
||||
pass = grub_malloc (sizeof (*pass));
|
||||
if (!pass)
|
||||
return grub_errno;
|
||||
|
||||
pass->c = grub_strtoul (ptr, &ptr, 0);
|
||||
if (*ptr != '.')
|
||||
{
|
||||
grub_free (pass);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
|
||||
}
|
||||
ptr++;
|
||||
|
||||
ptr2 = grub_strchr (ptr, '.');
|
||||
if (!ptr2 || ((ptr2 - ptr) & 1) || grub_strlen (ptr2 + 1) & 1)
|
||||
{
|
||||
grub_free (pass);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
|
||||
}
|
||||
|
||||
pass->saltlen = (ptr2 - ptr) >> 1;
|
||||
pass->buflen = grub_strlen (ptr2 + 1) >> 1;
|
||||
ptro = pass->salt = grub_malloc (pass->saltlen);
|
||||
if (!ptro)
|
||||
{
|
||||
grub_free (pass);
|
||||
return grub_errno;
|
||||
}
|
||||
while (ptr < ptr2)
|
||||
{
|
||||
int hex1, hex2;
|
||||
hex1 = hex2val (*ptr);
|
||||
ptr++;
|
||||
hex2 = hex2val (*ptr);
|
||||
ptr++;
|
||||
if (hex1 < 0 || hex2 < 0)
|
||||
{
|
||||
grub_free (pass->salt);
|
||||
grub_free (pass);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Incorrect PBKDF2 password.");
|
||||
}
|
||||
|
||||
*ptro = (hex1 << 4) | hex2;
|
||||
ptro++;
|
||||
}
|
||||
|
||||
ptro = pass->expected = grub_malloc (pass->buflen);
|
||||
if (!ptro)
|
||||
{
|
||||
grub_free (pass->salt);
|
||||
grub_free (pass);
|
||||
return grub_errno;
|
||||
}
|
||||
ptr = ptr2 + 1;
|
||||
ptr2 += grub_strlen (ptr2);
|
||||
while (ptr < ptr2)
|
||||
{
|
||||
int hex1, hex2;
|
||||
hex1 = hex2val (*ptr);
|
||||
ptr++;
|
||||
hex2 = hex2val (*ptr);
|
||||
ptr++;
|
||||
if (hex1 < 0 || hex2 < 0)
|
||||
{
|
||||
grub_free (pass->expected);
|
||||
grub_free (pass->salt);
|
||||
grub_free (pass);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Incorrect PBKDF2 password.");
|
||||
}
|
||||
|
||||
*ptro = (hex1 << 4) | hex2;
|
||||
ptro++;
|
||||
}
|
||||
|
||||
err = grub_auth_register_authentication (args[0], check_password, pass);
|
||||
if (err)
|
||||
{
|
||||
grub_free (pass);
|
||||
return err;
|
||||
}
|
||||
grub_dl_ref (my_mod);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(password_pbkdf2)
|
||||
{
|
||||
my_mod = mod;
|
||||
cmd = grub_register_command ("password_pbkdf2", grub_cmd_password,
|
||||
"password_pbkdf2 USER PBKDF2_PASSWORD",
|
||||
"Set user password (PBKDF2). ");
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(password_pbkdf2)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
161
commands/probe.c
Normal file
161
commands/probe.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"set", 's', GRUB_ARG_OPTION_OPTIONAL,
|
||||
N_("Set a variable to return value."), "VAR", ARG_TYPE_STRING},
|
||||
{"driver", 'd', 0, N_("Determine driver."), 0, 0},
|
||||
{"partmap", 'p', 0, N_("Determine partition map type."), 0, 0},
|
||||
{"fs", 'f', 0, N_("Determine filesystem type."), 0, 0},
|
||||
{"fs-uuid", 'u', 0, N_("Determine filesystem UUID."), 0, 0},
|
||||
{"label", 'l', 0, N_("Determine filesystem label."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_probe (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
grub_device_t dev;
|
||||
grub_fs_t fs;
|
||||
char *ptr;
|
||||
grub_err_t err;
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
||||
|
||||
ptr = args[0] + grub_strlen (args[0]) - 1;
|
||||
if (args[0][0] == '(' && *ptr == ')')
|
||||
{
|
||||
*ptr = 0;
|
||||
dev = grub_device_open (args[0] + 1);
|
||||
*ptr = ')';
|
||||
}
|
||||
else
|
||||
dev = grub_device_open (args[0]);
|
||||
if (! dev)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "couldn't open device");
|
||||
|
||||
if (state[1].set)
|
||||
{
|
||||
const char *val = "none";
|
||||
if (dev->net)
|
||||
val = dev->net->dev->name;
|
||||
if (dev->disk)
|
||||
val = dev->disk->dev->name;
|
||||
if (state[0].set)
|
||||
grub_env_set (state[0].arg, val);
|
||||
else
|
||||
grub_printf ("%s", val);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
if (state[2].set)
|
||||
{
|
||||
const char *val = "none";
|
||||
if (dev->disk && dev->disk->partition)
|
||||
val = dev->disk->partition->partmap->name;
|
||||
if (state[0].set)
|
||||
grub_env_set (state[0].arg, val);
|
||||
else
|
||||
grub_printf ("%s", val);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
fs = grub_fs_probe (dev);
|
||||
if (! fs)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_FS, "unrecognised fs");
|
||||
if (state[3].set)
|
||||
{
|
||||
if (state[0].set)
|
||||
grub_env_set (state[0].arg, fs->name);
|
||||
else
|
||||
grub_printf ("%s", fs->name);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
if (state[4].set)
|
||||
{
|
||||
char *uuid;
|
||||
if (! fs->uuid)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"uuid for this FS isn't supported yet");
|
||||
err = fs->uuid (dev, &uuid);
|
||||
if (err)
|
||||
return err;
|
||||
if (! uuid)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"uuid for this FS isn't supported yet");
|
||||
|
||||
if (state[0].set)
|
||||
grub_env_set (state[0].arg, uuid);
|
||||
else
|
||||
grub_printf ("%s", uuid);
|
||||
grub_free (uuid);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
if (state[5].set)
|
||||
{
|
||||
char *label;
|
||||
if (! fs->label)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"label for this FS isn't supported yet");
|
||||
err = fs->label (dev, &label);
|
||||
if (err)
|
||||
return err;
|
||||
if (! label)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"uuid for this FS isn't supported yet");
|
||||
|
||||
if (state[0].set)
|
||||
grub_env_set (state[0].arg, label);
|
||||
else
|
||||
grub_printf ("%s", label);
|
||||
grub_free (label);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unrecognised target");
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT (probe)
|
||||
{
|
||||
cmd = grub_register_extcmd ("probe", grub_cmd_probe, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[DEVICE]"),
|
||||
N_("Retrieve device info."), options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (probe)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
90
commands/read.c
Normal file
90
commands/read.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/* read.c - Command to read variables from user. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006,2007,2008 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/mm.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static char *
|
||||
grub_getline (void)
|
||||
{
|
||||
int i;
|
||||
char *line;
|
||||
char *tmp;
|
||||
char c;
|
||||
|
||||
i = 0;
|
||||
line = grub_malloc (1 + i + sizeof('\0'));
|
||||
if (! line)
|
||||
return NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
c = grub_getkey ();
|
||||
if ((c == '\n') || (c == '\r'))
|
||||
break;
|
||||
|
||||
line[i] = c;
|
||||
if (grub_isprint (c))
|
||||
grub_putchar (c);
|
||||
i++;
|
||||
tmp = grub_realloc (line, 1 + i + sizeof('\0'));
|
||||
if (! tmp)
|
||||
{
|
||||
grub_free (line);
|
||||
return NULL;
|
||||
}
|
||||
line = tmp;
|
||||
}
|
||||
line[i] = '\0';
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_read (grub_command_t cmd __attribute__ ((unused)), int argc, char **args)
|
||||
{
|
||||
char *line = grub_getline ();
|
||||
if (! line)
|
||||
return grub_errno;
|
||||
if (argc > 0)
|
||||
grub_env_set (args[0], line);
|
||||
|
||||
grub_free (line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(read)
|
||||
{
|
||||
cmd = grub_register_command ("read", grub_cmd_read,
|
||||
N_("[ENVVAR]"),
|
||||
N_("Set variable with user input."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(read)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* reboot.c - command to reboot the computer. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2008 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
|
||||
|
@ -17,31 +17,29 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/machine/init.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_reboot (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
|
||||
{
|
||||
grub_reboot ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(reboot)
|
||||
{
|
||||
(void)mod; /* To stop warning. */
|
||||
grub_register_command ("reboot", grub_cmd_reboot, GRUB_COMMAND_FLAG_BOTH,
|
||||
"reboot", "Reboot the computer", 0);
|
||||
cmd = grub_register_command ("reboot", grub_cmd_reboot,
|
||||
0, N_("Reboot the computer."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(reboot)
|
||||
{
|
||||
grub_unregister_command ("reboot");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* search.c - search devices based on a file or a filesystem label */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2008,2009 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
|
||||
|
@ -22,144 +22,160 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/search.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"file", 'f', 0, "search devices by a file (default)", 0, 0},
|
||||
{"label", 'l', 0, "search devices by a filesystem label", 0, 0},
|
||||
{"set", 's', GRUB_ARG_OPTION_OPTIONAL, "set a variable to the first device found", "VAR", ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static void
|
||||
search_label (const char *key, const char *var)
|
||||
void
|
||||
FUNC_NAME (const char *key, const char *var, int no_floppy)
|
||||
{
|
||||
int count = 0;
|
||||
char *buf = NULL;
|
||||
grub_fs_autoload_hook_t saved_autoload;
|
||||
|
||||
auto int iterate_device (const char *name);
|
||||
|
||||
int iterate_device (const char *name)
|
||||
{
|
||||
grub_device_t dev;
|
||||
|
||||
dev = grub_device_open (name);
|
||||
if (dev)
|
||||
{
|
||||
grub_fs_t fs;
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
if (fs && fs->label)
|
||||
{
|
||||
char *label;
|
||||
|
||||
(fs->label) (dev, &label);
|
||||
if (grub_errno == GRUB_ERR_NONE && label)
|
||||
{
|
||||
if (grub_strcmp (label, key) == 0)
|
||||
{
|
||||
/* Found! */
|
||||
grub_printf (" %s", name);
|
||||
if (count++ == 0 && var)
|
||||
grub_env_set (var, name);
|
||||
}
|
||||
|
||||
grub_free (label);
|
||||
}
|
||||
}
|
||||
|
||||
grub_device_close (dev);
|
||||
}
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
/* Skip floppy drives when requested. */
|
||||
if (no_floppy &&
|
||||
name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
|
||||
return 0;
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
{
|
||||
grub_size_t len;
|
||||
char *p;
|
||||
grub_file_t file;
|
||||
|
||||
len = grub_strlen (name) + 2 + grub_strlen (key) + 1;
|
||||
p = grub_realloc (buf, len);
|
||||
if (! p)
|
||||
return 1;
|
||||
|
||||
buf = p;
|
||||
grub_sprintf (buf, "(%s)%s", name, key);
|
||||
|
||||
file = grub_file_open (buf);
|
||||
if (file)
|
||||
{
|
||||
found = 1;
|
||||
grub_file_close (file);
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* SEARCH_FS_UUID or SEARCH_LABEL */
|
||||
grub_device_t dev;
|
||||
grub_fs_t fs;
|
||||
char *quid;
|
||||
|
||||
dev = grub_device_open (name);
|
||||
if (dev)
|
||||
{
|
||||
fs = grub_fs_probe (dev);
|
||||
|
||||
#ifdef DO_SEARCH_FS_UUID
|
||||
#define compare_fn grub_strcasecmp
|
||||
#define read_fn uuid
|
||||
#else
|
||||
#define compare_fn grub_strcmp
|
||||
#define read_fn label
|
||||
#endif
|
||||
|
||||
if (fs && fs->read_fn)
|
||||
{
|
||||
fs->read_fn (dev, &quid);
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE && quid)
|
||||
{
|
||||
if (compare_fn (quid, key) == 0)
|
||||
found = 1;
|
||||
|
||||
grub_free (quid);
|
||||
}
|
||||
}
|
||||
|
||||
grub_device_close (dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (found)
|
||||
{
|
||||
count++;
|
||||
if (var)
|
||||
grub_env_set (var, name);
|
||||
else
|
||||
grub_printf (" %s", name);
|
||||
}
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return (found && var);
|
||||
}
|
||||
|
||||
/* First try without autoloading if we're setting variable. */
|
||||
if (var)
|
||||
{
|
||||
saved_autoload = grub_fs_autoload_hook;
|
||||
grub_fs_autoload_hook = 0;
|
||||
grub_device_iterate (iterate_device);
|
||||
|
||||
/* Restore autoload hook. */
|
||||
grub_fs_autoload_hook = saved_autoload;
|
||||
|
||||
/* Retry with autoload if nothing found. */
|
||||
if (grub_errno == GRUB_ERR_NONE && count == 0)
|
||||
grub_device_iterate (iterate_device);
|
||||
}
|
||||
|
||||
grub_device_iterate (iterate_device);
|
||||
|
||||
if (count == 0)
|
||||
else
|
||||
grub_device_iterate (iterate_device);
|
||||
|
||||
grub_free (buf);
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE && count == 0)
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
|
||||
}
|
||||
|
||||
static void
|
||||
search_file (const char *key, const char *var)
|
||||
{
|
||||
int count = 0;
|
||||
char *buf = 0;
|
||||
auto int iterate_device (const char *name);
|
||||
|
||||
int iterate_device (const char *name)
|
||||
{
|
||||
grub_size_t len;
|
||||
char *p;
|
||||
grub_file_t file;
|
||||
|
||||
len = grub_strlen (name) + 2 + grub_strlen (key) + 1;
|
||||
p = grub_realloc (buf, len);
|
||||
if (! p)
|
||||
return 1;
|
||||
|
||||
buf = p;
|
||||
grub_sprintf (buf, "(%s)%s", name, key);
|
||||
|
||||
file = grub_file_open (buf);
|
||||
if (file)
|
||||
{
|
||||
/* Found! */
|
||||
grub_printf (" %s", name);
|
||||
if (count++ == 0 && var)
|
||||
grub_env_set (var, name);
|
||||
|
||||
grub_file_close (file);
|
||||
}
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_device_iterate (iterate_device);
|
||||
|
||||
grub_free (buf);
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE && count == 0)
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device");
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_search (struct grub_arg_list *state, int argc, char **args)
|
||||
grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc,
|
||||
char **args)
|
||||
{
|
||||
const char *var = 0;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_INVALID_COMMAND, "no argument specified");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
|
||||
|
||||
if (state[2].set)
|
||||
var = state[2].arg ? : "root";
|
||||
|
||||
if (state[1].set)
|
||||
search_label (args[0], var);
|
||||
else
|
||||
search_file (args[0], var);
|
||||
FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT(search)
|
||||
static grub_command_t cmd;
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
GRUB_MOD_INIT(search_file)
|
||||
#elif defined (DO_SEARCH_FS_UUID)
|
||||
GRUB_MOD_INIT(search_fs_uuid)
|
||||
#else
|
||||
GRUB_MOD_INIT(search_fs_label)
|
||||
#endif
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
grub_register_command ("search", grub_cmd_search, GRUB_COMMAND_FLAG_BOTH,
|
||||
"search [-f|-l|-s] NAME",
|
||||
"Search devices by a file or a filesystem label."
|
||||
" If --set is specified, the first device found is"
|
||||
" set to a variable. If no variable name is"
|
||||
" specified, \"root\" is used.",
|
||||
options);
|
||||
cmd =
|
||||
grub_register_command (COMMAND_NAME, grub_cmd_do_search,
|
||||
N_("NAME [VARIABLE]"),
|
||||
HELP_MESSAGE);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(search)
|
||||
#ifdef DO_SEARCH_FILE
|
||||
GRUB_MOD_FINI(search_file)
|
||||
#elif defined (DO_SEARCH_FS_UUID)
|
||||
GRUB_MOD_FINI(search_fs_uuid)
|
||||
#else
|
||||
GRUB_MOD_FINI(search_fs_label)
|
||||
#endif
|
||||
{
|
||||
grub_unregister_command ("search");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
|
|
6
commands/search_file.c
Normal file
6
commands/search_file.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#define DO_SEARCH_FILE 1
|
||||
#define FUNC_NAME grub_search_fs_file
|
||||
#define COMMAND_NAME "search.file"
|
||||
#define SEARCH_TARGET "file"
|
||||
#define HELP_MESSAGE N_("Search devices by file. If VARIABLE is specified, the first device found is set to a variable.")
|
||||
#include "search.c"
|
6
commands/search_label.c
Normal file
6
commands/search_label.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#define DO_SEARCH_FS_LABEL 1
|
||||
#define FUNC_NAME grub_search_label
|
||||
#define COMMAND_NAME "search.fs_label"
|
||||
#define SEARCH_TARGET "filesystem label"
|
||||
#define HELP_MESSAGE N_("Search devices by label. If VARIABLE is specified, the first device found is set to a variable.")
|
||||
#include "search.c"
|
6
commands/search_uuid.c
Normal file
6
commands/search_uuid.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#define DO_SEARCH_FS_UUID 1
|
||||
#define FUNC_NAME grub_search_fs_uuid
|
||||
#define COMMAND_NAME "search.fs_uuid"
|
||||
#define SEARCH_TARGET "filesystem UUID"
|
||||
#define HELP_MESSAGE N_("Search devices by UUID. If VARIABLE is specified, the first device found is set to a variable.")
|
||||
#include "search.c"
|
95
commands/search_wrap.c
Normal file
95
commands/search_wrap.c
Normal file
|
@ -0,0 +1,95 @@
|
|||
/* search.c - search devices based on a file or a filesystem label */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007,2008,2009 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/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/search.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"file", 'f', 0, N_("Search devices by a file."), 0, 0},
|
||||
{"label", 'l', 0, N_("Search devices by a filesystem label."),
|
||||
0, 0},
|
||||
{"fs-uuid", 'u', 0, N_("Search devices by a filesystem UUID."),
|
||||
0, 0},
|
||||
{"set", 's', GRUB_ARG_OPTION_OPTIONAL,
|
||||
N_("Set a variable to the first device found."), "VAR", ARG_TYPE_STRING},
|
||||
{"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
enum options
|
||||
{
|
||||
SEARCH_FILE,
|
||||
SEARCH_LABEL,
|
||||
SEARCH_FS_UUID,
|
||||
SEARCH_SET,
|
||||
SEARCH_NO_FLOPPY,
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_search (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
const char *var = 0;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
|
||||
|
||||
if (state[SEARCH_SET].set)
|
||||
var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root";
|
||||
|
||||
if (state[SEARCH_LABEL].set)
|
||||
grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set);
|
||||
else if (state[SEARCH_FS_UUID].set)
|
||||
grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set);
|
||||
else if (state[SEARCH_FILE].set)
|
||||
grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set);
|
||||
else
|
||||
return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type");
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(search)
|
||||
{
|
||||
cmd =
|
||||
grub_register_extcmd ("search", grub_cmd_search,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("search [-f|-l|-u|-s|-n] NAME"),
|
||||
N_("Search devices by file, filesystem label"
|
||||
" or filesystem UUID."
|
||||
" If --set is specified, the first device found is"
|
||||
" set to a variable. If no variable name is"
|
||||
" specified, \"root\" is used."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(search)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
114
commands/sleep.c
Normal file
114
commands/sleep.c
Normal file
|
@ -0,0 +1,114 @@
|
|||
/* sleep.c - Command to wait a specified number of seconds. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006,2007,2008 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/term.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/machine/time.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"verbose", 'v', 0, N_("Verbose countdown."), 0, 0},
|
||||
{"interruptible", 'i', 0, N_("Interruptible with ESC."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static grub_uint16_t *pos;
|
||||
|
||||
static void
|
||||
do_print (int n)
|
||||
{
|
||||
grub_term_restore_pos (pos);
|
||||
/* NOTE: Do not remove the trailing space characters.
|
||||
They are required to clear the line. */
|
||||
grub_printf ("%d ", n);
|
||||
}
|
||||
|
||||
/* Based on grub_millisleep() from kern/generic/millisleep.c. */
|
||||
static int
|
||||
grub_interruptible_millisleep (grub_uint32_t ms)
|
||||
{
|
||||
grub_uint64_t start;
|
||||
|
||||
start = grub_get_time_ms ();
|
||||
|
||||
while (grub_get_time_ms () - start < ms)
|
||||
if (grub_checkkey () >= 0 &&
|
||||
GRUB_TERM_ASCII_CHAR (grub_getkey ()) == GRUB_TERM_ESC)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
int n;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing operand");
|
||||
|
||||
n = grub_strtoul (args[0], 0, 10);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
/* Either `0' or broken input. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
pos = grub_term_save_pos ();
|
||||
|
||||
for (; n; n--)
|
||||
{
|
||||
if (state[0].set)
|
||||
do_print (n);
|
||||
|
||||
if (state[1].set)
|
||||
{
|
||||
if (grub_interruptible_millisleep (1000))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
grub_millisleep (1000);
|
||||
}
|
||||
if (state[0].set)
|
||||
do_print (0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(sleep)
|
||||
{
|
||||
cmd = grub_register_extcmd ("sleep", grub_cmd_sleep, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("NUMBER_OF_SECONDS"),
|
||||
N_("Wait for a specified number of seconds."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(sleep)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
/* terminal.c - command to show and select a terminal */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2009 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
|
||||
|
@ -17,67 +16,349 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
struct grub_term_autoload *grub_term_input_autoload = NULL;
|
||||
struct grub_term_autoload *grub_term_output_autoload = NULL;
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_terminal (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_term_t term = 0;
|
||||
|
||||
auto int print_terminal (grub_term_t);
|
||||
auto int find_terminal (grub_term_t);
|
||||
|
||||
int print_terminal (grub_term_t t)
|
||||
{
|
||||
grub_printf (" %s", t->name);
|
||||
return 0;
|
||||
}
|
||||
int i;
|
||||
grub_term_input_t term;
|
||||
struct grub_term_autoload *aut;
|
||||
|
||||
int find_terminal (grub_term_t t)
|
||||
{
|
||||
if (grub_strcmp (t->name, args[0]) == 0)
|
||||
{
|
||||
term = t;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_printf ("Available terminal(s):");
|
||||
grub_term_iterate (print_terminal);
|
||||
grub_putchar ('\n');
|
||||
|
||||
grub_printf ("Current terminal: %s\n", grub_term_get_current ()->name);
|
||||
grub_puts_ (N_ ("Active input terminals:"));
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
grub_printf ("%s ", term->name);
|
||||
grub_printf ("\n");
|
||||
grub_puts_ (N_ ("Available input terminals:"));
|
||||
FOR_DISABLED_TERM_INPUTS(term)
|
||||
grub_printf ("%s ", term->name);
|
||||
/* This is quadratic but we don't expect mode than 30 terminal
|
||||
modules ever. */
|
||||
for (aut = grub_term_input_autoload; aut; aut = aut->next)
|
||||
{
|
||||
FOR_DISABLED_TERM_INPUTS(term)
|
||||
if (grub_strcmp (term->name, aut->name) == 0)
|
||||
break;
|
||||
if (!term)
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
if (grub_strcmp (term->name, aut->name) == 0)
|
||||
break;
|
||||
if (!term)
|
||||
grub_printf ("%s ", aut->name);
|
||||
}
|
||||
grub_printf ("\n");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_term_iterate (find_terminal);
|
||||
if (! term)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such terminal");
|
||||
i = 0;
|
||||
|
||||
grub_term_set_current (term);
|
||||
if (grub_strcmp (args[0], "--append") == 0
|
||||
|| grub_strcmp (args[0], "--remove") == 0)
|
||||
i++;
|
||||
|
||||
if (i == argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified"));
|
||||
|
||||
for (; i < argc; i++)
|
||||
{
|
||||
int again = 0;
|
||||
while (1)
|
||||
{
|
||||
FOR_DISABLED_TERM_INPUTS(term)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term == 0)
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
break;
|
||||
if (again)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
|
||||
args[i]);
|
||||
for (aut = grub_term_input_autoload; aut; aut = aut->next)
|
||||
if (grub_strcmp (args[i], aut->name) == 0)
|
||||
{
|
||||
grub_dl_t mod;
|
||||
mod = grub_dl_load (aut->modname);
|
||||
if (mod)
|
||||
grub_dl_ref (mod);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
break;
|
||||
}
|
||||
if (!aut)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
|
||||
args[i]);
|
||||
again = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[0], "--append") == 0)
|
||||
{
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
FOR_DISABLED_TERM_INPUTS(term)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)),
|
||||
GRUB_AS_LIST (term));
|
||||
if (term->init)
|
||||
term->init ();
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs),
|
||||
GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[0], "--remove") == 0)
|
||||
{
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
if (!term->next && term == grub_term_inputs)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"can't remove the last terminal");
|
||||
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs)),
|
||||
GRUB_AS_LIST (term));
|
||||
if (term->fini)
|
||||
term->fini ();
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
|
||||
GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
FOR_DISABLED_TERM_INPUTS(term)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)),
|
||||
GRUB_AS_LIST (term));
|
||||
if (term->init)
|
||||
term->init ();
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs),
|
||||
GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
{
|
||||
for (i = 0; i < argc; i++)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (i == argc)
|
||||
{
|
||||
if (!term->next && term == grub_term_inputs)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"can't remove the last terminal");
|
||||
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs)),
|
||||
GRUB_AS_LIST (term));
|
||||
if (term->fini)
|
||||
term->fini ();
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
|
||||
GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
grub_term_output_t term;
|
||||
struct grub_term_autoload *aut;
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_puts_ (N_ ("Active output terminals:"));
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
grub_printf ("%s ", term->name);
|
||||
grub_printf ("\n");
|
||||
grub_puts_ (N_ ("Available output terminals:"));
|
||||
FOR_DISABLED_TERM_OUTPUTS(term)
|
||||
grub_printf ("%s ", term->name);
|
||||
/* This is quadratic but we don't expect mode than 30 terminal
|
||||
modules ever. */
|
||||
for (aut = grub_term_output_autoload; aut; aut = aut->next)
|
||||
{
|
||||
FOR_DISABLED_TERM_OUTPUTS(term)
|
||||
if (grub_strcmp (term->name, aut->name) == 0)
|
||||
break;
|
||||
if (!term)
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
if (grub_strcmp (term->name, aut->name) == 0)
|
||||
break;
|
||||
if (!term)
|
||||
grub_printf ("%s ", aut->name);
|
||||
}
|
||||
grub_printf ("\n");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
i = 0;
|
||||
|
||||
if (grub_strcmp (args[0], "--append") == 0
|
||||
|| grub_strcmp (args[0], "--remove") == 0)
|
||||
i++;
|
||||
|
||||
if (i == argc)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified"));
|
||||
|
||||
for (; i < argc; i++)
|
||||
{
|
||||
int again = 0;
|
||||
while (1)
|
||||
{
|
||||
FOR_DISABLED_TERM_OUTPUTS(term)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term == 0)
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
break;
|
||||
if (again)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
|
||||
args[i]);
|
||||
for (aut = grub_term_output_autoload; aut; aut = aut->next)
|
||||
if (grub_strcmp (args[i], aut->name) == 0)
|
||||
{
|
||||
grub_dl_t mod;
|
||||
mod = grub_dl_load (aut->modname);
|
||||
if (mod)
|
||||
grub_dl_ref (mod);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
break;
|
||||
}
|
||||
if (!aut)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
|
||||
args[i]);
|
||||
again = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[0], "--append") == 0)
|
||||
{
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
FOR_DISABLED_TERM_OUTPUTS(term)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
|
||||
GRUB_AS_LIST (term));
|
||||
if (term->init)
|
||||
term->init ();
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
|
||||
GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[0], "--remove") == 0)
|
||||
{
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
if (!term->next && term == grub_term_outputs)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"can't remove the last terminal");
|
||||
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs)),
|
||||
GRUB_AS_LIST (term));
|
||||
if (term->fini)
|
||||
term->fini ();
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
|
||||
GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
FOR_DISABLED_TERM_OUTPUTS(term)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
|
||||
GRUB_AS_LIST (term));
|
||||
if (term->init)
|
||||
term->init ();
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
|
||||
GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
{
|
||||
for (i = 0; i < argc; i++)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (i == argc)
|
||||
{
|
||||
if (!term->next && term == grub_term_outputs)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"can't remove the last terminal");
|
||||
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs)),
|
||||
GRUB_AS_LIST (term));
|
||||
if (term->fini)
|
||||
term->fini ();
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
|
||||
GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_terminal_input, cmd_terminal_output;
|
||||
|
||||
GRUB_MOD_INIT(terminal)
|
||||
{
|
||||
(void)mod; /* To stop warning. */
|
||||
grub_register_command ("terminal", grub_cmd_terminal, GRUB_COMMAND_FLAG_BOTH,
|
||||
"terminal [TERM...]", "Select a terminal.", 0);
|
||||
cmd_terminal_input =
|
||||
grub_register_command ("terminal_input", grub_cmd_terminal_input,
|
||||
"[--append|--remove] "
|
||||
"[TERMINAL1] [TERMINAL2] ...",
|
||||
"List or select an input terminal.");
|
||||
cmd_terminal_output =
|
||||
grub_register_command ("terminal_output", grub_cmd_terminal_output,
|
||||
"[--append|--remove] "
|
||||
"[TERMINAL1] [TERMINAL2] ...",
|
||||
"List or select an output terminal.");
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(terminal)
|
||||
{
|
||||
grub_unregister_command ("terminal");
|
||||
grub_unregister_command (cmd_terminal_input);
|
||||
grub_unregister_command (cmd_terminal_output);
|
||||
}
|
||||
|
|
433
commands/test.c
433
commands/test.c
|
@ -1,7 +1,7 @@
|
|||
/* test.c -- The test command.. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2009 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
|
||||
|
@ -17,54 +17,417 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/normal.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_test (struct grub_arg_list *state __attribute__ ((unused)), int argc,
|
||||
char **args)
|
||||
|
||||
/* A simple implementation for signed numbers. */
|
||||
static int
|
||||
grub_strtosl (char *arg, char **end, int base)
|
||||
{
|
||||
char *eq;
|
||||
char *eqis;
|
||||
|
||||
/* XXX: No fancy expression evaluation yet. */
|
||||
|
||||
if (argc == 0)
|
||||
return 0;
|
||||
|
||||
eq = grub_strdup (args[0]);
|
||||
eqis = grub_strchr (eq, '=');
|
||||
if (! eqis)
|
||||
return 0;
|
||||
|
||||
*eqis = '\0';
|
||||
eqis++;
|
||||
/* Check an expression in the form `A=B'. */
|
||||
if (grub_strcmp (eq, eqis))
|
||||
grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
grub_free (eq);
|
||||
|
||||
return grub_errno;
|
||||
if (arg[0] == '-')
|
||||
return -grub_strtoul (arg + 1, end, base);
|
||||
return grub_strtoul (arg, end, base);
|
||||
}
|
||||
|
||||
/* Parse a test expression starting from *argn. */
|
||||
static int
|
||||
test_parse (char **args, int *argn, int argc)
|
||||
{
|
||||
int ret = 0, discard = 0, invert = 0;
|
||||
int file_exists;
|
||||
struct grub_dirhook_info file_info;
|
||||
|
||||
auto void update_val (int val);
|
||||
auto void get_fileinfo (char *pathname);
|
||||
|
||||
/* Take care of discarding and inverting. */
|
||||
void update_val (int val)
|
||||
{
|
||||
if (! discard)
|
||||
ret = invert ? ! val : val;
|
||||
invert = discard = 0;
|
||||
}
|
||||
|
||||
/* Check if file exists and fetch its information. */
|
||||
void get_fileinfo (char *path)
|
||||
{
|
||||
char *filename, *pathname;
|
||||
char *device_name;
|
||||
grub_fs_t fs;
|
||||
grub_device_t dev;
|
||||
|
||||
/* A hook for iterating directories. */
|
||||
auto int find_file (const char *cur_filename,
|
||||
const struct grub_dirhook_info *info);
|
||||
int find_file (const char *cur_filename,
|
||||
const struct grub_dirhook_info *info)
|
||||
{
|
||||
if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename)
|
||||
: grub_strcmp (cur_filename, filename)) == 0)
|
||||
{
|
||||
file_info = *info;
|
||||
file_exists = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
file_exists = 0;
|
||||
device_name = grub_file_get_device_name (path);
|
||||
dev = grub_device_open (device_name);
|
||||
if (! dev)
|
||||
{
|
||||
grub_free (device_name);
|
||||
return;
|
||||
}
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
if (! fs)
|
||||
{
|
||||
grub_free (device_name);
|
||||
grub_device_close (dev);
|
||||
return;
|
||||
}
|
||||
|
||||
pathname = grub_strchr (path, ')');
|
||||
if (! pathname)
|
||||
pathname = path;
|
||||
else
|
||||
pathname++;
|
||||
|
||||
/* Remove trailing '/'. */
|
||||
while (*pathname && pathname[grub_strlen (pathname) - 1] == '/')
|
||||
pathname[grub_strlen (pathname) - 1] = 0;
|
||||
|
||||
/* Split into path and filename. */
|
||||
filename = grub_strrchr (pathname, '/');
|
||||
if (! filename)
|
||||
{
|
||||
path = grub_strdup ("/");
|
||||
filename = pathname;
|
||||
}
|
||||
else
|
||||
{
|
||||
filename++;
|
||||
path = grub_strdup (pathname);
|
||||
path[filename - pathname] = 0;
|
||||
}
|
||||
|
||||
/* It's the whole device. */
|
||||
if (! *pathname)
|
||||
{
|
||||
file_exists = 1;
|
||||
grub_memset (&file_info, 0, sizeof (file_info));
|
||||
/* Root is always a directory. */
|
||||
file_info.dir = 1;
|
||||
|
||||
/* Fetch writing time. */
|
||||
file_info.mtimeset = 0;
|
||||
if (fs->mtime)
|
||||
{
|
||||
if (! fs->mtime (dev, &file_info.mtime))
|
||||
file_info.mtimeset = 1;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
(fs->dir) (dev, path, find_file);
|
||||
|
||||
grub_device_close (dev);
|
||||
grub_free (path);
|
||||
grub_free (device_name);
|
||||
}
|
||||
|
||||
/* Here we have the real parsing. */
|
||||
while (*argn < argc)
|
||||
{
|
||||
/* First try 3 argument tests. */
|
||||
if (*argn + 2 < argc)
|
||||
{
|
||||
/* String tests. */
|
||||
if (grub_strcmp (args[*argn + 1], "=") == 0
|
||||
|| grub_strcmp (args[*argn + 1], "==") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "!=") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* GRUB extension: lexicographical sorting. */
|
||||
if (grub_strcmp (args[*argn + 1], "<") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "<=") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], ">") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], ">=") == 0)
|
||||
{
|
||||
update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0);
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Number tests. */
|
||||
if (grub_strcmp (args[*argn + 1], "-eq") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
== grub_strtosl (args[*argn + 2], 0, 0));
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-ge") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
>= grub_strtosl (args[*argn + 2], 0, 0));
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-gt") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
> grub_strtosl (args[*argn + 2], 0, 0));
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-le") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
<= grub_strtosl (args[*argn + 2], 0, 0));
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-lt") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
< grub_strtosl (args[*argn + 2], 0, 0));
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-ne") == 0)
|
||||
{
|
||||
update_val (grub_strtosl (args[*argn], 0, 0)
|
||||
!= grub_strtosl (args[*argn + 2], 0, 0));
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* GRUB extension: compare numbers skipping prefixes.
|
||||
Useful for comparing versions. E.g. vmlinuz-2 -plt vmlinuz-11. */
|
||||
if (grub_strcmp (args[*argn + 1], "-pgt") == 0
|
||||
|| grub_strcmp (args[*argn + 1], "-plt") == 0)
|
||||
{
|
||||
int i;
|
||||
/* Skip common prefix. */
|
||||
for (i = 0; args[*argn][i] == args[*argn + 2][i]
|
||||
&& args[*argn][i]; i++);
|
||||
|
||||
/* Go the digits back. */
|
||||
i--;
|
||||
while (grub_isdigit (args[*argn][i]) && i > 0)
|
||||
i--;
|
||||
i++;
|
||||
|
||||
if (grub_strcmp (args[*argn + 1], "-pgt") == 0)
|
||||
update_val (grub_strtoul (args[*argn] + i, 0, 0)
|
||||
> grub_strtoul (args[*argn + 2] + i, 0, 0));
|
||||
else
|
||||
update_val (grub_strtoul (args[*argn] + i, 0, 0)
|
||||
< grub_strtoul (args[*argn + 2] + i, 0, 0));
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* -nt and -ot tests. GRUB extension: when doing -?t<bias> bias
|
||||
will be added to the first mtime. */
|
||||
if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0
|
||||
|| grub_memcmp (args[*argn + 1], "-ot", 3) == 0)
|
||||
{
|
||||
struct grub_dirhook_info file1;
|
||||
int file1exists;
|
||||
int bias = 0;
|
||||
|
||||
/* Fetch fileinfo. */
|
||||
get_fileinfo (args[*argn]);
|
||||
file1 = file_info;
|
||||
file1exists = file_exists;
|
||||
get_fileinfo (args[*argn + 2]);
|
||||
|
||||
if (args[*argn + 1][3])
|
||||
bias = grub_strtosl (args[*argn + 1] + 3, 0, 0);
|
||||
|
||||
if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0)
|
||||
update_val ((file1exists && ! file_exists)
|
||||
|| (file1.mtimeset && file_info.mtimeset
|
||||
&& file1.mtime + bias > file_info.mtime));
|
||||
else
|
||||
update_val ((! file1exists && file_exists)
|
||||
|| (file1.mtimeset && file_info.mtimeset
|
||||
&& file1.mtime + bias < file_info.mtime));
|
||||
(*argn) += 3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Two-argument tests. */
|
||||
if (*argn + 1 < argc)
|
||||
{
|
||||
/* File tests. */
|
||||
if (grub_strcmp (args[*argn], "-d") == 0)
|
||||
{
|
||||
get_fileinfo (args[*argn + 1]);
|
||||
update_val (file_exists && file_info.dir);
|
||||
(*argn) += 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-e") == 0)
|
||||
{
|
||||
get_fileinfo (args[*argn + 1]);
|
||||
update_val (file_exists);
|
||||
(*argn) += 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-f") == 0)
|
||||
{
|
||||
get_fileinfo (args[*argn + 1]);
|
||||
/* FIXME: check for other types. */
|
||||
update_val (file_exists && ! file_info.dir);
|
||||
(*argn) += 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "-s") == 0)
|
||||
{
|
||||
grub_file_t file;
|
||||
file = grub_file_open (args[*argn + 1]);
|
||||
update_val (file && (grub_file_size (file) != 0));
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
(*argn) += 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* String tests. */
|
||||
if (grub_strcmp (args[*argn], "-n") == 0)
|
||||
{
|
||||
update_val (args[*argn + 1][0]);
|
||||
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-z") == 0)
|
||||
{
|
||||
update_val (! args[*argn + 1][0]);
|
||||
(*argn) += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special modifiers. */
|
||||
|
||||
/* End of expression. return to parent. */
|
||||
if (grub_strcmp (args[*argn], ")") == 0)
|
||||
{
|
||||
(*argn)++;
|
||||
return ret;
|
||||
}
|
||||
/* Recursively invoke if parenthesis. */
|
||||
if (grub_strcmp (args[*argn], "(") == 0)
|
||||
{
|
||||
(*argn)++;
|
||||
update_val (test_parse (args, argn, argc));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[*argn], "!") == 0)
|
||||
{
|
||||
invert = ! invert;
|
||||
(*argn)++;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-a") == 0)
|
||||
{
|
||||
/* If current value is 0 second value is to be discarded. */
|
||||
discard = ! ret;
|
||||
(*argn)++;
|
||||
continue;
|
||||
}
|
||||
if (grub_strcmp (args[*argn], "-o") == 0)
|
||||
{
|
||||
/* If current value is 1 second value is to be discarded. */
|
||||
discard = ret;
|
||||
(*argn)++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No test found. Interpret if as just a string. */
|
||||
update_val (args[*argn][0]);
|
||||
(*argn)++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_test (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int argn = 0;
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[argc - 1], "]") == 0)
|
||||
argc--;
|
||||
|
||||
return test_parse (args, &argn, argc) ? GRUB_ERR_NONE
|
||||
: grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
}
|
||||
|
||||
static grub_command_t cmd_1, cmd_2;
|
||||
|
||||
GRUB_MOD_INIT(test)
|
||||
{
|
||||
(void)mod; /* To stop warning. */
|
||||
grub_register_command ("[", grub_cmd_test, GRUB_COMMAND_FLAG_CMDLINE,
|
||||
"[ EXPRESSION ]", "Evaluate an expression", 0);
|
||||
grub_register_command ("test", grub_cmd_test, GRUB_COMMAND_FLAG_CMDLINE,
|
||||
"test EXPRESSION", "Evaluate an expression", 0);
|
||||
cmd_1 = grub_register_command ("[", grub_cmd_test,
|
||||
N_("EXPRESSION ]"), N_("Evaluate an expression."));
|
||||
cmd_2 = grub_register_command ("test", grub_cmd_test,
|
||||
N_("EXPRESSION"), N_("Evaluate an expression."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(test)
|
||||
{
|
||||
grub_unregister_command ("[");
|
||||
grub_unregister_command ("test");
|
||||
grub_unregister_command (cmd_1);
|
||||
grub_unregister_command (cmd_2);
|
||||
}
|
||||
|
|
57
commands/true.c
Normal file
57
commands/true.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* true.c - true and false commands. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 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/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_true (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_false (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
}
|
||||
|
||||
static grub_command_t cmd_true, cmd_false;
|
||||
|
||||
|
||||
GRUB_MOD_INIT(true)
|
||||
{
|
||||
cmd_true =
|
||||
grub_register_command ("true", grub_cmd_true,
|
||||
0, N_("Do nothing, successfully."));
|
||||
cmd_false =
|
||||
grub_register_command ("false", grub_cmd_false,
|
||||
0, N_("Do nothing, unsuccessfully."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(true)
|
||||
{
|
||||
grub_unregister_command (cmd_true);
|
||||
grub_unregister_command (cmd_false);
|
||||
}
|
205
commands/usbtest.c
Normal file
205
commands/usbtest.c
Normal file
|
@ -0,0 +1,205 @@
|
|||
/* usbtest.c - test module for USB */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 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/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/usb.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const char *usb_classes[] =
|
||||
{
|
||||
"",
|
||||
"Audio",
|
||||
"Communication Interface",
|
||||
"HID",
|
||||
"",
|
||||
"Physical",
|
||||
"Image",
|
||||
"Printer",
|
||||
"Mass Storage",
|
||||
"Hub",
|
||||
"Data Interface",
|
||||
"Smart Card",
|
||||
"Content Security",
|
||||
"Video"
|
||||
};
|
||||
|
||||
static const char *usb_endp_type[] =
|
||||
{
|
||||
"Control",
|
||||
"Isochronous",
|
||||
"Bulk",
|
||||
"Interrupt"
|
||||
};
|
||||
|
||||
static const char *usb_devspeed[] =
|
||||
{
|
||||
"",
|
||||
"Low",
|
||||
"Full",
|
||||
"High"
|
||||
};
|
||||
|
||||
static grub_usb_err_t
|
||||
grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid,
|
||||
char **string)
|
||||
{
|
||||
struct grub_usb_desc_str descstr;
|
||||
struct grub_usb_desc_str *descstrp;
|
||||
grub_usb_err_t err;
|
||||
|
||||
/* Only get the length. */
|
||||
err = grub_usb_control_msg (dev, 1 << 7,
|
||||
0x06, (3 << 8) | index,
|
||||
langid, 1, (char *) &descstr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
descstrp = grub_malloc (descstr.length);
|
||||
if (! descstrp)
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
err = grub_usb_control_msg (dev, 1 << 7,
|
||||
0x06, (3 << 8) | index,
|
||||
langid, descstr.length, (char *) descstrp);
|
||||
|
||||
*string = grub_malloc (descstr.length / 2);
|
||||
if (! *string)
|
||||
{
|
||||
grub_free (descstrp);
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
grub_utf16_to_utf8 ((grub_uint8_t *) *string, descstrp->str, descstrp->length / 2 - 1);
|
||||
(*string)[descstr.length / 2 - 1] = '\0';
|
||||
grub_free (descstrp);
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
usb_print_str (const char *description, grub_usb_device_t dev, int idx)
|
||||
{
|
||||
char *name;
|
||||
grub_usb_err_t err;
|
||||
/* XXX: LANGID */
|
||||
|
||||
if (! idx)
|
||||
return;
|
||||
|
||||
err = grub_usb_get_string (dev, idx, 0x0409, &name);
|
||||
if (err)
|
||||
grub_printf ("Error %d retrieving %s\n", err, description);
|
||||
else
|
||||
{
|
||||
grub_printf ("%s: `%s'\n", description, name);
|
||||
grub_free (name);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
usb_iterate (grub_usb_device_t dev)
|
||||
{
|
||||
struct grub_usb_desc_device *descdev;
|
||||
int i;
|
||||
|
||||
descdev = &dev->descdev;
|
||||
|
||||
usb_print_str ("Product", dev, descdev->strprod);
|
||||
usb_print_str ("Vendor", dev, descdev->strvendor);
|
||||
usb_print_str ("Serial", dev, descdev->strserial);
|
||||
|
||||
if (descdev->class > 0 && descdev->class <= 0x0E)
|
||||
grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n",
|
||||
descdev->class, usb_classes[descdev->class],
|
||||
descdev->subclass, descdev->protocol);
|
||||
grub_printf ("USB version %d.%d, VendorID: 0x%02x, ProductID: 0x%02x, #conf: %d\n",
|
||||
descdev->usbrel >> 8, (descdev->usbrel >> 4) & 0x0F,
|
||||
descdev->vendorid, descdev->prodid, descdev->configcnt);
|
||||
|
||||
grub_printf ("%s speed device\n", usb_devspeed[dev->speed]);
|
||||
|
||||
for (i = 0; i < descdev->configcnt; i++)
|
||||
{
|
||||
struct grub_usb_desc_config *config;
|
||||
|
||||
config = dev->config[i].descconf;
|
||||
usb_print_str ("Configuration:", dev, config->strconfig);
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->config[0].descconf->numif; i++)
|
||||
{
|
||||
int j;
|
||||
struct grub_usb_desc_if *interf;
|
||||
interf = dev->config[0].interf[i].descif;
|
||||
|
||||
grub_printf ("Interface #%d: #Endpoints: %d ",
|
||||
i, interf->endpointcnt);
|
||||
if (interf->class > 0 && interf->class <= 0x0E)
|
||||
grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n",
|
||||
interf->class, usb_classes[interf->class],
|
||||
interf->subclass, interf->protocol);
|
||||
|
||||
usb_print_str ("Interface", dev, interf->strif);
|
||||
|
||||
for (j = 0; j < interf->endpointcnt; j++)
|
||||
{
|
||||
struct grub_usb_desc_endp *endp;
|
||||
endp = &dev->config[0].interf[i].descendp[j];
|
||||
|
||||
grub_printf ("Endpoint #%d: %s, max packed size: %d, transfer type: %s, latency: %d\n",
|
||||
endp->endp_addr & 15,
|
||||
(endp->endp_addr & 128) ? "IN" : "OUT",
|
||||
endp->maxpacket, usb_endp_type[endp->attrib & 3],
|
||||
endp->interval);
|
||||
}
|
||||
}
|
||||
|
||||
grub_printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_usbtest (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
grub_printf ("USB devices:\n\n");
|
||||
grub_usb_iterate (usb_iterate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(usbtest)
|
||||
{
|
||||
cmd = grub_register_command ("usb", grub_cmd_usbtest,
|
||||
0, N_("Test USB support."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(usbtest)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2006,2007,2009 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
|
||||
|
@ -16,37 +16,41 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/arg.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/font.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
|
||||
grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
if (grub_video_setup (1024, 768,
|
||||
GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
grub_getkey ();
|
||||
|
||||
grub_err_t err;
|
||||
grub_video_color_t color;
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
int i;
|
||||
struct grub_font_glyph glyph;
|
||||
grub_font_t sansbig;
|
||||
grub_font_t sans;
|
||||
grub_font_t sanssmall;
|
||||
grub_font_t fixed;
|
||||
struct grub_font_glyph *glyph;
|
||||
struct grub_video_render_target *text_layer;
|
||||
grub_video_color_t palette[16];
|
||||
const char *str;
|
||||
int texty;
|
||||
|
||||
err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
grub_video_get_viewport (&x, &y, &width, &height);
|
||||
|
||||
|
@ -65,8 +69,15 @@ grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
color = grub_video_map_rgb (0, 255, 255);
|
||||
grub_video_fill_rect (color, 100, 100, 100, 100);
|
||||
|
||||
grub_font_get_glyph ('*', &glyph);
|
||||
grub_video_blit_glyph (&glyph, color, 200 ,0);
|
||||
sansbig = grub_font_get ("Helvetica Bold 24");
|
||||
sans = grub_font_get ("Helvetica Bold 14");
|
||||
sanssmall = grub_font_get ("Helvetica 8");
|
||||
fixed = grub_font_get ("Fixed 20");
|
||||
if (! sansbig || ! sans || ! sanssmall || ! fixed)
|
||||
return grub_error (GRUB_ERR_BAD_FONT, "no font loaded");
|
||||
|
||||
glyph = grub_font_get_glyph (fixed, '*');
|
||||
grub_font_draw_glyph (glyph, color, 200 ,0);
|
||||
|
||||
grub_video_set_viewport (x + 150, y + 150,
|
||||
width - 150 * 2, height - 150 * 2);
|
||||
|
@ -77,28 +88,80 @@ grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
|
||||
color = grub_video_map_rgb (255, 255, 255);
|
||||
|
||||
grub_font_get_glyph ('A', &glyph);
|
||||
grub_video_blit_glyph (&glyph, color, 16, 16);
|
||||
grub_font_get_glyph ('B', &glyph);
|
||||
grub_video_blit_glyph (&glyph, color, 16 * 2, 16);
|
||||
texty = 32;
|
||||
grub_font_draw_string ("The quick brown fox jumped over the lazy dog.",
|
||||
sans, color, 16, texty);
|
||||
texty += grub_font_get_descent (sans) + grub_font_get_leading (sans);
|
||||
|
||||
grub_font_get_glyph ('*', &glyph);
|
||||
texty += grub_font_get_ascent (fixed);
|
||||
grub_font_draw_string ("The quick brown fox jumped over the lazy dog.",
|
||||
fixed, color, 16, texty);
|
||||
texty += grub_font_get_descent (fixed) + grub_font_get_leading (fixed);
|
||||
|
||||
/* To convert Unicode characters into UTF-8 for this test, the following
|
||||
command is useful:
|
||||
echo -ne '\x00\x00\x26\x3A' | iconv -f UTF-32BE -t UTF-8 | od -t x1
|
||||
This converts the Unicode character U+263A to UTF-8. */
|
||||
|
||||
/* Characters used:
|
||||
Code point Description UTF-8 encoding
|
||||
----------- ------------------------------ --------------
|
||||
U+263A unfilled smiley face E2 98 BA
|
||||
U+00A1 inverted exclamation point C2 A1
|
||||
U+00A3 British pound currency symbol C2 A3
|
||||
U+03C4 Greek tau CF 84
|
||||
U+00E4 lowercase letter a with umlaut C3 A4
|
||||
U+2124 set 'Z' symbol (integers) E2 84 A4
|
||||
U+2287 subset symbol E2 8A 87
|
||||
U+211D set 'R' symbol (real numbers) E2 84 9D */
|
||||
|
||||
str =
|
||||
"Unicode test: happy\xE2\x98\xBA \xC2\xA3 5.00"
|
||||
" \xC2\xA1\xCF\x84\xC3\xA4u! "
|
||||
" \xE2\x84\xA4\xE2\x8A\x87\xE2\x84\x9D";
|
||||
color = grub_video_map_rgb (128, 128, 255);
|
||||
|
||||
/* All characters in the string exist in the 'Fixed 20' (10x20) font. */
|
||||
texty += grub_font_get_ascent(fixed);
|
||||
grub_font_draw_string (str, fixed, color, 16, texty);
|
||||
texty += grub_font_get_descent (fixed) + grub_font_get_leading (fixed);
|
||||
|
||||
/* Some character don't exist in the Helvetica font, so the font engine
|
||||
will fall back to using glyphs from another font that does contain them.
|
||||
TODO The font engine should be smart about selecting a replacement font
|
||||
and prioritize fonts with similar sizes. */
|
||||
|
||||
texty += grub_font_get_ascent(sansbig);
|
||||
grub_font_draw_string (str, sansbig, color, 16, texty);
|
||||
texty += grub_font_get_descent (sansbig) + grub_font_get_leading (sansbig);
|
||||
|
||||
texty += grub_font_get_ascent(sans);
|
||||
grub_font_draw_string (str, sans, color, 16, texty);
|
||||
texty += grub_font_get_descent (sans) + grub_font_get_leading (sans);
|
||||
|
||||
texty += grub_font_get_ascent(sanssmall);
|
||||
grub_font_draw_string (str, sanssmall, color, 16, texty);
|
||||
texty += (grub_font_get_descent (sanssmall)
|
||||
+ grub_font_get_leading (sanssmall));
|
||||
|
||||
glyph = grub_font_get_glyph (fixed, '*');
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
color = grub_video_map_color (i);
|
||||
palette[i] = color;
|
||||
grub_video_blit_glyph (&glyph, color, 16 + i * 16, 32);
|
||||
grub_font_draw_glyph (glyph, color, 16 + i * 16, 220);
|
||||
}
|
||||
|
||||
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
|
||||
|
||||
for (i = 0; i < 255; i++)
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
color = grub_video_map_rgb (i, 33, 77);
|
||||
grub_video_fill_rect (color, 0, 0, width, height);
|
||||
grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0, 0,
|
||||
0, 0, width, height);
|
||||
grub_video_swap_buffers ();
|
||||
}
|
||||
|
||||
grub_getkey ();
|
||||
|
@ -114,17 +177,15 @@ grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(videotest)
|
||||
{
|
||||
grub_register_command ("videotest",
|
||||
grub_cmd_videotest,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"videotest",
|
||||
"Test video subsystem",
|
||||
0);
|
||||
cmd = grub_register_command ("videotest", grub_cmd_videotest,
|
||||
0, N_("Test video subsystem."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(videotest)
|
||||
{
|
||||
grub_unregister_command ("videotest");
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
|
|
100
commands/xnu_uuid.c
Normal file
100
commands/xnu_uuid.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/* xnu_uuid.c - transform 64-bit serial number
|
||||
to 128-bit uuid suitable for xnu. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1995,1996,1998,1999,2001,2002,
|
||||
* 2003, 2009 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/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/crypto.h>
|
||||
|
||||
/* This prefix is used by xnu and boot-132 to hash
|
||||
together with volume serial. */
|
||||
static grub_uint8_t hash_prefix[16]
|
||||
= {0xB3, 0xE2, 0x0F, 0x39, 0xF2, 0x92, 0x11, 0xD6,
|
||||
0x97, 0xA4, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_uint64_t serial;
|
||||
grub_uint8_t *xnu_uuid;
|
||||
char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
|
||||
char *ptr;
|
||||
grub_uint8_t ctx[GRUB_MD_MD5->contextsize];
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required");
|
||||
|
||||
serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16));
|
||||
|
||||
GRUB_MD_MD5->init (&ctx);
|
||||
GRUB_MD_MD5->write (&ctx, hash_prefix, sizeof (hash_prefix));
|
||||
GRUB_MD_MD5->write (&ctx, &serial, sizeof (serial));
|
||||
GRUB_MD_MD5->final (&ctx);
|
||||
xnu_uuid = GRUB_MD_MD5->read (&ctx);
|
||||
|
||||
grub_sprintf (uuid_string,
|
||||
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
(unsigned int) xnu_uuid[0], (unsigned int) xnu_uuid[1],
|
||||
(unsigned int) xnu_uuid[2], (unsigned int) xnu_uuid[3],
|
||||
(unsigned int) xnu_uuid[4], (unsigned int) xnu_uuid[5],
|
||||
(unsigned int) ((xnu_uuid[6] & 0xf) | 0x30),
|
||||
(unsigned int) xnu_uuid[7],
|
||||
(unsigned int) ((xnu_uuid[8] & 0x3f) | 0x80),
|
||||
(unsigned int) xnu_uuid[9],
|
||||
(unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11],
|
||||
(unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13],
|
||||
(unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]);
|
||||
for (ptr = uuid_string; *ptr; ptr++)
|
||||
*ptr = grub_toupper (*ptr);
|
||||
if (argc == 1)
|
||||
grub_printf ("%s", uuid_string);
|
||||
if (argc > 1)
|
||||
grub_env_set (args[1], uuid_string);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
|
||||
GRUB_MOD_INIT (xnu_uuid)
|
||||
{
|
||||
cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid,
|
||||
N_("GRUBUUID [VARNAME]"),
|
||||
N_("Transform 64-bit UUID to format "
|
||||
"suitable for XNU."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (xnu_uuid)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue