merge with mainline
This commit is contained in:
commit
8fdefb9253
571 changed files with 9244 additions and 5950 deletions
776
grub-core/commands/acpi.c
Normal file
776
grub-core/commands/acpi.c
Normal file
|
@ -0,0 +1,776 @@
|
|||
/* 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",
|
||||
sizeof (fadt->hdr.signature)) == 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, sizeof (rsdt->oemid));
|
||||
grub_memcpy (&(rsdt->oemtable), root_oemtable, sizeof (rsdt->oemtable));
|
||||
rsdt->oemrev = root_oemrev;
|
||||
grub_memcpy (&(rsdt->creator_id), root_creator_id, sizeof (rsdt->creator_id));
|
||||
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 ",
|
||||
sizeof (rsdpv1_new->signature));
|
||||
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);
|
||||
}
|
119
grub-core/commands/blocklist.c
Normal file
119
grub-core/commands/blocklist.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* blocklist.c - print the block list of a file */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006,2007 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/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 (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_file_t file;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
unsigned long start_sector = 0;
|
||||
unsigned num_sectors = 0;
|
||||
int num_entries = 0;
|
||||
grub_disk_addr_t part_start = 0;
|
||||
auto void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
|
||||
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)
|
||||
{
|
||||
if (num_sectors > 0)
|
||||
{
|
||||
if (start_sector + num_sectors == sector
|
||||
&& offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
|
||||
{
|
||||
num_sectors++;
|
||||
return;
|
||||
}
|
||||
|
||||
print_blocklist (start_sector, num_sectors, 0, 0);
|
||||
num_sectors = 0;
|
||||
}
|
||||
|
||||
if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
|
||||
{
|
||||
start_sector = sector;
|
||||
num_sectors++;
|
||||
}
|
||||
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", (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");
|
||||
|
||||
file = grub_file_open (args[0]);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
if (! file->device->disk)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
"this command is available only for disk devices");
|
||||
|
||||
part_start = grub_partition_get_start (file->device->disk->partition);
|
||||
|
||||
file->read_hook = read_blocklist;
|
||||
|
||||
while (grub_file_read (file, buf, sizeof (buf)) > 0)
|
||||
;
|
||||
|
||||
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)
|
||||
{
|
||||
cmd = grub_register_command ("blocklist", grub_cmd_blocklist,
|
||||
N_("FILE"), N_("Print a block list."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(blocklist)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
196
grub-core/commands/boot.c
Normal file
196
grub-core/commands/boot.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
/* boot.c - command to boot an operating system */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/normal.h>
|
||||
#include <grub/dl.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_loader_boot_func) (void);
|
||||
static grub_err_t (*grub_loader_unload_func) (void);
|
||||
static int grub_loader_noreturn;
|
||||
|
||||
struct grub_preboot_t
|
||||
{
|
||||
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)
|
||||
{
|
||||
cmd_boot =
|
||||
grub_register_command ("boot", grub_cmd_boot,
|
||||
0, N_("Boot an operating system."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(boot)
|
||||
{
|
||||
grub_unregister_command (cmd_boot);
|
||||
}
|
103
grub-core/commands/cat.c
Normal file
103
grub-core/commands/cat.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* cat.c - command to show the contents of a file */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"dos", -1, 0, N_("Accept DOS-style CR/NL line endings."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
int dos = 0;
|
||||
grub_file_t file;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
grub_ssize_t size;
|
||||
int key = 0;
|
||||
|
||||
if (state[0].set)
|
||||
dos = 1;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
file = grub_gzfile_open (args[0], 1);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
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)) && c != '\r')
|
||||
grub_printf ("%c", c);
|
||||
else if (dos && c == '\r' && i + 1 < size && buf[i + 1] == '\n')
|
||||
{
|
||||
grub_printf ("\n");
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
|
||||
grub_printf ("<%x>", (int) c);
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
|
||||
}
|
||||
}
|
||||
|
||||
while (grub_checkkey () >= 0 &&
|
||||
(key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != GRUB_TERM_ESC)
|
||||
;
|
||||
}
|
||||
|
||||
grub_xputs ("\n");
|
||||
grub_refresh ();
|
||||
grub_file_close (file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(cat)
|
||||
{
|
||||
cmd = grub_register_extcmd ("cat", grub_cmd_cat, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("FILE"), N_("Show the contents of a file."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(cat)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
119
grub-core/commands/cmp.c
Normal file
119
grub-core/commands/cmp.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* cmd.c - command to cmp an operating system */
|
||||
/*
|
||||
* 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/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 (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_ssize_t rd1, rd2;
|
||||
grub_off_t pos;
|
||||
grub_file_t file1 = 0;
|
||||
grub_file_t file2 = 0;
|
||||
char *buf1 = 0;
|
||||
char *buf2 = 0;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
|
||||
|
||||
grub_printf ("Compare file `%s' with `%s':\n", args[0],
|
||||
args[1]);
|
||||
|
||||
file1 = grub_gzfile_open (args[0], 1);
|
||||
file2 = grub_gzfile_open (args[1], 1);
|
||||
if (! file1 || ! file2)
|
||||
goto cleanup;
|
||||
|
||||
if (grub_file_size (file1) != grub_file_size (file2))
|
||||
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);
|
||||
|
||||
if (rd1 != rd2)
|
||||
goto cleanup;
|
||||
|
||||
for (i = 0; i < rd2; i++)
|
||||
{
|
||||
if (buf1[i] != buf2[i])
|
||||
{
|
||||
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)
|
||||
grub_free (buf2);
|
||||
if (file1)
|
||||
grub_file_close (file1);
|
||||
if (file2)
|
||||
grub_file_close (file2);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(cmp)
|
||||
{
|
||||
cmd = grub_register_command ("cmp", grub_cmd_cmp,
|
||||
N_("FILE1 FILE2"), N_("Compare two files."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(cmp)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
75
grub-core/commands/configfile.c
Normal file
75
grub-core/commands/configfile.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* configfile.c - command to manually load config file */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/env.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
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");
|
||||
|
||||
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)
|
||||
{
|
||||
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 (cmd_configfile);
|
||||
grub_unregister_command (cmd_source);
|
||||
grub_unregister_command (cmd_dot);
|
||||
}
|
71
grub-core/commands/crc.c
Normal file
71
grub-core/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
grub-core/commands/date.c
Normal file
146
grub-core/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);
|
||||
}
|
124
grub-core/commands/echo.c
Normal file
124
grub-core/commands/echo.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/* echo.c - Command to display a line of text */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006,2007 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/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{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 (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
int newline = 1;
|
||||
int i;
|
||||
|
||||
/* Check if `-n' was used. */
|
||||
if (state[0].set)
|
||||
newline = 0;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
char *arg = *args;
|
||||
args++;
|
||||
|
||||
while (*arg)
|
||||
{
|
||||
/* In case `-e' is used, parse backslashes. */
|
||||
if (*arg == '\\' && state[1].set)
|
||||
{
|
||||
arg++;
|
||||
if (*arg == '\0')
|
||||
break;
|
||||
|
||||
switch (*arg)
|
||||
{
|
||||
case '\\':
|
||||
grub_printf ("\\");
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
grub_printf ("\a");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
newline = 0;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
grub_printf ("\f");
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
grub_printf ("\n");
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
grub_printf ("\r");
|
||||
break;
|
||||
|
||||
case 't':
|
||||
grub_printf ("\t");
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
grub_printf ("\v");
|
||||
break;
|
||||
}
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This was not an escaped character, or escaping is not
|
||||
enabled. */
|
||||
grub_printf ("%c", *arg);
|
||||
arg++;
|
||||
}
|
||||
|
||||
/* If another argument follows, insert a space. */
|
||||
if (i != argc - 1)
|
||||
grub_printf (" " );
|
||||
}
|
||||
|
||||
if (newline)
|
||||
grub_printf ("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(echo)
|
||||
{
|
||||
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_extcmd (cmd);
|
||||
}
|
59
grub-core/commands/efi/acpi.c
Normal file
59
grub-core/commands/efi/acpi.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* 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>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/api.h>
|
||||
|
||||
struct grub_acpi_rsdp_v10 *
|
||||
grub_machine_acpi_get_rsdpv1 (void)
|
||||
{
|
||||
unsigned i;
|
||||
static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
|
||||
|
||||
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, &acpi_guid, sizeof (grub_efi_guid_t)))
|
||||
return (struct grub_acpi_rsdp_v10 *)
|
||||
grub_efi_system_table->configuration_table[i].vendor_table;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct grub_acpi_rsdp_v20 *
|
||||
grub_machine_acpi_get_rsdpv2 (void)
|
||||
{
|
||||
unsigned i;
|
||||
static grub_efi_guid_t acpi20_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
|
||||
|
||||
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, &acpi20_guid, sizeof (grub_efi_guid_t)))
|
||||
return (struct grub_acpi_rsdp_v20 *)
|
||||
grub_efi_system_table->configuration_table[i].vendor_table;
|
||||
}
|
||||
return 0;
|
||||
}
|
110
grub-core/commands/efi/fixvideo.c
Normal file
110
grub-core/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, GRUB_PCI_REG_CLASS);
|
||||
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);
|
||||
}
|
218
grub-core/commands/efi/loadbios.c
Normal file
218
grub-core/commands/efi/loadbios.c
Normal file
|
@ -0,0 +1,218 @@
|
|||
/* 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;
|
||||
}
|
||||
|
||||
/* FIXME: should be macroified. */
|
||||
addr = grub_pci_make_address (dev, 144);
|
||||
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};
|
||||
|
||||
/* FIXME: should be macroified. */
|
||||
addr = grub_pci_make_address (dev, 144);
|
||||
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
grub-core/commands/extcmd.c
Normal file
96
grub-core/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
grub-core/commands/gptsync.c
Normal file
256
grub-core/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 residing in the first 2TB "
|
||||
"can be present 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);
|
||||
}
|
46
grub-core/commands/halt.c
Normal file
46
grub-core/commands/halt.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* halt.c - command to halt the computer. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/misc.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
grub_halt ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(halt)
|
||||
{
|
||||
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(halt)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
277
grub-core/commands/hashsum.c
Normal file
277
grub-core/commands/hashsum.c
Normal file
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* 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>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"hash", 'h', 0, N_("Specify hash to use."), N_("HASH"), ARG_TYPE_STRING},
|
||||
{"check", 'c', 0, N_("Check hash list file."), N_("FILE"), ARG_TYPE_STRING},
|
||||
{"prefix", 'p', 0, N_("Base directory for hash list."), N_("DIRECTORY"),
|
||||
ARG_TYPE_STRING},
|
||||
{"keep-going", 'k', 0, N_("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];
|
||||
grub_uint8_t 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_xasprintf ("%s/%s", prefix, p);
|
||||
if (!filename)
|
||||
return grub_errno;
|
||||
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,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[-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,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("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
grub-core/commands/hdparm.c
Normal file
421
grub-core/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);
|
||||
}
|
142
grub-core/commands/help.c
Normal file
142
grub-core/commands/help.c
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* help.c - command to show a help text. */
|
||||
/*
|
||||
* 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/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#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 (grub_extcmd_t ext __attribute__ ((unused)), int argc,
|
||||
char **args)
|
||||
{
|
||||
int cnt = 0;
|
||||
char *currarg;
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_command_t cmd;
|
||||
FOR_COMMANDS(cmd)
|
||||
{
|
||||
if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) &&
|
||||
(cmd->flags & GRUB_COMMAND_FLAG_CMDLINE))
|
||||
{
|
||||
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_xasprintf ("%s %s", cmd->name, summary_translated);
|
||||
if (!command_help)
|
||||
break;
|
||||
|
||||
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))
|
||||
{
|
||||
struct grub_unicode_glyph glyph;
|
||||
unicode_last_screen_position
|
||||
+= grub_unicode_aglomerate_comb (unicode_last_screen_position,
|
||||
unicode_last_position
|
||||
- unicode_last_screen_position,
|
||||
&glyph);
|
||||
|
||||
stringwidth
|
||||
+= grub_term_getcharwidth (term, &glyph);
|
||||
}
|
||||
|
||||
grub_print_ucs4 (unicode_command_help,
|
||||
unicode_last_screen_position, 0, 0, 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);
|
||||
}
|
||||
}
|
||||
if (!(cnt % 2))
|
||||
grub_printf ("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
grub_command_t cmd;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
currarg = args[i];
|
||||
FOR_COMMANDS(cmd)
|
||||
{
|
||||
if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE)
|
||||
{
|
||||
if (! grub_strncmp (cmd->name, currarg, grub_strlen (currarg)))
|
||||
{
|
||||
if (cnt++ > 0)
|
||||
grub_printf ("\n\n");
|
||||
|
||||
if (cmd->flags & GRUB_COMMAND_FLAG_EXTCMD)
|
||||
grub_arg_show_help ((grub_extcmd_t) cmd->data);
|
||||
else
|
||||
grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name, _(cmd->summary),
|
||||
_(cmd->description));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(help)
|
||||
{
|
||||
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_extcmd (cmd);
|
||||
}
|
133
grub-core/commands/hexdump.c
Normal file
133
grub-core/commands/hexdump.c
Normal file
|
@ -0,0 +1,133 @@
|
|||
/* hexdump.c - command to dump the contents of a file or memory */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/lib/hexdump.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"skip", 's', 0, N_("Skip offset bytes from the beginning of file."), 0,
|
||||
ARG_TYPE_INT},
|
||||
{"length", 'n', 0, N_("Read only LENGTH bytes."), 0, ARG_TYPE_INT},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE * 4];
|
||||
grub_ssize_t size, length;
|
||||
grub_disk_addr_t skip;
|
||||
int namelen;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
return 0;
|
||||
|
||||
file->offset = skip;
|
||||
|
||||
while ((size = grub_file_read (file, buf, sizeof (buf))) > 0)
|
||||
{
|
||||
unsigned long len;
|
||||
|
||||
len = ((length) && (size > length)) ? length : size;
|
||||
hexdump (skip, buf, len);
|
||||
skip += len;
|
||||
if (length)
|
||||
{
|
||||
length -= len;
|
||||
if (!length)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
grub_file_close (file);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT (hexdump)
|
||||
{
|
||||
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_extcmd (cmd);
|
||||
}
|
59
grub-core/commands/i386/cmostest.c
Normal file
59
grub-core/commands/i386/cmostest.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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/misc.h>
|
||||
#include <grub/cmos.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int byte, bit;
|
||||
char *rest;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required.");
|
||||
|
||||
byte = grub_strtoul (argv[0], &rest, 0);
|
||||
if (*rest != ':')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required.");
|
||||
|
||||
bit = grub_strtoul (rest + 1, 0, 0);
|
||||
|
||||
if (grub_cmos_read (byte) & (1 << bit))
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
|
||||
GRUB_MOD_INIT(cmostest)
|
||||
{
|
||||
cmd = grub_register_command ("cmostest", grub_cmd_cmostest,
|
||||
"cmostest BYTE:BIT",
|
||||
"Test bit at BYTE:BIT in CMOS.");
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(cmostest)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
98
grub-core/commands/i386/cpuid.c
Normal file
98
grub-core/commands/i386/cpuid.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* cpuid.c - test for CPU features */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/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))
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"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 (grub_extcmd_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
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 */
|
||||
grub_cpuid_has_longmode = 1;
|
||||
#else
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
unsigned int max_level;
|
||||
unsigned int ext_level;
|
||||
|
||||
/* See if we can use cpuid. */
|
||||
asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
|
||||
"pushl %0; popfl; pushfl; popl %0; popfl"
|
||||
: "=&r" (eax), "=&r" (ebx)
|
||||
: "i" (0x00200000));
|
||||
if (((eax ^ ebx) & 0x00200000) == 0)
|
||||
goto done;
|
||||
|
||||
/* Check the highest input value for eax. */
|
||||
cpuid (0, eax, ebx, ecx, edx);
|
||||
/* We only look at the first four characters. */
|
||||
max_level = eax;
|
||||
if (max_level == 0)
|
||||
goto done;
|
||||
|
||||
cpuid (0x80000000, eax, ebx, ecx, edx);
|
||||
ext_level = eax;
|
||||
if (ext_level < 0x80000000)
|
||||
goto done;
|
||||
|
||||
cpuid (0x80000001, eax, ebx, ecx, edx);
|
||||
grub_cpuid_has_longmode = !!(edx & bit_LM);
|
||||
done:
|
||||
#endif
|
||||
|
||||
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_extcmd (cmd);
|
||||
}
|
81
grub-core/commands/i386/pc/acpi.c
Normal file
81
grub-core/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;
|
||||
}
|
421
grub-core/commands/i386/pc/drivemap.c
Normal file
421
grub-core/commands/i386/pc/drivemap.c
Normal file
|
@ -0,0 +1,421 @@
|
|||
/* 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,
|
||||
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);
|
||||
}
|
110
grub-core/commands/i386/pc/drivemap_int13h.S
Normal file
110
grub-core/commands/i386/pc/drivemap_int13h.S
Normal file
|
@ -0,0 +1,110 @@
|
|||
/* 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) - LOCAL (base))
|
||||
|
||||
.code16
|
||||
|
||||
/* Copy starts here. When deployed, this code must be segment-aligned. */
|
||||
|
||||
/* The replacement int13 handler. Preserve all registers. */
|
||||
FUNCTION(grub_drivemap_handler)
|
||||
LOCAL (base):
|
||||
/* 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
|
||||
movw $INT13H_OFFSET(LOCAL (mapstart)), %bx
|
||||
|
||||
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
|
||||
|
||||
lcall *%cs:INT13H_OFFSET (LOCAL (oldhandler))
|
||||
|
||||
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
|
||||
|
||||
lcall *%cs:INT13H_OFFSET (LOCAL (oldhandler))
|
||||
|
||||
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)
|
||||
LOCAL (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)
|
||||
LOCAL (mapstart):
|
||||
.byte 0
|
58
grub-core/commands/i386/pc/halt.c
Normal file
58
grub-core/commands/i386/pc/halt.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* halt.c - command to halt the computer. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/i18n.h>
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"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 (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;
|
||||
grub_halt (no_apm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(halt)
|
||||
{
|
||||
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_extcmd (cmd);
|
||||
}
|
273
grub-core/commands/i386/pc/play.c
Normal file
273
grub-core/commands/i386/pc/play.c
Normal file
|
@ -0,0 +1,273 @@
|
|||
/* play.c - command to play a tune */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Lots of this file is borrowed from GNU/Hurd generic-speaker driver. */
|
||||
|
||||
#include <grub/dl.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 (60 * GRUB_TICKS_PER_SECOND)
|
||||
|
||||
/* The speaker port. */
|
||||
#define SPEAKER 0x61
|
||||
|
||||
/* If 0, follow state of SPEAKER_DATA bit, otherwise enable output
|
||||
from timer 2. */
|
||||
#define SPEAKER_TMR2 0x01
|
||||
|
||||
/* If SPEAKER_TMR2 is not set, this provides direct input into the
|
||||
speaker. Otherwise, this enables or disables the output from the
|
||||
timer. */
|
||||
#define SPEAKER_DATA 0x02
|
||||
|
||||
/* The PIT channel value ports. You can write to and read from them.
|
||||
Do not mess with timer 0 or 1. */
|
||||
#define PIT_COUNTER_0 0x40
|
||||
#define PIT_COUNTER_1 0x41
|
||||
#define PIT_COUNTER_2 0x42
|
||||
|
||||
/* The frequency of the PIT clock. */
|
||||
#define PIT_FREQUENCY 0x1234dd
|
||||
|
||||
/* The PIT control port. You can only write to it. Do not mess with
|
||||
timer 0 or 1. */
|
||||
#define PIT_CTRL 0x43
|
||||
#define PIT_CTRL_SELECT_MASK 0xc0
|
||||
#define PIT_CTRL_SELECT_0 0x00
|
||||
#define PIT_CTRL_SELECT_1 0x40
|
||||
#define PIT_CTRL_SELECT_2 0x80
|
||||
|
||||
/* Read and load control. */
|
||||
#define PIT_CTRL_READLOAD_MASK 0x30
|
||||
#define PIT_CTRL_COUNTER_LATCH 0x00 /* Hold timer value until read. */
|
||||
#define PIT_CTRL_READLOAD_LSB 0x10 /* Read/load the LSB. */
|
||||
#define PIT_CTRL_READLOAD_MSB 0x20 /* Read/load the MSB. */
|
||||
#define PIT_CTRL_READLOAD_WORD 0x30 /* Read/load the LSB then the MSB. */
|
||||
|
||||
/* Mode control. */
|
||||
#define PIT_CTRL_MODE_MASK 0x0e
|
||||
|
||||
/* Interrupt on terminal count. Setting the mode sets output to low.
|
||||
When counter is set and terminated, output is set to high. */
|
||||
#define PIT_CTRL_INTR_ON_TERM 0x00
|
||||
|
||||
/* Programmable one-shot. When loading counter, output is set to
|
||||
high. When counter terminated, output is set to low. Can be
|
||||
triggered again from that point on by setting the gate pin to
|
||||
high. */
|
||||
#define PIT_CTRL_PROGR_ONE_SHOT 0x02
|
||||
|
||||
/* Rate generator. Output is low for one period of the counter, and
|
||||
high for the other. */
|
||||
#define PIT_CTRL_RATE_GEN 0x04
|
||||
|
||||
/* Square wave generator. Output is low for one half of the period,
|
||||
and high for the other half. */
|
||||
#define PIT_CTRL_SQUAREWAVE_GEN 0x06
|
||||
|
||||
/* Software triggered strobe. Setting the mode sets output to high.
|
||||
When counter is set and terminated, output is set to low. */
|
||||
#define PIT_CTRL_SOFTSTROBE 0x08
|
||||
|
||||
/* Hardware triggered strobe. Like software triggered strobe, but
|
||||
only starts the counter when the gate pin is set to high. */
|
||||
#define PIT_CTRL_HARDSTROBE 0x0a
|
||||
|
||||
/* Count mode. */
|
||||
#define PIT_CTRL_COUNT_MASK 0x01
|
||||
#define PIT_CTRL_COUNT_BINARY 0x00 /* 16-bit binary counter. */
|
||||
#define PIT_CTRL_COUNT_BCD 0x01 /* 4-decade BCD counter. */
|
||||
|
||||
#define T_REST ((grub_uint16_t) 0)
|
||||
#define T_FINE ((grub_uint16_t) -1)
|
||||
|
||||
struct note
|
||||
{
|
||||
grub_uint16_t pitch;
|
||||
grub_uint16_t duration;
|
||||
};
|
||||
|
||||
static void
|
||||
beep_off (void)
|
||||
{
|
||||
unsigned char status;
|
||||
|
||||
status = grub_inb (SPEAKER);
|
||||
grub_outb (status & ~(SPEAKER_TMR2 | SPEAKER_DATA), SPEAKER);
|
||||
}
|
||||
|
||||
static void
|
||||
beep_on (grub_uint16_t pitch)
|
||||
{
|
||||
unsigned char status;
|
||||
unsigned int counter;
|
||||
|
||||
if (pitch < 20)
|
||||
pitch = 20;
|
||||
else if (pitch > 20000)
|
||||
pitch = 20000;
|
||||
|
||||
counter = PIT_FREQUENCY / pitch;
|
||||
|
||||
/* Program timer 2. */
|
||||
grub_outb (PIT_CTRL_SELECT_2 | PIT_CTRL_READLOAD_WORD
|
||||
| PIT_CTRL_SQUAREWAVE_GEN | PIT_CTRL_COUNT_BINARY, PIT_CTRL);
|
||||
grub_outb (counter & 0xff, PIT_COUNTER_2); /* LSB */
|
||||
grub_outb ((counter >> 8) & 0xff, PIT_COUNTER_2); /* MSB */
|
||||
|
||||
/* Start speaker. */
|
||||
status = grub_inb (SPEAKER);
|
||||
grub_outb (status | SPEAKER_TMR2 | SPEAKER_DATA, SPEAKER);
|
||||
}
|
||||
|
||||
/* Returns whether playing should continue. */
|
||||
static int
|
||||
play (unsigned tempo, struct note *note)
|
||||
{
|
||||
unsigned int to;
|
||||
|
||||
if (note->pitch == T_FINE || grub_checkkey () >= 0)
|
||||
return 1;
|
||||
|
||||
grub_dprintf ("play", "pitch = %d, duration = %d\n", note->pitch,
|
||||
note->duration);
|
||||
|
||||
switch (note->pitch)
|
||||
{
|
||||
case T_REST:
|
||||
beep_off ();
|
||||
break;
|
||||
|
||||
default:
|
||||
beep_on (note->pitch);
|
||||
break;
|
||||
}
|
||||
|
||||
to = grub_get_rtc () + BASE_TEMPO * note->duration / tempo;
|
||||
while (((unsigned int) grub_get_rtc () <= to) && (grub_checkkey () < 0))
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name or tempo and notes required");
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
struct note buf;
|
||||
grub_uint32_t tempo;
|
||||
grub_file_t file;
|
||||
|
||||
file = grub_file_open (args[0]);
|
||||
|
||||
if (! file)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
|
||||
|
||||
if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo))
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_error (GRUB_ERR_FILE_READ_ERROR,
|
||||
"file doesn't even contains a full tempo record");
|
||||
}
|
||||
|
||||
tempo = grub_le_to_cpu32 (tempo);
|
||||
grub_dprintf ("play","tempo = %d\n", tempo);
|
||||
|
||||
while (grub_file_read (file, &buf,
|
||||
sizeof (struct note)) == sizeof (struct note))
|
||||
{
|
||||
buf.pitch = grub_le_to_cpu16 (buf.pitch);
|
||||
buf.duration = grub_le_to_cpu16 (buf.duration);
|
||||
|
||||
if (play (tempo, &buf))
|
||||
break;
|
||||
}
|
||||
|
||||
grub_file_close (file);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *end;
|
||||
unsigned tempo;
|
||||
struct note note;
|
||||
int i;
|
||||
|
||||
tempo = grub_strtoul (args[0], &end, 0);
|
||||
|
||||
if (*end)
|
||||
/* Was not a number either, assume it was supposed to be a file name. */
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
|
||||
|
||||
grub_dprintf ("play","tempo = %d\n", tempo);
|
||||
|
||||
for (i = 1; i + 1 < argc; i += 2)
|
||||
{
|
||||
note.pitch = grub_strtoul (args[i], &end, 0);
|
||||
if (*end)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_NUMBER, "bogus pitch number");
|
||||
break;
|
||||
}
|
||||
|
||||
note.duration = grub_strtoul (args[i + 1], &end, 0);
|
||||
if (*end)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_NUMBER, "bogus duration number");
|
||||
break;
|
||||
}
|
||||
|
||||
if (play (tempo, ¬e))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
beep_off ();
|
||||
|
||||
while (grub_checkkey () > 0)
|
||||
grub_getkey ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(play)
|
||||
{
|
||||
cmd = grub_register_command ("play", grub_cmd_play,
|
||||
N_("FILE | TEMPO [PITCH1 DURATION1] [PITCH2 DURATION2] ... "),
|
||||
N_("Play a tune."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(play)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
52
grub-core/commands/i386/pc/pxecmd.c
Normal file
52
grub-core/commands/i386/pc/pxecmd.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* pxe.c - command to control the pxe driver */
|
||||
/*
|
||||
* 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/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/machine/pxe.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
if (! grub_pxe_pxenv)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment");
|
||||
|
||||
grub_pxe_unload ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(pxecmd)
|
||||
{
|
||||
cmd = grub_register_command ("pxe_unload", grub_cmd_pxe_unload,
|
||||
0,
|
||||
N_("Unload PXE environment."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(pxecmd)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
384
grub-core/commands/i386/pc/sendkey.c
Normal file
384
grub-core/commands/i386/pc/sendkey.c
Normal file
|
@ -0,0 +1,384 @@
|
|||
/* sendkey.c - fake keystroke. */
|
||||
/*
|
||||
* 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/extcmd.h>
|
||||
#include <grub/cpu/io.h>
|
||||
#include <grub/loader.h>
|
||||
|
||||
static char sendkey[0x20];
|
||||
/* Length of sendkey. */
|
||||
static int keylen = 0;
|
||||
static int noled = 0;
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"num", 'n', 0, "set numlock mode", "[on|off]", ARG_TYPE_STRING},
|
||||
{"caps", 'c', 0, "set capslock mode", "[on|off]", ARG_TYPE_STRING},
|
||||
{"scroll", 's', 0, "set scrolllock mode", "[on|off]", ARG_TYPE_STRING},
|
||||
{"insert", 0, 0, "set insert mode", "[on|off]", ARG_TYPE_STRING},
|
||||
{"pause", 0, 0, "set pause mode", "[on|off]", ARG_TYPE_STRING},
|
||||
{"left-shift", 0, 0, "press left shift", "[on|off]", ARG_TYPE_STRING},
|
||||
{"right-shift", 0, 0, "press right shift", "[on|off]", ARG_TYPE_STRING},
|
||||
{"sysrq", 0, 0, "press SysRq", "[on|off]", ARG_TYPE_STRING},
|
||||
{"numkey", 0, 0, "press NumLock key", "[on|off]", ARG_TYPE_STRING},
|
||||
{"capskey", 0, 0, "press CapsLock key", "[on|off]", ARG_TYPE_STRING},
|
||||
{"scrollkey", 0, 0, "press ScrollLock key", "[on|off]", ARG_TYPE_STRING},
|
||||
{"insertkey", 0, 0, "press Insert key", "[on|off]", ARG_TYPE_STRING},
|
||||
{"left-alt", 0, 0, "press left alt", "[on|off]", ARG_TYPE_STRING},
|
||||
{"right-alt", 0, 0, "press right alt", "[on|off]", ARG_TYPE_STRING},
|
||||
{"left-ctrl", 0, 0, "press left ctrl", "[on|off]", ARG_TYPE_STRING},
|
||||
{"right-ctrl", 0, 0, "press right ctrl", "[on|off]", ARG_TYPE_STRING},
|
||||
{"no-led", 0, 0, "don't update LED state", 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
static int simple_flag_offsets[]
|
||||
= {5, 6, 4, 7, 11, 1, 0, 10, 13, 14, 12, 15, 9, 3, 8, 2};
|
||||
|
||||
static grub_uint32_t andmask = 0xffffffff, ormask = 0;
|
||||
|
||||
struct
|
||||
keysym
|
||||
{
|
||||
char *unshifted_name; /* the name in unshifted state */
|
||||
char *shifted_name; /* the name in shifted state */
|
||||
unsigned char unshifted_ascii; /* the ascii code in unshifted state */
|
||||
unsigned char shifted_ascii; /* the ascii code in shifted state */
|
||||
unsigned char keycode; /* keyboard scancode */
|
||||
};
|
||||
|
||||
/* The table for key symbols. If the "shifted" member of an entry is
|
||||
NULL, the entry does not have shifted state. Copied from GRUB Legacy setkey fuction */
|
||||
static struct keysym keysym_table[] =
|
||||
{
|
||||
{"escape", 0, 0x1b, 0, 0x01},
|
||||
{"1", "exclam", '1', '!', 0x02},
|
||||
{"2", "at", '2', '@', 0x03},
|
||||
{"3", "numbersign", '3', '#', 0x04},
|
||||
{"4", "dollar", '4', '$', 0x05},
|
||||
{"5", "percent", '5', '%', 0x06},
|
||||
{"6", "caret", '6', '^', 0x07},
|
||||
{"7", "ampersand", '7', '&', 0x08},
|
||||
{"8", "asterisk", '8', '*', 0x09},
|
||||
{"9", "parenleft", '9', '(', 0x0a},
|
||||
{"0", "parenright", '0', ')', 0x0b},
|
||||
{"minus", "underscore", '-', '_', 0x0c},
|
||||
{"equal", "plus", '=', '+', 0x0d},
|
||||
{"backspace", 0, '\b', 0, 0x0e},
|
||||
{"tab", 0, '\t', 0, 0x0f},
|
||||
{"q", "Q", 'q', 'Q', 0x10},
|
||||
{"w", "W", 'w', 'W', 0x11},
|
||||
{"e", "E", 'e', 'E', 0x12},
|
||||
{"r", "R", 'r', 'R', 0x13},
|
||||
{"t", "T", 't', 'T', 0x14},
|
||||
{"y", "Y", 'y', 'Y', 0x15},
|
||||
{"u", "U", 'u', 'U', 0x16},
|
||||
{"i", "I", 'i', 'I', 0x17},
|
||||
{"o", "O", 'o', 'O', 0x18},
|
||||
{"p", "P", 'p', 'P', 0x19},
|
||||
{"bracketleft", "braceleft", '[', '{', 0x1a},
|
||||
{"bracketright", "braceright", ']', '}', 0x1b},
|
||||
{"enter", 0, '\r', 0, 0x1c},
|
||||
{"control", 0, 0, 0, 0x1d},
|
||||
{"a", "A", 'a', 'A', 0x1e},
|
||||
{"s", "S", 's', 'S', 0x1f},
|
||||
{"d", "D", 'd', 'D', 0x20},
|
||||
{"f", "F", 'f', 'F', 0x21},
|
||||
{"g", "G", 'g', 'G', 0x22},
|
||||
{"h", "H", 'h', 'H', 0x23},
|
||||
{"j", "J", 'j', 'J', 0x24},
|
||||
{"k", "K", 'k', 'K', 0x25},
|
||||
{"l", "L", 'l', 'L', 0x26},
|
||||
{"semicolon", "colon", ';', ':', 0x27},
|
||||
{"quote", "doublequote", '\'', '"', 0x28},
|
||||
{"backquote", "tilde", '`', '~', 0x29},
|
||||
{"shift", 0, 0, 0, 0x2a},
|
||||
{"backslash", "bar", '\\', '|', 0x2b},
|
||||
{"z", "Z", 'z', 'Z', 0x2c},
|
||||
{"x", "X", 'x', 'X', 0x2d},
|
||||
{"c", "C", 'c', 'C', 0x2e},
|
||||
{"v", "V", 'v', 'V', 0x2f},
|
||||
{"b", "B", 'b', 'B', 0x30},
|
||||
{"n", "N", 'n', 'N', 0x31},
|
||||
{"m", "M", 'm', 'M', 0x32},
|
||||
{"comma", "less", ',', '<', 0x33},
|
||||
{"period", "greater", '.', '>', 0x34},
|
||||
{"slash", "question", '/', '?', 0x35},
|
||||
{"rshift", 0, 0, 0, 0x36},
|
||||
{"numasterisk", 0, '*', 0, 0x37},
|
||||
{"alt", 0, 0, 0, 0x38},
|
||||
{"space", 0, ' ', 0, 0x39},
|
||||
{"capslock", 0, 0, 0, 0x3a},
|
||||
{"F1", 0, 0, 0, 0x3b},
|
||||
{"F2", 0, 0, 0, 0x3c},
|
||||
{"F3", 0, 0, 0, 0x3d},
|
||||
{"F4", 0, 0, 0, 0x3e},
|
||||
{"F5", 0, 0, 0, 0x3f},
|
||||
{"F6", 0, 0, 0, 0x40},
|
||||
{"F7", 0, 0, 0, 0x41},
|
||||
{"F8", 0, 0, 0, 0x42},
|
||||
{"F9", 0, 0, 0, 0x43},
|
||||
{"F10", 0, 0, 0, 0x44},
|
||||
{"num7", "numhome", '7', 0, 0x47},
|
||||
{"num8", "numup", '8', 0, 0x48},
|
||||
{"num9", "numpgup", '9', 0, 0x49},
|
||||
{"numminus", 0, '-', 0, 0x4a},
|
||||
{"num4", "numleft", '4', 0, 0x4b},
|
||||
{"num5", "numcenter", '5', 0, 0x4c},
|
||||
{"num6", "numright", '6', 0, 0x4d},
|
||||
{"numplus", 0, '-', 0, 0x4e},
|
||||
{"num1", "numend", '1', 0, 0x4f},
|
||||
{"num2", "numdown", '2', 0, 0x50},
|
||||
{"num3", "numpgdown", '3', 0, 0x51},
|
||||
{"num0", "numinsert", '0', 0, 0x52},
|
||||
{"numperiod", "numdelete", 0, 0x7f, 0x53},
|
||||
{"F11", 0, 0, 0, 0x57},
|
||||
{"F12", 0, 0, 0, 0x58},
|
||||
{"numenter", 0, '\r', 0, 0xe0},
|
||||
{"numslash", 0, '/', 0, 0xe0},
|
||||
{"delete", 0, 0x7f, 0, 0xe0},
|
||||
{"insert", 0, 0xe0, 0, 0x52},
|
||||
{"home", 0, 0xe0, 0, 0x47},
|
||||
{"end", 0, 0xe0, 0, 0x4f},
|
||||
{"pgdown", 0, 0xe0, 0, 0x51},
|
||||
{"pgup", 0, 0xe0, 0, 0x49},
|
||||
{"down", 0, 0xe0, 0, 0x50},
|
||||
{"up", 0, 0xe0, 0, 0x48},
|
||||
{"left", 0, 0xe0, 0, 0x4b},
|
||||
{"right", 0, 0xe0, 0, 0x4d}
|
||||
};
|
||||
|
||||
/* Set a simple flag in flags variable
|
||||
OUTOFFSET - offset of flag in FLAGS,
|
||||
OP - action id
|
||||
*/
|
||||
static void
|
||||
grub_sendkey_set_simple_flag (int outoffset, int op)
|
||||
{
|
||||
if (op == 2)
|
||||
{
|
||||
andmask |= (1 << outoffset);
|
||||
ormask &= ~(1 << outoffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
andmask &= (~(1 << outoffset));
|
||||
if (op == 1)
|
||||
ormask |= (1 << outoffset);
|
||||
else
|
||||
ormask &= ~(1 << outoffset);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
grub_sendkey_parse_op (struct grub_arg_list state)
|
||||
{
|
||||
if (! state.set)
|
||||
return 2;
|
||||
|
||||
if (grub_strcmp (state.arg, "off") == 0 || grub_strcmp (state.arg, "0") == 0
|
||||
|| grub_strcmp (state.arg, "unpress") == 0)
|
||||
return 0;
|
||||
|
||||
if (grub_strcmp (state.arg, "on") == 0 || grub_strcmp (state.arg, "1") == 0
|
||||
|| grub_strcmp (state.arg, "press") == 0)
|
||||
return 1;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static grub_uint32_t oldflags;
|
||||
|
||||
static grub_err_t
|
||||
grub_sendkey_postboot (void)
|
||||
{
|
||||
/* For convention: pointer to flags. */
|
||||
grub_uint32_t *flags = (grub_uint32_t *) 0x417;
|
||||
|
||||
*flags = oldflags;
|
||||
|
||||
*((char *) 0x41a) = 0x1e;
|
||||
*((char *) 0x41c) = 0x1e;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Set keyboard buffer to our sendkey */
|
||||
static grub_err_t
|
||||
grub_sendkey_preboot (int noret __attribute__ ((unused)))
|
||||
{
|
||||
/* For convention: pointer to flags. */
|
||||
grub_uint32_t *flags = (grub_uint32_t *) 0x417;
|
||||
|
||||
oldflags = *flags;
|
||||
|
||||
/* Set the sendkey. */
|
||||
*((char *) 0x41a) = 0x1e;
|
||||
*((char *) 0x41c) = keylen + 0x1e;
|
||||
grub_memcpy ((char *) 0x41e, sendkey, 0x20);
|
||||
|
||||
/* Transform "any ctrl" to "right ctrl" flag. */
|
||||
if (*flags & (1 << 8))
|
||||
*flags &= ~(1 << 2);
|
||||
|
||||
/* Transform "any alt" to "right alt" flag. */
|
||||
if (*flags & (1 << 9))
|
||||
*flags &= ~(1 << 3);
|
||||
|
||||
*flags = (*flags & andmask) | ormask;
|
||||
|
||||
/* Transform "right ctrl" to "any ctrl" flag. */
|
||||
if (*flags & (1 << 8))
|
||||
*flags |= (1 << 2);
|
||||
|
||||
/* Transform "right alt" to "any alt" flag. */
|
||||
if (*flags & (1 << 9))
|
||||
*flags |= (1 << 3);
|
||||
|
||||
/* Write new LED state */
|
||||
if (!noled)
|
||||
{
|
||||
int value = 0;
|
||||
int failed;
|
||||
/* Try 5 times */
|
||||
for (failed = 0; failed < 5; failed++)
|
||||
{
|
||||
value = 0;
|
||||
/* Send command change LEDs */
|
||||
grub_outb (0xed, 0x60);
|
||||
|
||||
/* Wait */
|
||||
do
|
||||
value = grub_inb (0x60);
|
||||
while ((value != 0xfa) && (value != 0xfe));
|
||||
|
||||
if (value == 0xfa)
|
||||
{
|
||||
/* Set new LEDs*/
|
||||
grub_outb ((*flags >> 4) & 7, 0x60);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_sendkey (grub_extcmd_t cmd, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
|
||||
auto int find_key_code (char *key);
|
||||
auto int find_ascii_code (char *key);
|
||||
|
||||
int find_key_code (char *key)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
|
||||
{
|
||||
if (keysym_table[i].unshifted_name
|
||||
&& grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
|
||||
return keysym_table[i].keycode;
|
||||
else if (keysym_table[i].shifted_name
|
||||
&& grub_strcmp (key, keysym_table[i].shifted_name) == 0)
|
||||
return keysym_table[i].keycode;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int find_ascii_code (char *key)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
|
||||
{
|
||||
if (keysym_table[i].unshifted_name
|
||||
&& grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
|
||||
return keysym_table[i].unshifted_ascii;
|
||||
else if (keysym_table[i].shifted_name
|
||||
&& grub_strcmp (key, keysym_table[i].shifted_name) == 0)
|
||||
return keysym_table[i].shifted_ascii;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
andmask = 0xffffffff;
|
||||
ormask = 0;
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
keylen = 0;
|
||||
|
||||
for (i = 0; i < argc && keylen < 0x20; i++)
|
||||
{
|
||||
int key_code;
|
||||
|
||||
key_code = find_key_code (args[i]);
|
||||
if (key_code)
|
||||
{
|
||||
sendkey[keylen++] = find_ascii_code (args[i]);
|
||||
sendkey[keylen++] = key_code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof (simple_flag_offsets)
|
||||
/ sizeof (simple_flag_offsets[0]); i++)
|
||||
grub_sendkey_set_simple_flag (simple_flag_offsets[i],
|
||||
grub_sendkey_parse_op(state[i]));
|
||||
}
|
||||
|
||||
/* Set noled. */
|
||||
noled = (state[sizeof (simple_flag_offsets)
|
||||
/ sizeof (simple_flag_offsets[0])].set);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
static void *preboot_hook;
|
||||
|
||||
GRUB_MOD_INIT (sendkey)
|
||||
{
|
||||
cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"sendkey [KEYSTROKE1] [KEYSTROKE2] ...",
|
||||
"Emulate a keystroke", options);
|
||||
|
||||
preboot_hook
|
||||
= grub_loader_register_preboot_hook (grub_sendkey_preboot,
|
||||
grub_sendkey_postboot,
|
||||
GRUB_LOADER_PREBOOT_HOOK_PRIO_CONSOLE);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (sendkey)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_loader_unregister_preboot_hook (preboot_hook);
|
||||
}
|
185
grub-core/commands/i386/pc/vbeinfo.c
Normal file
185
grub-core/commands/i386/pc/vbeinfo.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
/* vbeinfo.c - command to list compatible VBE video modes. */
|
||||
/*
|
||||
* 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/dl.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)
|
||||
{
|
||||
return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL)
|
||||
+ ((unsigned long) ptr & 0x0000FFFF));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_vbeinfo (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_vbe_info_block controller_info;
|
||||
struct grub_vbe_mode_info_block mode_info_tmp;
|
||||
grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
|
||||
grub_uint16_t *video_mode_list;
|
||||
grub_uint16_t *p;
|
||||
grub_uint16_t *saved_video_mode_list;
|
||||
grub_size_t video_mode_list_size;
|
||||
grub_err_t err;
|
||||
char *modevar;
|
||||
|
||||
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)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_SUPPORTED) == 0)
|
||||
/* If not available, skip it. */
|
||||
continue;
|
||||
|
||||
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_RESERVED_1) == 0)
|
||||
/* Not enough information. */
|
||||
continue;
|
||||
|
||||
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_COLOR) == 0)
|
||||
/* Monochrome is unusable. */
|
||||
continue;
|
||||
|
||||
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 & GRUB_VBE_MODEATTR_GRAPHICS) == 0)
|
||||
/* We allow only graphical modes. */
|
||||
continue;
|
||||
|
||||
switch (mode_info_tmp.memory_model)
|
||||
{
|
||||
case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
|
||||
memory_model = "Packed";
|
||||
break;
|
||||
case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
|
||||
memory_model = "Direct";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (! memory_model)
|
||||
continue;
|
||||
|
||||
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);
|
||||
|
||||
/* 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");
|
||||
|
||||
if (modevar != 0)
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
value = grub_strtoul (modevar, 0, 0);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
use_mode = value;
|
||||
else
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_printf ("Configured VBE mode (vbe_mode) = 0x%03x\n", use_mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(vbeinfo)
|
||||
{
|
||||
cmd =
|
||||
grub_register_command ("vbeinfo", grub_cmd_vbeinfo, 0,
|
||||
N_("List compatible VESA BIOS extension video modes."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(vbeinfo)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
179
grub-core/commands/i386/pc/vbetest.c
Normal file
179
grub-core/commands/i386/pc/vbetest.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/* vbetest.c - command to test VESA BIOS Extension 2.0+ support. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 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/normal.h>
|
||||
#include <grub/dl.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/video.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_vbetest (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
grub_err_t err;
|
||||
char *modevar;
|
||||
struct grub_vbe_mode_info_block mode_info;
|
||||
struct grub_vbe_info_block controller_info;
|
||||
grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
|
||||
grub_uint32_t old_mode;
|
||||
grub_uint8_t *framebuffer = 0;
|
||||
grub_uint32_t bytes_per_scan_line = 0;
|
||||
unsigned char *ptr;
|
||||
int i;
|
||||
|
||||
grub_printf ("Probing for VESA BIOS Extension ... ");
|
||||
|
||||
/* Check if VESA BIOS exists. */
|
||||
err = grub_vbe_probe (&controller_info);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
||||
grub_printf ("found!\n");
|
||||
|
||||
/* Dump out controller information. */
|
||||
grub_printf ("VBE signature = %c%c%c%c\n",
|
||||
controller_info.signature[0],
|
||||
controller_info.signature[1],
|
||||
controller_info.signature[2],
|
||||
controller_info.signature[3]);
|
||||
|
||||
grub_printf ("VBE version = %d.%d\n",
|
||||
controller_info.version >> 8,
|
||||
controller_info.version & 0xFF);
|
||||
grub_printf ("OEM string ptr = %08x\n",
|
||||
controller_info.oem_string_ptr);
|
||||
grub_printf ("Total memory = %d\n",
|
||||
controller_info.total_memory);
|
||||
|
||||
err = grub_vbe_get_video_mode (&old_mode);
|
||||
grub_printf ("Get video mode err = %04x\n", err);
|
||||
|
||||
if (err == GRUB_ERR_NONE)
|
||||
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)
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
value = grub_strtoul (modevar, 0, 0);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
use_mode = value;
|
||||
else
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
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);
|
||||
grub_printf ("width : %d\n",
|
||||
mode_info.x_resolution);
|
||||
grub_printf ("height: %d\n",
|
||||
mode_info.y_resolution);
|
||||
grub_printf ("memory model: %02x\n",
|
||||
mode_info.memory_model);
|
||||
grub_printf ("bytes/scanline: %d\n",
|
||||
mode_info.bytes_per_scan_line);
|
||||
grub_printf ("bytes/scanline (lin): %d\n",
|
||||
mode_info.lin_bytes_per_scan_line);
|
||||
grub_printf ("base address: %08x\n",
|
||||
mode_info.phys_base_addr);
|
||||
grub_printf ("red mask/pos: %d/%d\n",
|
||||
mode_info.red_mask_size,
|
||||
mode_info.red_field_position);
|
||||
grub_printf ("green mask/pos: %d/%d\n",
|
||||
mode_info.green_mask_size,
|
||||
mode_info.green_field_position);
|
||||
grub_printf ("blue mask/pos: %d/%d\n",
|
||||
mode_info.blue_mask_size,
|
||||
mode_info.blue_field_position);
|
||||
|
||||
grub_printf ("Press any key to continue.\n");
|
||||
|
||||
grub_getkey ();
|
||||
|
||||
/* Setup GFX mode. */
|
||||
err = grub_vbe_set_video_mode (use_mode, &mode_info);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
||||
/* Determine framebuffer address and how many bytes are in scan line. */
|
||||
framebuffer = (grub_uint8_t *) mode_info.phys_base_addr;
|
||||
ptr = framebuffer;
|
||||
|
||||
if (controller_info.version >= 0x300)
|
||||
{
|
||||
bytes_per_scan_line = mode_info.lin_bytes_per_scan_line;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes_per_scan_line = mode_info.bytes_per_scan_line;
|
||||
}
|
||||
|
||||
/* Draw some random data to screen. */
|
||||
for (i = 0; i < 256 * 256; i++)
|
||||
{
|
||||
ptr[i] = i & 0x0F;
|
||||
}
|
||||
|
||||
/* Draw white line to screen. */
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
ptr[mode_info.bytes_per_scan_line * 50 + i] = 0x0F;
|
||||
}
|
||||
|
||||
/* Draw another white line to screen. */
|
||||
grub_memset (ptr + bytes_per_scan_line * 51, 0x0f, bytes_per_scan_line);
|
||||
|
||||
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)
|
||||
{
|
||||
cmd = grub_register_command ("vbetest", grub_cmd_vbetest,
|
||||
0, N_("Test VESA BIOS Extension 2.0+ support."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(vbetest)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
49
grub-core/commands/ieee1275/suspend.c
Normal file
49
grub-core/commands/ieee1275/suspend.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* suspend.c - command to suspend GRUB and return to Open Firmware */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 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/term.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_suspend (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
grub_printf ("Run 'go' to resume GRUB.\n");
|
||||
grub_ieee1275_enter ();
|
||||
grub_cls ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(ieee1275_suspend)
|
||||
{
|
||||
cmd = grub_register_command ("suspend", grub_cmd_suspend,
|
||||
0, N_("Return to Open Firmware prompt."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(ieee1275_suspend)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
150
grub-core/commands/iorw.c
Normal file
150
grub-core/commands/iorw.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
/* 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/cpu/io.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."),
|
||||
N_("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 ("in") - 1])
|
||||
{
|
||||
case 'l':
|
||||
value = grub_inl (addr);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
value = grub_inw (addr);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
value = grub_inb (addr);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd->state[0].set)
|
||||
{
|
||||
grub_snprintf (buf, sizeof (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 ("out") - 1])
|
||||
{
|
||||
case 'l':
|
||||
if (mask != 0xffffffff)
|
||||
grub_outl ((grub_inl (addr) & ~mask) | value, addr);
|
||||
else
|
||||
grub_outl (value, addr);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if ((mask & 0xffff) != 0xffff)
|
||||
grub_outw ((grub_inw (addr) & ~mask) | value, addr);
|
||||
else
|
||||
grub_outw (value, addr);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
if ((mask & 0xff) != 0xff)
|
||||
grub_outb ((grub_inb (addr) & ~mask) | value, addr);
|
||||
else
|
||||
grub_outb (value, addr);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GRUB_MOD_INIT(memrw)
|
||||
{
|
||||
cmd_read_byte =
|
||||
grub_register_extcmd ("inb", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("PORT"), N_("Read byte from PORT."), options);
|
||||
cmd_read_word =
|
||||
grub_register_extcmd ("inw", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("PORT"), N_("Read word from PORT."), options);
|
||||
cmd_read_dword =
|
||||
grub_register_extcmd ("inl", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("PORT"), N_("Read dword from PORT."), options);
|
||||
cmd_write_byte =
|
||||
grub_register_command ("outb", grub_cmd_write,
|
||||
N_("PORT VALUE [MASK]"),
|
||||
N_("Write byte VALUE to PORT."));
|
||||
cmd_write_word =
|
||||
grub_register_command ("outw", grub_cmd_write,
|
||||
N_("PORT VALUE [MASK]"),
|
||||
N_("Write word VALUE to PORT."));
|
||||
cmd_write_dword =
|
||||
grub_register_command ("outl", grub_cmd_write,
|
||||
N_("ADDR VALUE [MASK]"),
|
||||
N_("Write dword VALUE to PORT."));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
93
grub-core/commands/keystatus.c
Normal file
93
grub-core/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);
|
||||
}
|
400
grub-core/commands/loadenv.c
Normal file
400
grub-core/commands/loadenv.c
Normal file
|
@ -0,0 +1,400 @@
|
|||
/* loadenv.c - command to load/save environment variable. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009,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/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 grub_err_t
|
||||
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. */
|
||||
return grub_error (GRUB_ERR_BAD_FS, "malformed file");
|
||||
}
|
||||
}
|
||||
|
||||
total_length += p->length;
|
||||
}
|
||||
|
||||
if (total_length != grub_file_size (file))
|
||||
{
|
||||
/* Maybe sparse, unallocated sectors. No way in GRUB. */
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "sparse file not allowed");
|
||||
}
|
||||
|
||||
/* One more sanity check. Re-read all sectors by blocklists, and compare
|
||||
those with the data read via a file. */
|
||||
disk = file->device->disk;
|
||||
|
||||
part_start = grub_partition_get_start (disk->partition);
|
||||
|
||||
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 grub_errno;
|
||||
|
||||
if (grub_memcmp (buf + index, blockbuf, p->length) != 0)
|
||||
return grub_error (GRUB_ERR_FILE_READ_ERROR, "invalid blocklist");
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
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;
|
||||
part_start = grub_partition_get_start (disk->partition);
|
||||
|
||||
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);
|
||||
}
|
276
grub-core/commands/ls.c
Normal file
276
grub-core/commands/ls.c
Normal file
|
@ -0,0 +1,276 @@
|
|||
/* ls.c - command to list files and devices */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/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, 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}
|
||||
};
|
||||
|
||||
static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'};
|
||||
|
||||
static grub_err_t
|
||||
grub_ls_list_devices (int longlist)
|
||||
{
|
||||
auto int grub_ls_print_devices (const char *name);
|
||||
int grub_ls_print_devices (const char *name)
|
||||
{
|
||||
if (longlist)
|
||||
grub_normal_print_device_info (name);
|
||||
else
|
||||
grub_printf ("(%s) ", name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_device_iterate (grub_ls_print_devices);
|
||||
grub_xputs ("\n");
|
||||
grub_refresh ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
||||
{
|
||||
char *device_name;
|
||||
grub_fs_t fs;
|
||||
const char *path;
|
||||
grub_device_t dev;
|
||||
|
||||
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, info->dir ? "/" : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_files_long (const char *filename,
|
||||
const struct grub_dirhook_info *info)
|
||||
{
|
||||
if ((! all) && (filename[0] == '.'))
|
||||
return 0;
|
||||
|
||||
if (! info->dir)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *pathname;
|
||||
|
||||
if (dirname[grub_strlen (dirname) - 1] == '/')
|
||||
pathname = grub_xasprintf ("%s%s", dirname, filename);
|
||||
else
|
||||
pathname = grub_xasprintf ("%s/%s", dirname, filename);
|
||||
|
||||
if (!pathname)
|
||||
return 1;
|
||||
|
||||
/* XXX: For ext2fs symlinks are detected as files while they
|
||||
should be reported as directories. */
|
||||
file = grub_file_open (pathname);
|
||||
if (! file)
|
||||
{
|
||||
grub_errno = 0;
|
||||
grub_free (pathname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (! human)
|
||||
grub_printf ("%-12llu", (unsigned long long) file->size);
|
||||
else
|
||||
{
|
||||
grub_uint64_t fsize = file->size * 100ULL;
|
||||
int fsz = file->size;
|
||||
int units = 0;
|
||||
char buf[20];
|
||||
|
||||
while (fsz / 1024)
|
||||
{
|
||||
fsize = (fsize + 512) / 1024;
|
||||
fsz /= 1024;
|
||||
units++;
|
||||
}
|
||||
|
||||
if (units)
|
||||
{
|
||||
grub_uint32_t whole, fraction;
|
||||
|
||||
whole = grub_divmod64 (fsize, 100, &fraction);
|
||||
grub_snprintf (buf, sizeof (buf),
|
||||
"%u.%02u%c", whole, fraction,
|
||||
grub_human_sizes[units]);
|
||||
grub_printf ("%-12s", buf);
|
||||
}
|
||||
else
|
||||
grub_printf ("%-12llu", (unsigned long long) file->size);
|
||||
|
||||
}
|
||||
grub_file_close (file);
|
||||
grub_free (pathname);
|
||||
}
|
||||
else
|
||||
grub_printf ("%-12s", "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;
|
||||
}
|
||||
|
||||
device_name = grub_file_get_device_name (dirname);
|
||||
dev = grub_device_open (device_name);
|
||||
if (! dev)
|
||||
goto fail;
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
path = grub_strchr (dirname, ')');
|
||||
if (! path)
|
||||
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)
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
grub_normal_print_device_info (device_name);
|
||||
}
|
||||
else if (fs)
|
||||
{
|
||||
if (longlist)
|
||||
(fs->dir) (dev, path, print_files_long);
|
||||
else
|
||||
(fs->dir) (dev, path, print_files);
|
||||
|
||||
if (grub_errno == GRUB_ERR_BAD_FILE_TYPE
|
||||
&& path[grub_strlen (path) - 1] != '/')
|
||||
{
|
||||
/* 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, &info);
|
||||
else
|
||||
print_files (p, &info);
|
||||
|
||||
grub_free (dirname);
|
||||
}
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
grub_xputs ("\n");
|
||||
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
fail:
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
grub_free (device_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
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
|
||||
grub_ls_list_files (args[0], state[0].set, state[2].set,
|
||||
state[1].set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(ls)
|
||||
{
|
||||
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_extcmd (cmd);
|
||||
}
|
57
grub-core/commands/lsmmap.c
Normal file
57
grub-core/commands/lsmmap.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_MACHINE_EMU
|
||||
#include <grub/machine/memory.h>
|
||||
#endif
|
||||
#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;
|
||||
}
|
||||
#ifndef GRUB_MACHINE_EMU
|
||||
grub_machine_mmap_iterate (hook);
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
234
grub-core/commands/lspci.c
Normal file
234
grub-core/commands/lspci.c
Normal file
|
@ -0,0 +1,234 @@
|
|||
/* 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, GRUB_PCI_REG_CLASS);
|
||||
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 = GRUB_PCI_REG_ADDRESSES;
|
||||
while (reg < GRUB_PCI_REG_CIS_POINTER)
|
||||
{
|
||||
grub_uint64_t space;
|
||||
addr = grub_pci_make_address (dev, reg);
|
||||
space = grub_pci_read (addr);
|
||||
|
||||
reg += sizeof (grub_uint32_t);
|
||||
|
||||
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",
|
||||
(unsigned) ((reg - GRUB_PCI_REG_ADDRESSES)
|
||||
/ sizeof (grub_uint32_t)) - 1,
|
||||
(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 += sizeof (grub_uint32_t);
|
||||
grub_printf ("\t64-bit memory space %d at 0x%016llx [%s]\n",
|
||||
(unsigned) ((reg - GRUB_PCI_REG_ADDRESSES)
|
||||
/ sizeof (grub_uint32_t)) - 2,
|
||||
(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",
|
||||
(unsigned) ((reg - GRUB_PCI_REG_ADDRESSES)
|
||||
/ sizeof (grub_uint32_t)) - 1,
|
||||
(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
grub-core/commands/memrw.c
Normal file
149
grub-core/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_snprintf (buf, sizeof (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);
|
||||
}
|
372
grub-core/commands/minicmd.c
Normal file
372
grub-core/commands/minicmd.c
Normal file
|
@ -0,0 +1,372 @@
|
|||
/* 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_printf ("%c", c);
|
||||
else
|
||||
{
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
|
||||
grub_printf ("<%x>", (int) c);
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grub_xputs ("\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)))
|
||||
{
|
||||
grub_dl_t mod;
|
||||
|
||||
grub_printf ("Name\tRef Count\tDependencies\n");
|
||||
FOR_DL_MODULES (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_xputs (",");
|
||||
|
||||
grub_printf ("%s", dep->mod->name);
|
||||
}
|
||||
grub_xputs ("\n");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_cat, cmd_help, cmd_root;
|
||||
static grub_command_t cmd_dump, cmd_rmmod, cmd_lsmod, cmd_exit;
|
||||
|
||||
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."));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
92
grub-core/commands/mips/yeeloong/lsspd.c
Normal file
92
grub-core/commands/mips/yeeloong/lsspd.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 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/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/cs5536.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
grub_pci_device_t dev;
|
||||
grub_port_t smbbase;
|
||||
int i;
|
||||
grub_err_t err;
|
||||
|
||||
if (!grub_cs5536_find (&dev))
|
||||
{
|
||||
grub_printf ("No CS5536 found\n");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
grub_printf ("CS5536 at %d:%d.%d\n", grub_pci_get_bus (dev),
|
||||
grub_pci_get_device (dev), grub_pci_get_function (dev));
|
||||
|
||||
err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
grub_printf ("SMB base = 0x%x\n", smbbase);
|
||||
|
||||
for (i = GRUB_SMB_RAM_START_ADDR;
|
||||
i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++)
|
||||
{
|
||||
struct grub_smbus_spd spd;
|
||||
grub_memset (&spd, 0, sizeof (spd));
|
||||
grub_printf ("Device %d\n", i);
|
||||
err = grub_cs5536_read_spd (smbbase, i, &spd);
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
continue;
|
||||
}
|
||||
grub_printf ("Written SPD bytes: %d B.\n", spd.written_size);
|
||||
grub_printf ("Total flash size: %d B.\n", 1 << spd.log_total_flash_size);
|
||||
if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2)
|
||||
{
|
||||
char str[sizeof (spd.ddr2.part_number) + 1];
|
||||
grub_printf ("Memory type: DDR2.\n");
|
||||
grub_memcpy (str, spd.ddr2.part_number,
|
||||
sizeof (spd.ddr2.part_number));
|
||||
str[sizeof (spd.ddr2.part_number)] = 0;
|
||||
grub_printf ("Part no: %s.\n", str);
|
||||
}
|
||||
else
|
||||
grub_printf ("Memory type: Unknown.\n");
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(lsspd)
|
||||
{
|
||||
cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0,
|
||||
"Print Memory information.");
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(lsspd)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
331
grub-core/commands/parttool.c
Normal file
331
grub-core/commands/parttool.c
Normal file
|
@ -0,0 +1,331 @@
|
|||
/* 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. */
|
||||
if (! grub_no_autoload)
|
||||
{
|
||||
const char *prefix;
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (prefix)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = grub_xasprintf ("%s/parttool.lst", prefix);
|
||||
if (filename)
|
||||
{
|
||||
grub_file_t file;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
grub-core/commands/password.c
Normal file
86
grub-core/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);
|
||||
}
|
197
grub-core/commands/password_pbkdf2.c
Normal file
197
grub-core/commands/password_pbkdf2.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
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,
|
||||
N_("USER PBKDF2_PASSWORD"),
|
||||
N_("Set user password (PBKDF2). "));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(password_pbkdf2)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
161
grub-core/commands/probe.c
Normal file
161
grub-core/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
grub-core/commands/read.c
Normal file
90
grub-core/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_printf ("%c", 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);
|
||||
}
|
45
grub-core/commands/reboot.c
Normal file
45
grub-core/commands/reboot.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* reboot.c - command to reboot the computer. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/misc.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
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)
|
||||
{
|
||||
cmd = grub_register_command ("reboot", grub_cmd_reboot,
|
||||
0, N_("Reboot the computer."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(reboot)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
86
grub-core/commands/regexp.c
Normal file
86
grub-core/commands/regexp.c
Normal file
|
@ -0,0 +1,86 @@
|
|||
/* regexp.c -- The regexp command. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 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/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <regex.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_regexp (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int argn = 0;
|
||||
int matches = 0;
|
||||
regex_t regex;
|
||||
int ret;
|
||||
grub_size_t s;
|
||||
char *comperr;
|
||||
grub_err_t err;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "2 arguments expected");
|
||||
|
||||
ret = regcomp (®ex, args[0], RE_SYNTAX_GNU_AWK);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = regexec (®ex, args[1], 0, 0, 0);
|
||||
if (!ret)
|
||||
{
|
||||
regfree (®ex);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
fail:
|
||||
s = regerror (ret, ®ex, 0, 0);
|
||||
comperr = grub_malloc (s);
|
||||
if (!comperr)
|
||||
{
|
||||
regfree (®ex);
|
||||
return grub_errno;
|
||||
}
|
||||
regerror (ret, ®ex, comperr, s);
|
||||
err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr);
|
||||
regfree (®ex);
|
||||
grub_free (comperr);
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(regexp)
|
||||
{
|
||||
extern struct grub_script_wildcard_translator translator;
|
||||
|
||||
cmd = grub_register_command ("regexp", grub_cmd_regexp,
|
||||
N_("REGEXP STRING"),
|
||||
N_("Test if REGEXP matches STRING."));
|
||||
|
||||
/* Setup GRUB script wildcard translator. */
|
||||
wildcard_translator = &translator;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(regexp)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
174
grub-core/commands/search.c
Normal file
174
grub-core/commands/search.c
Normal file
|
@ -0,0 +1,174 @@
|
|||
/* 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/device.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/search.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
void
|
||||
FUNC_NAME (const char *key, const char *var, int no_floppy)
|
||||
{
|
||||
int count = 0;
|
||||
grub_fs_autoload_hook_t saved_autoload;
|
||||
|
||||
auto int iterate_device (const char *name);
|
||||
int iterate_device (const char *name)
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
/* 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
|
||||
{
|
||||
char *buf;
|
||||
grub_file_t file;
|
||||
|
||||
buf = grub_xasprintf ("(%s)%s", name, key);
|
||||
if (! buf)
|
||||
return 1;
|
||||
|
||||
file = grub_file_open (buf);
|
||||
if (file)
|
||||
{
|
||||
found = 1;
|
||||
grub_file_close (file);
|
||||
}
|
||||
grub_free (buf);
|
||||
}
|
||||
#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);
|
||||
}
|
||||
else
|
||||
grub_device_iterate (iterate_device);
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE && count == 0)
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc,
|
||||
char **args)
|
||||
{
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
|
||||
|
||||
FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
GRUB_MOD_INIT(search_fs_file)
|
||||
#elif defined (DO_SEARCH_FS_UUID)
|
||||
GRUB_MOD_INIT(search_fs_uuid)
|
||||
#else
|
||||
GRUB_MOD_INIT(search_label)
|
||||
#endif
|
||||
{
|
||||
cmd =
|
||||
grub_register_command (COMMAND_NAME, grub_cmd_do_search,
|
||||
N_("NAME [VARIABLE]"),
|
||||
HELP_MESSAGE);
|
||||
}
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
GRUB_MOD_FINI(search_fs_file)
|
||||
#elif defined (DO_SEARCH_FS_UUID)
|
||||
GRUB_MOD_FINI(search_fs_uuid)
|
||||
#else
|
||||
GRUB_MOD_FINI(search_label)
|
||||
#endif
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
6
grub-core/commands/search_file.c
Normal file
6
grub-core/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
grub-core/commands/search_label.c
Normal file
6
grub-core/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
grub-core/commands/search_uuid.c
Normal file
6
grub-core/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
grub-core/commands/search_wrap.c
Normal file
95
grub-core/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);
|
||||
}
|
341
grub-core/commands/setpci.c
Normal file
341
grub-core/commands/setpci.c
Normal file
|
@ -0,0 +1,341 @@
|
|||
/* 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/env.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
struct pci_register
|
||||
{
|
||||
const char *name;
|
||||
grub_uint16_t addr;
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
struct pci_register pci_registers[] =
|
||||
{
|
||||
{"VENDOR_ID", GRUB_PCI_REG_VENDOR , 2},
|
||||
{"DEVICE_ID", GRUB_PCI_REG_DEVICE , 2},
|
||||
{"COMMAND", GRUB_PCI_REG_COMMAND , 2},
|
||||
{"STATUS", GRUB_PCI_REG_STATUS , 2},
|
||||
{"REVISION", GRUB_PCI_REG_REVISION , 1},
|
||||
{"CLASS_PROG", GRUB_PCI_REG_CLASS + 1 , 1},
|
||||
{"CLASS_DEVICE", GRUB_PCI_REG_CLASS + 2 , 2},
|
||||
{"CACHE_LINE_SIZE", GRUB_PCI_REG_CACHELINE , 1},
|
||||
{"LATENCY_TIMER", GRUB_PCI_REG_LAT_TIMER , 1},
|
||||
{"HEADER_TYPE", GRUB_PCI_REG_HEADER_TYPE , 1},
|
||||
{"BIST", GRUB_PCI_REG_BIST , 1},
|
||||
{"BASE_ADDRESS_0", GRUB_PCI_REG_ADDRESS_REG0, 4},
|
||||
{"BASE_ADDRESS_1", GRUB_PCI_REG_ADDRESS_REG1, 4},
|
||||
{"BASE_ADDRESS_2", GRUB_PCI_REG_ADDRESS_REG2, 4},
|
||||
{"BASE_ADDRESS_3", GRUB_PCI_REG_ADDRESS_REG3, 4},
|
||||
{"BASE_ADDRESS_4", GRUB_PCI_REG_ADDRESS_REG4, 4},
|
||||
{"BASE_ADDRESS_5", GRUB_PCI_REG_ADDRESS_REG5, 4},
|
||||
{"CARDBUS_CIS", GRUB_PCI_REG_CIS_POINTER , 4},
|
||||
{"SUBVENDOR_ID", GRUB_PCI_REG_SUBVENDOR , 2},
|
||||
{"SUBSYSTEM_ID", GRUB_PCI_REG_SUBSYSTEM , 2},
|
||||
{"ROM_ADDRESS", GRUB_PCI_REG_ROM_ADDRESS , 4},
|
||||
{"CAP_POINTER", GRUB_PCI_REG_CAP_POINTER , 1},
|
||||
{"INTERRUPT_LINE", GRUB_PCI_REG_IRQ_LINE , 1},
|
||||
{"INTERRUPT_PIN", GRUB_PCI_REG_IRQ_PIN , 1},
|
||||
{"MIN_GNT", GRUB_PCI_REG_MIN_GNT , 1},
|
||||
{"MAX_LAT", GRUB_PCI_REG_MIN_GNT , 1},
|
||||
};
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{0, 'd', 0, "Select device by vendor and device IDs.",
|
||||
"[vendor]:[device]", ARG_TYPE_STRING},
|
||||
{0, 's', 0, "Select device by its position on the bus.",
|
||||
"[bus]:[slot][.func]", ARG_TYPE_STRING},
|
||||
{0, 'v', 0, "Save read value into variable VARNAME.",
|
||||
"VARNAME", ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static grub_uint32_t pciid_check_mask, pciid_check_value;
|
||||
static int bus, device, function;
|
||||
static int check_bus, check_device, check_function;
|
||||
static grub_uint32_t write_mask, regwrite;
|
||||
static int regsize;
|
||||
static grub_uint16_t regaddr;
|
||||
static const char *varname;
|
||||
|
||||
static int NESTED_FUNC_ATTR
|
||||
grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
|
||||
{
|
||||
grub_uint32_t regval = 0;
|
||||
grub_pci_address_t addr;
|
||||
|
||||
if ((pciid & pciid_check_mask) != pciid_check_value)
|
||||
return 0;
|
||||
|
||||
if (check_bus && grub_pci_get_bus (dev) != bus)
|
||||
return 0;
|
||||
|
||||
if (check_device && grub_pci_get_device (dev) != device)
|
||||
return 0;
|
||||
|
||||
if (check_function && grub_pci_get_function (dev) != function)
|
||||
return 0;
|
||||
|
||||
addr = grub_pci_make_address (dev, regaddr);
|
||||
|
||||
switch (regsize)
|
||||
{
|
||||
case 1:
|
||||
regval = grub_pci_read_byte (addr);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
regval = grub_pci_read_word (addr);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
regval = grub_pci_read (addr);
|
||||
break;
|
||||
}
|
||||
|
||||
if (varname)
|
||||
{
|
||||
char buf[sizeof ("XXXXXXXX")];
|
||||
grub_snprintf (buf, sizeof (buf), "%x", regval);
|
||||
grub_env_set (varname, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!write_mask)
|
||||
{
|
||||
grub_printf ("Register %x of %d:%d.%d is %x\n", regaddr,
|
||||
grub_pci_get_bus (dev),
|
||||
grub_pci_get_device (dev),
|
||||
grub_pci_get_function (dev),
|
||||
regval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
regval = (regval & ~write_mask) | regwrite;
|
||||
|
||||
switch (regsize)
|
||||
{
|
||||
case 1:
|
||||
grub_pci_write_byte (addr, regval);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
grub_pci_write_word (addr, regval);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
grub_pci_write (addr, regval);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv)
|
||||
{
|
||||
const char *ptr;
|
||||
unsigned i;
|
||||
|
||||
pciid_check_value = 0;
|
||||
pciid_check_mask = 0;
|
||||
|
||||
if (cmd->state[0].set)
|
||||
{
|
||||
ptr = cmd->state[0].arg;
|
||||
pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff);
|
||||
if (grub_errno == GRUB_ERR_BAD_NUMBER)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
ptr = cmd->state[0].arg;
|
||||
}
|
||||
else
|
||||
pciid_check_mask |= 0xffff;
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (*ptr != ':')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected.");
|
||||
ptr++;
|
||||
pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff)
|
||||
<< 16;
|
||||
if (grub_errno == GRUB_ERR_BAD_NUMBER)
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
else
|
||||
pciid_check_mask |= 0xffff0000;
|
||||
}
|
||||
|
||||
pciid_check_value &= pciid_check_mask;
|
||||
|
||||
check_bus = check_device = check_function = 0;
|
||||
|
||||
if (cmd->state[1].set)
|
||||
{
|
||||
const char *optr;
|
||||
|
||||
ptr = cmd->state[1].arg;
|
||||
optr = ptr;
|
||||
bus = grub_strtoul (ptr, (char **) &ptr, 16);
|
||||
if (grub_errno == GRUB_ERR_BAD_NUMBER)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
ptr = optr;
|
||||
}
|
||||
else
|
||||
check_bus = 1;
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (*ptr != ':')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected.");
|
||||
ptr++;
|
||||
optr = ptr;
|
||||
device = grub_strtoul (ptr, (char **) &ptr, 16);
|
||||
if (grub_errno == GRUB_ERR_BAD_NUMBER)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
ptr = optr;
|
||||
}
|
||||
else
|
||||
check_device = 1;
|
||||
if (*ptr == '.')
|
||||
{
|
||||
ptr++;
|
||||
function = grub_strtoul (ptr, (char **) &ptr, 16);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
check_function = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd->state[2].set)
|
||||
varname = cmd->state[2].arg;
|
||||
else
|
||||
varname = NULL;
|
||||
|
||||
write_mask = 0;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Command expected.");
|
||||
|
||||
if (argc > 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Only one command is supported.");
|
||||
|
||||
ptr = argv[0];
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (pci_registers); i++)
|
||||
{
|
||||
if (grub_strncmp (ptr, pci_registers[i].name,
|
||||
grub_strlen (pci_registers[i].name)) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE (pci_registers))
|
||||
{
|
||||
regsize = 0;
|
||||
regaddr = grub_strtoul (ptr, (char **) &ptr, 16);
|
||||
if (grub_errno)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown register");
|
||||
}
|
||||
else
|
||||
{
|
||||
regaddr = pci_registers[i].addr;
|
||||
regsize = pci_registers[i].size;
|
||||
ptr += grub_strlen (pci_registers[i].name);
|
||||
}
|
||||
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
|
||||
if (*ptr == '+')
|
||||
{
|
||||
ptr++;
|
||||
regaddr += grub_strtoul (ptr, (char **) &ptr, 16);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_memcmp (ptr, ".L", sizeof (".L") - 1) == 0
|
||||
|| grub_memcmp (ptr, ".l", sizeof (".l") - 1) == 0)
|
||||
{
|
||||
regsize = 4;
|
||||
ptr += sizeof (".l") - 1;
|
||||
}
|
||||
else if (grub_memcmp (ptr, ".W", sizeof (".W") - 1) == 0
|
||||
|| grub_memcmp (ptr, ".w", sizeof (".w") - 1) == 0)
|
||||
{
|
||||
regsize = 2;
|
||||
ptr += sizeof (".w") - 1;
|
||||
}
|
||||
else if (grub_memcmp (ptr, ".B", sizeof (".B") - 1) == 0
|
||||
|| grub_memcmp (ptr, ".b", sizeof (".b") - 1) == 0)
|
||||
{
|
||||
regsize = 1;
|
||||
ptr += sizeof (".b") - 1;
|
||||
}
|
||||
|
||||
if (!regsize)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unknown register size.");
|
||||
|
||||
write_mask = 0;
|
||||
if (*ptr == '=')
|
||||
{
|
||||
ptr++;
|
||||
regwrite = grub_strtoul (ptr, (char **) &ptr, 16);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
write_mask = 0xffffffff;
|
||||
if (*ptr == ':')
|
||||
{
|
||||
ptr++;
|
||||
write_mask = grub_strtoul (ptr, (char **) &ptr, 16);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
write_mask = 0xffffffff;
|
||||
}
|
||||
regwrite &= write_mask;
|
||||
}
|
||||
|
||||
if (write_mask && varname)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Option -v isn't valid for writes.");
|
||||
|
||||
grub_pci_iterate (grub_setpci_iter);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(setpci)
|
||||
{
|
||||
cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, GRUB_COMMAND_FLAG_BOTH,
|
||||
N_("[-s POSITION] [-d DEVICE] [-v VAR] "
|
||||
"[REGISTER][=VALUE[:MASK]]"),
|
||||
N_("Manipulate PCI devices."), options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(setpci)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
113
grub-core/commands/sleep.c
Normal file
113
grub-core/commands/sleep.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/* 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/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);
|
||||
}
|
255
grub-core/commands/terminal.c
Normal file
255
grub-core/commands/terminal.c
Normal file
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009,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/mm.h>
|
||||
#include <grub/dl.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;
|
||||
|
||||
struct abstract_terminal
|
||||
{
|
||||
struct abstract_terminal *next;
|
||||
const char *name;
|
||||
grub_err_t (*init) (struct abstract_terminal *term);
|
||||
grub_err_t (*fini) (struct abstract_terminal *term);
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
||||
struct abstract_terminal **disabled,
|
||||
struct grub_term_autoload *autoloads,
|
||||
const char *active_str,
|
||||
const char *available_str)
|
||||
{
|
||||
int i;
|
||||
struct abstract_terminal *term;
|
||||
struct grub_term_autoload *aut;
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_puts_ (active_str);
|
||||
for (term = *enabled; term; term = term->next)
|
||||
grub_printf ("%s ", term->name);
|
||||
grub_printf ("\n");
|
||||
grub_puts_ (available_str);
|
||||
for (term = *disabled; term; term = term->next)
|
||||
grub_printf ("%s ", term->name);
|
||||
/* This is quadratic but we don't expect mode than 30 terminal
|
||||
modules ever. */
|
||||
for (aut = autoloads; aut; aut = aut->next)
|
||||
{
|
||||
for (term = *disabled; term; term = term->next)
|
||||
if (grub_strcmp (term->name, aut->name) == 0
|
||||
|| (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*'
|
||||
&& grub_memcmp (term->name, aut->name,
|
||||
grub_strlen (aut->name) - 1) == 0))
|
||||
break;
|
||||
if (!term)
|
||||
for (term = *enabled; term; term = term->next)
|
||||
if (grub_strcmp (term->name, aut->name) == 0
|
||||
|| (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*'
|
||||
&& grub_memcmp (term->name, aut->name,
|
||||
grub_strlen (aut->name) - 1) == 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 (term = *disabled; term; term = term->next)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term == 0)
|
||||
for (term = *enabled; term; term = term->next)
|
||||
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 = autoloads; aut; aut = aut->next)
|
||||
if (grub_strcmp (args[i], aut->name) == 0
|
||||
|| (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*'
|
||||
&& grub_memcmp (args[i], aut->name,
|
||||
grub_strlen (aut->name) - 1) == 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 (term = *disabled; term; term = term->next)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
if (term->init && term->init (term) != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
||||
grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_strcmp (args[0], "--remove") == 0)
|
||||
{
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
for (term = *enabled; term; term = term->next)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
if (!term->next && term == *enabled)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"can't remove the last terminal");
|
||||
grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
|
||||
if (term->fini)
|
||||
term->fini (term);
|
||||
grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
for (term = *disabled; term; term = term->next)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (term)
|
||||
{
|
||||
if (term->init && term->init (term) != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
||||
grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct abstract_terminal *next;
|
||||
for (term = *enabled; term; term = next)
|
||||
{
|
||||
next = term->next;
|
||||
for (i = 0; i < argc; i++)
|
||||
if (grub_strcmp (args[i], term->name) == 0)
|
||||
break;
|
||||
if (i == argc)
|
||||
{
|
||||
if (!term->next && term == *enabled)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"can't remove the last terminal");
|
||||
grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
|
||||
if (term->fini)
|
||||
term->fini (term);
|
||||
grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, next);
|
||||
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, name);
|
||||
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, init);
|
||||
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, fini);
|
||||
return handle_command (argc, args,
|
||||
(struct abstract_terminal **) &grub_term_inputs,
|
||||
(struct abstract_terminal **) &grub_term_inputs_disabled,
|
||||
grub_term_input_autoload,
|
||||
N_ ("Active input terminals:"),
|
||||
N_ ("Available input terminals:"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, next);
|
||||
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, name);
|
||||
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, init);
|
||||
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, fini);
|
||||
return handle_command (argc, args, (struct abstract_terminal **) &grub_term_outputs,
|
||||
(struct abstract_terminal **) &grub_term_outputs_disabled,
|
||||
grub_term_output_autoload,
|
||||
N_ ("Active output terminals:"),
|
||||
N_ ("Available output terminals:"));
|
||||
}
|
||||
|
||||
static grub_command_t cmd_terminal_input, cmd_terminal_output;
|
||||
|
||||
GRUB_MOD_INIT(terminal)
|
||||
{
|
||||
cmd_terminal_input =
|
||||
grub_register_command ("terminal_input", grub_cmd_terminal_input,
|
||||
N_("[--append|--remove] "
|
||||
"[TERMINAL1] [TERMINAL2] ..."),
|
||||
N_("List or select an input terminal."));
|
||||
cmd_terminal_output =
|
||||
grub_register_command ("terminal_output", grub_cmd_terminal_output,
|
||||
N_("[--append|--remove] "
|
||||
"[TERMINAL1] [TERMINAL2] ..."),
|
||||
N_("List or select an output terminal."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(terminal)
|
||||
{
|
||||
grub_unregister_command (cmd_terminal_input);
|
||||
grub_unregister_command (cmd_terminal_output);
|
||||
}
|
433
grub-core/commands/test.c
Normal file
433
grub-core/commands/test.c
Normal file
|
@ -0,0 +1,433 @@
|
|||
/* test.c -- The test command.. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/fs.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
/* A simple implementation for signed numbers. */
|
||||
static int
|
||||
grub_strtosl (char *arg, char **end, int base)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 (cmd_1);
|
||||
grub_unregister_command (cmd_2);
|
||||
}
|
57
grub-core/commands/true.c
Normal file
57
grub-core/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);
|
||||
}
|
216
grub-core/commands/usbtest.c
Normal file
216
grub-core/commands/usbtest.c
Normal file
|
@ -0,0 +1,216 @@
|
|||
/* 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[] =
|
||||
{
|
||||
"Unknown",
|
||||
"Audio",
|
||||
"Communication Interface",
|
||||
"HID",
|
||||
"Unknown",
|
||||
"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);
|
||||
|
||||
if (descstrp->length == 0)
|
||||
{
|
||||
grub_free (descstrp);
|
||||
*string = grub_strdup ("");
|
||||
if (! *string)
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
*string = grub_malloc (descstr.length * 2 + 1);
|
||||
if (! *string)
|
||||
{
|
||||
grub_free (descstrp);
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
*grub_utf16_to_utf8 ((grub_uint8_t *) *string, descstrp->str,
|
||||
descstrp->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);
|
||||
|
||||
grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n",
|
||||
descdev->class, descdev->class < ARRAY_SIZE (usb_classes)
|
||||
? usb_classes[descdev->class] : "Unknown",
|
||||
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);
|
||||
grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n",
|
||||
interf->class, interf->class < ARRAY_SIZE (usb_classes)
|
||||
? usb_classes[interf->class] : "Unknown",
|
||||
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_usb_poll_devices ();
|
||||
|
||||
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);
|
||||
}
|
193
grub-core/commands/videotest.c
Normal file
193
grub-core/commands/videotest.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* 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
|
||||
* 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/video.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/font.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/gfxmenu_view.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
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_video_render_target *text_layer;
|
||||
grub_video_color_t palette[16];
|
||||
|
||||
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);
|
||||
|
||||
{
|
||||
const char *str;
|
||||
int texty;
|
||||
grub_font_t sansbig;
|
||||
grub_font_t sans;
|
||||
grub_font_t sanssmall;
|
||||
grub_font_t fixed;
|
||||
struct grub_font_glyph *glyph;
|
||||
|
||||
grub_video_create_render_target (&text_layer, width, height,
|
||||
GRUB_VIDEO_MODE_TYPE_RGB
|
||||
| GRUB_VIDEO_MODE_TYPE_ALPHA);
|
||||
|
||||
grub_video_set_active_render_target (text_layer);
|
||||
|
||||
color = grub_video_map_rgb (0, 255, 255);
|
||||
sansbig = grub_font_get ("Unknown Regular 16");
|
||||
sans = grub_font_get ("Unknown Regular 16");
|
||||
sanssmall = grub_font_get ("Unknown Regular 16");
|
||||
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);
|
||||
|
||||
color = grub_video_map_rgb (255, 255, 255);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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_font_draw_glyph (glyph, color, 16 + i * 16, 220);
|
||||
}
|
||||
}
|
||||
|
||||
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
color = grub_video_map_rgb (0, 0, 0);
|
||||
grub_video_fill_rect (color, 0, 0, width, height);
|
||||
|
||||
color = grub_video_map_rgb (255, 0, 0);
|
||||
grub_video_fill_rect (color, 0, 0, 100, 100);
|
||||
|
||||
color = grub_video_map_rgb (0, 255, 255);
|
||||
grub_video_fill_rect (color, 100, 100, 100, 100);
|
||||
|
||||
grub_video_set_viewport (x + 150, y + 150,
|
||||
width - 150 * 2, height - 150 * 2);
|
||||
color = grub_video_map_rgb (77, 33, 77);
|
||||
grub_video_fill_rect (color, 0, 0, width, height);
|
||||
grub_video_swap_buffers ();
|
||||
}
|
||||
|
||||
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 ();
|
||||
|
||||
grub_video_delete_render_target (text_layer);
|
||||
|
||||
grub_video_restore ();
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
grub_printf("color %d: %08x\n", i, palette[i]);
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(videotest)
|
||||
{
|
||||
cmd = grub_register_command ("videotest", grub_cmd_videotest,
|
||||
0, N_("Test video subsystem."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(videotest)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
493
grub-core/commands/wildcard.c
Normal file
493
grub-core/commands/wildcard.c
Normal file
|
@ -0,0 +1,493 @@
|
|||
/* wildcard.c - Wildcard character expansion for GRUB script. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 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/mm.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/script_sh.h>
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
static inline int isregexop (char ch);
|
||||
static char ** merge (char **lhs, char **rhs);
|
||||
static char *make_dir (const char *prefix, const char *start, const char *end);
|
||||
static int make_regex (const char *regex_start, const char *regex_end,
|
||||
regex_t *regexp);
|
||||
static void split_path (const char *path, const char **suffix_end, const char **regex_end);
|
||||
static char ** match_devices (const regex_t *regexp, int noparts);
|
||||
static char ** match_files (const char *prefix, const char *suffix_start,
|
||||
const char *suffix_end, const regex_t *regexp);
|
||||
|
||||
static char* wildcard_escape (const char *s);
|
||||
static char* wildcard_unescape (const char *s);
|
||||
static grub_err_t wildcard_expand (const char *s, char ***strs);
|
||||
|
||||
struct grub_script_wildcard_translator translator = {
|
||||
.expand = wildcard_expand,
|
||||
.escape = wildcard_escape,
|
||||
.unescape = wildcard_unescape
|
||||
};
|
||||
|
||||
static char **
|
||||
merge (char **dest, char **ps)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
char **p;
|
||||
|
||||
if (! dest)
|
||||
return ps;
|
||||
|
||||
if (! ps)
|
||||
return dest;
|
||||
|
||||
for (i = 0; dest[i]; i++)
|
||||
;
|
||||
for (j = 0; ps[j]; j++)
|
||||
;
|
||||
|
||||
p = grub_realloc (dest, sizeof (char*) * (i + j + 1));
|
||||
if (! p)
|
||||
{
|
||||
grub_free (dest);
|
||||
grub_free (ps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (j = 0; ps[j]; j++)
|
||||
dest[i++] = ps[j];
|
||||
dest[i] = 0;
|
||||
|
||||
grub_free (ps);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static inline int
|
||||
isregexop (char ch)
|
||||
{
|
||||
return grub_strchr ("*.\\", ch) ? 1 : 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
make_dir (const char *prefix, const char *start, const char *end)
|
||||
{
|
||||
char ch;
|
||||
unsigned i;
|
||||
unsigned n;
|
||||
char *result;
|
||||
|
||||
i = grub_strlen (prefix);
|
||||
n = i + end - start;
|
||||
|
||||
result = grub_malloc (n + 1);
|
||||
if (! result)
|
||||
return 0;
|
||||
|
||||
grub_strcpy (result, prefix);
|
||||
while (start < end && (ch = *start++))
|
||||
if (ch == '\\' && isregexop (*start))
|
||||
result[i++] = *start++;
|
||||
else
|
||||
result[i++] = ch;
|
||||
|
||||
result[i] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
make_regex (const char *start, const char *end, regex_t *regexp)
|
||||
{
|
||||
char ch;
|
||||
int i = 0;
|
||||
unsigned len = end - start;
|
||||
char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */
|
||||
|
||||
if (! buffer)
|
||||
return 1;
|
||||
|
||||
buffer[i++] = '^';
|
||||
while (start < end)
|
||||
{
|
||||
/* XXX Only * expansion for now. */
|
||||
switch ((ch = *start++))
|
||||
{
|
||||
case '\\':
|
||||
buffer[i++] = ch;
|
||||
if (*start != '\0')
|
||||
buffer[i++] = *start++;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
buffer[i++] = '\\';
|
||||
buffer[i++] = '.';
|
||||
break;
|
||||
|
||||
case '*':
|
||||
buffer[i++] = '.';
|
||||
buffer[i++] = '*';
|
||||
break;
|
||||
|
||||
default:
|
||||
buffer[i++] = ch;
|
||||
}
|
||||
}
|
||||
buffer[i++] = '$';
|
||||
buffer[i] = '\0';
|
||||
|
||||
if (regcomp (regexp, buffer, RE_SYNTAX_GNU_AWK))
|
||||
{
|
||||
grub_free (buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_free (buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Split `str' into two parts: (1) dirname that is regexop free (2)
|
||||
dirname that has a regexop. */
|
||||
static void
|
||||
split_path (const char *str, const char **noregexop, const char **regexop)
|
||||
{
|
||||
char ch = 0;
|
||||
int regex = 0;
|
||||
|
||||
const char *end;
|
||||
const char *split; /* points till the end of dirnaname that doesn't
|
||||
need expansion. */
|
||||
|
||||
split = end = str;
|
||||
while ((ch = *end))
|
||||
{
|
||||
if (ch == '\\' && end[1])
|
||||
end++;
|
||||
|
||||
else if (isregexop (ch))
|
||||
regex = 1;
|
||||
|
||||
else if (ch == '/' && ! regex)
|
||||
split = end + 1; /* forward to next regexop-free dirname */
|
||||
|
||||
else if (ch == '/' && regex)
|
||||
break; /* stop at the first dirname with a regexop */
|
||||
|
||||
end++;
|
||||
}
|
||||
|
||||
*regexop = end;
|
||||
if (! regex)
|
||||
*noregexop = end;
|
||||
else
|
||||
*noregexop = split;
|
||||
}
|
||||
|
||||
static char **
|
||||
match_devices (const regex_t *regexp, int noparts)
|
||||
{
|
||||
int i;
|
||||
int ndev;
|
||||
char **devs;
|
||||
|
||||
auto int match (const char *name);
|
||||
int match (const char *name)
|
||||
{
|
||||
char **t;
|
||||
char *buffer;
|
||||
|
||||
/* skip partitions if asked to. */
|
||||
if (noparts && grub_strchr(name, ','))
|
||||
return 0;
|
||||
|
||||
buffer = grub_xasprintf ("(%s)", name);
|
||||
if (! buffer)
|
||||
return 1;
|
||||
|
||||
grub_dprintf ("expand", "matching: %s\n", buffer);
|
||||
if (regexec (regexp, buffer, 0, 0, 0))
|
||||
{
|
||||
grub_free (buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
t = grub_realloc (devs, sizeof (char*) * (ndev + 2));
|
||||
if (! t)
|
||||
return 1;
|
||||
|
||||
devs = t;
|
||||
devs[ndev++] = buffer;
|
||||
devs[ndev] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ndev = 0;
|
||||
devs = 0;
|
||||
|
||||
if (grub_device_iterate (match))
|
||||
goto fail;
|
||||
|
||||
return devs;
|
||||
|
||||
fail:
|
||||
|
||||
for (i = 0; devs && devs[i]; i++)
|
||||
grub_free (devs[i]);
|
||||
|
||||
if (devs)
|
||||
grub_free (devs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char **
|
||||
match_files (const char *prefix, const char *suffix, const char *end,
|
||||
const regex_t *regexp)
|
||||
{
|
||||
int i;
|
||||
int error;
|
||||
char **files;
|
||||
unsigned nfile;
|
||||
char *dir;
|
||||
const char *path;
|
||||
char *device_name;
|
||||
grub_fs_t fs;
|
||||
grub_device_t dev;
|
||||
|
||||
auto int match (const char *name, const struct grub_dirhook_info *info);
|
||||
int match (const char *name, const struct grub_dirhook_info *info)
|
||||
{
|
||||
char **t;
|
||||
char *buffer;
|
||||
|
||||
/* skip hidden files, . and .. */
|
||||
if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0)
|
||||
return 0;
|
||||
|
||||
grub_dprintf ("expand", "matching: %s in %s\n", name, dir);
|
||||
if (regexec (regexp, name, 0, 0, 0))
|
||||
return 0;
|
||||
|
||||
buffer = grub_xasprintf ("%s%s", dir, name);
|
||||
if (! buffer)
|
||||
return 1;
|
||||
|
||||
t = grub_realloc (files, sizeof (char*) * (nfile + 2));
|
||||
if (! t)
|
||||
{
|
||||
grub_free (buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
files = t;
|
||||
files[nfile++] = buffer;
|
||||
files[nfile] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nfile = 0;
|
||||
files = 0;
|
||||
dev = 0;
|
||||
device_name = 0;
|
||||
grub_error_push ();
|
||||
|
||||
dir = make_dir (prefix, suffix, end);
|
||||
if (! dir)
|
||||
goto fail;
|
||||
|
||||
device_name = grub_file_get_device_name (dir);
|
||||
dev = grub_device_open (device_name);
|
||||
if (! dev)
|
||||
goto fail;
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
if (! fs)
|
||||
goto fail;
|
||||
|
||||
path = grub_strchr (dir, ')');
|
||||
if (! path)
|
||||
goto fail;
|
||||
path++;
|
||||
|
||||
if (fs->dir (dev, path, match))
|
||||
goto fail;
|
||||
|
||||
grub_free (dir);
|
||||
grub_device_close (dev);
|
||||
grub_free (device_name);
|
||||
grub_error_pop ();
|
||||
return files;
|
||||
|
||||
fail:
|
||||
|
||||
if (dir)
|
||||
grub_free (dir);
|
||||
|
||||
for (i = 0; files && files[i]; i++)
|
||||
grub_free (files[i]);
|
||||
|
||||
if (files)
|
||||
grub_free (files);
|
||||
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
if (device_name)
|
||||
grub_free (device_name);
|
||||
|
||||
grub_error_pop ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char*
|
||||
wildcard_escape (const char *s)
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
char ch;
|
||||
char *p;
|
||||
|
||||
len = grub_strlen (s);
|
||||
p = grub_malloc (len * 2 + 1);
|
||||
if (! p)
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
while ((ch = *s++))
|
||||
{
|
||||
if (isregexop (ch))
|
||||
p[i++] = '\\';
|
||||
p[i++] = ch;
|
||||
}
|
||||
p[i] = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
static char*
|
||||
wildcard_unescape (const char *s)
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
char ch;
|
||||
char *p;
|
||||
|
||||
len = grub_strlen (s);
|
||||
p = grub_malloc (len + 1);
|
||||
if (! p)
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
while ((ch = *s++))
|
||||
{
|
||||
if (ch == '\\' && isregexop (*s))
|
||||
p[i++] = *s++;
|
||||
else
|
||||
p[i++] = ch;
|
||||
}
|
||||
p[i] = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
wildcard_expand (const char *s, char ***strs)
|
||||
{
|
||||
const char *start;
|
||||
const char *regexop;
|
||||
const char *noregexop;
|
||||
char **paths = 0;
|
||||
|
||||
unsigned i;
|
||||
regex_t regexp;
|
||||
|
||||
start = s;
|
||||
while (*start)
|
||||
{
|
||||
split_path (start, &noregexop, ®exop);
|
||||
if (noregexop >= regexop) /* no more wildcards */
|
||||
break;
|
||||
|
||||
if (make_regex (noregexop, regexop, ®exp))
|
||||
goto fail;
|
||||
|
||||
if (paths == 0)
|
||||
{
|
||||
if (start == noregexop) /* device part has regexop */
|
||||
paths = match_devices (®exp, *start != '(');
|
||||
|
||||
else if (*start == '(') /* device part explicit wo regexop */
|
||||
paths = match_files ("", start, noregexop, ®exp);
|
||||
|
||||
else if (*start == '/') /* no device part */
|
||||
{
|
||||
char **r;
|
||||
unsigned n;
|
||||
char *root;
|
||||
char *prefix;
|
||||
|
||||
root = grub_env_get ("root");
|
||||
if (! root)
|
||||
goto fail;
|
||||
|
||||
prefix = grub_xasprintf ("(%s)", root);
|
||||
if (! prefix)
|
||||
goto fail;
|
||||
|
||||
paths = match_files (prefix, start, noregexop, ®exp);
|
||||
grub_free (prefix);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char **r = 0;
|
||||
|
||||
for (i = 0; paths[i]; i++)
|
||||
{
|
||||
char **p;
|
||||
|
||||
p = match_files (paths[i], start, noregexop, ®exp);
|
||||
if (! p)
|
||||
continue;
|
||||
|
||||
r = merge (r, p);
|
||||
if (! r)
|
||||
goto fail;
|
||||
}
|
||||
paths = r;
|
||||
}
|
||||
|
||||
regfree (®exp);
|
||||
if (! paths)
|
||||
goto done;
|
||||
|
||||
start = regexop;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
*strs = paths;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
||||
for (i = 0; paths && paths[i]; i++)
|
||||
grub_free (paths[i]);
|
||||
grub_free (paths[i]);
|
||||
regfree (®exp);
|
||||
return grub_errno;
|
||||
}
|
100
grub-core/commands/xnu_uuid.c
Normal file
100
grub-core/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_snprintf (uuid_string, sizeof (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