Resync with trunk
This commit is contained in:
commit
e68d3b243f
706 changed files with 157184 additions and 45875 deletions
58
kern/command.c
Normal file
58
kern/command.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* command.c - support basic 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/command.h>
|
||||
|
||||
grub_command_t grub_command_list;
|
||||
|
||||
grub_command_t
|
||||
grub_register_command_prio (const char *name,
|
||||
grub_command_func_t func,
|
||||
const char *summary,
|
||||
const char *description,
|
||||
int prio)
|
||||
{
|
||||
grub_command_t cmd;
|
||||
|
||||
cmd = (grub_command_t) grub_zalloc (sizeof (*cmd));
|
||||
if (! cmd)
|
||||
return 0;
|
||||
|
||||
cmd->name = name;
|
||||
cmd->func = func;
|
||||
cmd->summary = (summary) ? summary : "";
|
||||
cmd->description = description;
|
||||
|
||||
cmd->flags = GRUB_COMMAND_FLAG_BOTH;
|
||||
cmd->prio = prio;
|
||||
|
||||
grub_prio_list_insert (GRUB_AS_PRIO_LIST_P (&grub_command_list),
|
||||
GRUB_AS_PRIO_LIST (cmd));
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void
|
||||
grub_unregister_command (grub_command_t cmd)
|
||||
{
|
||||
grub_prio_list_remove (GRUB_AS_PRIO_LIST_P (&grub_command_list),
|
||||
GRUB_AS_PRIO_LIST (cmd));
|
||||
grub_free (cmd);
|
||||
}
|
202
kern/corecmd.c
Normal file
202
kern/corecmd.c
Normal file
|
@ -0,0 +1,202 @@
|
|||
/* corecmd.c - critical commands which are registered in kernel */
|
||||
/*
|
||||
* 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/dl.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/command.h>
|
||||
|
||||
/* set ENVVAR=VALUE */
|
||||
static grub_err_t
|
||||
grub_core_cmd_set (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char *var;
|
||||
char *val;
|
||||
|
||||
auto int print_env (struct grub_env_var *env);
|
||||
|
||||
int print_env (struct grub_env_var *env)
|
||||
{
|
||||
grub_printf ("%s=%s\n", env->name, env->value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
grub_env_iterate (print_env);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var = argv[0];
|
||||
val = grub_strchr (var, '=');
|
||||
if (! val)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not an assignment");
|
||||
|
||||
val[0] = 0;
|
||||
grub_env_set (var, val + 1);
|
||||
val[0] = '=';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_core_cmd_unset (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"no environment variable specified");
|
||||
|
||||
grub_env_unset (argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_core_cmd_export (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"no environment variable specified");
|
||||
|
||||
grub_env_export (args[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* insmod MODULE */
|
||||
static grub_err_t
|
||||
grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char *p;
|
||||
grub_dl_t mod;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
|
||||
|
||||
p = grub_strchr (argv[0], '/');
|
||||
if (! p)
|
||||
mod = grub_dl_load (argv[0]);
|
||||
else
|
||||
mod = grub_dl_load_file (argv[0]);
|
||||
|
||||
if (mod)
|
||||
grub_dl_ref (mod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_mini_print_devices (const char *name)
|
||||
{
|
||||
grub_printf ("(%s) ", name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_mini_print_files (const char *filename,
|
||||
const struct grub_dirhook_info *info)
|
||||
{
|
||||
grub_printf ("%s%s ", filename, info->dir ? "/" : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ls [ARG] */
|
||||
static grub_err_t
|
||||
grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
{
|
||||
grub_device_iterate (grub_mini_print_devices);
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
}
|
||||
else
|
||||
{
|
||||
char *device_name;
|
||||
grub_device_t dev;
|
||||
grub_fs_t fs;
|
||||
char *path;
|
||||
|
||||
device_name = grub_file_get_device_name (argv[0]);
|
||||
dev = grub_device_open (device_name);
|
||||
if (! dev)
|
||||
goto fail;
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
path = grub_strchr (argv[0], ')');
|
||||
if (! path)
|
||||
path = argv[0];
|
||||
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_printf ("(%s): Filesystem is %s.\n",
|
||||
device_name, fs ? fs->name : "unknown");
|
||||
}
|
||||
else if (fs)
|
||||
{
|
||||
(fs->dir) (dev, path, grub_mini_print_files);
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
fail:
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
grub_free (device_name);
|
||||
}
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
void
|
||||
grub_register_core_commands (void)
|
||||
{
|
||||
grub_register_command ("set", grub_core_cmd_set,
|
||||
"[ENVVAR=VALUE]", "Set an environment variable.");
|
||||
grub_register_command ("unset", grub_core_cmd_unset,
|
||||
"ENVVAR", "Remove an environment variable.");
|
||||
grub_register_command ("export", grub_core_cmd_export,
|
||||
"ENVVAR", "Export a variable.");
|
||||
grub_register_command ("ls", grub_core_cmd_ls,
|
||||
"[ARG]", "List devices or files.");
|
||||
grub_register_command ("insmod", grub_core_cmd_insmod,
|
||||
"MODULE", "Insert a module.");
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* device.c - device manager */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2005,2007,2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,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
|
||||
|
@ -41,18 +41,15 @@ grub_device_open (const char *name)
|
|||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dev = grub_malloc (sizeof (*dev));
|
||||
if (! dev)
|
||||
goto fail;
|
||||
|
||||
|
||||
/* Try to open a disk. */
|
||||
disk = grub_disk_open (name);
|
||||
if (! disk)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE, "unknown device");
|
||||
goto fail;
|
||||
}
|
||||
goto fail;
|
||||
|
||||
dev->disk = disk;
|
||||
dev->net = 0; /* FIXME */
|
||||
|
@ -62,7 +59,7 @@ grub_device_open (const char *name)
|
|||
fail:
|
||||
if (disk)
|
||||
grub_disk_close (disk);
|
||||
|
||||
|
||||
grub_free (dev);
|
||||
|
||||
return 0;
|
||||
|
@ -85,53 +82,77 @@ grub_device_iterate (int (*hook) (const char *name))
|
|||
auto int iterate_disk (const char *disk_name);
|
||||
auto int iterate_partition (grub_disk_t disk,
|
||||
const grub_partition_t partition);
|
||||
|
||||
|
||||
struct part_ent
|
||||
{
|
||||
struct part_ent *next;
|
||||
char name[0];
|
||||
} *ents;
|
||||
|
||||
int iterate_disk (const char *disk_name)
|
||||
{
|
||||
grub_device_t dev;
|
||||
|
||||
if (hook (disk_name))
|
||||
return 1;
|
||||
|
||||
|
||||
dev = grub_device_open (disk_name);
|
||||
if (! dev)
|
||||
return 0;
|
||||
|
||||
|
||||
if (dev->disk && dev->disk->has_partitions)
|
||||
if (grub_partition_iterate (dev->disk, iterate_partition))
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
struct part_ent *p;
|
||||
int ret = 0;
|
||||
|
||||
ents = NULL;
|
||||
(void) grub_partition_iterate (dev->disk, iterate_partition);
|
||||
grub_device_close (dev);
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
p = ents;
|
||||
while (p != NULL)
|
||||
{
|
||||
struct part_ent *next = p->next;
|
||||
|
||||
if (!ret)
|
||||
ret = hook (p->name);
|
||||
grub_free (p);
|
||||
p = next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
grub_device_close (dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int iterate_partition (grub_disk_t disk, const grub_partition_t partition)
|
||||
{
|
||||
char *partition_name;
|
||||
char *device_name;
|
||||
int ret;
|
||||
|
||||
struct part_ent *p;
|
||||
|
||||
partition_name = grub_partition_get_name (partition);
|
||||
if (! partition_name)
|
||||
return 1;
|
||||
|
||||
device_name = grub_malloc (grub_strlen (disk->name) + 1
|
||||
+ grub_strlen (partition_name) + 1);
|
||||
if (! device_name)
|
||||
|
||||
p = grub_malloc (sizeof (p->next) + grub_strlen (disk->name) + 1 +
|
||||
grub_strlen (partition_name) + 1);
|
||||
if (!p)
|
||||
{
|
||||
grub_free (partition_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_sprintf (device_name, "%s,%s", disk->name, partition_name);
|
||||
grub_sprintf (p->name, "%s,%s", disk->name, partition_name);
|
||||
grub_free (partition_name);
|
||||
|
||||
ret = hook (device_name);
|
||||
grub_free (device_name);
|
||||
return ret;
|
||||
p->next = ents;
|
||||
ents = p;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only disk devices are supported at the moment. */
|
||||
|
|
153
kern/disk.c
153
kern/disk.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2004,2006,2007,2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,2003,2004,2006,2007,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
|
||||
|
@ -22,19 +22,19 @@
|
|||
#include <grub/types.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/machine/time.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/file.h>
|
||||
|
||||
#define GRUB_CACHE_TIMEOUT 2
|
||||
|
||||
/* The last time the disk was used. */
|
||||
static unsigned long grub_last_time = 0;
|
||||
static grub_uint64_t grub_last_time = 0;
|
||||
|
||||
|
||||
/* Disk cache. */
|
||||
struct grub_disk_cache
|
||||
{
|
||||
unsigned long dev_id;
|
||||
enum grub_disk_dev_id dev_id;
|
||||
unsigned long disk_id;
|
||||
grub_disk_addr_t sector;
|
||||
char *data;
|
||||
|
@ -46,6 +46,10 @@ static struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM];
|
|||
void (*grub_disk_firmware_fini) (void);
|
||||
int grub_disk_firmware_is_tainted;
|
||||
|
||||
grub_err_t (* grub_disk_ata_pass_through) (grub_disk_t,
|
||||
struct grub_disk_ata_pass_through_parms *);
|
||||
|
||||
|
||||
#if 0
|
||||
static unsigned long grub_disk_cache_hits;
|
||||
static unsigned long grub_disk_cache_misses;
|
||||
|
@ -128,7 +132,7 @@ grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id,
|
|||
#if 0
|
||||
grub_disk_cache_misses++;
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -153,16 +157,19 @@ grub_disk_cache_store (unsigned long dev_id, unsigned long disk_id,
|
|||
{
|
||||
unsigned index;
|
||||
struct grub_disk_cache *cache;
|
||||
|
||||
grub_disk_cache_invalidate (dev_id, disk_id, sector);
|
||||
|
||||
|
||||
index = grub_disk_cache_get_index (dev_id, disk_id, sector);
|
||||
cache = grub_disk_cache_table + index;
|
||||
|
||||
|
||||
cache->lock = 1;
|
||||
grub_free (cache->data);
|
||||
cache->data = 0;
|
||||
cache->lock = 0;
|
||||
|
||||
cache->data = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
|
||||
if (! cache->data)
|
||||
return grub_errno;
|
||||
|
||||
|
||||
grub_memcpy (cache->data, data,
|
||||
GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
|
||||
cache->dev_id = dev_id;
|
||||
|
@ -187,7 +194,7 @@ void
|
|||
grub_disk_dev_unregister (grub_disk_dev_t dev)
|
||||
{
|
||||
grub_disk_dev_t *p, q;
|
||||
|
||||
|
||||
for (p = &grub_disk_dev_list, q = *p; q; p = &(q->next), q = q->next)
|
||||
if (q == dev)
|
||||
{
|
||||
|
@ -202,40 +209,54 @@ grub_disk_dev_iterate (int (*hook) (const char *name))
|
|||
grub_disk_dev_t p;
|
||||
|
||||
for (p = grub_disk_dev_list; p; p = p->next)
|
||||
if ((p->iterate) (hook))
|
||||
if (p->iterate && (p->iterate) (hook))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the location of the first ',', if any, which is not
|
||||
escaped by a '\'. */
|
||||
static const char *
|
||||
find_part_sep (const char *name)
|
||||
{
|
||||
const char *p = name;
|
||||
char c;
|
||||
|
||||
while ((c = *p++) != '\0')
|
||||
{
|
||||
if (c == '\\' && *p == ',')
|
||||
p++;
|
||||
else if (c == ',')
|
||||
return p - 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
grub_disk_t
|
||||
grub_disk_open (const char *name)
|
||||
{
|
||||
char *p;
|
||||
const char *p;
|
||||
grub_disk_t disk;
|
||||
grub_disk_dev_t dev;
|
||||
char *raw = (char *) name;
|
||||
unsigned long current_time;
|
||||
grub_uint64_t current_time;
|
||||
|
||||
grub_dprintf ("disk", "Opening `%s'...\n", name);
|
||||
|
||||
disk = (grub_disk_t) grub_malloc (sizeof (*disk));
|
||||
disk = (grub_disk_t) grub_zalloc (sizeof (*disk));
|
||||
if (! disk)
|
||||
return 0;
|
||||
|
||||
disk->dev = 0;
|
||||
disk->read_hook = 0;
|
||||
disk->partition = 0;
|
||||
disk->data = 0;
|
||||
disk->name = grub_strdup (name);
|
||||
if (! disk->name)
|
||||
goto fail;
|
||||
|
||||
p = grub_strchr (name, ',');
|
||||
|
||||
p = find_part_sep (name);
|
||||
if (p)
|
||||
{
|
||||
grub_size_t len = p - name;
|
||||
|
||||
|
||||
raw = grub_malloc (len + 1);
|
||||
if (! raw)
|
||||
goto fail;
|
||||
|
@ -265,7 +286,7 @@ grub_disk_open (const char *name)
|
|||
grub_error (GRUB_ERR_BAD_DEVICE, "no partition on this disk");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
disk->dev = dev;
|
||||
|
||||
if (p)
|
||||
|
@ -280,16 +301,16 @@ grub_disk_open (const char *name)
|
|||
|
||||
/* The cache will be invalidated about 2 seconds after a device was
|
||||
closed. */
|
||||
current_time = grub_get_rtc ();
|
||||
current_time = grub_get_time_ms ();
|
||||
|
||||
if (current_time > (grub_last_time
|
||||
+ GRUB_CACHE_TIMEOUT * GRUB_TICKS_PER_SECOND))
|
||||
+ GRUB_CACHE_TIMEOUT * 1000))
|
||||
grub_disk_cache_invalidate_all ();
|
||||
|
||||
|
||||
grub_last_time = current_time;
|
||||
|
||||
|
||||
fail:
|
||||
|
||||
|
||||
if (raw && raw != name)
|
||||
grub_free (raw);
|
||||
|
||||
|
@ -315,20 +336,24 @@ grub_disk_close (grub_disk_t disk)
|
|||
(disk->dev->close) (disk);
|
||||
|
||||
/* Reset the timer. */
|
||||
grub_last_time = grub_get_rtc ();
|
||||
grub_last_time = grub_get_time_ms ();
|
||||
|
||||
grub_free (disk->partition);
|
||||
grub_free ((void *) disk->name);
|
||||
grub_free (disk);
|
||||
}
|
||||
|
||||
/* This function performs three tasks:
|
||||
- Make sectors disk relative from partition relative.
|
||||
- Normalize offset to be less than the sector size.
|
||||
- Verify that the range is inside the partition. */
|
||||
static grub_err_t
|
||||
grub_disk_check_range (grub_disk_t disk, grub_disk_addr_t *sector,
|
||||
grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector,
|
||||
grub_off_t *offset, grub_size_t size)
|
||||
{
|
||||
*sector += *offset >> GRUB_DISK_SECTOR_BITS;
|
||||
*offset &= GRUB_DISK_SECTOR_SIZE - 1;
|
||||
|
||||
|
||||
if (disk->partition)
|
||||
{
|
||||
grub_disk_addr_t start;
|
||||
|
@ -356,23 +381,23 @@ grub_disk_check_range (grub_disk_t disk, grub_disk_addr_t *sector,
|
|||
/* Read data from the disk. */
|
||||
grub_err_t
|
||||
grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_off_t offset, grub_size_t size, char *buf)
|
||||
grub_off_t offset, grub_size_t size, void *buf)
|
||||
{
|
||||
char *tmp_buf;
|
||||
unsigned real_offset;
|
||||
|
||||
|
||||
/* First of all, check if the region is within the disk. */
|
||||
if (grub_disk_check_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
|
||||
if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_error_push ();
|
||||
grub_dprintf ("disk", "Read out of range: sector 0x%llx.\n",
|
||||
(unsigned long long) sector);
|
||||
grub_dprintf ("disk", "Read out of range: sector 0x%llx (%s).\n",
|
||||
(unsigned long long) sector, grub_errmsg);
|
||||
grub_error_pop ();
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
real_offset = offset;
|
||||
|
||||
|
||||
/* Allocate a temporary buffer. */
|
||||
tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
|
||||
if (! tmp_buf)
|
||||
|
@ -405,8 +430,9 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
else
|
||||
{
|
||||
/* Otherwise read data from the disk actually. */
|
||||
if ((disk->dev->read) (disk, start_sector,
|
||||
GRUB_DISK_CACHE_SIZE, tmp_buf)
|
||||
if (start_sector + GRUB_DISK_CACHE_SIZE > disk->total_sectors
|
||||
|| (disk->dev->read) (disk, start_sector,
|
||||
GRUB_DISK_CACHE_SIZE, tmp_buf)
|
||||
!= GRUB_ERR_NONE)
|
||||
{
|
||||
/* Uggh... Failed. Instead, just read necessary data. */
|
||||
|
@ -423,7 +449,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
goto finish;
|
||||
|
||||
tmp_buf = p;
|
||||
|
||||
|
||||
if ((disk->dev->read) (disk, sector, num, tmp_buf))
|
||||
{
|
||||
grub_error_push ();
|
||||
|
@ -462,62 +488,71 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
{
|
||||
grub_disk_addr_t s = sector;
|
||||
grub_size_t l = len;
|
||||
|
||||
|
||||
while (l)
|
||||
{
|
||||
(disk->read_hook) (s, real_offset,
|
||||
((l > GRUB_DISK_SECTOR_SIZE)
|
||||
? GRUB_DISK_SECTOR_SIZE
|
||||
: l));
|
||||
|
||||
|
||||
if (l < GRUB_DISK_SECTOR_SIZE - real_offset)
|
||||
break;
|
||||
|
||||
|
||||
s++;
|
||||
l -= GRUB_DISK_SECTOR_SIZE - real_offset;
|
||||
real_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sector = start_sector + GRUB_DISK_CACHE_SIZE;
|
||||
buf += len;
|
||||
buf = (char *) buf + len;
|
||||
size -= len;
|
||||
real_offset = 0;
|
||||
}
|
||||
|
||||
|
||||
finish:
|
||||
|
||||
|
||||
grub_free (tmp_buf);
|
||||
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_off_t offset, grub_size_t size, const char *buf)
|
||||
grub_off_t offset, grub_size_t size, const void *buf)
|
||||
{
|
||||
unsigned real_offset;
|
||||
|
||||
if (grub_disk_check_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
|
||||
|
||||
grub_dprintf ("disk", "Writing `%s'...\n", disk->name);
|
||||
|
||||
if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE)
|
||||
return -1;
|
||||
|
||||
real_offset = offset;
|
||||
|
||||
|
||||
while (size)
|
||||
{
|
||||
if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0))
|
||||
{
|
||||
char tmp_buf[GRUB_DISK_SECTOR_SIZE];
|
||||
grub_size_t len;
|
||||
|
||||
grub_partition_t part;
|
||||
|
||||
part = disk->partition;
|
||||
disk->partition = 0;
|
||||
if (grub_disk_read (disk, sector, 0, GRUB_DISK_SECTOR_SIZE, tmp_buf)
|
||||
!= GRUB_ERR_NONE)
|
||||
goto finish;
|
||||
{
|
||||
disk->partition = part;
|
||||
goto finish;
|
||||
}
|
||||
disk->partition = part;
|
||||
|
||||
len = GRUB_DISK_SECTOR_SIZE - real_offset;
|
||||
if (len > size)
|
||||
len = size;
|
||||
|
||||
|
||||
grub_memcpy (tmp_buf + real_offset, buf, len);
|
||||
|
||||
grub_disk_cache_invalidate (disk->dev->id, disk->id, sector);
|
||||
|
@ -526,7 +561,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
goto finish;
|
||||
|
||||
sector++;
|
||||
buf += len;
|
||||
buf = (char *) buf + len;
|
||||
size -= len;
|
||||
real_offset = 0;
|
||||
}
|
||||
|
@ -537,14 +572,14 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
|
||||
len = size & ~(GRUB_DISK_SECTOR_SIZE - 1);
|
||||
n = size >> GRUB_DISK_SECTOR_BITS;
|
||||
|
||||
|
||||
if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE)
|
||||
goto finish;
|
||||
|
||||
while (n--)
|
||||
grub_disk_cache_invalidate (disk->dev->id, disk->id, sector++);
|
||||
|
||||
buf += len;
|
||||
buf = (char *) buf + len;
|
||||
size -= len;
|
||||
}
|
||||
}
|
||||
|
@ -554,7 +589,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_uint64_t
|
||||
grub_uint64_t
|
||||
grub_disk_get_size (grub_disk_t disk)
|
||||
{
|
||||
if (disk->partition)
|
||||
|
|
153
kern/dl.c
153
kern/dl.c
|
@ -1,7 +1,7 @@
|
|||
/* dl.c - loadable module support */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2004,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -17,6 +17,9 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Force native word size */
|
||||
#define GRUB_TARGET_WORDSIZE (8 * GRUB_CPU_SIZEOF_VOID_P)
|
||||
|
||||
#include <config.h>
|
||||
#include <grub/elf.h>
|
||||
#include <grub/dl.h>
|
||||
|
@ -29,28 +32,9 @@
|
|||
#include <grub/env.h>
|
||||
#include <grub/cache.h>
|
||||
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 4
|
||||
|
||||
typedef Elf32_Word Elf_Word;
|
||||
typedef Elf32_Addr Elf_Addr;
|
||||
typedef Elf32_Ehdr Elf_Ehdr;
|
||||
typedef Elf32_Shdr Elf_Shdr;
|
||||
typedef Elf32_Sym Elf_Sym;
|
||||
|
||||
# define ELF_ST_BIND(val) ELF32_ST_BIND (val)
|
||||
# define ELF_ST_TYPE(val) ELF32_ST_TYPE (val)
|
||||
|
||||
#elif GRUB_CPU_SIZEOF_VOID_P == 8
|
||||
|
||||
typedef Elf64_Word Elf_Word;
|
||||
typedef Elf64_Addr Elf_Addr;
|
||||
typedef Elf64_Ehdr Elf_Ehdr;
|
||||
typedef Elf64_Shdr Elf_Shdr;
|
||||
typedef Elf64_Sym Elf_Sym;
|
||||
|
||||
# define ELF_ST_BIND(val) ELF64_ST_BIND (val)
|
||||
# define ELF_ST_TYPE(val) ELF64_ST_TYPE (val)
|
||||
|
||||
/* Platforms where modules are in a readonly area of memory. */
|
||||
#if defined(GRUB_MACHINE_QEMU)
|
||||
#define GRUB_MODULES_MACHINE_READONLY
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -72,7 +56,7 @@ grub_dl_add (grub_dl_t mod)
|
|||
if (grub_dl_get (mod->name))
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"`%s' is already loaded", mod->name);
|
||||
|
||||
|
||||
l = (grub_dl_list_t) grub_malloc (sizeof (*l));
|
||||
if (! l)
|
||||
return grub_errno;
|
||||
|
@ -151,7 +135,7 @@ grub_symbol_hash (const char *s)
|
|||
|
||||
/* Resolve the symbol name NAME and return the address.
|
||||
Return NULL, if not found. */
|
||||
void *
|
||||
static void *
|
||||
grub_dl_resolve_symbol (const char *name)
|
||||
{
|
||||
grub_symbol_t sym;
|
||||
|
@ -169,7 +153,7 @@ grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod)
|
|||
{
|
||||
grub_symbol_t sym;
|
||||
unsigned k;
|
||||
|
||||
|
||||
sym = (grub_symbol_t) grub_malloc (sizeof (*sym));
|
||||
if (! sym)
|
||||
return grub_errno;
|
||||
|
@ -185,10 +169,10 @@ grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod)
|
|||
}
|
||||
else
|
||||
sym->name = name;
|
||||
|
||||
|
||||
sym->addr = addr;
|
||||
sym->mod = mod;
|
||||
|
||||
|
||||
k = grub_symbol_hash (name);
|
||||
sym->next = grub_symtab[k];
|
||||
grub_symtab[k] = sym;
|
||||
|
@ -204,7 +188,7 @@ grub_dl_unregister_symbols (grub_dl_t mod)
|
|||
|
||||
if (! mod)
|
||||
grub_fatal ("core symbols cannot be unregistered");
|
||||
|
||||
|
||||
for (i = 0; i < GRUB_SYMTAB_SIZE; i++)
|
||||
{
|
||||
grub_symbol_t sym, *p, q;
|
||||
|
@ -238,7 +222,7 @@ grub_dl_get_section_addr (grub_dl_t mod, unsigned n)
|
|||
}
|
||||
|
||||
/* Check if EHDR is a valid ELF header. */
|
||||
grub_err_t
|
||||
static grub_err_t
|
||||
grub_dl_check_header (void *ehdr, grub_size_t size)
|
||||
{
|
||||
Elf_Ehdr *e = ehdr;
|
||||
|
@ -266,7 +250,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
|
|||
{
|
||||
unsigned i;
|
||||
Elf_Shdr *s;
|
||||
|
||||
|
||||
for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
|
||||
|
@ -278,7 +262,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
|
|||
seg = (grub_dl_segment_t) grub_malloc (sizeof (*seg));
|
||||
if (! seg)
|
||||
return grub_errno;
|
||||
|
||||
|
||||
if (s->sh_size)
|
||||
{
|
||||
void *addr;
|
||||
|
@ -323,7 +307,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
|
|||
Elf_Sym *sym;
|
||||
const char *str;
|
||||
Elf_Word size, entsize;
|
||||
|
||||
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||||
|
@ -333,10 +317,16 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
|
|||
if (i == e->e_shnum)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "no symbol table");
|
||||
|
||||
sym = (Elf_Sym *) ((char *) e + s->sh_offset);
|
||||
#ifdef GRUB_MODULES_MACHINE_READONLY
|
||||
mod->symtab = grub_malloc (s->sh_size);
|
||||
memcpy (mod->symtab, (char *) e + s->sh_offset, s->sh_size);
|
||||
#else
|
||||
mod->symtab = (Elf_Sym *) ((char *) e + s->sh_offset);
|
||||
#endif
|
||||
sym = mod->symtab;
|
||||
size = s->sh_size;
|
||||
entsize = s->sh_entsize;
|
||||
|
||||
|
||||
s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shentsize * s->sh_link);
|
||||
str = (char *) e + s->sh_offset;
|
||||
|
||||
|
@ -347,7 +337,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
|
|||
unsigned char type = ELF_ST_TYPE (sym->st_info);
|
||||
unsigned char bind = ELF_ST_BIND (sym->st_info);
|
||||
const char *name = str + sym->st_name;
|
||||
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case STT_NOTYPE:
|
||||
|
@ -377,7 +367,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
|
|||
if (bind != STB_LOCAL)
|
||||
if (grub_dl_register_symbol (name, (void *) sym->st_value, mod))
|
||||
return grub_errno;
|
||||
|
||||
|
||||
if (grub_strcmp (name, "grub_mod_init") == 0)
|
||||
mod->init = (void (*) (grub_dl_t)) sym->st_value;
|
||||
else if (grub_strcmp (name, "grub_mod_fini") == 0)
|
||||
|
@ -445,7 +435,7 @@ grub_dl_resolve_dependencies (grub_dl_t mod, Elf_Ehdr *e)
|
|||
|
||||
s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize);
|
||||
str = (char *) e + s->sh_offset;
|
||||
|
||||
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||||
|
@ -454,25 +444,25 @@ grub_dl_resolve_dependencies (grub_dl_t mod, Elf_Ehdr *e)
|
|||
const char *name = (char *) e + s->sh_offset;
|
||||
const char *max = name + s->sh_size;
|
||||
|
||||
while (name < max)
|
||||
while ((name < max) && (*name))
|
||||
{
|
||||
grub_dl_t m;
|
||||
grub_dl_dep_t dep;
|
||||
|
||||
|
||||
m = grub_dl_load (name);
|
||||
if (! m)
|
||||
return grub_errno;
|
||||
|
||||
grub_dl_ref (m);
|
||||
|
||||
|
||||
dep = (grub_dl_dep_t) grub_malloc (sizeof (*dep));
|
||||
if (! dep)
|
||||
return grub_errno;
|
||||
|
||||
|
||||
dep->mod = m;
|
||||
dep->next = mod->dep;
|
||||
mod->dep = dep;
|
||||
|
||||
|
||||
name += grub_strlen (name) + 1;
|
||||
}
|
||||
}
|
||||
|
@ -480,6 +470,7 @@ grub_dl_resolve_dependencies (grub_dl_t mod, Elf_Ehdr *e)
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
#ifndef GRUB_UTIL
|
||||
int
|
||||
grub_dl_ref (grub_dl_t mod)
|
||||
{
|
||||
|
@ -487,7 +478,7 @@ grub_dl_ref (grub_dl_t mod)
|
|||
|
||||
for (dep = mod->dep; dep; dep = dep->next)
|
||||
grub_dl_ref (dep->mod);
|
||||
|
||||
|
||||
return ++mod->ref_count;
|
||||
}
|
||||
|
||||
|
@ -498,9 +489,10 @@ grub_dl_unref (grub_dl_t mod)
|
|||
|
||||
for (dep = mod->dep; dep; dep = dep->next)
|
||||
grub_dl_unref (dep->mod);
|
||||
|
||||
|
||||
return --mod->ref_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
grub_dl_flush_cache (grub_dl_t mod)
|
||||
|
@ -509,8 +501,8 @@ grub_dl_flush_cache (grub_dl_t mod)
|
|||
|
||||
for (seg = mod->segment; seg; seg = seg->next) {
|
||||
if (seg->size) {
|
||||
grub_dprintf ("modules", "flushing 0x%x bytes at %p\n", seg->size,
|
||||
seg->addr);
|
||||
grub_dprintf ("modules", "flushing 0x%lx bytes at %p\n",
|
||||
(unsigned long) seg->size, seg->addr);
|
||||
grub_arch_sync_caches (seg->addr, seg->size);
|
||||
}
|
||||
}
|
||||
|
@ -523,7 +515,8 @@ grub_dl_load_core (void *addr, grub_size_t size)
|
|||
Elf_Ehdr *e;
|
||||
grub_dl_t mod;
|
||||
|
||||
grub_dprintf ("modules", "module at %p, size 0x%x\n", addr, size);
|
||||
grub_dprintf ("modules", "module at %p, size 0x%lx\n", addr,
|
||||
(unsigned long) size);
|
||||
e = addr;
|
||||
if (grub_dl_check_header (e, size))
|
||||
return 0;
|
||||
|
@ -541,16 +534,11 @@ grub_dl_load_core (void *addr, grub_size_t size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
mod = (grub_dl_t) grub_malloc (sizeof (*mod));
|
||||
mod = (grub_dl_t) grub_zalloc (sizeof (*mod));
|
||||
if (! mod)
|
||||
return 0;
|
||||
|
||||
mod->name = 0;
|
||||
mod->ref_count = 1;
|
||||
mod->dep = 0;
|
||||
mod->segment = 0;
|
||||
mod->init = 0;
|
||||
mod->fini = 0;
|
||||
|
||||
grub_dprintf ("modules", "relocating to %p\n", mod);
|
||||
if (grub_dl_resolve_name (mod, e)
|
||||
|
@ -606,11 +594,11 @@ grub_init_module (const char *name,
|
|||
grub_dl_t
|
||||
grub_dl_load_file (const char *filename)
|
||||
{
|
||||
grub_file_t file;
|
||||
grub_file_t file = NULL;
|
||||
grub_ssize_t size;
|
||||
void *core = 0;
|
||||
grub_dl_t mod = 0;
|
||||
|
||||
|
||||
file = grub_file_open (filename);
|
||||
if (! file)
|
||||
return 0;
|
||||
|
@ -618,21 +606,31 @@ grub_dl_load_file (const char *filename)
|
|||
size = grub_file_size (file);
|
||||
core = grub_malloc (size);
|
||||
if (! core)
|
||||
goto failed;
|
||||
{
|
||||
grub_file_close (file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (grub_file_read (file, core, size) != (int) size)
|
||||
goto failed;
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_free (core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We must close this before we try to process dependencies.
|
||||
Some disk backends do not handle gracefully multiple concurrent
|
||||
opens of the same device. */
|
||||
grub_file_close (file);
|
||||
|
||||
mod = grub_dl_load_core (core, size);
|
||||
if (! mod)
|
||||
goto failed;
|
||||
|
||||
{
|
||||
grub_free (core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mod->ref_count = 0;
|
||||
|
||||
failed:
|
||||
grub_file_close (file);
|
||||
grub_free (core);
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
|
@ -647,7 +645,7 @@ grub_dl_load (const char *name)
|
|||
mod = grub_dl_get (name);
|
||||
if (mod)
|
||||
return mod;
|
||||
|
||||
|
||||
if (! grub_dl_dir) {
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, "\"prefix\" is not set");
|
||||
return 0;
|
||||
|
@ -657,17 +655,17 @@ grub_dl_load (const char *name)
|
|||
+ grub_strlen (name) + 4 + 1);
|
||||
if (! filename)
|
||||
return 0;
|
||||
|
||||
|
||||
grub_sprintf (filename, "%s/%s.mod", grub_dl_dir, name);
|
||||
mod = grub_dl_load_file (filename);
|
||||
grub_free (filename);
|
||||
|
||||
if (! mod)
|
||||
return 0;
|
||||
|
||||
|
||||
if (grub_strcmp (mod->name, name) != 0)
|
||||
grub_error (GRUB_ERR_BAD_MODULE, "mismatched names");
|
||||
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
|
@ -683,17 +681,17 @@ grub_dl_unload (grub_dl_t mod)
|
|||
|
||||
if (mod->fini)
|
||||
(mod->fini) ();
|
||||
|
||||
|
||||
grub_dl_remove (mod);
|
||||
grub_dl_unregister_symbols (mod);
|
||||
|
||||
|
||||
for (dep = mod->dep; dep; dep = depn)
|
||||
{
|
||||
depn = dep->next;
|
||||
|
||||
|
||||
if (! grub_dl_unref (dep->mod))
|
||||
grub_dl_unload (dep->mod);
|
||||
|
||||
|
||||
grub_free (dep);
|
||||
}
|
||||
|
||||
|
@ -703,8 +701,11 @@ grub_dl_unload (grub_dl_t mod)
|
|||
grub_free (seg->addr);
|
||||
grub_free (seg);
|
||||
}
|
||||
|
||||
|
||||
grub_free (mod->name);
|
||||
#ifdef GRUB_MODULES_MACHINE_READONLY
|
||||
grub_free (mod->symtab);
|
||||
#endif
|
||||
grub_free (mod);
|
||||
return 1;
|
||||
}
|
||||
|
@ -716,7 +717,7 @@ grub_dl_unload_unneeded (void)
|
|||
/* Because grub_dl_remove modifies the list of modules, this
|
||||
implementation is tricky. */
|
||||
grub_dl_list_t p = grub_dl_head;
|
||||
|
||||
|
||||
while (p)
|
||||
{
|
||||
if (grub_dl_unload (p->mod))
|
||||
|
@ -736,7 +737,7 @@ grub_dl_unload_all (void)
|
|||
while (grub_dl_head)
|
||||
{
|
||||
grub_dl_list_t p;
|
||||
|
||||
|
||||
grub_dl_unload_unneeded ();
|
||||
|
||||
/* Force to decrement the ref count. This will purge pre-loaded
|
||||
|
|
153
kern/efi/efi.c
153
kern/efi/efi.c
|
@ -1,7 +1,7 @@
|
|||
/* efi.c - generic EFI support */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2006,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
|
||||
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <grub/misc.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/efi/api.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/console_control.h>
|
||||
|
@ -42,13 +43,12 @@ grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
|
|||
{
|
||||
void *interface;
|
||||
grub_efi_status_t status;
|
||||
|
||||
status = grub_efi_system_table->boot_services->locate_protocol (protocol,
|
||||
registration,
|
||||
&interface);
|
||||
|
||||
status = efi_call_3 (grub_efi_system_table->boot_services->locate_protocol,
|
||||
protocol, registration, &interface);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return 0;
|
||||
|
||||
|
||||
return interface;
|
||||
}
|
||||
|
||||
|
@ -65,13 +65,13 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
|
|||
grub_efi_status_t status;
|
||||
grub_efi_handle_t *buffer;
|
||||
grub_efi_uintn_t buffer_size = 8 * sizeof (grub_efi_handle_t);
|
||||
|
||||
|
||||
buffer = grub_malloc (buffer_size);
|
||||
if (! buffer)
|
||||
return 0;
|
||||
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = b->locate_handle (search_type, protocol, search_key,
|
||||
status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
|
||||
&buffer_size, buffer);
|
||||
if (status == GRUB_EFI_BUFFER_TOO_SMALL)
|
||||
{
|
||||
|
@ -79,8 +79,8 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
|
|||
buffer = grub_malloc (buffer_size);
|
||||
if (! buffer)
|
||||
return 0;
|
||||
|
||||
status = b->locate_handle (search_type, protocol, search_key,
|
||||
|
||||
status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
|
||||
&buffer_size, buffer);
|
||||
}
|
||||
|
||||
|
@ -102,14 +102,14 @@ grub_efi_open_protocol (grub_efi_handle_t handle,
|
|||
grub_efi_boot_services_t *b;
|
||||
grub_efi_status_t status;
|
||||
void *interface;
|
||||
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = b->open_protocol (handle,
|
||||
protocol,
|
||||
&interface,
|
||||
grub_efi_image_handle,
|
||||
0,
|
||||
attributes);
|
||||
status = efi_call_6 (b->open_protocol, handle,
|
||||
protocol,
|
||||
&interface,
|
||||
grub_efi_image_handle,
|
||||
0,
|
||||
attributes);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return 0;
|
||||
|
||||
|
@ -127,13 +127,13 @@ grub_efi_set_text_mode (int on)
|
|||
/* No console control protocol instance available, assume it is
|
||||
already in text mode. */
|
||||
return 1;
|
||||
|
||||
if (c->get_mode (c, &mode, 0, 0) != GRUB_EFI_SUCCESS)
|
||||
|
||||
if (efi_call_4 (c->get_mode, c, &mode, 0, 0) != GRUB_EFI_SUCCESS)
|
||||
return 0;
|
||||
|
||||
new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS;
|
||||
if (mode != new_mode)
|
||||
if (c->set_mode (c, new_mode) != GRUB_EFI_SUCCESS)
|
||||
if (efi_call_2 (c->set_mode, c, new_mode) != GRUB_EFI_SUCCESS)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
@ -142,7 +142,7 @@ grub_efi_set_text_mode (int on)
|
|||
void
|
||||
grub_efi_stall (grub_efi_uintn_t microseconds)
|
||||
{
|
||||
grub_efi_system_table->boot_services->stall (microseconds);
|
||||
efi_call_1 (grub_efi_system_table->boot_services->stall, microseconds);
|
||||
}
|
||||
|
||||
grub_efi_loaded_image_t *
|
||||
|
@ -157,9 +157,25 @@ void
|
|||
grub_exit (void)
|
||||
{
|
||||
grub_efi_fini ();
|
||||
grub_efi_system_table->boot_services->exit (grub_efi_image_handle,
|
||||
GRUB_EFI_SUCCESS,
|
||||
0, 0);
|
||||
efi_call_4 (grub_efi_system_table->boot_services->exit,
|
||||
grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
|
||||
for (;;) ;
|
||||
}
|
||||
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
grub_efi_fini ();
|
||||
efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
|
||||
GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
grub_halt (void)
|
||||
{
|
||||
grub_efi_fini ();
|
||||
efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
|
||||
GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -167,12 +183,31 @@ grub_efi_exit_boot_services (grub_efi_uintn_t map_key)
|
|||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_status_t status;
|
||||
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = b->exit_boot_services (grub_efi_image_handle, map_key);
|
||||
status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle, map_key);
|
||||
return status == GRUB_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
|
||||
grub_efi_uintn_t descriptor_size,
|
||||
grub_efi_uint32_t descriptor_version,
|
||||
grub_efi_memory_descriptor_t *virtual_map)
|
||||
{
|
||||
grub_efi_runtime_services_t *r;
|
||||
grub_efi_status_t status;
|
||||
|
||||
r = grub_efi_system_table->runtime_services;
|
||||
status = efi_call_4 (r->set_virtual_address_map, memory_map_size,
|
||||
descriptor_size, descriptor_version, virtual_map);
|
||||
|
||||
if (status == GRUB_EFI_SUCCESS)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed");
|
||||
}
|
||||
|
||||
grub_uint32_t
|
||||
grub_get_rtc (void)
|
||||
{
|
||||
|
@ -180,7 +215,7 @@ grub_get_rtc (void)
|
|||
grub_efi_runtime_services_t *r;
|
||||
|
||||
r = grub_efi_system_table->runtime_services;
|
||||
if (r->get_time (&time, 0) != GRUB_EFI_SUCCESS)
|
||||
if (efi_call_2 (r->get_time, &time, 0) != GRUB_EFI_SUCCESS)
|
||||
/* What is possible in this case? */
|
||||
return 0;
|
||||
|
||||
|
@ -201,7 +236,7 @@ grub_arch_modules_addr (void)
|
|||
struct grub_pe32_section_table *section;
|
||||
struct grub_module_info *info;
|
||||
grub_uint16_t i;
|
||||
|
||||
|
||||
image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||
if (! image)
|
||||
return 0;
|
||||
|
@ -236,7 +271,7 @@ char *
|
|||
grub_efi_get_filename (grub_efi_device_path_t *dp)
|
||||
{
|
||||
char *name = 0;
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
|
||||
|
@ -260,7 +295,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp)
|
|||
}
|
||||
else
|
||||
size = 0;
|
||||
|
||||
|
||||
len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
|
||||
/ sizeof (grub_efi_char16_t));
|
||||
p = grub_realloc (name, size + len * 4 + 1);
|
||||
|
@ -353,8 +388,8 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
|||
grub_memcpy (&mmapped, dp, len);
|
||||
grub_printf ("/MMap(%x,%llx,%llx)",
|
||||
(unsigned) mmapped.memory_type,
|
||||
mmapped.start_address,
|
||||
mmapped.end_address);
|
||||
(unsigned long long) mmapped.start_address,
|
||||
(unsigned long long) mmapped.end_address);
|
||||
}
|
||||
break;
|
||||
case GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE:
|
||||
|
@ -406,17 +441,17 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
|||
grub_efi_expanded_acpi_device_path_t eacpi;
|
||||
grub_memcpy (&eacpi, dp, sizeof (eacpi));
|
||||
grub_printf ("/ACPI(");
|
||||
|
||||
|
||||
if (GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)[0] == '\0')
|
||||
grub_printf ("%x,", (unsigned) eacpi.hid);
|
||||
else
|
||||
grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp));
|
||||
|
||||
|
||||
if (GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)[0] == '\0')
|
||||
grub_printf ("%x,", (unsigned) eacpi.uid);
|
||||
else
|
||||
grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp));
|
||||
|
||||
|
||||
if (GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)[0] == '\0')
|
||||
grub_printf ("%x)", (unsigned) eacpi.cid);
|
||||
else
|
||||
|
@ -456,14 +491,15 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
|||
grub_efi_fibre_channel_device_path_t fc;
|
||||
grub_memcpy (&fc, dp, len);
|
||||
grub_printf ("/FibreChannel(%llx,%llx)",
|
||||
fc.wwn, fc.lun);
|
||||
(unsigned long long) fc.wwn,
|
||||
(unsigned long long) fc.lun);
|
||||
}
|
||||
break;
|
||||
case GRUB_EFI_1394_DEVICE_PATH_SUBTYPE:
|
||||
{
|
||||
grub_efi_1394_device_path_t firewire;
|
||||
grub_memcpy (&firewire, dp, len);
|
||||
grub_printf ("/1394(%llx)", firewire.guid);
|
||||
grub_printf ("/1394(%llx)", (unsigned long long) firewire.guid);
|
||||
}
|
||||
break;
|
||||
case GRUB_EFI_USB_DEVICE_PATH_SUBTYPE:
|
||||
|
@ -560,9 +596,9 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
|||
grub_memcpy (&ib, dp, len);
|
||||
grub_printf ("/InfiniBand(%x,%llx,%llx,%llx)",
|
||||
(unsigned) ib.port_gid[0], /* XXX */
|
||||
ib.remote_id,
|
||||
ib.target_port_id,
|
||||
ib.device_id);
|
||||
(unsigned long long) ib.remote_id,
|
||||
(unsigned long long) ib.target_port_id,
|
||||
(unsigned long long) ib.device_id);
|
||||
}
|
||||
break;
|
||||
case GRUB_EFI_UART_DEVICE_PATH_SUBTYPE:
|
||||
|
@ -570,7 +606,7 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
|||
grub_efi_uart_device_path_t uart;
|
||||
grub_memcpy (&uart, dp, len);
|
||||
grub_printf ("/UART(%llu,%u,%x,%x)",
|
||||
uart.baud_rate,
|
||||
(unsigned long long) uart.baud_rate,
|
||||
uart.data_bits,
|
||||
uart.parity,
|
||||
uart.stop_bits);
|
||||
|
@ -609,8 +645,8 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
|||
grub_memcpy (&hd, dp, len);
|
||||
grub_printf ("/HD(%u,%llx,%llx,%02x%02x%02x%02x%02x%02x%02x%02x,%x,%x)",
|
||||
hd.partition_number,
|
||||
hd.partition_start,
|
||||
hd.partition_size,
|
||||
(unsigned long long) hd.partition_start,
|
||||
(unsigned long long) hd.partition_size,
|
||||
(unsigned) hd.partition_signature[0],
|
||||
(unsigned) hd.partition_signature[1],
|
||||
(unsigned) hd.partition_signature[2],
|
||||
|
@ -629,8 +665,8 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
|||
grub_memcpy (&cd, dp, len);
|
||||
grub_printf ("/CD(%u,%llx,%llx)",
|
||||
cd.boot_entry,
|
||||
cd.partition_start,
|
||||
cd.partition_size);
|
||||
(unsigned long long) cd.partition_start,
|
||||
(unsigned long long) cd.partition_size);
|
||||
}
|
||||
break;
|
||||
case GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE:
|
||||
|
@ -712,10 +748,33 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
|||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
|
||||
break;
|
||||
|
||||
dp = (grub_efi_device_path_t *) ((char *) dp + len);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
grub_efi_finish_boot_services (void)
|
||||
{
|
||||
grub_efi_uintn_t mmap_size = 0;
|
||||
grub_efi_uintn_t map_key;
|
||||
grub_efi_uintn_t desc_size;
|
||||
grub_efi_uint32_t desc_version;
|
||||
void *mmap_buf = 0;
|
||||
|
||||
if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
|
||||
&desc_size, &desc_version) < 0)
|
||||
return 0;
|
||||
|
||||
mmap_buf = grub_malloc (mmap_size);
|
||||
|
||||
if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
|
||||
&desc_size, &desc_version) <= 0)
|
||||
return 0;
|
||||
|
||||
return grub_efi_exit_boot_services (map_key);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ void
|
|||
grub_efi_set_prefix (void)
|
||||
{
|
||||
grub_efi_loaded_image_t *image;
|
||||
|
||||
|
||||
image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||
if (image)
|
||||
{
|
||||
|
@ -52,12 +52,12 @@ grub_efi_set_prefix (void)
|
|||
|
||||
device = grub_efidisk_get_device_name (image->device_handle);
|
||||
file = grub_efi_get_filename (image->file_path);
|
||||
|
||||
|
||||
if (device && file)
|
||||
{
|
||||
char *p;
|
||||
char *prefix;
|
||||
|
||||
|
||||
/* Get the directory. */
|
||||
p = grub_strrchr (file, '/');
|
||||
if (p)
|
||||
|
@ -72,7 +72,7 @@ grub_efi_set_prefix (void)
|
|||
grub_free (prefix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
grub_free (device);
|
||||
grub_free (file);
|
||||
}
|
||||
|
@ -82,6 +82,5 @@ void
|
|||
grub_efi_fini (void)
|
||||
{
|
||||
grub_efidisk_fini ();
|
||||
grub_efi_mm_fini ();
|
||||
grub_console_fini ();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* mm.c - generic EFI memory management */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,14 +22,16 @@
|
|||
#include <grub/efi/api.h>
|
||||
#include <grub/efi/efi.h>
|
||||
|
||||
//#define DEBUG_MM
|
||||
|
||||
#define NEXT_MEMORY_DESCRIPTOR(desc, size) \
|
||||
((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
|
||||
|
||||
#define BYTES_TO_PAGES(bytes) ((bytes + 0xfff) >> 12)
|
||||
#define PAGES_TO_BYTES(pages) ((pages) << 12)
|
||||
|
||||
/* The size of a memory map obtained from the firmware. This must be
|
||||
a multiplier of 4KB. */
|
||||
#define MEMORY_MAP_SIZE 0x3000
|
||||
|
||||
/* Maintain the list of allocated pages. */
|
||||
struct allocated_page
|
||||
{
|
||||
|
@ -45,7 +47,8 @@ static struct allocated_page *allocated_pages = 0;
|
|||
|
||||
/* The minimum and maximum heap size for GRUB itself. */
|
||||
#define MIN_HEAP_SIZE 0x100000
|
||||
#define MAX_HEAP_SIZE (16 * 0x100000)
|
||||
#define MAX_HEAP_SIZE (1600 * 0x100000)
|
||||
|
||||
|
||||
/* Allocate pages. Return the pointer to the first of allocated pages. */
|
||||
void *
|
||||
|
@ -56,11 +59,13 @@ grub_efi_allocate_boot_pages (grub_efi_physical_address_t address,
|
|||
grub_efi_status_t status;
|
||||
grub_efi_boot_services_t *b;
|
||||
|
||||
#if GRUB_CPU_SIZEOF_VOID_P < 8
|
||||
#if GRUB_TARGET_SIZEOF_VOID_P < 8
|
||||
/* Limit the memory access to less than 4GB for 32-bit platforms. */
|
||||
if (address > 0xffffffff)
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
|
||||
#if GRUB_TARGET_SIZEOF_VOID_P < 8 || defined (MCMODEL_SMALL)
|
||||
if (address == 0)
|
||||
{
|
||||
type = GRUB_EFI_ALLOCATE_MAX_ADDRESS;
|
||||
|
@ -76,7 +81,7 @@ grub_efi_allocate_boot_pages (grub_efi_physical_address_t address,
|
|||
#endif
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = b->allocate_pages (type, GRUB_EFI_LOADER_DATA, pages, &address);
|
||||
status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return 0;
|
||||
|
||||
|
@ -84,13 +89,13 @@ grub_efi_allocate_boot_pages (grub_efi_physical_address_t address,
|
|||
{
|
||||
/* Uggh, the address 0 was allocated... This is too annoying,
|
||||
so reallocate another one. */
|
||||
status = b->allocate_pages (type, GRUB_EFI_LOADER_DATA, pages, &address);
|
||||
status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
|
||||
grub_efi_free_boot_pages (0, pages);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (void *)address;
|
||||
|
||||
return (void *) address;
|
||||
}
|
||||
|
||||
/* Free pages starting from ADDRESS. */
|
||||
|
@ -111,7 +116,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
|
|||
{
|
||||
address = grub_efi_allocate_boot_pages (address, pages);
|
||||
|
||||
if (address != 0 && allocated_pages)
|
||||
if (address && allocated_pages)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
|
@ -126,7 +131,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
|
|||
if (i == MAX_ALLOCATED_PAGES)
|
||||
grub_fatal ("too many page allocations");
|
||||
}
|
||||
|
||||
|
||||
return (void *) ((grub_addr_t) address);
|
||||
}
|
||||
|
||||
|
@ -140,7 +145,7 @@ grub_efi_free_pages (grub_efi_physical_address_t address,
|
|||
!= address))
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
|
||||
for (i = 0; i < MAX_ALLOCATED_PAGES; i++)
|
||||
if (allocated_pages[i].addr == address)
|
||||
{
|
||||
|
@ -171,9 +176,9 @@ grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size,
|
|||
map_key = &key;
|
||||
if (! descriptor_version)
|
||||
descriptor_version = &version;
|
||||
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
status = b->get_memory_map (memory_map_size, memory_map, map_key,
|
||||
status = efi_call_5 (b->get_memory_map, memory_map_size, memory_map, map_key,
|
||||
descriptor_size, descriptor_version);
|
||||
if (status == GRUB_EFI_SUCCESS)
|
||||
return 1;
|
||||
|
@ -191,13 +196,13 @@ sort_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
|||
{
|
||||
grub_efi_memory_descriptor_t *d1;
|
||||
grub_efi_memory_descriptor_t *d2;
|
||||
|
||||
|
||||
for (d1 = memory_map;
|
||||
d1 < memory_map_end;
|
||||
d1 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size))
|
||||
{
|
||||
grub_efi_memory_descriptor_t *max_desc = d1;
|
||||
|
||||
|
||||
for (d2 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size);
|
||||
d2 < memory_map_end;
|
||||
d2 = NEXT_MEMORY_DESCRIPTOR (d2, desc_size))
|
||||
|
@ -232,14 +237,14 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
|||
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
{
|
||||
if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
|
||||
#if GRUB_CPU_SIZEOF_VOID_P < 8
|
||||
#if GRUB_TARGET_SIZEOF_VOID_P < 8 || defined (MCMODEL_SMALL)
|
||||
&& desc->physical_start <= 0xffffffff
|
||||
#endif
|
||||
&& desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
|
||||
&& desc->num_pages != 0)
|
||||
{
|
||||
grub_memcpy (filtered_desc, desc, desc_size);
|
||||
|
||||
|
||||
/* Avoid less than 1MB, because some loaders seem to be confused. */
|
||||
if (desc->physical_start < 0x100000)
|
||||
{
|
||||
|
@ -247,8 +252,8 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
|||
- desc->physical_start);
|
||||
desc->physical_start = 0x100000;
|
||||
}
|
||||
|
||||
#if GRUB_CPU_SIZEOF_VOID_P < 8
|
||||
|
||||
#if GRUB_TARGET_SIZEOF_VOID_P < 8 || defined (MCMODEL_SMALL)
|
||||
if (BYTES_TO_PAGES (filtered_desc->physical_start)
|
||||
+ filtered_desc->num_pages
|
||||
> BYTES_TO_PAGES (0x100000000LL))
|
||||
|
@ -256,10 +261,10 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
|||
= (BYTES_TO_PAGES (0x100000000LL)
|
||||
- BYTES_TO_PAGES (filtered_desc->physical_start));
|
||||
#endif
|
||||
|
||||
|
||||
if (filtered_desc->num_pages == 0)
|
||||
continue;
|
||||
|
||||
|
||||
filtered_desc = NEXT_MEMORY_DESCRIPTOR (filtered_desc, desc_size);
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +280,7 @@ get_total_pages (grub_efi_memory_descriptor_t *memory_map,
|
|||
{
|
||||
grub_efi_memory_descriptor_t *desc;
|
||||
grub_efi_uint64_t total = 0;
|
||||
|
||||
|
||||
for (desc = memory_map;
|
||||
desc < memory_map_end;
|
||||
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
|
@ -343,7 +348,7 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
|||
{
|
||||
grub_efi_memory_descriptor_t *desc;
|
||||
int i;
|
||||
|
||||
|
||||
for (desc = memory_map, i = 0;
|
||||
desc < memory_map_end;
|
||||
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size), i++)
|
||||
|
@ -401,7 +406,7 @@ grub_efi_mm_init (void)
|
|||
grub_fatal ("cannot get memory map");
|
||||
|
||||
memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size);
|
||||
|
||||
|
||||
filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
|
||||
desc_size, memory_map_end);
|
||||
|
||||
|
@ -434,7 +439,7 @@ grub_efi_mm_init (void)
|
|||
NEXT_MEMORY_DESCRIPTOR (memory_map, map_size));
|
||||
grub_abort ();
|
||||
#endif
|
||||
|
||||
|
||||
/* Release the memory maps. */
|
||||
grub_efi_free_pages ((grub_addr_t) memory_map,
|
||||
2 * BYTES_TO_PAGES (memory_map_size));
|
||||
|
|
83
kern/elf.c
83
kern/elf.c
|
@ -1,7 +1,7 @@
|
|||
/* elf.c - load ELF files */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003,2004,2005,2006,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
|
||||
|
@ -61,21 +61,20 @@ grub_elf_file (grub_file_t file)
|
|||
{
|
||||
grub_elf_t elf;
|
||||
|
||||
elf = grub_malloc (sizeof (*elf));
|
||||
elf = grub_zalloc (sizeof (*elf));
|
||||
if (! elf)
|
||||
return 0;
|
||||
|
||||
elf->file = file;
|
||||
elf->phdrs = 0;
|
||||
|
||||
if (grub_file_seek (elf->file, 0) == (grub_off_t) -1)
|
||||
goto fail;
|
||||
|
||||
if (grub_file_read (elf->file, (char *) &elf->ehdr, sizeof (elf->ehdr))
|
||||
if (grub_file_read (elf->file, &elf->ehdr, sizeof (elf->ehdr))
|
||||
!= sizeof (elf->ehdr))
|
||||
{
|
||||
grub_error_push ();
|
||||
grub_error (GRUB_ERR_READ_ERROR, "Cannot read ELF header.");
|
||||
grub_error (GRUB_ERR_READ_ERROR, "cannot read ELF header");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -85,9 +84,8 @@ grub_elf_file (grub_file_t file)
|
|||
return elf;
|
||||
|
||||
fail:
|
||||
grub_error_push ();
|
||||
grub_elf_close (elf);
|
||||
grub_error_pop ();
|
||||
grub_free (elf->phdrs);
|
||||
grub_free (elf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -95,12 +93,17 @@ grub_elf_t
|
|||
grub_elf_open (const char *name)
|
||||
{
|
||||
grub_file_t file;
|
||||
grub_elf_t elf;
|
||||
|
||||
file = grub_gzfile_open (name, 1);
|
||||
if (! file)
|
||||
return 0;
|
||||
|
||||
return grub_elf_file (file);
|
||||
elf = grub_elf_file (file);
|
||||
if (! elf)
|
||||
grub_file_close (file);
|
||||
|
||||
return elf;
|
||||
}
|
||||
|
||||
|
||||
|
@ -119,9 +122,9 @@ grub_elf32_load_phdrs (grub_elf_t elf)
|
|||
|
||||
phdrs_size = elf->ehdr.ehdr32.e_phnum * elf->ehdr.ehdr32.e_phentsize;
|
||||
|
||||
grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%x.\n",
|
||||
grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n",
|
||||
(unsigned long long) elf->ehdr.ehdr32.e_phoff,
|
||||
phdrs_size);
|
||||
(unsigned long) phdrs_size);
|
||||
|
||||
elf->phdrs = grub_malloc (phdrs_size);
|
||||
if (! elf->phdrs)
|
||||
|
@ -131,7 +134,7 @@ grub_elf32_load_phdrs (grub_elf_t elf)
|
|||
|| (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size))
|
||||
{
|
||||
grub_error_push ();
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "Cannot read program headers");
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "cannot read program headers");
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -177,8 +180,10 @@ grub_elf32_size (grub_elf_t elf)
|
|||
|
||||
/* Run through the program headers to calculate the total memory size we
|
||||
* should claim. */
|
||||
auto int calcsize (grub_elf_t _elf, Elf32_Phdr *phdr, void *_arg);
|
||||
int calcsize (grub_elf_t UNUSED _elf, Elf32_Phdr *phdr, void UNUSED *_arg)
|
||||
auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf32_Phdr *phdr, void *_arg);
|
||||
int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)),
|
||||
Elf32_Phdr *phdr,
|
||||
void *_arg __attribute__ ((unused)))
|
||||
{
|
||||
/* Only consider loadable segments. */
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
|
@ -195,14 +200,14 @@ grub_elf32_size (grub_elf_t elf)
|
|||
|
||||
if (nr_phdrs == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_OS, "No program headers present");
|
||||
grub_error (GRUB_ERR_BAD_OS, "no program headers present");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (segments_end < segments_start)
|
||||
{
|
||||
/* Very bad addresses. */
|
||||
grub_error (GRUB_ERR_BAD_OS, "Bad program header load addresses");
|
||||
grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -224,14 +229,15 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
|
|||
{
|
||||
grub_elf32_load_hook_t load_hook = (grub_elf32_load_hook_t) hook;
|
||||
grub_addr_t load_addr;
|
||||
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
return 0;
|
||||
int do_load = 1;
|
||||
|
||||
load_addr = phdr->p_paddr;
|
||||
if (load_hook && load_hook (phdr, &load_addr))
|
||||
if (load_hook && load_hook (phdr, &load_addr, &do_load))
|
||||
return 1;
|
||||
|
||||
if (! do_load)
|
||||
return 0;
|
||||
|
||||
if (load_addr < load_base)
|
||||
load_base = load_addr;
|
||||
|
||||
|
@ -243,7 +249,7 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
|
|||
{
|
||||
grub_error_push ();
|
||||
return grub_error (GRUB_ERR_BAD_OS,
|
||||
"Invalid offset in program header.");
|
||||
"invalid offset in program header");
|
||||
}
|
||||
|
||||
if (phdr->p_filesz)
|
||||
|
@ -255,8 +261,8 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
|
|||
/* XXX How can we free memory from `load_hook'? */
|
||||
grub_error_push ();
|
||||
return grub_error (GRUB_ERR_BAD_OS,
|
||||
"Couldn't read segment from file: "
|
||||
"wanted 0x%lx bytes; read 0x%lx bytes.",
|
||||
"couldn't read segment from file: "
|
||||
"wanted 0x%lx bytes; read 0x%lx bytes",
|
||||
phdr->p_filesz, read);
|
||||
}
|
||||
}
|
||||
|
@ -297,9 +303,9 @@ grub_elf64_load_phdrs (grub_elf_t elf)
|
|||
|
||||
phdrs_size = elf->ehdr.ehdr64.e_phnum * elf->ehdr.ehdr64.e_phentsize;
|
||||
|
||||
grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%x.\n",
|
||||
grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n",
|
||||
(unsigned long long) elf->ehdr.ehdr64.e_phoff,
|
||||
phdrs_size);
|
||||
(unsigned long) phdrs_size);
|
||||
|
||||
elf->phdrs = grub_malloc (phdrs_size);
|
||||
if (! elf->phdrs)
|
||||
|
@ -309,7 +315,7 @@ grub_elf64_load_phdrs (grub_elf_t elf)
|
|||
|| (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size))
|
||||
{
|
||||
grub_error_push ();
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "Cannot read program headers");
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "cannot read program headers");
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -355,8 +361,10 @@ grub_elf64_size (grub_elf_t elf)
|
|||
|
||||
/* Run through the program headers to calculate the total memory size we
|
||||
* should claim. */
|
||||
auto int calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg);
|
||||
int calcsize (grub_elf_t UNUSED _elf, Elf64_Phdr *phdr, void UNUSED *_arg)
|
||||
auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg);
|
||||
int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)),
|
||||
Elf64_Phdr *phdr,
|
||||
void *_arg __attribute__ ((unused)))
|
||||
{
|
||||
/* Only consider loadable segments. */
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
|
@ -373,14 +381,14 @@ grub_elf64_size (grub_elf_t elf)
|
|||
|
||||
if (nr_phdrs == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_OS, "No program headers present");
|
||||
grub_error (GRUB_ERR_BAD_OS, "no program headers present");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (segments_end < segments_start)
|
||||
{
|
||||
/* Very bad addresses. */
|
||||
grub_error (GRUB_ERR_BAD_OS, "Bad program header load addresses");
|
||||
grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -403,14 +411,15 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
|
|||
{
|
||||
grub_elf64_load_hook_t load_hook = (grub_elf64_load_hook_t) hook;
|
||||
grub_addr_t load_addr;
|
||||
|
||||
if (phdr->p_type != PT_LOAD)
|
||||
return 0;
|
||||
int do_load = 1;
|
||||
|
||||
load_addr = phdr->p_paddr;
|
||||
if (load_hook && load_hook (phdr, &load_addr))
|
||||
if (load_hook && load_hook (phdr, &load_addr, &do_load))
|
||||
return 1;
|
||||
|
||||
if (! do_load)
|
||||
return 0;
|
||||
|
||||
if (load_addr < load_base)
|
||||
load_base = load_addr;
|
||||
|
||||
|
@ -422,7 +431,7 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
|
|||
{
|
||||
grub_error_push ();
|
||||
return grub_error (GRUB_ERR_BAD_OS,
|
||||
"Invalid offset in program header.");
|
||||
"invalid offset in program header");
|
||||
}
|
||||
|
||||
if (phdr->p_filesz)
|
||||
|
@ -434,8 +443,8 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
|
|||
/* XXX How can we free memory from `load_hook'? */
|
||||
grub_error_push ();
|
||||
return grub_error (GRUB_ERR_BAD_OS,
|
||||
"Couldn't read segment from file: "
|
||||
"wanted 0x%lx bytes; read 0x%lx bytes.",
|
||||
"couldn't read segment from file: "
|
||||
"wanted 0x%lx bytes; read 0x%lx bytes",
|
||||
phdr->p_filesz, read);
|
||||
}
|
||||
}
|
||||
|
|
93
kern/env.c
93
kern/env.c
|
@ -1,7 +1,7 @@
|
|||
/* env.c - Environment variables */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2005,2006,2007,2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003,2005,2006,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
|
||||
|
@ -29,7 +29,7 @@ struct grub_env_context
|
|||
{
|
||||
/* A hash table for variables. */
|
||||
struct grub_env_var *vars[HASHSZ];
|
||||
|
||||
|
||||
/* One level deeper on the stack. */
|
||||
struct grub_env_context *prev;
|
||||
};
|
||||
|
@ -75,16 +75,15 @@ grub_env_find (const char *name)
|
|||
}
|
||||
|
||||
grub_err_t
|
||||
grub_env_context_open (void)
|
||||
grub_env_context_open (int export)
|
||||
{
|
||||
struct grub_env_context *context;
|
||||
int i;
|
||||
|
||||
context = grub_malloc (sizeof (*context));
|
||||
context = grub_zalloc (sizeof (*context));
|
||||
if (! context)
|
||||
return grub_errno;
|
||||
|
||||
grub_memset (context, 0, sizeof (*context));
|
||||
context->prev = current_context;
|
||||
current_context = context;
|
||||
|
||||
|
@ -92,21 +91,22 @@ grub_env_context_open (void)
|
|||
for (i = 0; i < HASHSZ; i++)
|
||||
{
|
||||
struct grub_env_var *var;
|
||||
|
||||
|
||||
for (var = context->prev->vars[i]; var; var = var->next)
|
||||
{
|
||||
if (var->type == GRUB_ENV_VAR_GLOBAL)
|
||||
if (export && var->type == GRUB_ENV_VAR_GLOBAL)
|
||||
{
|
||||
if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_env_context_close ();
|
||||
return grub_errno;
|
||||
}
|
||||
grub_env_export (var->name);
|
||||
grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -118,15 +118,18 @@ grub_env_context_close (void)
|
|||
|
||||
if (! current_context->prev)
|
||||
grub_fatal ("cannot close the initial context");
|
||||
|
||||
|
||||
/* Free the variables associated with this context. */
|
||||
for (i = 0; i < HASHSZ; i++)
|
||||
{
|
||||
struct grub_env_var *p, *q;
|
||||
|
||||
for (p = current_context->prev->vars[i]; p; p = q)
|
||||
|
||||
for (p = current_context->vars[i]; p; p = q)
|
||||
{
|
||||
q = p->next;
|
||||
grub_free (p->name);
|
||||
if (p->type != GRUB_ENV_VAR_DATA)
|
||||
grub_free (p->value);
|
||||
grub_free (p);
|
||||
}
|
||||
}
|
||||
|
@ -146,10 +149,10 @@ grub_env_insert (struct grub_env_context *context,
|
|||
int idx = grub_env_hashval (var->name);
|
||||
|
||||
/* Insert the variable into the hashtable. */
|
||||
var->prevp = &context->vars[idx];;
|
||||
var->prevp = &context->vars[idx];
|
||||
var->next = context->vars[idx];
|
||||
if (var->next)
|
||||
var->next->prevp = &var;
|
||||
var->next->prevp = &(var->next);
|
||||
context->vars[idx] = var;
|
||||
}
|
||||
|
||||
|
@ -168,8 +171,16 @@ grub_env_export (const char *name)
|
|||
struct grub_env_var *var;
|
||||
|
||||
var = grub_env_find (name);
|
||||
if (var)
|
||||
var->type = GRUB_ENV_VAR_GLOBAL;
|
||||
if (! var)
|
||||
{
|
||||
grub_err_t err;
|
||||
|
||||
err = grub_env_set (name, "");
|
||||
if (err)
|
||||
return err;
|
||||
var = grub_env_find (name);
|
||||
}
|
||||
var->type = GRUB_ENV_VAR_GLOBAL;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -189,7 +200,7 @@ grub_env_set (const char *name, const char *val)
|
|||
var->value = var->write_hook (var, val);
|
||||
else
|
||||
var->value = grub_strdup (val);
|
||||
|
||||
|
||||
if (! var->value)
|
||||
{
|
||||
var->value = old;
|
||||
|
@ -201,20 +212,18 @@ grub_env_set (const char *name, const char *val)
|
|||
}
|
||||
|
||||
/* The variable does not exist, so create a new one. */
|
||||
var = grub_malloc (sizeof (*var));
|
||||
var = grub_zalloc (sizeof (*var));
|
||||
if (! var)
|
||||
return grub_errno;
|
||||
|
||||
grub_memset (var, 0, sizeof (*var));
|
||||
|
||||
/* This is not necessary, because GRUB_ENV_VAR_LOCAL == 0. But leave
|
||||
this for readability. */
|
||||
var->type = GRUB_ENV_VAR_LOCAL;
|
||||
|
||||
|
||||
var->name = grub_strdup (name);
|
||||
if (! var->name)
|
||||
goto fail;
|
||||
|
||||
|
||||
var->value = grub_strdup (val);
|
||||
if (! var->value)
|
||||
goto fail;
|
||||
|
@ -235,7 +244,7 @@ char *
|
|||
grub_env_get (const char *name)
|
||||
{
|
||||
struct grub_env_var *var;
|
||||
|
||||
|
||||
var = grub_env_find (name);
|
||||
if (! var)
|
||||
return 0;
|
||||
|
@ -250,15 +259,16 @@ void
|
|||
grub_env_unset (const char *name)
|
||||
{
|
||||
struct grub_env_var *var;
|
||||
|
||||
|
||||
var = grub_env_find (name);
|
||||
if (! var)
|
||||
return;
|
||||
|
||||
/* XXX: It is not possible to unset variables with a read or write
|
||||
hook. */
|
||||
if (var->read_hook || var->write_hook)
|
||||
return;
|
||||
{
|
||||
grub_env_set (name, "");
|
||||
return;
|
||||
}
|
||||
|
||||
grub_env_remove (var);
|
||||
|
||||
|
@ -274,12 +284,12 @@ grub_env_iterate (int (*func) (struct grub_env_var *var))
|
|||
struct grub_env_sorted_var *sorted_list = 0;
|
||||
struct grub_env_sorted_var *sorted_var;
|
||||
int i;
|
||||
|
||||
|
||||
/* Add variables associated with this context into a sorted list. */
|
||||
for (i = 0; i < HASHSZ; i++)
|
||||
{
|
||||
struct grub_env_var *var;
|
||||
|
||||
|
||||
for (var = current_context->vars[i]; var; var = var->next)
|
||||
{
|
||||
struct grub_env_sorted_var *p, **q;
|
||||
|
@ -287,7 +297,7 @@ grub_env_iterate (int (*func) (struct grub_env_var *var))
|
|||
/* Ignore data slots. */
|
||||
if (var->type == GRUB_ENV_VAR_DATA)
|
||||
continue;
|
||||
|
||||
|
||||
sorted_var = grub_malloc (sizeof (*sorted_var));
|
||||
if (! sorted_var)
|
||||
goto fail;
|
||||
|
@ -299,7 +309,7 @@ grub_env_iterate (int (*func) (struct grub_env_var *var))
|
|||
if (grub_strcmp (p->var->name, var->name) > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
sorted_var->next = *q;
|
||||
*q = sorted_var;
|
||||
}
|
||||
|
@ -331,18 +341,13 @@ grub_register_variable_hook (const char *name,
|
|||
|
||||
if (! var)
|
||||
{
|
||||
char *val = grub_strdup ("");
|
||||
if (grub_env_set (name, "") != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
if (! val)
|
||||
return grub_errno;
|
||||
|
||||
if (grub_env_set (name, val) != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
var = grub_env_find (name);
|
||||
/* XXX Insert an assertion? */
|
||||
}
|
||||
|
||||
|
||||
var->read_hook = read_hook;
|
||||
var->write_hook = write_hook;
|
||||
|
||||
|
@ -357,7 +362,7 @@ mangle_data_slot_name (const char *name)
|
|||
mangled_name = grub_malloc (grub_strlen (name) + 2);
|
||||
if (! mangled_name)
|
||||
return 0;
|
||||
|
||||
|
||||
grub_sprintf (mangled_name, "\e%s", name);
|
||||
return mangled_name;
|
||||
}
|
||||
|
@ -381,11 +386,9 @@ grub_env_set_data_slot (const char *name, const void *ptr)
|
|||
}
|
||||
|
||||
/* The variable does not exist, so create a new one. */
|
||||
var = grub_malloc (sizeof (*var));
|
||||
var = grub_zalloc (sizeof (*var));
|
||||
if (! var)
|
||||
goto fail;
|
||||
|
||||
grub_memset (var, 0, sizeof (*var));
|
||||
|
||||
var->type = GRUB_ENV_VAR_DATA;
|
||||
var->name = mangled_name;
|
||||
|
@ -406,7 +409,7 @@ grub_env_get_data_slot (const char *name)
|
|||
{
|
||||
char *mangled_name;
|
||||
void *ptr = 0;
|
||||
|
||||
|
||||
mangled_name = mangle_data_slot_name (name);
|
||||
if (! mangled_name)
|
||||
goto fail;
|
||||
|
@ -415,7 +418,7 @@ grub_env_get_data_slot (const char *name)
|
|||
grub_free (mangled_name);
|
||||
|
||||
fail:
|
||||
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -423,7 +426,7 @@ void
|
|||
grub_env_unset_data_slot (const char *name)
|
||||
{
|
||||
char *mangled_name;
|
||||
|
||||
|
||||
mangled_name = mangle_data_slot_name (name);
|
||||
if (! mangled_name)
|
||||
return;
|
||||
|
|
25
kern/err.c
25
kern/err.c
|
@ -1,7 +1,7 @@
|
|||
/* err.c - error handling routines */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,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
|
||||
|
@ -20,6 +20,7 @@
|
|||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <stdarg.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#define GRUB_MAX_ERRMSG 256
|
||||
#define GRUB_ERROR_STACK_SIZE 10
|
||||
|
@ -40,11 +41,11 @@ grub_err_t
|
|||
grub_error (grub_err_t n, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
|
||||
grub_errno = n;
|
||||
|
||||
va_start (ap, fmt);
|
||||
grub_vsprintf (grub_errmsg, fmt, ap);
|
||||
grub_vsprintf (grub_errmsg, _(fmt), ap);
|
||||
va_end (ap);
|
||||
|
||||
return n;
|
||||
|
@ -56,7 +57,7 @@ grub_fatal (const char *fmt, ...)
|
|||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
grub_vprintf (fmt, ap);
|
||||
grub_vprintf (_(fmt), ap);
|
||||
va_end (ap);
|
||||
|
||||
grub_abort ();
|
||||
|
@ -73,7 +74,7 @@ grub_error_push (void)
|
|||
grub_memcpy (grub_error_stack_items[grub_error_stack_pos].errmsg,
|
||||
grub_errmsg,
|
||||
sizeof (grub_errmsg));
|
||||
|
||||
|
||||
/* Advance to next error stack position. */
|
||||
grub_error_stack_pos++;
|
||||
}
|
||||
|
@ -96,19 +97,19 @@ grub_error_pop (void)
|
|||
{
|
||||
/* Pop error message from error stack to current active error. */
|
||||
grub_error_stack_pos--;
|
||||
|
||||
|
||||
grub_errno = grub_error_stack_items[grub_error_stack_pos].errno;
|
||||
grub_memcpy (grub_errmsg,
|
||||
grub_error_stack_items[grub_error_stack_pos].errmsg,
|
||||
sizeof (grub_errmsg));
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is no more items on error stack, reset to no error state. */
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -121,14 +122,14 @@ grub_print_error (void)
|
|||
do
|
||||
{
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
grub_printf ("error: %s\n", grub_errmsg);
|
||||
}
|
||||
grub_err_printf (_("error: %s.\n"), grub_errmsg);
|
||||
}
|
||||
while (grub_error_pop ());
|
||||
|
||||
|
||||
/* If there was an assert while using error stack, report about it. */
|
||||
if (grub_error_stack_assert)
|
||||
{
|
||||
grub_printf ("assert: error stack overflow detected!\n");
|
||||
grub_err_printf ("assert: error stack overflow detected!\n");
|
||||
grub_error_stack_assert = 0;
|
||||
}
|
||||
}
|
||||
|
|
36
kern/file.c
36
kern/file.c
|
@ -1,7 +1,7 @@
|
|||
/* file.c - file I/O functions */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,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
|
||||
|
@ -32,7 +32,7 @@ grub_file_get_device_name (const char *name)
|
|||
{
|
||||
char *p = grub_strchr (name, ')');
|
||||
char *ret;
|
||||
|
||||
|
||||
if (! p)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FILENAME, "missing `)'");
|
||||
|
@ -42,7 +42,7 @@ grub_file_get_device_name (const char *name)
|
|||
ret = (char *) grub_malloc (p - name);
|
||||
if (! ret)
|
||||
return 0;
|
||||
|
||||
|
||||
grub_memcpy (ret, name + 1, p - name - 1);
|
||||
ret[p - name - 1] = '\0';
|
||||
return ret;
|
||||
|
@ -74,16 +74,13 @@ grub_file_open (const char *name)
|
|||
grub_free (device_name);
|
||||
if (! device)
|
||||
goto fail;
|
||||
|
||||
file = (grub_file_t) grub_malloc (sizeof (*file));
|
||||
|
||||
file = (grub_file_t) grub_zalloc (sizeof (*file));
|
||||
if (! file)
|
||||
goto fail;
|
||||
|
||||
|
||||
file->device = device;
|
||||
file->offset = 0;
|
||||
file->data = 0;
|
||||
file->read_hook = 0;
|
||||
|
||||
|
||||
if (device->disk && file_name[0] != '/')
|
||||
/* This is a block list. */
|
||||
file->fs = &grub_fs_blocklist;
|
||||
|
@ -106,25 +103,32 @@ grub_file_open (const char *name)
|
|||
/* if (net) grub_net_close (net); */
|
||||
|
||||
grub_free (file);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_ssize_t
|
||||
grub_file_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
grub_file_read (grub_file_t file, void *buf, grub_size_t len)
|
||||
{
|
||||
grub_ssize_t res;
|
||||
|
||||
|
||||
if (file->offset > file->size)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"attempt to read past the end of file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len == 0 || len > file->size - file->offset)
|
||||
len = file->size - file->offset;
|
||||
|
||||
/* Prevent an overflow. */
|
||||
if ((grub_ssize_t) len < 0)
|
||||
len >>= 1;
|
||||
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
res = (file->fs->read) (file, buf, len);
|
||||
if (res > 0)
|
||||
file->offset += res;
|
||||
|
@ -155,7 +159,7 @@ grub_file_seek (grub_file_t file, grub_off_t offset)
|
|||
"attempt to seek outside of the file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
old = file->offset;
|
||||
file->offset = offset;
|
||||
return old;
|
||||
|
|
28
kern/fs.c
28
kern/fs.c
|
@ -65,10 +65,11 @@ grub_fs_t
|
|||
grub_fs_probe (grub_device_t device)
|
||||
{
|
||||
grub_fs_t p;
|
||||
auto int dummy_func (const char *filename, int dir);
|
||||
auto int dummy_func (const char *filename,
|
||||
const struct grub_dirhook_info *info);
|
||||
|
||||
int dummy_func (const char *filename __attribute__ ((unused)),
|
||||
int dir __attribute__ ((unused)))
|
||||
const struct grub_dirhook_info *info __attribute__ ((unused)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -99,24 +100,24 @@ grub_fs_probe (grub_device_t device)
|
|||
if (grub_fs_autoload_hook && count == 0)
|
||||
{
|
||||
count++;
|
||||
|
||||
|
||||
while (grub_fs_autoload_hook ())
|
||||
{
|
||||
p = grub_fs_list;
|
||||
|
||||
|
||||
(p->dir) (device, "/", dummy_func);
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
{
|
||||
count--;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
if (grub_errno != GRUB_ERR_BAD_FS)
|
||||
{
|
||||
count--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -148,7 +149,7 @@ grub_fs_blocklist_open (grub_file_t file, const char *name)
|
|||
unsigned i;
|
||||
grub_disk_t disk = file->device->disk;
|
||||
struct grub_fs_block *blocks;
|
||||
|
||||
|
||||
/* First, count the number of blocks. */
|
||||
do
|
||||
{
|
||||
|
@ -160,7 +161,7 @@ grub_fs_blocklist_open (grub_file_t file, const char *name)
|
|||
while (p);
|
||||
|
||||
/* Allocate a block list. */
|
||||
blocks = grub_malloc (sizeof (struct grub_fs_block) * (num + 1));
|
||||
blocks = grub_zalloc (sizeof (struct grub_fs_block) * (num + 1));
|
||||
if (! blocks)
|
||||
return 0;
|
||||
|
||||
|
@ -178,8 +179,6 @@ grub_fs_blocklist_open (grub_file_t file, const char *name)
|
|||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
blocks[i].offset = 0;
|
||||
|
||||
p++;
|
||||
blocks[i].length = grub_strtoul (p, &p, 0);
|
||||
|
@ -197,14 +196,13 @@ grub_fs_blocklist_open (grub_file_t file, const char *name)
|
|||
grub_error (GRUB_ERR_BAD_FILENAME, "beyond the total sectors");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
file->size += (blocks[i].length << GRUB_DISK_SECTOR_BITS);
|
||||
p++;
|
||||
}
|
||||
|
||||
blocks[i].length = 0;
|
||||
file->data = blocks;
|
||||
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
|
@ -235,11 +233,11 @@ grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len)
|
|||
if (((size + offset + GRUB_DISK_SECTOR_SIZE - 1)
|
||||
>> GRUB_DISK_SECTOR_BITS) > p->length - sector)
|
||||
size = ((p->length - sector) << GRUB_DISK_SECTOR_BITS) - offset;
|
||||
|
||||
|
||||
if (grub_disk_read (file->device->disk, p->offset + sector, offset,
|
||||
size, buf) != GRUB_ERR_NONE)
|
||||
return -1;
|
||||
|
||||
|
||||
ret += size;
|
||||
len -= size;
|
||||
sector -= ((size + offset) >> GRUB_DISK_SECTOR_BITS);
|
||||
|
|
39
kern/generic/millisleep.c
Normal file
39
kern/generic/millisleep.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* millisleep.c - generic millisleep function.
|
||||
* The generic implementation of these functions can be used for architectures
|
||||
* or platforms that do not have a more specialized implementation. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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/misc.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
void
|
||||
grub_millisleep (grub_uint32_t ms)
|
||||
{
|
||||
grub_uint64_t start;
|
||||
|
||||
start = grub_get_time_ms ();
|
||||
|
||||
/* Instead of setting an end time and looping while the current time is
|
||||
less than that, comparing the elapsed sleep time with the desired sleep
|
||||
time handles the (unlikely!) case that the timer would wrap around
|
||||
during the sleep. */
|
||||
|
||||
while (grub_get_time_ms () - start < ms)
|
||||
grub_cpu_idle ();
|
||||
}
|
37
kern/generic/rtc_get_time_ms.c
Normal file
37
kern/generic/rtc_get_time_ms.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* rtc_get_time_ms.c - get_time_ms implementation using platform RTC.
|
||||
* The generic implementation of these functions can be used for architectures
|
||||
* or platforms that do not have a more specialized implementation. */
|
||||
/*
|
||||
* 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/time.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
/* Calculate the time in milliseconds since the epoch based on the RTC. */
|
||||
grub_uint64_t
|
||||
grub_rtc_get_time_ms (void)
|
||||
{
|
||||
/* By dimensional analysis:
|
||||
|
||||
1000 ms N rtc ticks 1 s
|
||||
------- * ----------- * ----------- = 1000*N/T ms
|
||||
1 s 1 T rtc ticks
|
||||
*/
|
||||
grub_uint64_t ticks_ms_per_sec = ((grub_uint64_t) 1000) * grub_get_rtc ();
|
||||
return grub_divmod64 (ticks_ms_per_sec, GRUB_TICKS_PER_SECOND, 0);
|
||||
}
|
64
kern/handler.c
Normal file
64
kern/handler.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* handler.c - grub handler function */
|
||||
/*
|
||||
* 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/handler.h>
|
||||
|
||||
grub_handler_class_t grub_handler_class_list;
|
||||
|
||||
void
|
||||
grub_handler_register (grub_handler_class_t class, grub_handler_t handler)
|
||||
{
|
||||
int first_handler = (class->handler_list == 0);
|
||||
|
||||
grub_list_push (GRUB_AS_LIST_P (&class->handler_list),
|
||||
GRUB_AS_LIST (handler));
|
||||
|
||||
if (first_handler)
|
||||
{
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_handler_class_list),
|
||||
GRUB_AS_LIST (class));
|
||||
grub_handler_set_current (class, handler);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_handler_unregister (grub_handler_class_t class, grub_handler_t handler)
|
||||
{
|
||||
grub_list_remove (GRUB_AS_LIST_P (&class->handler_list),
|
||||
GRUB_AS_LIST (handler));
|
||||
|
||||
if (class->handler_list == 0)
|
||||
grub_list_remove (GRUB_AS_LIST_P (&grub_handler_class_list),
|
||||
GRUB_AS_LIST (class));
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_handler_set_current (grub_handler_class_t class, grub_handler_t handler)
|
||||
{
|
||||
if (class->cur_handler && class->cur_handler->fini)
|
||||
if ((class->cur_handler->fini) () != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
if (handler->init)
|
||||
if ((handler->init) () != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
class->cur_handler = handler;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,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
|
||||
|
@ -33,6 +33,8 @@
|
|||
#include <grub/time.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/cpu/io.h>
|
||||
#include <grub/cpu/kernel.h>
|
||||
#include <grub/cpu/tsc.h>
|
||||
|
||||
#define GRUB_FLOPPY_REG_DIGITAL_OUTPUT 0x3f2
|
||||
|
||||
|
@ -41,15 +43,11 @@ extern char _end[];
|
|||
|
||||
grub_addr_t grub_os_area_addr;
|
||||
grub_size_t grub_os_area_size;
|
||||
grub_size_t grub_lower_mem, grub_upper_mem;
|
||||
|
||||
/* FIXME: we need interrupts to do this right */
|
||||
static grub_uint32_t grub_time_tics = 0;
|
||||
|
||||
grub_uint32_t
|
||||
grub_get_rtc (void)
|
||||
{
|
||||
return grub_time_tics;
|
||||
grub_fatal ("grub_get_rtc() is not implemented.\n");
|
||||
}
|
||||
|
||||
/* Stop the floppy drive from spinning, so that other software is
|
||||
|
@ -60,30 +58,13 @@ grub_stop_floppy (void)
|
|||
grub_outb (0, GRUB_FLOPPY_REG_DIGITAL_OUTPUT);
|
||||
}
|
||||
|
||||
void
|
||||
grub_millisleep (grub_uint32_t ms __attribute__ ((unused)))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
grub_exit (void)
|
||||
{
|
||||
grub_printf ("grub_exit() is not implemented.\n");
|
||||
grub_stop ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
grub_printf ("grub_reboot() is not implemented.\n");
|
||||
grub_stop ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_halt (int no_apm __attribute__ ((unused)))
|
||||
{
|
||||
grub_printf ("grub_halt() is not implemented.\n");
|
||||
grub_stop ();
|
||||
/* We can't use grub_fatal() in this function. This would create an infinite
|
||||
loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */
|
||||
while (1)
|
||||
grub_cpu_idle ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -92,41 +73,24 @@ grub_arch_sync_caches (void *address __attribute__ ((unused)),
|
|||
{
|
||||
}
|
||||
|
||||
static char *
|
||||
make_install_device (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
/* Initialize the console as early as possible. */
|
||||
grub_console_init ();
|
||||
grub_vga_text_init ();
|
||||
|
||||
grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE;
|
||||
grub_upper_mem = 0;
|
||||
|
||||
auto int heap_init (mem_region_t);
|
||||
int heap_init (mem_region_t mem_region)
|
||||
auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t, grub_uint64_t, grub_uint32_t);
|
||||
int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
|
||||
{
|
||||
grub_uint64_t addr = mem_region->addr;
|
||||
grub_uint64_t size = mem_region->size;
|
||||
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 4
|
||||
/* Restrict ourselves to 32-bit memory space. */
|
||||
if (addr > ULONG_MAX)
|
||||
{
|
||||
grub_upper_mem = ULONG_MAX;
|
||||
return 0;
|
||||
}
|
||||
if (addr + size > ULONG_MAX)
|
||||
size = ULONG_MAX - addr;
|
||||
if (addr > GRUB_ULONG_MAX)
|
||||
return 0;
|
||||
if (addr + size > GRUB_ULONG_MAX)
|
||||
size = GRUB_ULONG_MAX - addr;
|
||||
#endif
|
||||
|
||||
grub_upper_mem = grub_max (grub_upper_mem, addr + size);
|
||||
|
||||
if (mem_region->type != GRUB_LINUXBIOS_MEMORY_AVAILABLE)
|
||||
if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
|
||||
return 0;
|
||||
|
||||
/* Avoid the lower memory. */
|
||||
|
@ -154,33 +118,38 @@ grub_machine_init (void)
|
|||
quarter);
|
||||
}
|
||||
else
|
||||
grub_mm_init_region ((void *) addr, (grub_size_t) size);
|
||||
grub_mm_init_region ((void *) (grub_addr_t) addr, (grub_size_t) size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_available_iterate (heap_init);
|
||||
grub_machine_mmap_init ();
|
||||
grub_machine_mmap_iterate (heap_init);
|
||||
|
||||
/* This variable indicates size, not offset. */
|
||||
grub_upper_mem -= GRUB_MEMORY_MACHINE_UPPER_START;
|
||||
grub_tsc_init ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
{
|
||||
/* Initialize the prefix. */
|
||||
grub_env_set ("prefix", make_install_device ());
|
||||
grub_env_set ("prefix", grub_prefix);
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_fini (void)
|
||||
{
|
||||
grub_console_fini ();
|
||||
grub_vga_text_fini ();
|
||||
grub_stop_floppy ();
|
||||
}
|
||||
|
||||
/* Return the end of the core image. */
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
return ALIGN_UP(_end, GRUB_MOD_ALIGN);
|
||||
#ifdef GRUB_MACHINE_QEMU
|
||||
return grub_core_entry_addr + grub_kernel_image_size;
|
||||
#else
|
||||
return ALIGN_UP((grub_addr_t) _end, GRUB_MOD_ALIGN);
|
||||
#endif
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
#include <grub/machine/memory.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t))
|
||||
|
@ -27,9 +28,9 @@ grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t))
|
|||
grub_linuxbios_table_item_t table_item;
|
||||
|
||||
auto int check_signature (grub_linuxbios_table_header_t);
|
||||
int check_signature (grub_linuxbios_table_header_t table_header)
|
||||
int check_signature (grub_linuxbios_table_header_t tbl_header)
|
||||
{
|
||||
if (! grub_memcmp (table_header->signature, "LBIO", 4))
|
||||
if (! grub_memcmp (tbl_header->signature, "LBIO", 4))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -37,11 +38,13 @@ grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t))
|
|||
|
||||
/* Assuming table_header is aligned to its size (8 bytes). */
|
||||
|
||||
for (table_header = 0x500; table_header < 0x1000; table_header++)
|
||||
for (table_header = (grub_linuxbios_table_header_t) 0x500;
|
||||
table_header < (grub_linuxbios_table_header_t) 0x1000; table_header++)
|
||||
if (check_signature (table_header))
|
||||
goto signature_found;
|
||||
|
||||
for (table_header = 0xf0000; table_header < 0x100000; table_header++)
|
||||
for (table_header = (grub_linuxbios_table_header_t) 0xf0000;
|
||||
table_header < (grub_linuxbios_table_header_t) 0x100000; table_header++)
|
||||
if (check_signature (table_header))
|
||||
goto signature_found;
|
||||
|
||||
|
@ -60,8 +63,8 @@ signature_found:
|
|||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_available_iterate (int (*hook) (mem_region_t))
|
||||
void
|
||||
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
|
||||
{
|
||||
mem_region_t mem_region;
|
||||
|
||||
|
@ -74,10 +77,16 @@ grub_available_iterate (int (*hook) (mem_region_t))
|
|||
mem_region =
|
||||
(mem_region_t) ((long) table_item +
|
||||
sizeof (struct grub_linuxbios_table_item));
|
||||
for (; (long) mem_region < (long) table_item + (long) table_item->size;
|
||||
mem_region++)
|
||||
if (hook (mem_region))
|
||||
return 1;
|
||||
while ((long) mem_region < (long) table_item + (long) table_item->size)
|
||||
{
|
||||
if (hook (mem_region->addr, mem_region->size,
|
||||
/* Multiboot mmaps match with the coreboot mmap definition.
|
||||
Therefore, we can just pass type through. */
|
||||
mem_region->type))
|
||||
return 1;
|
||||
|
||||
mem_region++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2005,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
|
||||
|
@ -16,11 +16,10 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define ASM_FILE 1
|
||||
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/cpu/linux.h>
|
||||
#include <grub/cpu/kernel.h>
|
||||
#include <multiboot.h>
|
||||
#include <multiboot2.h>
|
||||
|
||||
|
@ -35,36 +34,49 @@
|
|||
.file "startup.S"
|
||||
.text
|
||||
.globl start, _start
|
||||
start:
|
||||
_start:
|
||||
jmp codestart
|
||||
|
||||
/*
|
||||
* This is a special data area at a fixed offset from the beginning.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_CPU_PREFIX
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_CPU_DATA_END
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
|
||||
*/
|
||||
.p2align 2 /* force 4-byte alignment */
|
||||
multiboot_header:
|
||||
/* magic */
|
||||
.long 0x1BADB002
|
||||
/* flags */
|
||||
.long 0
|
||||
.long MULTIBOOT_MEMORY_INFO
|
||||
/* checksum */
|
||||
.long -0x1BADB002
|
||||
#endif
|
||||
.long -0x1BADB002 - MULTIBOOT_MEMORY_INFO
|
||||
|
||||
codestart:
|
||||
cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
|
||||
jne 0f
|
||||
movl %ebx, EXT_C(startup_multiboot_info)
|
||||
0:
|
||||
|
||||
start:
|
||||
_start:
|
||||
/* initialize the stack */
|
||||
movl $GRUB_MEMORY_MACHINE_PROT_STACK, %esp
|
||||
|
||||
/* jump to the main body of C code */
|
||||
jmp EXT_C(grub_main)
|
||||
|
||||
/*
|
||||
* This call is special... it never returns... in fact it should simply
|
||||
* hang at this point!
|
||||
*/
|
||||
FUNCTION(grub_stop)
|
||||
hlt
|
||||
jmp EXT_C(grub_stop)
|
||||
|
||||
/*
|
||||
* prot_to_real and associated structures (but NOT real_to_prot, that is
|
||||
* only needed for BIOS gates).
|
|
@ -1,7 +1,7 @@
|
|||
/* dl-386.c - arch-dependent part of loadable module support */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,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
|
||||
|
@ -26,7 +26,7 @@
|
|||
grub_err_t
|
||||
grub_arch_dl_check_header (void *ehdr)
|
||||
{
|
||||
Elf32_Ehdr *e = ehdr;
|
||||
Elf_Ehdr *e = ehdr;
|
||||
|
||||
/* Check the magic numbers. */
|
||||
if (e->e_ident[EI_CLASS] != ELFCLASS32
|
||||
|
@ -41,28 +41,26 @@ grub_arch_dl_check_header (void *ehdr)
|
|||
grub_err_t
|
||||
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
||||
{
|
||||
Elf32_Ehdr *e = ehdr;
|
||||
Elf32_Shdr *s;
|
||||
Elf32_Sym *symtab;
|
||||
Elf32_Word entsize;
|
||||
Elf_Ehdr *e = ehdr;
|
||||
Elf_Shdr *s;
|
||||
Elf_Word entsize;
|
||||
unsigned i;
|
||||
|
||||
/* Find a symbol table. */
|
||||
for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
|
||||
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_SYMTAB)
|
||||
break;
|
||||
|
||||
if (i == e->e_shnum)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
|
||||
|
||||
symtab = (Elf32_Sym *) ((char *) e + s->sh_offset);
|
||||
|
||||
entsize = s->sh_entsize;
|
||||
|
||||
for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
|
||||
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_REL)
|
||||
{
|
||||
grub_dl_segment_t seg;
|
||||
|
@ -74,32 +72,32 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
|||
|
||||
if (seg)
|
||||
{
|
||||
Elf32_Rel *rel, *max;
|
||||
|
||||
for (rel = (Elf32_Rel *) ((char *) e + s->sh_offset),
|
||||
Elf_Rel *rel, *max;
|
||||
|
||||
for (rel = (Elf_Rel *) ((char *) e + s->sh_offset),
|
||||
max = rel + s->sh_size / s->sh_entsize;
|
||||
rel < max;
|
||||
rel++)
|
||||
{
|
||||
Elf32_Word *addr;
|
||||
Elf32_Sym *sym;
|
||||
|
||||
Elf_Word *addr;
|
||||
Elf_Sym *sym;
|
||||
|
||||
if (seg->size < rel->r_offset)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"reloc offset is out of the segment");
|
||||
|
||||
addr = (Elf32_Word *) ((char *) seg->addr + rel->r_offset);
|
||||
sym = (Elf32_Sym *) ((char *) symtab
|
||||
+ entsize * ELF32_R_SYM (rel->r_info));
|
||||
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
|
||||
addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset);
|
||||
sym = (Elf_Sym *) ((char *) mod->symtab
|
||||
+ entsize * ELF_R_SYM (rel->r_info));
|
||||
|
||||
switch (ELF_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_386_32:
|
||||
*addr += sym->st_value;
|
||||
break;
|
||||
|
||||
case R_386_PC32:
|
||||
*addr += (sym->st_value - (Elf32_Word) seg->addr
|
||||
*addr += (sym->st_value - (Elf_Word) seg->addr
|
||||
- rel->r_offset);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,18 +25,13 @@
|
|||
#include <grub/cache.h>
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
void
|
||||
grub_millisleep (grub_uint32_t ms)
|
||||
{
|
||||
grub_millisleep_generic (ms);
|
||||
}
|
||||
#include <grub/i386/tsc.h>
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
grub_efi_init ();
|
||||
grub_tsc_init ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -34,14 +34,14 @@ _start:
|
|||
* These MUST be at byte offset 6 and 7 of the executable
|
||||
* DO NOT MOVE !!!
|
||||
*/
|
||||
. = EXT_C(start) + 0x6
|
||||
. = _start + 0x6
|
||||
.byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
|
||||
|
||||
/*
|
||||
* This is a special data area 8 bytes from the beginning.
|
||||
*/
|
||||
|
||||
. = EXT_C(start) + 0x8
|
||||
. = _start + 0x8
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
@ -50,7 +50,7 @@ VARIABLE(grub_prefix)
|
|||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = EXT_C(start) + 0x50
|
||||
. = _start + 0x50
|
||||
|
||||
codestart:
|
||||
/*
|
||||
|
|
42
kern/i386/halt.c
Normal file
42
kern/i386/halt.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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/cpu/io.h>
|
||||
#include <grub/machine/init.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
const char bochs_shutdown[] = "Shutdown";
|
||||
|
||||
void
|
||||
grub_halt (void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Disable interrupts. */
|
||||
__asm__ __volatile__ ("cli");
|
||||
|
||||
/* Bochs, QEMU, etc. */
|
||||
for (i = 0; i < sizeof (bochs_shutdown) - 1; i++)
|
||||
grub_outb (bochs_shutdown[i], 0x8900);
|
||||
|
||||
grub_printf ("GRUB doesn't know how to halt this machine yet!\n");
|
||||
|
||||
/* In order to return we'd have to check what the previous status of IF
|
||||
flag was. But user most likely doesn't want to return anyway ... */
|
||||
grub_stop ();
|
||||
}
|
|
@ -18,13 +18,16 @@
|
|||
*/
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/cache.h>
|
||||
|
||||
void grub_stop_floppy (void);
|
||||
|
||||
void
|
||||
grub_stop_floppy (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
grub_arch_sync_caches (void *address __attribute__ ((unused)),
|
||||
grub_size_t len __attribute__ ((unused)))
|
||||
{
|
||||
|
|
|
@ -16,11 +16,10 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define ASM_FILE 1
|
||||
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/cpu/linux.h>
|
||||
#include <grub/cpu/kernel.h>
|
||||
#include <multiboot.h>
|
||||
#include <multiboot2.h>
|
||||
|
||||
|
@ -38,16 +37,26 @@
|
|||
|
||||
start:
|
||||
_start:
|
||||
movl %eax, EXT_C(grub_ieee1275_entry_fn)
|
||||
jmp EXT_C(cmain)
|
||||
jmp codestart
|
||||
|
||||
/*
|
||||
* This call is special... it never returns... in fact it should simply
|
||||
* hang at this point!
|
||||
*/
|
||||
FUNCTION(grub_stop)
|
||||
hlt
|
||||
jmp EXT_C(grub_stop)
|
||||
/*
|
||||
* This is a special data area at a fixed offset from the beginning.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_CPU_PREFIX
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_CPU_DATA_END
|
||||
|
||||
codestart:
|
||||
movl %eax, EXT_C(grub_ieee1275_entry_fn)
|
||||
jmp EXT_C(grub_main)
|
||||
|
||||
/*
|
||||
* prot_to_real and associated structures (but NOT real_to_prot, that is
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* Note: These functions defined in this file may be called from C.
|
||||
* Be careful of that you must not modify some registers. Quote
|
||||
* from gcc-2.95.2/gcc/config/i386/i386.h:
|
||||
|
||||
|
||||
1 for registers not available across function calls.
|
||||
These must include the FIXED_REGISTERS and also any
|
||||
registers that can be used without being saved.
|
||||
|
@ -46,7 +46,7 @@
|
|||
*/
|
||||
|
||||
.p2align 2 /* force 4-byte alignment */
|
||||
|
||||
|
||||
/*
|
||||
* void grub_linux_boot_zimage (void)
|
||||
*/
|
||||
|
@ -58,8 +58,8 @@ VARIABLE(grub_linux_real_addr)
|
|||
.long 0
|
||||
VARIABLE(grub_linux_is_bzimage)
|
||||
.long 0
|
||||
|
||||
FUNCTION(grub_linux_boot)
|
||||
|
||||
FUNCTION(grub_linux16_real_boot)
|
||||
/* Must be done before zImage copy. */
|
||||
call EXT_C(grub_dl_unload_all)
|
||||
|
||||
|
@ -118,47 +118,3 @@ linux_setup_seg:
|
|||
.word 0
|
||||
.code32
|
||||
|
||||
|
||||
/*
|
||||
* This starts the multiboot kernel.
|
||||
*/
|
||||
|
||||
FUNCTION(grub_multiboot_real_boot)
|
||||
/* Push the entry address on the stack. */
|
||||
pushl %eax
|
||||
/* Move the address of the multiboot information structure to ebx. */
|
||||
movl %edx,%ebx
|
||||
|
||||
/* Unload all modules and stop the floppy driver. */
|
||||
call EXT_C(grub_dl_unload_all)
|
||||
call EXT_C(grub_stop_floppy)
|
||||
|
||||
/* Interrupts should be disabled. */
|
||||
cli
|
||||
|
||||
/* Move the magic value into eax and jump to the kernel. */
|
||||
movl $MULTIBOOT_MAGIC2,%eax
|
||||
popl %ecx
|
||||
jmp *%ecx
|
||||
|
||||
/*
|
||||
* This starts the multiboot 2 kernel.
|
||||
*/
|
||||
|
||||
FUNCTION(grub_multiboot2_real_boot)
|
||||
/* Push the entry address on the stack. */
|
||||
pushl %eax
|
||||
/* Move the address of the multiboot information structure to ebx. */
|
||||
movl %edx,%ebx
|
||||
|
||||
/* Unload all modules and stop the floppy driver. */
|
||||
call EXT_C(grub_dl_unload_all)
|
||||
call EXT_C(grub_stop_floppy)
|
||||
|
||||
/* Interrupts should be disabled. */
|
||||
cli
|
||||
|
||||
/* Move the magic value into eax and jump to the kernel. */
|
||||
movl $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
|
||||
popl %ecx
|
||||
jmp *%ecx
|
||||
|
|
29
kern/i386/misc.S
Normal file
29
kern/i386/misc.S
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2005,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/symbol.h>
|
||||
|
||||
.text
|
||||
/*
|
||||
* This call is special... it never returns... in fact it should simply
|
||||
* hang at this point!
|
||||
*/
|
||||
FUNCTION(grub_stop)
|
||||
cli
|
||||
1: hlt
|
||||
jmp 1b
|
87
kern/i386/multiboot_mmap.c
Normal file
87
kern/i386/multiboot_mmap.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,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/machine/init.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/multiboot.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
grub_size_t grub_lower_mem, grub_upper_mem;
|
||||
|
||||
/* A pointer to the MBI in its initial location. */
|
||||
struct multiboot_info *startup_multiboot_info;
|
||||
|
||||
/* The MBI has to be copied to our BSS so that it won't be
|
||||
overwritten. This is its final location. */
|
||||
static struct multiboot_info kern_multiboot_info;
|
||||
|
||||
/* Unfortunately we can't use heap at this point. But 32 looks like a sane
|
||||
limit (used by memtest86). */
|
||||
static grub_uint8_t mmap_entries[sizeof (struct multiboot_mmap_entry) * 32];
|
||||
|
||||
void
|
||||
grub_machine_mmap_init ()
|
||||
{
|
||||
if (! startup_multiboot_info)
|
||||
grub_fatal ("Unable to find Multiboot Information (is CONFIG_MULTIBOOT disabled in coreboot?)");
|
||||
|
||||
/* Move MBI to a safe place. */
|
||||
grub_memmove (&kern_multiboot_info, startup_multiboot_info, sizeof (struct multiboot_info));
|
||||
|
||||
if ((kern_multiboot_info.flags & MULTIBOOT_INFO_MEM_MAP) == 0)
|
||||
grub_fatal ("Missing Multiboot memory information");
|
||||
|
||||
/* Move the memory map to a safe place. */
|
||||
if (kern_multiboot_info.mmap_length > sizeof (mmap_entries))
|
||||
{
|
||||
grub_printf ("WARNING: Memory map size exceeds limit (0x%x > 0x%x); it will be truncated\n",
|
||||
kern_multiboot_info.mmap_length, sizeof (mmap_entries));
|
||||
kern_multiboot_info.mmap_length = sizeof (mmap_entries);
|
||||
}
|
||||
grub_memmove (mmap_entries, (void *) kern_multiboot_info.mmap_addr, kern_multiboot_info.mmap_length);
|
||||
kern_multiboot_info.mmap_addr = (grub_uint32_t) mmap_entries;
|
||||
|
||||
if ((kern_multiboot_info.flags & MULTIBOOT_INFO_MEMORY) == 0)
|
||||
{
|
||||
grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE;
|
||||
grub_upper_mem = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_lower_mem = kern_multiboot_info.mem_lower * 1024;
|
||||
grub_upper_mem = kern_multiboot_info.mem_upper * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
|
||||
{
|
||||
struct multiboot_mmap_entry *entry = (void *) kern_multiboot_info.mmap_addr;
|
||||
|
||||
while ((unsigned long) entry < kern_multiboot_info.mmap_addr + kern_multiboot_info.mmap_length)
|
||||
{
|
||||
if (hook (entry->addr, entry->len, entry->type))
|
||||
break;
|
||||
|
||||
entry = (void *) ((grub_addr_t) entry + entry->size + sizeof (entry->size));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,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
|
||||
|
@ -30,6 +30,7 @@
|
|||
#include <grub/env.h>
|
||||
#include <grub/cache.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/cpu/tsc.h>
|
||||
|
||||
struct mem_region
|
||||
{
|
||||
|
@ -44,15 +45,8 @@ static int num_regions;
|
|||
|
||||
grub_addr_t grub_os_area_addr;
|
||||
grub_size_t grub_os_area_size;
|
||||
grub_size_t grub_lower_mem, grub_upper_mem;
|
||||
|
||||
void
|
||||
grub_millisleep (grub_uint32_t ms)
|
||||
{
|
||||
grub_millisleep_generic (ms);
|
||||
}
|
||||
|
||||
void
|
||||
grub_arch_sync_caches (void *address __attribute__ ((unused)),
|
||||
grub_size_t len __attribute__ ((unused)))
|
||||
{
|
||||
|
@ -64,27 +58,23 @@ make_install_device (void)
|
|||
/* XXX: This should be enough. */
|
||||
char dev[100];
|
||||
|
||||
if (grub_memdisk_image_size)
|
||||
if (grub_prefix[0] != '(')
|
||||
{
|
||||
grub_sprintf (dev, "(memdisk)%s", grub_prefix);
|
||||
grub_strcpy (grub_prefix, dev);
|
||||
}
|
||||
else if (grub_install_dos_part != -2)
|
||||
{
|
||||
grub_sprintf (dev, "(%cd%u",
|
||||
(grub_boot_drive & 0x80) ? 'h' : 'f',
|
||||
/* No hardcoded root partition - make it from the boot drive and the
|
||||
partition number encoded at the install time. */
|
||||
grub_sprintf (dev, "(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f',
|
||||
grub_boot_drive & 0x7f);
|
||||
|
||||
|
||||
if (grub_install_dos_part >= 0)
|
||||
grub_sprintf (dev + grub_strlen (dev), ",%u", grub_install_dos_part + 1);
|
||||
|
||||
|
||||
if (grub_install_bsd_part >= 0)
|
||||
grub_sprintf (dev + grub_strlen (dev), ",%c", grub_install_bsd_part + 'a');
|
||||
|
||||
|
||||
grub_sprintf (dev + grub_strlen (dev), ")%s", grub_prefix);
|
||||
grub_strcpy (grub_prefix, dev);
|
||||
}
|
||||
|
||||
|
||||
return grub_prefix;
|
||||
}
|
||||
|
||||
|
@ -122,7 +112,7 @@ compact_mem_regions (void)
|
|||
if (mem_regions[i].addr + mem_regions[i].size >= mem_regions[i + 1].addr)
|
||||
{
|
||||
j = i + 1;
|
||||
|
||||
|
||||
if (mem_regions[i].addr + mem_regions[i].size
|
||||
< mem_regions[j].addr + mem_regions[j].size)
|
||||
mem_regions[i].size = (mem_regions[j].addr + mem_regions[j].size
|
||||
|
@ -138,16 +128,14 @@ compact_mem_regions (void)
|
|||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
grub_uint32_t cont;
|
||||
struct grub_machine_mmap_entry *entry
|
||||
= (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
int i;
|
||||
|
||||
int grub_lower_mem;
|
||||
|
||||
/* Initialize the console as early as possible. */
|
||||
grub_console_init ();
|
||||
|
||||
|
||||
grub_lower_mem = grub_get_memsize (0) << 10;
|
||||
|
||||
|
||||
/* Sanity check. */
|
||||
if (grub_lower_mem < GRUB_MEMORY_MACHINE_RESERVED_END)
|
||||
grub_fatal ("too small memory");
|
||||
|
@ -157,60 +145,45 @@ grub_machine_init (void)
|
|||
grub_gate_a20 (1);
|
||||
#endif
|
||||
|
||||
/* FIXME: This prevents loader/i386/linux.c from using low memory. When our
|
||||
heap implements support for requesting a chunk in low memory, this should
|
||||
no longer be a problem. */
|
||||
#if 0
|
||||
/* Add the lower memory into free memory. */
|
||||
if (grub_lower_mem >= GRUB_MEMORY_MACHINE_RESERVED_END)
|
||||
add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END,
|
||||
grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);
|
||||
|
||||
/* Check if grub_get_mmap_entry works. */
|
||||
cont = grub_get_mmap_entry (entry, 0);
|
||||
#endif
|
||||
|
||||
if (entry->size)
|
||||
do
|
||||
{
|
||||
/* Avoid the lower memory. */
|
||||
if (entry->addr < 0x100000)
|
||||
{
|
||||
if (entry->len <= 0x100000 - entry->addr)
|
||||
goto next;
|
||||
|
||||
entry->len -= 0x100000 - entry->addr;
|
||||
entry->addr = 0x100000;
|
||||
}
|
||||
|
||||
/* Ignore >4GB. */
|
||||
if (entry->addr <= 0xFFFFFFFF && entry->type == 1)
|
||||
{
|
||||
grub_addr_t addr;
|
||||
grub_size_t len;
|
||||
|
||||
addr = (grub_addr_t) entry->addr;
|
||||
len = ((addr + entry->len > 0xFFFFFFFF)
|
||||
? 0xFFFFFFFF - addr
|
||||
: (grub_size_t) entry->len);
|
||||
add_mem_region (addr, len);
|
||||
}
|
||||
|
||||
next:
|
||||
if (! cont)
|
||||
break;
|
||||
|
||||
cont = grub_get_mmap_entry (entry, cont);
|
||||
}
|
||||
while (entry->size);
|
||||
else
|
||||
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_uint32_t eisa_mmap = grub_get_eisa_mmap ();
|
||||
|
||||
if (eisa_mmap)
|
||||
/* Avoid the lower memory. */
|
||||
if (addr < 0x100000)
|
||||
{
|
||||
add_mem_region (0x100000, (eisa_mmap & 0xFFFF) << 10);
|
||||
add_mem_region (0x1000000, eisa_mmap & ~0xFFFF);
|
||||
if (size <= 0x100000 - addr)
|
||||
return 0;
|
||||
|
||||
size -= 0x100000 - addr;
|
||||
addr = 0x100000;
|
||||
}
|
||||
else
|
||||
add_mem_region (0x100000, grub_get_memsize (1) << 10);
|
||||
|
||||
/* Ignore >4GB. */
|
||||
if (addr <= 0xFFFFFFFF && type == GRUB_MACHINE_MEMORY_AVAILABLE)
|
||||
{
|
||||
grub_size_t len;
|
||||
|
||||
len = (grub_size_t) ((addr + size > 0xFFFFFFFF)
|
||||
? 0xFFFFFFFF - addr
|
||||
: size);
|
||||
add_mem_region (addr, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_machine_mmap_iterate (hook);
|
||||
|
||||
compact_mem_regions ();
|
||||
|
||||
/* Add the memory regions to free memory, except for the region starting
|
||||
|
@ -221,7 +194,6 @@ grub_machine_init (void)
|
|||
{
|
||||
grub_size_t quarter = mem_regions[i].size >> 2;
|
||||
|
||||
grub_upper_mem = mem_regions[i].size;
|
||||
grub_os_area_addr = mem_regions[i].addr;
|
||||
grub_os_area_size = mem_regions[i].size - quarter;
|
||||
grub_mm_init_region ((void *) (grub_os_area_addr + grub_os_area_size),
|
||||
|
@ -229,9 +201,11 @@ grub_machine_init (void)
|
|||
}
|
||||
else
|
||||
grub_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size);
|
||||
|
||||
|
||||
if (! grub_os_area_addr)
|
||||
grub_fatal ("no upper memory");
|
||||
|
||||
grub_tsc_init ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -245,27 +219,13 @@ void
|
|||
grub_machine_fini (void)
|
||||
{
|
||||
grub_console_fini ();
|
||||
grub_stop_floppy ();
|
||||
}
|
||||
|
||||
/* Return the end of the core image. */
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
return grub_end_addr;
|
||||
}
|
||||
|
||||
/* Return the start of the memdisk image. */
|
||||
grub_addr_t
|
||||
grub_arch_memdisk_addr (void)
|
||||
{
|
||||
return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
|
||||
+ (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE)
|
||||
+ grub_total_module_size;
|
||||
}
|
||||
|
||||
/* Return the size of the memdisk image. */
|
||||
grub_off_t
|
||||
grub_arch_memdisk_size (void)
|
||||
{
|
||||
return grub_memdisk_image_size;
|
||||
+ (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
|
||||
}
|
||||
|
|
677
kern/i386/pc/lzma_decode.S
Normal file
677
kern/i386/pc/lzma_decode.S
Normal file
|
@ -0,0 +1,677 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#define FIXED_PROPS
|
||||
|
||||
#define LZMA_BASE_SIZE 1846
|
||||
#define LZMA_LIT_SIZE 768
|
||||
|
||||
#define LZMA_PROPERTIES_SIZE 5
|
||||
|
||||
#define kNumTopBits 24
|
||||
#define kTopValue (1 << kNumTopBits)
|
||||
|
||||
#define kNumBitModelTotalBits 11
|
||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||
#define kNumMoveBits 5
|
||||
|
||||
|
||||
#define kNumPosBitsMax 4
|
||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
||||
|
||||
#define kLenNumLowBits 3
|
||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
||||
#define kLenNumMidBits 3
|
||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
||||
#define kLenNumHighBits 8
|
||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
||||
|
||||
#define LenChoice 0
|
||||
#define LenChoice2 (LenChoice + 1)
|
||||
#define LenLow (LenChoice2 + 1)
|
||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
||||
|
||||
|
||||
#define kNumStates 12
|
||||
#define kNumLitStates 7
|
||||
|
||||
#define kStartPosModelIndex 4
|
||||
#define kEndPosModelIndex 14
|
||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
||||
|
||||
#define kNumPosSlotBits 6
|
||||
#define kNumLenToPosStates 4
|
||||
|
||||
#define kNumAlignBits 4
|
||||
#define kAlignTableSize (1 << kNumAlignBits)
|
||||
|
||||
#define kMatchMinLen 2
|
||||
|
||||
#define IsMatch 0
|
||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
||||
#define IsRepG0 (IsRep + kNumStates)
|
||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
||||
#define LenCoder (Align + kAlignTableSize)
|
||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
||||
#define Literal (RepLenCoder + kNumLenProbs)
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
DbgOut:
|
||||
pushf
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
|
||||
call _DebugPrint
|
||||
|
||||
popl %eax
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
popf
|
||||
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* int LzmaDecodeProperties(CLzmaProperties *propsRes,
|
||||
* const unsigned char *propsData,
|
||||
* int size);
|
||||
*/
|
||||
|
||||
_LzmaDecodePropertiesA:
|
||||
movb (%edx), %dl
|
||||
|
||||
xorl %ecx, %ecx
|
||||
1:
|
||||
cmpb $45, %dl
|
||||
jb 2f
|
||||
incl %ecx
|
||||
subb $45, %dl
|
||||
jmp 1b
|
||||
2:
|
||||
movl %ecx, 8(%eax) /* pb */
|
||||
xorl %ecx, %ecx
|
||||
1:
|
||||
cmpb $9, %dl
|
||||
jb 2f
|
||||
incl %ecx
|
||||
subb $9, %dl
|
||||
2:
|
||||
movl %ecx, 4(%eax) /* lp */
|
||||
movb %dl, %cl
|
||||
movl %ecx, (%eax) /* lc */
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef ASM_FILE
|
||||
xorl %eax, %eax
|
||||
#endif
|
||||
ret
|
||||
|
||||
#define out_size 8(%ebp)
|
||||
|
||||
#define now_pos -4(%ebp)
|
||||
#define prev_byte -8(%ebp)
|
||||
#define range -12(%ebp)
|
||||
#define code -16(%ebp)
|
||||
#define state -20(%ebp)
|
||||
#define rep0 -24(%ebp)
|
||||
#define rep1 -28(%ebp)
|
||||
#define rep2 -32(%ebp)
|
||||
#define rep3 -36(%ebp)
|
||||
|
||||
#ifdef FIXED_PROPS
|
||||
|
||||
#define FIXED_LC 3
|
||||
#define FIXED_LP 0
|
||||
#define FIXED_PB 2
|
||||
|
||||
#define POS_STATE_MASK ((1 << (FIXED_PB)) - 1)
|
||||
#define LIT_POS_MASK ((1 << (FIXED_LP)) - 1)
|
||||
|
||||
#define LOCAL_SIZE 36
|
||||
|
||||
#else
|
||||
|
||||
#define lc (%ebx)
|
||||
#define lp 4(%ebx)
|
||||
#define pb 8(%ebx)
|
||||
#define probs 12(%ebx)
|
||||
|
||||
#define pos_state_mask -40(%ebp)
|
||||
#define lit_pos_mask -44(%ebp)
|
||||
|
||||
#define LOCAL_SIZE 44
|
||||
|
||||
#endif
|
||||
|
||||
RangeDecoderBitDecode:
|
||||
#ifdef FIXED_PROPS
|
||||
leal (%ebx, %eax, 4), %eax
|
||||
#else
|
||||
shll $2, %eax
|
||||
addl probs, %eax
|
||||
#endif
|
||||
|
||||
movl %eax, %ecx
|
||||
movl (%ecx), %eax
|
||||
|
||||
movl range, %edx
|
||||
shrl $kNumBitModelTotalBits, %edx
|
||||
mull %edx
|
||||
|
||||
cmpl code, %eax
|
||||
jbe 1f
|
||||
|
||||
movl %eax, range
|
||||
movl $kBitModelTotal, %edx
|
||||
subl (%ecx), %edx
|
||||
shrl $kNumMoveBits, %edx
|
||||
addl %edx, (%ecx)
|
||||
clc
|
||||
3:
|
||||
pushf
|
||||
cmpl $kTopValue, range
|
||||
jnc 2f
|
||||
shll $8, code
|
||||
lodsb
|
||||
movb %al, code
|
||||
shll $8, range
|
||||
2:
|
||||
popf
|
||||
ret
|
||||
1:
|
||||
subl %eax, range
|
||||
subl %eax, code
|
||||
movl (%ecx), %edx
|
||||
shrl $kNumMoveBits, %edx
|
||||
subl %edx, (%ecx)
|
||||
stc
|
||||
jmp 3b
|
||||
|
||||
RangeDecoderBitTreeDecode:
|
||||
RangeDecoderReverseBitTreeDecode:
|
||||
movzbl %cl, %ecx
|
||||
xorl %edx, %edx
|
||||
pushl %edx
|
||||
incl %edx
|
||||
pushl %edx
|
||||
|
||||
1:
|
||||
pushl %eax
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
|
||||
addl %edx, %eax
|
||||
call RangeDecoderBitDecode
|
||||
|
||||
popl %edx
|
||||
popl %ecx
|
||||
|
||||
jnc 2f
|
||||
movl 4(%esp), %eax
|
||||
orl %eax, 8(%esp)
|
||||
stc
|
||||
|
||||
2:
|
||||
adcl %edx, %edx
|
||||
popl %eax
|
||||
|
||||
shll $1, (%esp)
|
||||
loop 1b
|
||||
|
||||
popl %ecx
|
||||
subl %ecx, %edx /* RangeDecoderBitTreeDecode */
|
||||
popl %ecx /* RangeDecoderReverseBitTreeDecode */
|
||||
ret
|
||||
|
||||
LzmaLenDecode:
|
||||
pushl %eax
|
||||
addl $LenChoice, %eax
|
||||
call RangeDecoderBitDecode
|
||||
popl %eax
|
||||
jc 1f
|
||||
pushl $0
|
||||
movb $kLenNumLowBits, %cl
|
||||
addl $LenLow, %eax
|
||||
2:
|
||||
movl 12(%esp), %edx
|
||||
shll %cl, %edx
|
||||
addl %edx, %eax
|
||||
3:
|
||||
|
||||
call RangeDecoderBitTreeDecode
|
||||
popl %eax
|
||||
addl %eax, %edx
|
||||
ret
|
||||
|
||||
1:
|
||||
pushl %eax
|
||||
addl $LenChoice2, %eax
|
||||
call RangeDecoderBitDecode
|
||||
popl %eax
|
||||
jc 1f
|
||||
pushl $kLenNumLowSymbols
|
||||
movb $kLenNumMidBits, %cl
|
||||
addl $LenMid, %eax
|
||||
jmp 2b
|
||||
|
||||
1:
|
||||
pushl $(kLenNumLowSymbols + kLenNumMidSymbols)
|
||||
addl $LenHigh, %eax
|
||||
movb $kLenNumHighBits, %cl
|
||||
jmp 3b
|
||||
|
||||
WriteByte:
|
||||
movb %al, prev_byte
|
||||
stosb
|
||||
incl now_pos
|
||||
ret
|
||||
|
||||
/*
|
||||
* int LzmaDecode(CLzmaDecoderState *vs,
|
||||
* const unsigned char *inStream,
|
||||
* unsigned char *outStream,
|
||||
* SizeT outSize);
|
||||
*/
|
||||
|
||||
_LzmaDecodeA:
|
||||
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
subl $LOCAL_SIZE, %esp
|
||||
|
||||
#ifndef ASM_FILE
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
pushl %ebx
|
||||
|
||||
movl %eax, %ebx
|
||||
movl %edx, %esi
|
||||
pushl %ecx
|
||||
#else
|
||||
pushl %edi
|
||||
#endif
|
||||
|
||||
cld
|
||||
|
||||
#ifdef FIXED_PROPS
|
||||
movl %ebx, %edi
|
||||
movl $(Literal + (LZMA_LIT_SIZE << (FIXED_LC + FIXED_LP))), %ecx
|
||||
#else
|
||||
movl $LZMA_LIT_SIZE, %eax
|
||||
movb lc, %cl
|
||||
addb lp, %cl
|
||||
shll %cl, %eax
|
||||
addl $Literal, %eax
|
||||
movl %eax, %ecx
|
||||
movl probs, %edi
|
||||
#endif
|
||||
|
||||
movl $(kBitModelTotal >> 1), %eax
|
||||
|
||||
rep
|
||||
stosl
|
||||
|
||||
popl %edi
|
||||
|
||||
xorl %eax, %eax
|
||||
movl %eax, now_pos
|
||||
movl %eax, prev_byte
|
||||
movl %eax, state
|
||||
|
||||
incl %eax
|
||||
movl %eax, rep0
|
||||
movl %eax, rep1
|
||||
movl %eax, rep2
|
||||
movl %eax, rep3
|
||||
|
||||
#ifndef FIXED_PROPS
|
||||
movl %eax, %edx
|
||||
movb pb, %cl
|
||||
shll %cl, %edx
|
||||
decl %edx
|
||||
movl %edx, pos_state_mask
|
||||
|
||||
movl %eax, %edx
|
||||
movb lp, %cl
|
||||
shll %cl, %edx
|
||||
decl %edx
|
||||
movl %edx, lit_pos_mask;
|
||||
#endif
|
||||
|
||||
/* RangeDecoderInit */
|
||||
negl %eax
|
||||
movl %eax, range
|
||||
|
||||
incl %eax
|
||||
movb $5, %cl
|
||||
|
||||
1:
|
||||
shll $8, %eax
|
||||
lodsb
|
||||
loop 1b
|
||||
|
||||
movl %eax, code
|
||||
|
||||
lzma_decode_loop:
|
||||
movl now_pos, %eax
|
||||
cmpl out_size, %eax
|
||||
|
||||
jb 1f
|
||||
|
||||
#ifndef ASM_FILE
|
||||
xorl %eax, %eax
|
||||
|
||||
popl %ebx
|
||||
popl %edi
|
||||
popl %esi
|
||||
#endif
|
||||
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
1:
|
||||
#ifdef FIXED_PROPS
|
||||
andl $POS_STATE_MASK, %eax
|
||||
#else
|
||||
andl pos_state_mask, %eax
|
||||
#endif
|
||||
pushl %eax /* posState */
|
||||
movl state, %edx
|
||||
shll $kNumPosBitsMax, %edx
|
||||
addl %edx, %eax
|
||||
pushl %eax /* (state << kNumPosBitsMax) + posState */
|
||||
|
||||
call RangeDecoderBitDecode
|
||||
jc 1f
|
||||
|
||||
movl now_pos, %eax
|
||||
|
||||
#ifdef FIXED_PROPS
|
||||
andl $LIT_POS_MASK, %eax
|
||||
shll $FIXED_LC, %eax
|
||||
movl prev_byte, %edx
|
||||
shrl $(8 - FIXED_LC), %edx
|
||||
#else
|
||||
andl lit_pos_mask, %eax
|
||||
movb lc, %cl
|
||||
shll %cl, %eax
|
||||
negb %cl
|
||||
addb $8, %cl
|
||||
movl prev_byte, %edx
|
||||
shrl %cl, %edx
|
||||
#endif
|
||||
|
||||
addl %edx, %eax
|
||||
movl $LZMA_LIT_SIZE, %edx
|
||||
mull %edx
|
||||
addl $Literal, %eax
|
||||
pushl %eax
|
||||
|
||||
incl %edx /* edx = 1 */
|
||||
|
||||
movl rep0, %eax
|
||||
negl %eax
|
||||
pushl (%edi, %eax) /* matchByte */
|
||||
|
||||
cmpb $kNumLitStates, state
|
||||
jb 5f
|
||||
|
||||
/* LzmaLiteralDecodeMatch */
|
||||
|
||||
3:
|
||||
cmpl $0x100, %edx
|
||||
jae 4f
|
||||
|
||||
xorl %eax, %eax
|
||||
shlb $1, (%esp)
|
||||
adcl %eax, %eax
|
||||
|
||||
pushl %eax
|
||||
pushl %edx
|
||||
|
||||
shll $8, %eax
|
||||
leal 0x100(%edx, %eax), %eax
|
||||
addl 12(%esp), %eax
|
||||
call RangeDecoderBitDecode
|
||||
|
||||
setc %al
|
||||
popl %edx
|
||||
adcl %edx, %edx
|
||||
|
||||
popl %ecx
|
||||
cmpb %cl, %al
|
||||
jz 3b
|
||||
|
||||
5:
|
||||
|
||||
/* LzmaLiteralDecode */
|
||||
|
||||
cmpl $0x100, %edx
|
||||
jae 4f
|
||||
|
||||
pushl %edx
|
||||
movl %edx, %eax
|
||||
addl 8(%esp), %eax
|
||||
call RangeDecoderBitDecode
|
||||
popl %edx
|
||||
adcl %edx, %edx
|
||||
jmp 5b
|
||||
|
||||
4:
|
||||
addl $16, %esp
|
||||
|
||||
movb %dl, %al
|
||||
call WriteByte
|
||||
|
||||
movb state, %al
|
||||
cmpb $4, %al
|
||||
jae 2f
|
||||
xorb %al, %al
|
||||
jmp 3f
|
||||
2:
|
||||
subb $3, %al
|
||||
cmpb $7, %al
|
||||
jb 3f
|
||||
subb $3, %al
|
||||
3:
|
||||
movb %al, state
|
||||
jmp lzma_decode_loop
|
||||
|
||||
1:
|
||||
movl state, %eax
|
||||
addl $IsRep, %eax
|
||||
call RangeDecoderBitDecode
|
||||
jnc 1f
|
||||
|
||||
movl state, %eax
|
||||
addl $IsRepG0, %eax
|
||||
call RangeDecoderBitDecode
|
||||
jc 10f
|
||||
|
||||
movl (%esp), %eax
|
||||
addl $IsRep0Long, %eax
|
||||
call RangeDecoderBitDecode
|
||||
jc 20f
|
||||
|
||||
cmpb $7, state
|
||||
movb $9, state
|
||||
jb 100f
|
||||
addb $2, state
|
||||
100:
|
||||
|
||||
movl $1, %ecx
|
||||
|
||||
3:
|
||||
movl rep0, %edx
|
||||
negl %edx
|
||||
|
||||
4:
|
||||
movb (%edi, %edx), %al
|
||||
call WriteByte
|
||||
loop 4b
|
||||
|
||||
popl %eax
|
||||
popl %eax
|
||||
jmp lzma_decode_loop
|
||||
|
||||
10:
|
||||
movl state, %eax
|
||||
addl $IsRepG1, %eax
|
||||
call RangeDecoderBitDecode
|
||||
movl rep1, %edx
|
||||
jnc 100f
|
||||
|
||||
movl state, %eax
|
||||
addl $IsRepG2, %eax
|
||||
call RangeDecoderBitDecode
|
||||
movl rep2, %edx
|
||||
jnc 1000f
|
||||
movl rep2, %edx
|
||||
xchgl rep3, %edx
|
||||
1000:
|
||||
pushl rep1
|
||||
popl rep2
|
||||
100:
|
||||
xchg rep0, %edx
|
||||
movl %edx, rep1
|
||||
20:
|
||||
|
||||
movl $RepLenCoder, %eax
|
||||
call LzmaLenDecode
|
||||
|
||||
cmpb $7, state
|
||||
movb $8, state
|
||||
jb 100f
|
||||
addb $3, state
|
||||
100:
|
||||
jmp 2f
|
||||
|
||||
1:
|
||||
movl rep0, %eax
|
||||
xchgl rep1, %eax
|
||||
xchgl rep2, %eax
|
||||
movl %eax, rep3
|
||||
|
||||
cmpb $7, state
|
||||
movb $7, state
|
||||
jb 10f
|
||||
addb $3, state
|
||||
10:
|
||||
|
||||
movl $LenCoder, %eax
|
||||
call LzmaLenDecode
|
||||
pushl %edx
|
||||
|
||||
movl $(kNumLenToPosStates - 1), %eax
|
||||
cmpl %eax, %edx
|
||||
jbe 100f
|
||||
movl %eax, %edx
|
||||
100:
|
||||
movb $kNumPosSlotBits, %cl
|
||||
shll %cl, %edx
|
||||
leal PosSlot(%edx), %eax
|
||||
call RangeDecoderBitTreeDecode
|
||||
|
||||
movl %edx, rep0
|
||||
cmpl $kStartPosModelIndex, %edx
|
||||
jb 100f
|
||||
|
||||
movl %edx, %ecx
|
||||
shrl $1, %ecx
|
||||
decl %ecx
|
||||
|
||||
movzbl %dl, %eax
|
||||
andb $1, %al
|
||||
orb $2, %al
|
||||
shll %cl, %eax
|
||||
movl %eax, rep0
|
||||
|
||||
cmpl $kEndPosModelIndex, %edx
|
||||
jae 200f
|
||||
movl rep0, %eax
|
||||
addl $(SpecPos - 1), %eax
|
||||
subl %edx, %eax
|
||||
jmp 300f
|
||||
200:
|
||||
|
||||
subb $kNumAlignBits, %cl
|
||||
|
||||
/* RangeDecoderDecodeDirectBits */
|
||||
xorl %edx, %edx
|
||||
|
||||
1000:
|
||||
shrl $1, range
|
||||
shll $1, %edx
|
||||
|
||||
movl range, %eax
|
||||
cmpl %eax, code
|
||||
jb 2000f
|
||||
subl %eax, code
|
||||
orb $1, %dl
|
||||
2000:
|
||||
|
||||
cmpl $kTopValue, %eax
|
||||
jae 3000f
|
||||
shll $8, range
|
||||
shll $8, code
|
||||
lodsb
|
||||
movb %al, code
|
||||
|
||||
3000:
|
||||
loop 1000b
|
||||
|
||||
movb $kNumAlignBits, %cl
|
||||
shll %cl, %edx
|
||||
addl %edx, rep0
|
||||
|
||||
movl $Align, %eax
|
||||
|
||||
300:
|
||||
call RangeDecoderReverseBitTreeDecode
|
||||
addl %ecx, rep0
|
||||
|
||||
100:
|
||||
incl rep0
|
||||
popl %edx
|
||||
|
||||
2:
|
||||
|
||||
addl $kMatchMinLen, %edx
|
||||
movl %edx, %ecx
|
||||
|
||||
jmp 3b
|
|
@ -1,322 +0,0 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||
* Copyright (C) 2003,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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code was stolen from the files enter.sh, leave.sh, lzo1x_d.sh,
|
||||
* lzo1x_f.s and lzo_asm.h in LZO version 1.08, and was heavily modified
|
||||
* to adapt it to GRUB's requirement.
|
||||
*
|
||||
* See <http://www.oberhumer.com/opensource/lzo/>, for more information
|
||||
* about LZO.
|
||||
*/
|
||||
|
||||
#define INP 4+16(%esp)
|
||||
#define INS 8+16(%esp)
|
||||
#define OUTP 12+16(%esp)
|
||||
#define NN 3
|
||||
#define N_3 %ebp
|
||||
#define N_255 $255
|
||||
#define LODSB movb (%esi), %al ; incl %esi
|
||||
#define NOTL_3(r) xorl N_3, r
|
||||
#define MOVSL(r1,r2,x) movl (r1), x ; addl $4, r1 ; movl x, (r2) ; addl $4, r2
|
||||
#define COPYL_C(r1,r2,x,rc) 9: MOVSL(r1,r2,x) ; decl rc ; jnz 9b
|
||||
#define COPYL(r1,r2,x) COPYL_C(r1,r2,x,%ecx)
|
||||
|
||||
lzo1x_decompress:
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
|
||||
cld
|
||||
|
||||
movl INP, %esi
|
||||
movl OUTP, %edi
|
||||
movl $3, %ebp
|
||||
|
||||
|
||||
xorl %eax, %eax
|
||||
xorl %ebx, %ebx /* high bits 9-32 stay 0 */
|
||||
lodsb
|
||||
cmpb $17, %al
|
||||
jbe .L01
|
||||
subb $17-NN, %al
|
||||
jmp .LFLR
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// literal run
|
||||
************************************************************************/
|
||||
|
||||
0: addl N_255, %eax
|
||||
1: movb (%esi), %bl
|
||||
incl %esi
|
||||
orb %bl, %bl
|
||||
jz 0b
|
||||
leal 18+NN(%eax,%ebx), %eax
|
||||
jmp 3f
|
||||
|
||||
|
||||
.align 8
|
||||
.L00:
|
||||
LODSB
|
||||
.L01:
|
||||
cmpb $16, %al
|
||||
jae .LMATCH
|
||||
|
||||
/* a literal run */
|
||||
orb %al, %al
|
||||
jz 1b
|
||||
addl $3+NN, %eax
|
||||
3:
|
||||
.LFLR:
|
||||
movl %eax, %ecx
|
||||
NOTL_3(%eax)
|
||||
shrl $2, %ecx
|
||||
andl N_3, %eax
|
||||
COPYL(%esi,%edi,%edx)
|
||||
subl %eax, %esi
|
||||
subl %eax, %edi
|
||||
|
||||
LODSB
|
||||
cmpb $16, %al
|
||||
jae .LMATCH
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// R1
|
||||
************************************************************************/
|
||||
|
||||
shrl $2, %eax
|
||||
movb (%esi), %bl
|
||||
leal -0x801(%edi), %edx
|
||||
leal (%eax,%ebx,4), %eax
|
||||
incl %esi
|
||||
subl %eax, %edx
|
||||
movl (%edx), %ecx
|
||||
movl %ecx, (%edi)
|
||||
addl N_3, %edi
|
||||
jmp .LMDONE
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// M2
|
||||
************************************************************************/
|
||||
|
||||
.align 8
|
||||
.LMATCH:
|
||||
cmpb $64, %al
|
||||
jb .LM3MATCH
|
||||
|
||||
/* a M2 match */
|
||||
movl %eax, %ecx
|
||||
shrl $2, %eax
|
||||
leal -1(%edi), %edx
|
||||
andl $7, %eax
|
||||
movb (%esi), %bl
|
||||
shrl $5, %ecx
|
||||
leal (%eax,%ebx,8), %eax
|
||||
incl %esi
|
||||
subl %eax, %edx
|
||||
|
||||
addl $1+3, %ecx
|
||||
|
||||
cmpl N_3, %eax
|
||||
jae .LCOPYLONG
|
||||
jmp .LCOPYBYTE
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// M3
|
||||
************************************************************************/
|
||||
|
||||
0: addl N_255, %eax
|
||||
1: movb (%esi), %bl
|
||||
incl %esi
|
||||
orb %bl, %bl
|
||||
jz 0b
|
||||
leal 33+NN(%eax,%ebx), %ecx
|
||||
xorl %eax, %eax
|
||||
jmp 3f
|
||||
|
||||
|
||||
.align 8
|
||||
.LM3MATCH:
|
||||
cmpb $32, %al
|
||||
jb .LM4MATCH
|
||||
|
||||
/* a M3 match */
|
||||
andl $31, %eax
|
||||
jz 1b
|
||||
lea 2+NN(%eax), %ecx
|
||||
3:
|
||||
movw (%esi), %ax
|
||||
leal -1(%edi), %edx
|
||||
shrl $2, %eax
|
||||
addl $2, %esi
|
||||
subl %eax, %edx
|
||||
|
||||
cmpl N_3, %eax
|
||||
jb .LCOPYBYTE
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// copy match
|
||||
************************************************************************/
|
||||
|
||||
.align 2
|
||||
.LCOPYLONG: /* copy match using longwords */
|
||||
leal -3(%edi,%ecx), %eax
|
||||
shrl $2, %ecx
|
||||
COPYL(%edx,%edi,%ebx)
|
||||
movl %eax, %edi
|
||||
xorl %ebx, %ebx
|
||||
|
||||
.LMDONE:
|
||||
movb -2(%esi), %al
|
||||
andl N_3, %eax
|
||||
jz .L00
|
||||
.LFLR3:
|
||||
movl (%esi), %edx
|
||||
addl %eax, %esi
|
||||
movl %edx, (%edi)
|
||||
addl %eax, %edi
|
||||
|
||||
LODSB
|
||||
jmp .LMATCH
|
||||
|
||||
|
||||
.align 8
|
||||
.LCOPYBYTE: /* copy match using bytes */
|
||||
xchgl %edx,%esi
|
||||
subl N_3,%ecx
|
||||
|
||||
rep
|
||||
movsb
|
||||
movl %edx, %esi
|
||||
jmp .LMDONE
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// M4
|
||||
************************************************************************/
|
||||
|
||||
0: addl N_255, %ecx
|
||||
1: movb (%esi), %bl
|
||||
incl %esi
|
||||
orb %bl, %bl
|
||||
jz 0b
|
||||
leal 9+NN(%ebx,%ecx), %ecx
|
||||
jmp 3f
|
||||
|
||||
|
||||
.align 8
|
||||
.LM4MATCH:
|
||||
cmpb $16, %al
|
||||
jb .LM1MATCH
|
||||
|
||||
/* a M4 match */
|
||||
movl %eax, %ecx
|
||||
andl $8, %eax
|
||||
shll $13, %eax /* save in bit 16 */
|
||||
andl $7, %ecx
|
||||
jz 1b
|
||||
addl $2+NN, %ecx
|
||||
3:
|
||||
movw (%esi), %ax
|
||||
addl $2, %esi
|
||||
leal -0x4000(%edi), %edx
|
||||
shrl $2, %eax
|
||||
jz .LEOF
|
||||
subl %eax, %edx
|
||||
jmp .LCOPYLONG
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
// M1
|
||||
************************************************************************/
|
||||
|
||||
.align 8
|
||||
.LM1MATCH:
|
||||
/* a M1 match */
|
||||
shrl $2, %eax
|
||||
movb (%esi), %bl
|
||||
leal -1(%edi), %edx
|
||||
leal (%eax,%ebx,4), %eax
|
||||
incl %esi
|
||||
subl %eax, %edx
|
||||
|
||||
movb (%edx), %al /* we must use this because edx can be edi-1 */
|
||||
movb %al, (%edi)
|
||||
movb 1(%edx), %bl
|
||||
movb %bl, 1(%edi)
|
||||
addl $2, %edi
|
||||
jmp .LMDONE
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
//
|
||||
************************************************************************/
|
||||
|
||||
.LEOF:
|
||||
/**** xorl %eax,%eax eax=0 from above */
|
||||
|
||||
cmpl $3+NN, %ecx /* ecx must be 3/6 */
|
||||
setnz %al
|
||||
|
||||
/* check compressed size */
|
||||
movl INP, %edx
|
||||
addl INS, %edx
|
||||
cmpl %edx, %esi /* check compressed size */
|
||||
ja .L_input_overrun
|
||||
jb .L_input_not_consumed
|
||||
|
||||
.L_leave:
|
||||
negl %eax
|
||||
jnz 1f
|
||||
|
||||
subl OUTP, %edi /* write back the uncompressed size */
|
||||
movl %edi, %eax
|
||||
|
||||
1: popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
.L_input_not_consumed:
|
||||
movl $8, %eax /* LZO_E_INPUT_NOT_CONSUMED */
|
||||
jmp .L_leave
|
||||
|
||||
.L_input_overrun:
|
||||
movl $4, %eax /* LZO_E_INPUT_OVERRUN */
|
||||
jmp .L_leave
|
||||
|
||||
#undef INP
|
||||
#undef INS
|
||||
#undef OUTP
|
||||
#undef NN
|
||||
#undef NN
|
||||
#undef N_3
|
||||
#undef N_255
|
||||
#undef LODSB
|
||||
#undef NOTL_3
|
||||
#undef MOVSL
|
||||
#undef COPYL_C
|
||||
#undef COPYL
|
63
kern/i386/pc/mmap.c
Normal file
63
kern/i386/pc/mmap.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2004,2005,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/machine/init.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/types.h>
|
||||
|
||||
grub_err_t
|
||||
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
|
||||
{
|
||||
grub_uint32_t cont;
|
||||
struct grub_machine_mmap_entry *entry
|
||||
= (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
|
||||
/* Check if grub_get_mmap_entry works. */
|
||||
cont = grub_get_mmap_entry (entry, 0);
|
||||
|
||||
if (entry->size)
|
||||
do
|
||||
{
|
||||
if (hook (entry->addr, entry->len,
|
||||
/* Multiboot mmaps have been defined to match with the E820 definition.
|
||||
Therefore, we can just pass type through. */
|
||||
entry->type))
|
||||
break;
|
||||
|
||||
if (! cont)
|
||||
break;
|
||||
|
||||
cont = grub_get_mmap_entry (entry, cont);
|
||||
}
|
||||
while (entry->size);
|
||||
else
|
||||
{
|
||||
grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
|
||||
|
||||
if (eisa_mmap)
|
||||
{
|
||||
if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, GRUB_MACHINE_MEMORY_AVAILABLE) == 0)
|
||||
hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MACHINE_MEMORY_AVAILABLE);
|
||||
}
|
||||
else
|
||||
hook (0x100000, grub_get_memsize (1) << 10, GRUB_MACHINE_MEMORY_AVAILABLE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load diff
56
kern/i386/pit.c
Normal file
56
kern/i386/pit.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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/i386/io.h>
|
||||
#include <grub/i386/pit.h>
|
||||
|
||||
#define TIMER2_REG_CONTROL 0x42
|
||||
#define TIMER_REG_COMMAND 0x43
|
||||
#define TIMER2_REG_LATCH 0x61
|
||||
|
||||
#define TIMER2_SELECT 0x80
|
||||
#define TIMER_ENABLE_LSB 0x20
|
||||
#define TIMER_ENABLE_MSB 0x10
|
||||
#define TIMER2_LATCH 0x20
|
||||
#define TIMER2_SPEAKER 0x02
|
||||
#define TIMER2_GATE 0x01
|
||||
|
||||
void
|
||||
grub_pit_wait (grub_uint16_t tics)
|
||||
{
|
||||
/* Disable timer2 gate and speaker. */
|
||||
grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE),
|
||||
TIMER2_REG_LATCH);
|
||||
|
||||
/* Set tics. */
|
||||
grub_outb (TIMER2_SELECT | TIMER_ENABLE_LSB | TIMER_ENABLE_MSB, TIMER_REG_COMMAND);
|
||||
grub_outb (tics & 0xff, TIMER2_REG_CONTROL);
|
||||
grub_outb (tics >> 8, TIMER2_REG_CONTROL);
|
||||
|
||||
/* Enable timer2 gate, keep speaker disabled. */
|
||||
grub_outb ((grub_inb (TIMER2_REG_LATCH) & ~ TIMER2_SPEAKER) | TIMER2_GATE,
|
||||
TIMER2_REG_LATCH);
|
||||
|
||||
/* Wait. */
|
||||
while ((grub_inb (TIMER2_REG_LATCH) & TIMER2_LATCH) == 0x00);
|
||||
|
||||
/* Disable timer2 gate and speaker. */
|
||||
grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE),
|
||||
TIMER2_REG_LATCH);
|
||||
}
|
74
kern/i386/qemu/mmap.c
Normal file
74
kern/i386/qemu/mmap.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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/machine/init.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/boot.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/i386/cmos.h>
|
||||
|
||||
#define QEMU_CMOS_MEMSIZE_HIGH 0x35
|
||||
#define QEMU_CMOS_MEMSIZE_LOW 0x34
|
||||
|
||||
#define min(a,b) ((a) > (b) ? (b) : (a))
|
||||
|
||||
extern char _start[];
|
||||
extern char _end[];
|
||||
|
||||
grub_size_t grub_lower_mem, grub_upper_mem;
|
||||
grub_uint64_t mem_size;
|
||||
|
||||
void
|
||||
grub_machine_mmap_init ()
|
||||
{
|
||||
mem_size = grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH) << 24 | grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW) << 16;
|
||||
|
||||
/* Don't ask... */
|
||||
mem_size += (16 * 1024 * 1024);
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
|
||||
{
|
||||
if (hook (0x0,
|
||||
(grub_addr_t) _start,
|
||||
GRUB_MACHINE_MEMORY_AVAILABLE))
|
||||
return 1;
|
||||
|
||||
if (hook (GRUB_MEMORY_MACHINE_UPPER,
|
||||
0x100000 - GRUB_MEMORY_MACHINE_UPPER,
|
||||
GRUB_MACHINE_MEMORY_RESERVED))
|
||||
return 1;
|
||||
|
||||
/* Protect boot.img, which contains the gdt. It is mapped at the top of memory
|
||||
(it is also mapped below 0x100000, but we already reserved that area). */
|
||||
if (hook ((grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE,
|
||||
GRUB_BOOT_MACHINE_SIZE,
|
||||
GRUB_MACHINE_MEMORY_RESERVED))
|
||||
return 1;
|
||||
|
||||
/* Everything else is free. */
|
||||
if (hook (0x100000,
|
||||
min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000,
|
||||
GRUB_MACHINE_MEMORY_AVAILABLE))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
99
kern/i386/qemu/startup.S
Normal file
99
kern/i386/qemu/startup.S
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,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 <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
|
||||
.text
|
||||
.code32
|
||||
.globl _start
|
||||
_start:
|
||||
jmp codestart
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_CORE_ENTRY_ADDR
|
||||
VARIABLE(grub_core_entry_addr)
|
||||
.long 0
|
||||
VARIABLE(grub_kernel_image_size)
|
||||
.long 0
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_DATA_END
|
||||
|
||||
codestart:
|
||||
/* Relocate to low memory. First we figure out our location.
|
||||
We will derive the rom start address from it. */
|
||||
call 1f
|
||||
1: popl %esi
|
||||
|
||||
/* Rom size is a multiple of 64 kiB. With this we get the
|
||||
value of `grub_core_entry_addr' in %esi. */
|
||||
xorw %si, %si
|
||||
|
||||
/* ... which allows us to access `grub_kernel_image_size'
|
||||
before relocation. */
|
||||
movl (grub_kernel_image_size - _start)(%esi), %ecx
|
||||
|
||||
|
||||
movl $_start, %edi
|
||||
cld
|
||||
rep
|
||||
movsb
|
||||
ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $1f
|
||||
1:
|
||||
|
||||
#ifdef APPLE_CC
|
||||
/* clean out the bss */
|
||||
bss_start_abs = ABS (bss_start)
|
||||
bss_end_abs = ABS (bss_end)
|
||||
|
||||
movl bss_start_abs, %edi
|
||||
|
||||
/* compute the bss length */
|
||||
movl bss_end_abs, %ecx
|
||||
subl %edi, %ecx
|
||||
#else
|
||||
/* clean out the bss */
|
||||
movl $BSS_START_SYMBOL, %edi
|
||||
|
||||
/* compute the bss length */
|
||||
movl $END_SYMBOL, %ecx
|
||||
subl %edi, %ecx
|
||||
#endif
|
||||
|
||||
/* clean out */
|
||||
xorl %eax, %eax
|
||||
cld
|
||||
rep
|
||||
stosb
|
||||
|
||||
/*
|
||||
* Call the start of main body of C code.
|
||||
*/
|
||||
call EXT_C(grub_main)
|
||||
|
||||
/* This should never happen. */
|
||||
jmp EXT_C(grub_stop)
|
||||
|
||||
#include "../realmode.S"
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1999,2000,2001,2002,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
|
||||
|
@ -21,7 +21,7 @@
|
|||
* Note: These functions defined in this file may be called from C.
|
||||
* Be careful of that you must not modify some registers. Quote
|
||||
* from gcc-2.95.2/gcc/config/i386/i386.h:
|
||||
|
||||
|
||||
1 for registers not available across function calls.
|
||||
These must include the FIXED_REGISTERS and also any
|
||||
registers that can be used without being saved.
|
||||
|
@ -84,7 +84,7 @@ gdt:
|
|||
|
||||
/* -- data segment --
|
||||
* base = 0x00000000, limit 0xFFFFF (4 KiB Granularity), present
|
||||
* type = 32 bit data read/write, DPL = 0
|
||||
* type = 32 bit data read/write, DPL = 0
|
||||
*/
|
||||
.word 0xFFFF, 0
|
||||
.byte 0, 0x92, 0xCF, 0
|
||||
|
@ -110,12 +110,58 @@ gdtdesc:
|
|||
.long gdt /* addr */
|
||||
|
||||
/*
|
||||
* These next routine, "prot_to_real" is structured in a very
|
||||
* specific way. Be very careful when changing it.
|
||||
* These next two routines, "real_to_prot" and "prot_to_real" are structured
|
||||
* in a very specific way. Be very careful when changing them.
|
||||
*
|
||||
* NOTE: Use of it messes up %eax and %ebp.
|
||||
* NOTE: Use of either one messes up %eax and %ebp.
|
||||
*/
|
||||
|
||||
real_to_prot:
|
||||
.code16
|
||||
cli
|
||||
|
||||
/* load the GDT register */
|
||||
xorw %ax, %ax
|
||||
movw %ax, %ds
|
||||
DATA32 ADDR32 lgdt gdtdesc
|
||||
|
||||
/* turn on protected mode */
|
||||
movl %cr0, %eax
|
||||
orl $GRUB_MEMORY_CPU_CR0_PE_ON, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* jump to relocation, flush prefetch queue, and reload %cs */
|
||||
DATA32 ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
|
||||
|
||||
.code32
|
||||
protcseg:
|
||||
/* reload other segment registers */
|
||||
movw $GRUB_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
movw %ax, %ss
|
||||
|
||||
/* put the return address in a known safe location */
|
||||
movl (%esp), %eax
|
||||
movl %eax, GRUB_MEMORY_MACHINE_REAL_STACK
|
||||
|
||||
/* get protected mode stack */
|
||||
movl protstack, %eax
|
||||
movl %eax, %esp
|
||||
movl %eax, %ebp
|
||||
|
||||
/* get return address onto the right stack */
|
||||
movl GRUB_MEMORY_MACHINE_REAL_STACK, %eax
|
||||
movl %eax, (%esp)
|
||||
|
||||
/* zero %eax */
|
||||
xorl %eax, %eax
|
||||
|
||||
/* return on the old (or initialized) stack! */
|
||||
ret
|
||||
|
||||
prot_to_real:
|
||||
/* just in case, set GDT */
|
||||
lgdt gdtdesc
|
||||
|
@ -150,7 +196,7 @@ tmpcseg:
|
|||
|
||||
/* clear the PE bit of CR0 */
|
||||
movl %cr0, %eax
|
||||
andl $(~GRUB_MEMORY_MACHINE_CR0_PE_ON), %eax
|
||||
andl $(~GRUB_MEMORY_CPU_CR0_PE_ON), %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* flush prefetch queue, reload %cs */
|
||||
|
@ -169,10 +215,27 @@ realcseg:
|
|||
movw %ax, %gs
|
||||
movw %ax, %ss
|
||||
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
/* restore interrupts */
|
||||
sti
|
||||
#endif
|
||||
|
||||
/* return on new stack! */
|
||||
DATA32 ret
|
||||
|
||||
.code32
|
||||
|
||||
/*
|
||||
* grub_reboot()
|
||||
*
|
||||
* Reboot the system. At the moment, rely on BIOS.
|
||||
*/
|
||||
FUNCTION(grub_reboot)
|
||||
call prot_to_real
|
||||
.code16
|
||||
cold_reboot:
|
||||
/* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */
|
||||
movw $0x0472, %di
|
||||
movw %ax, (%di)
|
||||
ljmp $0xf000, $0xfff0
|
||||
.code32
|
||||
|
|
74
kern/i386/tsc.c
Normal file
74
kern/i386/tsc.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* kern/i386/tsc.c - x86 TSC time source implementation
|
||||
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
|
||||
* This module uses the RTC (via grub_get_rtc()) to calibrate the TSC to
|
||||
* real time.
|
||||
*
|
||||
* 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/time.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/i386/tsc.h>
|
||||
#include <grub/i386/pit.h>
|
||||
|
||||
/* This defines the value TSC had at the epoch (that is, when we calibrated it). */
|
||||
static grub_uint64_t tsc_boot_time;
|
||||
|
||||
/* Calibrated TSC rate. (In TSC ticks per millisecond.) */
|
||||
static grub_uint64_t tsc_ticks_per_ms;
|
||||
|
||||
|
||||
grub_uint64_t
|
||||
grub_tsc_get_time_ms (void)
|
||||
{
|
||||
return tsc_boot_time + grub_divmod64 (grub_get_tsc (), tsc_ticks_per_ms, 0);
|
||||
}
|
||||
|
||||
|
||||
/* How many RTC ticks to use for calibration loop. (>= 1) */
|
||||
#define CALIBRATION_TICKS 2
|
||||
|
||||
/* Calibrate the TSC based on the RTC. */
|
||||
static void
|
||||
calibrate_tsc (void)
|
||||
{
|
||||
/* First calibrate the TSC rate (relative, not absolute time). */
|
||||
grub_uint64_t start_tsc;
|
||||
grub_uint64_t end_tsc;
|
||||
|
||||
start_tsc = grub_get_tsc ();
|
||||
grub_pit_wait (0xffff);
|
||||
end_tsc = grub_get_tsc ();
|
||||
|
||||
tsc_ticks_per_ms = grub_divmod64 (end_tsc - start_tsc, 55, 0);
|
||||
}
|
||||
|
||||
void
|
||||
grub_tsc_init (void)
|
||||
{
|
||||
if (grub_cpu_is_tsc_supported ())
|
||||
{
|
||||
tsc_boot_time = grub_get_tsc ();
|
||||
calibrate_tsc ();
|
||||
grub_install_get_time_ms (grub_tsc_get_time_ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_install_get_time_ms (grub_rtc_get_time_ms);
|
||||
}
|
||||
}
|
|
@ -17,8 +17,6 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <alloca.h>
|
||||
#include <stdint.h>
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/types.h>
|
||||
|
@ -57,7 +55,7 @@ grub_ieee1275_find_options (void)
|
|||
grub_ieee1275_phandle_t openprom;
|
||||
grub_ieee1275_phandle_t bootrom;
|
||||
int rc;
|
||||
int realmode = 0;
|
||||
grub_uint32_t realmode = 0;
|
||||
char tmp[32];
|
||||
int is_smartfirmware = 0;
|
||||
int is_olpc = 0;
|
||||
|
@ -130,7 +128,7 @@ grub_ieee1275_find_options (void)
|
|||
|
||||
- SD cards. These work fine.
|
||||
|
||||
To avoid brekage, we only need to skip USB probing. However,
|
||||
To avoid breakage, we only need to skip USB probing. However,
|
||||
since detecting SD cards is more reliable, we do that instead.
|
||||
*/
|
||||
|
||||
|
@ -144,6 +142,9 @@ grub_ieee1275_find_options (void)
|
|||
{
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT);
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS);
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET);
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM);
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_ANSI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,9 +152,8 @@ grub_ieee1275_find_options (void)
|
|||
#undef SF
|
||||
#undef OHW
|
||||
|
||||
void cmain (void);
|
||||
void
|
||||
cmain (void)
|
||||
grub_ieee1275_init (void)
|
||||
{
|
||||
grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen);
|
||||
|
||||
|
@ -162,9 +162,4 @@ cmain (void)
|
|||
grub_ieee1275_mmu = 0;
|
||||
|
||||
grub_ieee1275_find_options ();
|
||||
|
||||
/* Now invoke the main function. */
|
||||
grub_main ();
|
||||
|
||||
/* Never reached. */
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* of.c - Access the Open Firmware client interface. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2004,2005,2007,2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003,2004,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
|
||||
|
@ -20,8 +20,8 @@
|
|||
#include <grub/ieee1275/ieee1275.h>
|
||||
#include <grub/types.h>
|
||||
|
||||
#define IEEE1275_PHANDLE_INVALID ((grub_ieee1275_phandle_t) -1)
|
||||
#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t) 0)
|
||||
#define IEEE1275_PHANDLE_INVALID ((grub_ieee1275_cell_t) -1)
|
||||
#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0)
|
||||
#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) -1)
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ grub_ieee1275_finddevice (char *name, grub_ieee1275_phandle_t *phandlep)
|
|||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_cell_t device;
|
||||
grub_ieee1275_phandle_t phandle;
|
||||
grub_ieee1275_cell_t phandle;
|
||||
}
|
||||
args;
|
||||
|
||||
|
@ -56,7 +56,7 @@ grub_ieee1275_get_property (grub_ieee1275_phandle_t phandle,
|
|||
struct get_property_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_phandle_t phandle;
|
||||
grub_ieee1275_cell_t phandle;
|
||||
grub_ieee1275_cell_t prop;
|
||||
grub_ieee1275_cell_t buf;
|
||||
grub_ieee1275_cell_t buflen;
|
||||
|
@ -90,7 +90,7 @@ grub_ieee1275_get_integer_property (grub_ieee1275_phandle_t phandle,
|
|||
/* Integer properties are always in big endian. */
|
||||
if (ret == 0)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
size /= sizeof (grub_uint32_t);
|
||||
for (i = 0; i < size; i++)
|
||||
buf[i] = grub_be_to_cpu32 (buf[i]);
|
||||
|
@ -106,7 +106,7 @@ grub_ieee1275_next_property (grub_ieee1275_phandle_t phandle, char *prev_prop,
|
|||
struct get_property_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_phandle_t phandle;
|
||||
grub_ieee1275_cell_t phandle;
|
||||
grub_ieee1275_cell_t prev_prop;
|
||||
grub_ieee1275_cell_t next_prop;
|
||||
grub_ieee1275_cell_t flags;
|
||||
|
@ -125,13 +125,13 @@ grub_ieee1275_next_property (grub_ieee1275_phandle_t phandle, char *prev_prop,
|
|||
}
|
||||
|
||||
int
|
||||
grub_ieee1275_get_property_length (grub_ieee1275_phandle_t phandle,
|
||||
grub_ieee1275_get_property_length (grub_ieee1275_phandle_t phandle,
|
||||
const char *prop, grub_ssize_t *length)
|
||||
{
|
||||
struct get_property_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_phandle_t phandle;
|
||||
grub_ieee1275_cell_t phandle;
|
||||
grub_ieee1275_cell_t prop;
|
||||
grub_ieee1275_cell_t length;
|
||||
}
|
||||
|
@ -157,14 +157,14 @@ grub_ieee1275_instance_to_package (grub_ieee1275_ihandle_t ihandle,
|
|||
struct instance_to_package_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
grub_ieee1275_phandle_t phandle;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t phandle;
|
||||
}
|
||||
args;
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "instance-to-package", 1, 1);
|
||||
args.ihandle = ihandle;
|
||||
|
||||
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
return -1;
|
||||
*phandlep = args.phandle;
|
||||
|
@ -181,7 +181,7 @@ grub_ieee1275_package_to_path (grub_ieee1275_phandle_t phandle,
|
|||
struct instance_to_package_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_phandle_t phandle;
|
||||
grub_ieee1275_cell_t phandle;
|
||||
grub_ieee1275_cell_t buf;
|
||||
grub_ieee1275_cell_t buflen;
|
||||
grub_ieee1275_cell_t actual;
|
||||
|
@ -192,7 +192,7 @@ grub_ieee1275_package_to_path (grub_ieee1275_phandle_t phandle,
|
|||
args.phandle = phandle;
|
||||
args.buf = (grub_ieee1275_cell_t) path;
|
||||
args.buflen = (grub_ieee1275_cell_t) len;
|
||||
|
||||
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
return -1;
|
||||
if (actual)
|
||||
|
@ -210,7 +210,7 @@ grub_ieee1275_instance_to_path (grub_ieee1275_ihandle_t ihandle,
|
|||
struct instance_to_path_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t buf;
|
||||
grub_ieee1275_cell_t buflen;
|
||||
grub_ieee1275_cell_t actual;
|
||||
|
@ -221,7 +221,7 @@ grub_ieee1275_instance_to_path (grub_ieee1275_ihandle_t ihandle,
|
|||
args.ihandle = ihandle;
|
||||
args.buf = (grub_ieee1275_cell_t) path;
|
||||
args.buflen = (grub_ieee1275_cell_t) len;
|
||||
|
||||
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
return -1;
|
||||
if (actual)
|
||||
|
@ -232,13 +232,13 @@ grub_ieee1275_instance_to_path (grub_ieee1275_ihandle_t ihandle,
|
|||
}
|
||||
|
||||
int
|
||||
grub_ieee1275_write (grub_ieee1275_ihandle_t ihandle, void *buffer,
|
||||
grub_ieee1275_write (grub_ieee1275_ihandle_t ihandle, void *buffer,
|
||||
grub_size_t len, grub_ssize_t *actualp)
|
||||
{
|
||||
struct write_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t buf;
|
||||
grub_ieee1275_cell_t len;
|
||||
grub_ieee1275_cell_t actual;
|
||||
|
@ -264,7 +264,7 @@ grub_ieee1275_read (grub_ieee1275_ihandle_t ihandle, void *buffer,
|
|||
struct write_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t buf;
|
||||
grub_ieee1275_cell_t len;
|
||||
grub_ieee1275_cell_t actual;
|
||||
|
@ -290,7 +290,7 @@ grub_ieee1275_seek (grub_ieee1275_ihandle_t ihandle, int pos_hi,
|
|||
struct write_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t pos_hi;
|
||||
grub_ieee1275_cell_t pos_lo;
|
||||
grub_ieee1275_cell_t result;
|
||||
|
@ -317,8 +317,8 @@ grub_ieee1275_peer (grub_ieee1275_phandle_t node,
|
|||
struct peer_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_phandle_t node;
|
||||
grub_ieee1275_phandle_t result;
|
||||
grub_ieee1275_cell_t node;
|
||||
grub_ieee1275_cell_t result;
|
||||
}
|
||||
args;
|
||||
|
||||
|
@ -340,8 +340,8 @@ grub_ieee1275_child (grub_ieee1275_phandle_t node,
|
|||
struct child_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_phandle_t node;
|
||||
grub_ieee1275_phandle_t result;
|
||||
grub_ieee1275_cell_t node;
|
||||
grub_ieee1275_cell_t result;
|
||||
}
|
||||
args;
|
||||
|
||||
|
@ -364,8 +364,8 @@ grub_ieee1275_parent (grub_ieee1275_phandle_t node,
|
|||
struct parent_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_phandle_t node;
|
||||
grub_ieee1275_phandle_t result;
|
||||
grub_ieee1275_cell_t node;
|
||||
grub_ieee1275_cell_t result;
|
||||
}
|
||||
args;
|
||||
|
||||
|
@ -390,6 +390,9 @@ grub_ieee1275_interpret (const char *command, grub_ieee1275_cell_t *catch)
|
|||
}
|
||||
args;
|
||||
|
||||
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
|
||||
return -1;
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "interpret", 1, 1);
|
||||
args.command = (grub_ieee1275_cell_t) command;
|
||||
|
||||
|
@ -438,7 +441,7 @@ grub_ieee1275_open (const char *path, grub_ieee1275_ihandle_t *result)
|
|||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_cell_t path;
|
||||
grub_ieee1275_ihandle_t result;
|
||||
grub_ieee1275_cell_t result;
|
||||
}
|
||||
args;
|
||||
|
||||
|
@ -459,7 +462,7 @@ grub_ieee1275_close (grub_ieee1275_ihandle_t ihandle)
|
|||
struct close_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
}
|
||||
args;
|
||||
|
||||
|
@ -514,7 +517,7 @@ grub_ieee1275_release (grub_addr_t addr, grub_size_t size)
|
|||
INIT_IEEE1275_COMMON (&args.common, "release", 2, 0);
|
||||
args.addr = addr;
|
||||
args.size = size;
|
||||
|
||||
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
|
@ -528,7 +531,7 @@ grub_ieee1275_set_property (grub_ieee1275_phandle_t phandle,
|
|||
struct set_property_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_phandle_t phandle;
|
||||
grub_ieee1275_cell_t phandle;
|
||||
grub_ieee1275_cell_t propname;
|
||||
grub_ieee1275_cell_t buf;
|
||||
grub_ieee1275_cell_t size;
|
||||
|
@ -557,8 +560,8 @@ grub_ieee1275_set_color (grub_ieee1275_ihandle_t ihandle,
|
|||
struct set_color_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
char *method;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
grub_ieee1275_cell_t method;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t index;
|
||||
grub_ieee1275_cell_t b;
|
||||
grub_ieee1275_cell_t g;
|
||||
|
@ -568,7 +571,7 @@ grub_ieee1275_set_color (grub_ieee1275_ihandle_t ihandle,
|
|||
args;
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
|
||||
args.method = "color!";
|
||||
args.method = (grub_ieee1275_cell_t) "color!";
|
||||
args.ihandle = ihandle;
|
||||
args.index = index;
|
||||
args.r = r;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* init.c -- Initialize GRUB on the newworld mac (PPC). */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2004,2005,2007,2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003,2004,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
|
||||
|
@ -30,6 +30,7 @@
|
|||
#include <grub/time.h>
|
||||
#include <grub/machine/console.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/cpu/kernel.h>
|
||||
#include <grub/ieee1275/ofdisk.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
|
||||
|
@ -46,12 +47,6 @@
|
|||
extern char _start[];
|
||||
extern char _end[];
|
||||
|
||||
void
|
||||
grub_millisleep (grub_uint32_t ms)
|
||||
{
|
||||
grub_millisleep_generic (ms);
|
||||
}
|
||||
|
||||
void
|
||||
grub_exit (void)
|
||||
{
|
||||
|
@ -84,6 +79,13 @@ grub_machine_set_prefix (void)
|
|||
/* We already set prefix in grub_machine_init(). */
|
||||
return;
|
||||
|
||||
if (grub_prefix[0])
|
||||
{
|
||||
grub_env_set ("prefix", grub_prefix);
|
||||
/* Prefix is hardcoded in the core image. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath,
|
||||
sizeof (bootpath), 0))
|
||||
{
|
||||
|
@ -128,9 +130,12 @@ static void grub_claim_heap (void)
|
|||
{
|
||||
unsigned long total = 0;
|
||||
|
||||
auto int heap_init (grub_uint64_t addr, grub_uint64_t len);
|
||||
int heap_init (grub_uint64_t addr, grub_uint64_t len)
|
||||
auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type);
|
||||
int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type)
|
||||
{
|
||||
if (type != 1)
|
||||
return 0;
|
||||
|
||||
len -= 1; /* Required for some firmware. */
|
||||
|
||||
/* Never exceed HEAP_MAX_SIZE */
|
||||
|
@ -145,10 +150,10 @@ static void grub_claim_heap (void)
|
|||
|
||||
/* In theory, firmware should already prevent this from happening by not
|
||||
listing our own image in /memory/available. The check below is intended
|
||||
as a safegard in case that doesn't happen. It does, however, not protect
|
||||
as a safeguard in case that doesn't happen. However, it doesn't protect
|
||||
us from corrupting our module area, which extends up to a
|
||||
yet-undetermined region above _end. */
|
||||
if ((addr < _end) && ((addr + len) > _start))
|
||||
if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start))
|
||||
{
|
||||
grub_printf ("Warning: attempt to claim over our own code!\n");
|
||||
len = 0;
|
||||
|
@ -159,7 +164,7 @@ static void grub_claim_heap (void)
|
|||
/* Claim and use it. */
|
||||
if (grub_claimmap (addr, len) < 0)
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"Failed to claim heap at 0x%llx, len 0x%llx\n",
|
||||
"failed to claim heap at 0x%llx, len 0x%llx",
|
||||
addr, len);
|
||||
grub_mm_init_region ((void *) (grub_addr_t) addr, len);
|
||||
}
|
||||
|
@ -171,18 +176,50 @@ static void grub_claim_heap (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
grub_available_iterate (heap_init);
|
||||
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
|
||||
heap_init (HEAP_MAX_ADDR - HEAP_MIN_SIZE, HEAP_MIN_SIZE, 1);
|
||||
else
|
||||
grub_machine_mmap_iterate (heap_init);
|
||||
}
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
grub_uint32_t grub_upper_mem;
|
||||
|
||||
/* We need to call this before grub_claim_memory. */
|
||||
static void
|
||||
grub_get_extended_memory (void)
|
||||
{
|
||||
auto int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type);
|
||||
int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type)
|
||||
{
|
||||
if (type == 1 && addr == 0x100000)
|
||||
{
|
||||
grub_upper_mem = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_machine_mmap_iterate (find_ext_mem);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static grub_uint64_t ieee1275_get_time_ms (void);
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
char args[256];
|
||||
int actual;
|
||||
grub_ssize_t actual;
|
||||
|
||||
grub_ieee1275_init ();
|
||||
|
||||
grub_console_init ();
|
||||
#ifdef __i386__
|
||||
grub_keyboard_controller_init ();
|
||||
grub_get_extended_memory ();
|
||||
#endif
|
||||
grub_claim_heap ();
|
||||
grub_ofdisk_init ();
|
||||
|
@ -220,6 +257,8 @@ grub_machine_init (void)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
grub_install_get_time_ms (ieee1275_get_time_ms);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -229,8 +268,8 @@ grub_machine_fini (void)
|
|||
grub_console_fini ();
|
||||
}
|
||||
|
||||
grub_uint32_t
|
||||
grub_get_rtc (void)
|
||||
static grub_uint64_t
|
||||
ieee1275_get_time_ms (void)
|
||||
{
|
||||
grub_uint32_t msecs = 0;
|
||||
|
||||
|
@ -239,8 +278,14 @@ grub_get_rtc (void)
|
|||
return msecs;
|
||||
}
|
||||
|
||||
grub_uint32_t
|
||||
grub_get_rtc (void)
|
||||
{
|
||||
return ieee1275_get_time_ms ();
|
||||
}
|
||||
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
return ALIGN_UP(_end + GRUB_MOD_GAP, GRUB_MOD_ALIGN);
|
||||
return ALIGN_UP((grub_addr_t) _end + GRUB_MOD_GAP, GRUB_MOD_ALIGN);
|
||||
}
|
74
kern/ieee1275/mmap.c
Normal file
74
kern/ieee1275/mmap.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2004,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/machine/memory.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
#include <grub/types.h>
|
||||
|
||||
grub_err_t
|
||||
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
|
||||
{
|
||||
grub_ieee1275_phandle_t root;
|
||||
grub_ieee1275_phandle_t memory;
|
||||
grub_uint32_t available[32];
|
||||
grub_ssize_t available_size;
|
||||
grub_uint32_t address_cells = 1;
|
||||
grub_uint32_t size_cells = 1;
|
||||
int i;
|
||||
|
||||
/* Determine the format of each entry in `available'. */
|
||||
grub_ieee1275_finddevice ("/", &root);
|
||||
grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells,
|
||||
sizeof address_cells, 0);
|
||||
grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells,
|
||||
sizeof size_cells, 0);
|
||||
|
||||
if (size_cells > address_cells)
|
||||
address_cells = size_cells;
|
||||
|
||||
/* Load `/memory/available'. */
|
||||
if (grub_ieee1275_finddevice ("/memory", &memory))
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
"couldn't find /memory node");
|
||||
if (grub_ieee1275_get_integer_property (memory, "available", available,
|
||||
sizeof available, &available_size))
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
"couldn't examine /memory/available property");
|
||||
|
||||
/* Decode each entry and call `hook'. */
|
||||
i = 0;
|
||||
available_size /= sizeof (grub_uint32_t);
|
||||
while (i < available_size)
|
||||
{
|
||||
grub_uint64_t address;
|
||||
grub_uint64_t size;
|
||||
|
||||
address = available[i++];
|
||||
if (address_cells == 2)
|
||||
address = (address << 32) | available[i++];
|
||||
|
||||
size = available[i++];
|
||||
if (size_cells == 2)
|
||||
size = (size << 32) | available[i++];
|
||||
|
||||
if (hook (address, size, GRUB_MACHINE_MEMORY_AVAILABLE))
|
||||
break;
|
||||
}
|
||||
|
||||
return grub_errno;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* openfw.c -- Open firmware support functions. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2004,2005,2007,2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -17,7 +17,6 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <alloca.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
|
@ -32,39 +31,62 @@ enum grub_ieee1275_parse_type
|
|||
};
|
||||
|
||||
/* Walk children of 'devpath', calling hook for each. */
|
||||
grub_err_t
|
||||
int
|
||||
grub_children_iterate (char *devpath,
|
||||
int (*hook) (struct grub_ieee1275_devalias *alias))
|
||||
int (*hook) (struct grub_ieee1275_devalias *alias))
|
||||
{
|
||||
grub_ieee1275_phandle_t dev;
|
||||
grub_ieee1275_phandle_t child;
|
||||
char *childtype, *childpath;
|
||||
char *childname, *fullname;
|
||||
int ret = 0;
|
||||
|
||||
if (grub_ieee1275_finddevice (devpath, &dev))
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Unknown device");
|
||||
return 0;
|
||||
|
||||
if (grub_ieee1275_child (dev, &child))
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "Device has no children");
|
||||
return 0;
|
||||
|
||||
childtype = grub_malloc (IEEE1275_MAX_PROP_LEN);
|
||||
if (!childtype)
|
||||
return 0;
|
||||
childpath = grub_malloc (IEEE1275_MAX_PATH_LEN);
|
||||
if (!childpath)
|
||||
{
|
||||
grub_free (childtype);
|
||||
return 0;
|
||||
}
|
||||
childname = grub_malloc (IEEE1275_MAX_PROP_LEN);
|
||||
if (!childname)
|
||||
{
|
||||
grub_free (childpath);
|
||||
grub_free (childtype);
|
||||
return 0;
|
||||
}
|
||||
fullname = grub_malloc (IEEE1275_MAX_PATH_LEN);
|
||||
if (!fullname)
|
||||
{
|
||||
grub_free (childname);
|
||||
grub_free (childpath);
|
||||
grub_free (childtype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* XXX: Don't use hardcoded path lengths. */
|
||||
char childtype[64];
|
||||
char childpath[64];
|
||||
char childname[64];
|
||||
char fullname[64];
|
||||
struct grub_ieee1275_devalias alias;
|
||||
int actual;
|
||||
grub_ssize_t actual;
|
||||
|
||||
if (grub_ieee1275_get_property (child, "device_type", &childtype,
|
||||
sizeof childtype, &actual))
|
||||
if (grub_ieee1275_get_property (child, "device_type", childtype,
|
||||
IEEE1275_MAX_PROP_LEN, &actual))
|
||||
continue;
|
||||
|
||||
if (grub_ieee1275_package_to_path (child, childpath, sizeof childpath,
|
||||
&actual))
|
||||
if (grub_ieee1275_package_to_path (child, childpath,
|
||||
IEEE1275_MAX_PATH_LEN, &actual))
|
||||
continue;
|
||||
|
||||
if (grub_ieee1275_get_property (child, "name", &childname,
|
||||
sizeof childname, &actual))
|
||||
if (grub_ieee1275_get_property (child, "name", childname,
|
||||
IEEE1275_MAX_PROP_LEN, &actual))
|
||||
continue;
|
||||
|
||||
grub_sprintf (fullname, "%s/%s", devpath, childname);
|
||||
|
@ -72,25 +94,43 @@ grub_children_iterate (char *devpath,
|
|||
alias.type = childtype;
|
||||
alias.path = childpath;
|
||||
alias.name = fullname;
|
||||
hook (&alias);
|
||||
ret = hook (&alias);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
while (grub_ieee1275_peer (child, &child));
|
||||
|
||||
return 0;
|
||||
grub_free (fullname);
|
||||
grub_free (childname);
|
||||
grub_free (childpath);
|
||||
grub_free (childtype);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Iterate through all device aliases. This function can be used to
|
||||
find a device of a specific type. */
|
||||
grub_err_t
|
||||
int
|
||||
grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
|
||||
{
|
||||
grub_ieee1275_phandle_t aliases;
|
||||
char aliasname[32];
|
||||
int actual;
|
||||
char *aliasname, *devtype;
|
||||
grub_ssize_t actual;
|
||||
struct grub_ieee1275_devalias alias;
|
||||
int ret = 0;
|
||||
|
||||
if (grub_ieee1275_finddevice ("/aliases", &aliases))
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
aliasname = grub_malloc (IEEE1275_MAX_PROP_LEN);
|
||||
if (!aliasname)
|
||||
return 0;
|
||||
devtype = grub_malloc (IEEE1275_MAX_PROP_LEN);
|
||||
if (!devtype)
|
||||
{
|
||||
grub_free (aliasname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the first property. */
|
||||
aliasname[0] = '\0';
|
||||
|
@ -100,8 +140,6 @@ grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
|
|||
grub_ieee1275_phandle_t dev;
|
||||
grub_ssize_t pathlen;
|
||||
char *devpath;
|
||||
/* XXX: This should be large enough for any possible case. */
|
||||
char devtype[64];
|
||||
|
||||
grub_dprintf ("devalias", "devalias name = %s\n", aliasname);
|
||||
|
||||
|
@ -111,9 +149,17 @@ grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
|
|||
if (!grub_strcmp (aliasname, "name"))
|
||||
continue;
|
||||
|
||||
/* Sun's OpenBoot often doesn't zero terminate the device alias
|
||||
strings, so we will add a NULL byte at the end explicitly. */
|
||||
pathlen += 1;
|
||||
|
||||
devpath = grub_malloc (pathlen);
|
||||
if (! devpath)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (devtype);
|
||||
grub_free (aliasname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (grub_ieee1275_get_property (aliases, aliasname, devpath, pathlen,
|
||||
&actual))
|
||||
|
@ -121,6 +167,7 @@ grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
|
|||
grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname);
|
||||
goto nextprop;
|
||||
}
|
||||
devpath [actual] = '\0';
|
||||
|
||||
if (grub_ieee1275_finddevice (devpath, &dev))
|
||||
{
|
||||
|
@ -129,71 +176,26 @@ grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
|
|||
}
|
||||
|
||||
if (grub_ieee1275_get_property (dev, "device_type", devtype,
|
||||
sizeof devtype, &actual))
|
||||
IEEE1275_MAX_PROP_LEN, &actual))
|
||||
{
|
||||
grub_dprintf ("devalias", "get device type failed\n");
|
||||
goto nextprop;
|
||||
/* NAND device don't have device_type property. */
|
||||
devtype[0] = 0;
|
||||
}
|
||||
|
||||
alias.name = aliasname;
|
||||
alias.path = devpath;
|
||||
alias.type = devtype;
|
||||
hook (&alias);
|
||||
ret = hook (&alias);
|
||||
|
||||
nextprop:
|
||||
grub_free (devpath);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t grub_available_iterate (int (*hook) (grub_uint64_t, grub_uint64_t))
|
||||
{
|
||||
grub_ieee1275_phandle_t root;
|
||||
grub_ieee1275_phandle_t memory;
|
||||
grub_uint32_t available[32];
|
||||
grub_ssize_t available_size;
|
||||
int address_cells = 1;
|
||||
int size_cells = 1;
|
||||
unsigned int i;
|
||||
|
||||
/* Determine the format of each entry in `available'. */
|
||||
grub_ieee1275_finddevice ("/", &root);
|
||||
grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells,
|
||||
sizeof address_cells, 0);
|
||||
grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells,
|
||||
sizeof size_cells, 0);
|
||||
|
||||
/* Load `/memory/available'. */
|
||||
if (grub_ieee1275_finddevice ("/memory", &memory))
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
"Couldn't find /memory node");
|
||||
if (grub_ieee1275_get_integer_property (memory, "available", available,
|
||||
sizeof available, &available_size))
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
"Couldn't examine /memory/available property");
|
||||
|
||||
/* Decode each entry and call `hook'. */
|
||||
i = 0;
|
||||
available_size /= sizeof (grub_uint32_t);
|
||||
while (i < available_size)
|
||||
{
|
||||
grub_uint64_t address;
|
||||
grub_uint64_t size;
|
||||
|
||||
address = available[i++];
|
||||
if (address_cells == 2)
|
||||
address = (address << 32) | available[i++];
|
||||
|
||||
size = available[i++];
|
||||
if (size_cells == 2)
|
||||
size = (size << 32) | available[i++];
|
||||
|
||||
if (hook (address, size))
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return grub_errno;
|
||||
grub_free (devtype);
|
||||
grub_free (aliasname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Call the "map" method of /chosen/mmu. */
|
||||
|
@ -203,17 +205,17 @@ grub_map (grub_addr_t phys, grub_addr_t virt, grub_uint32_t size,
|
|||
{
|
||||
struct map_args {
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
char *method;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
grub_uint32_t mode;
|
||||
grub_uint32_t size;
|
||||
grub_uint32_t virt;
|
||||
grub_uint32_t phys;
|
||||
int catch_result;
|
||||
grub_ieee1275_cell_t method;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t mode;
|
||||
grub_ieee1275_cell_t size;
|
||||
grub_ieee1275_cell_t virt;
|
||||
grub_ieee1275_cell_t phys;
|
||||
grub_ieee1275_cell_t catch_result;
|
||||
} args;
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
|
||||
args.method = "map";
|
||||
args.method = (grub_ieee1275_cell_t) "map";
|
||||
args.ihandle = grub_ieee1275_mmu;
|
||||
args.phys = phys;
|
||||
args.virt = virt;
|
||||
|
@ -235,7 +237,8 @@ grub_claimmap (grub_addr_t addr, grub_size_t size)
|
|||
if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_REAL_MODE)
|
||||
&& grub_map (addr, addr, size, 0x00))
|
||||
{
|
||||
grub_printf ("map failed: address 0x%x, size 0x%x\n", addr, size);
|
||||
grub_printf ("map failed: address 0x%llx, size 0x%llx\n",
|
||||
(long long) addr, (long long) size);
|
||||
grub_ieee1275_release (addr, size);
|
||||
return -1;
|
||||
}
|
||||
|
@ -305,13 +308,13 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
|
|||
file path properly. */
|
||||
if (grub_ieee1275_finddevice (device, &dev))
|
||||
{
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s not found\n", device);
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "device %s not found", device);
|
||||
goto fail;
|
||||
}
|
||||
if (grub_ieee1275_get_property (dev, "device_type", &type, sizeof type, 0))
|
||||
{
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
"Device %s lacks a device_type property\n", device);
|
||||
"device %s lacks a device_type property", device);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -396,16 +399,19 @@ grub_ieee1275_encode_devname (const char *path)
|
|||
return encoding;
|
||||
}
|
||||
|
||||
/* On i386, a firmware-independant grub_reboot() is provided by realmode.S. */
|
||||
#ifndef __i386__
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
grub_ieee1275_interpret ("reset-all", 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
grub_halt (void)
|
||||
{
|
||||
/* Not standarized. We try both known commands. */
|
||||
/* Not standardized. We try both known commands. */
|
||||
|
||||
grub_ieee1275_interpret ("shut-down", 0);
|
||||
grub_ieee1275_interpret ("power-off", 0);
|
131
kern/list.c
Normal file
131
kern/list.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* list.c - grub list function */
|
||||
/*
|
||||
* 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/list.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
|
||||
void
|
||||
grub_list_push (grub_list_t *head, grub_list_t item)
|
||||
{
|
||||
item->next = *head;
|
||||
*head = item;
|
||||
}
|
||||
|
||||
void *
|
||||
grub_list_pop (grub_list_t *head)
|
||||
{
|
||||
grub_list_t item;
|
||||
|
||||
item = *head;
|
||||
if (item)
|
||||
*head = item->next;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void
|
||||
grub_list_remove (grub_list_t *head, grub_list_t item)
|
||||
{
|
||||
grub_list_t *p, q;
|
||||
|
||||
for (p = head, q = *p; q; p = &(q->next), q = q->next)
|
||||
if (q == item)
|
||||
{
|
||||
*p = q->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
grub_list_iterate (grub_list_t head, grub_list_hook_t hook)
|
||||
{
|
||||
grub_list_t p;
|
||||
|
||||
for (p = head; p; p = p->next)
|
||||
if (hook (p))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
grub_list_insert (grub_list_t *head, grub_list_t item,
|
||||
grub_list_test_t test)
|
||||
{
|
||||
grub_list_t *p, q;
|
||||
|
||||
for (p = head, q = *p; q; p = &(q->next), q = q->next)
|
||||
if (test (item, q))
|
||||
break;
|
||||
|
||||
*p = item;
|
||||
item->next = q;
|
||||
}
|
||||
|
||||
void *
|
||||
grub_named_list_find (grub_named_list_t head, const char *name)
|
||||
{
|
||||
grub_named_list_t result = NULL;
|
||||
|
||||
auto int list_find (grub_named_list_t item);
|
||||
int list_find (grub_named_list_t item)
|
||||
{
|
||||
if (! grub_strcmp (item->name, name))
|
||||
{
|
||||
result = item;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_find);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
grub_prio_list_insert (grub_prio_list_t *head, grub_prio_list_t nitem)
|
||||
{
|
||||
int inactive = 0;
|
||||
|
||||
auto int test (grub_prio_list_t new_item, grub_prio_list_t item);
|
||||
int test (grub_prio_list_t new_item, grub_prio_list_t item)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = grub_strcmp (new_item->name, item->name);
|
||||
if (r)
|
||||
return (r < 0);
|
||||
|
||||
if (new_item->prio >= (item->prio & GRUB_PRIO_LIST_PRIO_MASK))
|
||||
{
|
||||
item->prio &= ~GRUB_PRIO_LIST_FLAG_ACTIVE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
inactive = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_list_insert (GRUB_AS_LIST_P (head), GRUB_AS_LIST (nitem),
|
||||
(grub_list_test_t) test);
|
||||
if (! inactive)
|
||||
nitem->prio |= GRUB_PRIO_LIST_FLAG_ACTIVE;
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2004,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/loader.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/kernel.h>
|
||||
|
||||
static grub_err_t (*grub_loader_boot_func) (void);
|
||||
static grub_err_t (*grub_loader_unload_func) (void);
|
||||
static int grub_loader_noreturn;
|
||||
|
||||
static int grub_loader_loaded;
|
||||
|
||||
int
|
||||
grub_loader_is_loaded (void)
|
||||
{
|
||||
return grub_loader_loaded;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (! grub_loader_loaded)
|
||||
return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");
|
||||
|
||||
if (grub_loader_noreturn)
|
||||
grub_machine_fini ();
|
||||
|
||||
return (grub_loader_boot_func) ();
|
||||
}
|
||||
|
83
kern/main.c
83
kern/main.c
|
@ -1,7 +1,7 @@
|
|||
/* main.c - the kernel main routine */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2005,2006,2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,2003,2005,2006,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
|
||||
|
@ -19,18 +19,19 @@
|
|||
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/rescue.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/reader.h>
|
||||
#include <grub/parser.h>
|
||||
|
||||
/* Load all modules in core. */
|
||||
static void
|
||||
grub_load_modules (void)
|
||||
void
|
||||
grub_module_iterate (int (*hook) (struct grub_module_header *header))
|
||||
{
|
||||
struct grub_module_info *modinfo;
|
||||
struct grub_module_header *header;
|
||||
|
@ -38,7 +39,7 @@ grub_load_modules (void)
|
|||
|
||||
modbase = grub_arch_modules_addr ();
|
||||
modinfo = (struct grub_module_info *) modbase;
|
||||
|
||||
|
||||
/* Check if there are any modules. */
|
||||
if ((modinfo == 0) || modinfo->magic != GRUB_MODULE_MAGIC)
|
||||
return;
|
||||
|
@ -47,13 +48,48 @@ grub_load_modules (void)
|
|||
header < (struct grub_module_header *) (modbase + modinfo->size);
|
||||
header = (struct grub_module_header *) ((char *) header + header->size))
|
||||
{
|
||||
if (! grub_dl_load_core ((char *) header + header->offset,
|
||||
(header->size - header->offset)))
|
||||
if (hook (header))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load all modules in core. */
|
||||
static void
|
||||
grub_load_modules (void)
|
||||
{
|
||||
auto int hook (struct grub_module_header *);
|
||||
int hook (struct grub_module_header *header)
|
||||
{
|
||||
/* Not an ELF module, skip. */
|
||||
if (header->type != OBJ_TYPE_ELF)
|
||||
return 0;
|
||||
|
||||
if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header),
|
||||
(header->size - sizeof (struct grub_module_header))))
|
||||
grub_fatal ("%s", grub_errmsg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add the region where modules reside into dynamic memory. */
|
||||
grub_mm_init_region ((void *) modinfo, modinfo->size);
|
||||
grub_module_iterate (hook);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_load_config (void)
|
||||
{
|
||||
auto int hook (struct grub_module_header *);
|
||||
int hook (struct grub_module_header *header)
|
||||
{
|
||||
/* Not an ELF module, skip. */
|
||||
if (header->type != OBJ_TYPE_CONFIG)
|
||||
return 0;
|
||||
|
||||
grub_parser_execute ((char *) header +
|
||||
sizeof (struct grub_module_header));
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_module_iterate (hook);
|
||||
}
|
||||
|
||||
/* Write hook for the environment variables of root. Remove surrounding
|
||||
|
@ -64,7 +100,7 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
|
|||
{
|
||||
/* XXX Is it better to check the existence of the device? */
|
||||
grub_size_t len = grub_strlen (val);
|
||||
|
||||
|
||||
if (val[0] == '(' && val[len - 1] == ')')
|
||||
return grub_strndup (val + 1, len - 2);
|
||||
|
||||
|
@ -79,9 +115,9 @@ grub_set_root_dev (void)
|
|||
|
||||
grub_register_variable_hook ("root", 0, grub_env_write_root);
|
||||
grub_env_export ("root");
|
||||
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
|
||||
|
||||
if (prefix)
|
||||
{
|
||||
char *dev;
|
||||
|
@ -101,9 +137,12 @@ grub_load_normal_mode (void)
|
|||
{
|
||||
/* Load the module. */
|
||||
grub_dl_load ("normal");
|
||||
|
||||
/* Ignore any error, because we have the rescue mode anyway. */
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
/* Something went wrong. Print errors here to let user know why we're entering rescue mode. */
|
||||
grub_print_error ();
|
||||
grub_errno = 0;
|
||||
|
||||
grub_command_execute ("normal", 0, 0);
|
||||
}
|
||||
|
||||
/* The main routine. */
|
||||
|
@ -125,11 +164,13 @@ grub_main (void)
|
|||
/* It is better to set the root device as soon as possible,
|
||||
for convenience. */
|
||||
grub_machine_set_prefix ();
|
||||
grub_env_export ("prefix");
|
||||
grub_set_root_dev ();
|
||||
|
||||
/* Load the normal mode module. */
|
||||
grub_register_core_commands ();
|
||||
grub_register_rescue_parser ();
|
||||
|
||||
grub_load_config ();
|
||||
grub_load_normal_mode ();
|
||||
|
||||
/* Enter the rescue mode. */
|
||||
grub_enter_rescue_mode ();
|
||||
grub_rescue_run ();
|
||||
}
|
||||
|
|
538
kern/misc.c
538
kern/misc.c
|
@ -1,7 +1,7 @@
|
|||
/* misc.c - definitions of misc functions */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,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
|
||||
|
@ -23,7 +23,22 @@
|
|||
#include <stdarg.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static int
|
||||
grub_iswordseparator (int c)
|
||||
{
|
||||
return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
|
||||
}
|
||||
|
||||
/* grub_gettext_dummy is not translating anything. */
|
||||
const char *
|
||||
grub_gettext_dummy (const char *s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
const char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
|
||||
|
||||
void *
|
||||
grub_memmove (void *dest, const void *src, grub_size_t n)
|
||||
|
@ -38,18 +53,30 @@ grub_memmove (void *dest, const void *src, grub_size_t n)
|
|||
{
|
||||
d += n;
|
||||
s += n;
|
||||
|
||||
|
||||
while (n--)
|
||||
*--d = *--s;
|
||||
}
|
||||
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
#ifndef APPLE_CC
|
||||
void *memmove (void *dest, const void *src, grub_size_t n)
|
||||
__attribute__ ((alias ("grub_memmove")));
|
||||
/* GCC emits references to memcpy() for struct copies etc. */
|
||||
void *memcpy (void *dest, const void *src, grub_size_t n)
|
||||
__attribute__ ((alias ("grub_memmove")));
|
||||
#else
|
||||
void *memcpy (void *dest, const void *src, grub_size_t n)
|
||||
{
|
||||
return grub_memmove (dest, src, n);
|
||||
}
|
||||
void *memmove (void *dest, const void *src, grub_size_t n)
|
||||
{
|
||||
return grub_memmove (dest, src, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
char *
|
||||
grub_strcpy (char *dest, const char *src)
|
||||
|
@ -66,7 +93,7 @@ char *
|
|||
grub_strncpy (char *dest, const char *src, int c)
|
||||
{
|
||||
char *p = dest;
|
||||
|
||||
|
||||
while ((*p++ = *src++) != '\0' && --c)
|
||||
;
|
||||
|
||||
|
@ -86,47 +113,70 @@ grub_stpcpy (char *dest, const char *src)
|
|||
return d - 1;
|
||||
}
|
||||
|
||||
char *
|
||||
grub_strcat (char *dest, const char *src)
|
||||
{
|
||||
char *p = dest;
|
||||
|
||||
while (*p)
|
||||
p++;
|
||||
|
||||
while ((*p++ = *src++) != '\0')
|
||||
;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *
|
||||
grub_strncat (char *dest, const char *src, int c)
|
||||
{
|
||||
char *p = dest;
|
||||
|
||||
while (*p)
|
||||
p++;
|
||||
|
||||
while ((*p++ = *src++) != '\0' && --c)
|
||||
;
|
||||
*(--p) = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int
|
||||
grub_printf (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
|
||||
va_start (ap, fmt);
|
||||
ret = grub_vprintf (fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
grub_printf_ (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start (ap, fmt);
|
||||
ret = grub_vprintf (_(fmt), ap);
|
||||
va_end (ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
grub_puts (const char *s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
grub_putchar (*s);
|
||||
s++;
|
||||
}
|
||||
grub_putchar ('\n');
|
||||
|
||||
return 1; /* Cannot fail. */
|
||||
}
|
||||
|
||||
int
|
||||
grub_puts_ (const char *s)
|
||||
{
|
||||
return grub_puts (_(s));
|
||||
}
|
||||
|
||||
#if defined (APPLE_CC) && ! defined (GRUB_UTIL)
|
||||
int
|
||||
grub_err_printf (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start (ap, fmt);
|
||||
ret = grub_vprintf (fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ! defined (APPLE_CC) && ! defined (GRUB_UTIL)
|
||||
int grub_err_printf (const char *fmt, ...)
|
||||
__attribute__ ((alias("grub_printf")));
|
||||
#endif
|
||||
|
||||
void
|
||||
grub_real_dprintf (const char *file, const int line, const char *condition,
|
||||
|
@ -134,10 +184,10 @@ grub_real_dprintf (const char *file, const int line, const char *condition,
|
|||
{
|
||||
va_list args;
|
||||
const char *debug = grub_env_get ("debug");
|
||||
|
||||
|
||||
if (! debug)
|
||||
return;
|
||||
|
||||
|
||||
if (grub_strword (debug, "all") || grub_strword (debug, condition))
|
||||
{
|
||||
grub_printf ("%s:%d: ", file, line);
|
||||
|
@ -162,7 +212,7 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n)
|
|||
{
|
||||
const char *t1 = s1;
|
||||
const char *t2 = s2;
|
||||
|
||||
|
||||
while (n--)
|
||||
{
|
||||
if (*t1 != *t2)
|
||||
|
@ -174,8 +224,15 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#ifndef APPLE_CC
|
||||
int memcmp (const void *s1, const void *s2, grub_size_t n)
|
||||
__attribute__ ((alias ("grub_memcmp")));
|
||||
#else
|
||||
int memcmp (const void *s1, const void *s2, grub_size_t n)
|
||||
{
|
||||
return grub_memcmp (s1, s2, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
grub_strcmp (const char *s1, const char *s2)
|
||||
|
@ -183,8 +240,8 @@ grub_strcmp (const char *s1, const char *s2)
|
|||
while (*s1 && *s2)
|
||||
{
|
||||
if (*s1 != *s2)
|
||||
return (int) *s1 - (int) *s2;
|
||||
|
||||
break;
|
||||
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
@ -197,12 +254,12 @@ grub_strncmp (const char *s1, const char *s2, grub_size_t n)
|
|||
{
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
while (*s1 && *s2 && --n)
|
||||
{
|
||||
if (*s1 != *s2)
|
||||
return (int) *s1 - (int) *s2;
|
||||
|
||||
break;
|
||||
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
@ -210,33 +267,15 @@ grub_strncmp (const char *s1, const char *s2, grub_size_t n)
|
|||
return (int) *s1 - (int) *s2;
|
||||
}
|
||||
|
||||
int
|
||||
grub_strncasecmp (const char *s1, const char *s2, int c)
|
||||
{
|
||||
int p = 1;
|
||||
|
||||
while (grub_tolower (*s1) && grub_tolower (*s2) && p < c)
|
||||
{
|
||||
if (grub_tolower (*s1) != grub_tolower (*s2))
|
||||
return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
|
||||
|
||||
s1++;
|
||||
s2++;
|
||||
p++;
|
||||
}
|
||||
|
||||
return (int) *s1 - (int) *s2;
|
||||
}
|
||||
|
||||
char *
|
||||
grub_strchr (const char *s, int c)
|
||||
{
|
||||
while (*s)
|
||||
do
|
||||
{
|
||||
if (*s == c)
|
||||
return (char *) s;
|
||||
s++;
|
||||
}
|
||||
while (*s++);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -244,14 +283,14 @@ grub_strchr (const char *s, int c)
|
|||
char *
|
||||
grub_strrchr (const char *s, int c)
|
||||
{
|
||||
char *p = 0;
|
||||
char *p = NULL;
|
||||
|
||||
while (*s)
|
||||
do
|
||||
{
|
||||
if (*s == c)
|
||||
p = (char *) s;
|
||||
s++;
|
||||
}
|
||||
while (*s++);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -271,7 +310,7 @@ grub_strstr (const char *haystack, const char *needle)
|
|||
/* Speed up the following searches of needle by caching its first
|
||||
character. */
|
||||
char b = *needle++;
|
||||
|
||||
|
||||
for (;; haystack++)
|
||||
{
|
||||
if (*haystack == '\0')
|
||||
|
@ -339,12 +378,6 @@ grub_strword (const char *haystack, const char *needle)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
grub_iswordseparator (int c)
|
||||
{
|
||||
return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
|
||||
}
|
||||
|
||||
int
|
||||
grub_isspace (int c)
|
||||
{
|
||||
|
@ -357,33 +390,6 @@ grub_isprint (int c)
|
|||
return (c >= ' ' && c <= '~');
|
||||
}
|
||||
|
||||
int
|
||||
grub_isalpha (int c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
int
|
||||
grub_isdigit (int c)
|
||||
{
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
int
|
||||
grub_isgraph (int c)
|
||||
{
|
||||
return (c >= '!' && c <= '~');
|
||||
}
|
||||
|
||||
int
|
||||
grub_tolower (int c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return c - 'A' + 'a';
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
unsigned long
|
||||
grub_strtoul (const char *str, char **end, int base)
|
||||
|
@ -405,14 +411,14 @@ grub_strtoull (const char *str, char **end, int base)
|
|||
{
|
||||
unsigned long long num = 0;
|
||||
int found = 0;
|
||||
|
||||
|
||||
/* Skip white spaces. */
|
||||
while (*str && grub_isspace (*str))
|
||||
str++;
|
||||
|
||||
|
||||
/* Guess the base, if not specified. The prefix `0x' means 16, and
|
||||
the prefix `0' means 8. */
|
||||
if (base == 0 && str[0] == '0')
|
||||
if (str[0] == '0')
|
||||
{
|
||||
if (str[1] == 'x')
|
||||
{
|
||||
|
@ -422,10 +428,10 @@ grub_strtoull (const char *str, char **end, int base)
|
|||
str += 2;
|
||||
}
|
||||
}
|
||||
else if (str[1] >= '0' && str[1] <= '7')
|
||||
else if (base == 0 && str[1] >= '0' && str[1] <= '7')
|
||||
base = 8;
|
||||
}
|
||||
|
||||
|
||||
if (base == 0)
|
||||
base = 10;
|
||||
|
||||
|
@ -459,7 +465,7 @@ grub_strtoull (const char *str, char **end, int base)
|
|||
grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (end)
|
||||
*end = (char *) str;
|
||||
|
||||
|
@ -471,7 +477,7 @@ grub_strdup (const char *s)
|
|||
{
|
||||
grub_size_t len;
|
||||
char *p;
|
||||
|
||||
|
||||
len = grub_strlen (s) + 1;
|
||||
p = (char *) grub_malloc (len);
|
||||
if (! p)
|
||||
|
@ -485,14 +491,14 @@ grub_strndup (const char *s, grub_size_t n)
|
|||
{
|
||||
grub_size_t len;
|
||||
char *p;
|
||||
|
||||
|
||||
len = grub_strlen (s);
|
||||
if (len > n)
|
||||
len = n;
|
||||
p = (char *) grub_malloc (len + 1);
|
||||
if (! p)
|
||||
return 0;
|
||||
|
||||
|
||||
grub_memcpy (p, s, len);
|
||||
p[len] = '\0';
|
||||
return p;
|
||||
|
@ -508,8 +514,15 @@ grub_memset (void *s, int c, grub_size_t n)
|
|||
|
||||
return s;
|
||||
}
|
||||
#ifndef APPLE_CC
|
||||
void *memset (void *s, int c, grub_size_t n)
|
||||
__attribute__ ((alias ("grub_memset")));
|
||||
#else
|
||||
void *memset (void *s, int c, grub_size_t n)
|
||||
{
|
||||
return grub_memset (s, c, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
grub_size_t
|
||||
grub_strlen (const char *s)
|
||||
|
@ -539,31 +552,6 @@ grub_reverse (char *str)
|
|||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_itoa (char *str, int c, unsigned n)
|
||||
{
|
||||
unsigned base = (c == 'x') ? 16 : 10;
|
||||
char *p;
|
||||
|
||||
if ((int) n < 0 && c == 'd')
|
||||
{
|
||||
n = (unsigned) (-((int) n));
|
||||
*str++ = '-';
|
||||
}
|
||||
|
||||
p = str;
|
||||
do
|
||||
{
|
||||
unsigned d = n % base;
|
||||
*p++ = (d > 9) ? d + 'a' - 10 : d + '0';
|
||||
}
|
||||
while (n /= base);
|
||||
*p = 0;
|
||||
|
||||
grub_reverse (str);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Divide N by D, return the quotient, and store the remainder in *R. */
|
||||
grub_uint64_t
|
||||
grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
|
||||
|
@ -584,17 +572,17 @@ grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
|
|||
|
||||
return ((grub_uint32_t) n) / d;
|
||||
}
|
||||
|
||||
|
||||
while (bits--)
|
||||
{
|
||||
m <<= 1;
|
||||
|
||||
|
||||
if (n & (1ULL << 63))
|
||||
m |= 1;
|
||||
|
||||
|
||||
q <<= 1;
|
||||
n <<= 1;
|
||||
|
||||
|
||||
if (m >= d)
|
||||
{
|
||||
q |= 1;
|
||||
|
@ -604,7 +592,7 @@ grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
|
|||
|
||||
if (r)
|
||||
*r = m;
|
||||
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
|
@ -615,7 +603,7 @@ grub_lltoa (char *str, int c, unsigned long long n)
|
|||
{
|
||||
unsigned base = (c == 'x') ? 16 : 10;
|
||||
char *p;
|
||||
|
||||
|
||||
if ((long long) n < 0 && c == 'd')
|
||||
{
|
||||
n = (unsigned long long) (-((long long) n));
|
||||
|
@ -636,36 +624,18 @@ grub_lltoa (char *str, int c, unsigned long long n)
|
|||
do
|
||||
{
|
||||
unsigned m;
|
||||
|
||||
|
||||
n = grub_divmod64 (n, 10, &m);
|
||||
*p++ = m + '0';
|
||||
}
|
||||
while (n);
|
||||
|
||||
|
||||
*p = 0;
|
||||
|
||||
grub_reverse (str);
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_ftoa (char *str, double f, int round)
|
||||
{
|
||||
unsigned int intp;
|
||||
unsigned int fractp;
|
||||
unsigned int power = 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < round; i++)
|
||||
power *= 10;
|
||||
|
||||
intp = f;
|
||||
fractp = (f - (float) intp) * power;
|
||||
|
||||
grub_sprintf (str, "%d.%d", intp, fractp);
|
||||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
grub_vsprintf (char *str, const char *fmt, va_list args)
|
||||
{
|
||||
|
@ -674,7 +644,7 @@ grub_vsprintf (char *str, const char *fmt, va_list args)
|
|||
auto void write_char (unsigned char ch);
|
||||
auto void write_str (const char *s);
|
||||
auto void write_fill (const char ch, int n);
|
||||
|
||||
|
||||
void write_char (unsigned char ch)
|
||||
{
|
||||
if (str)
|
||||
|
@ -697,7 +667,7 @@ grub_vsprintf (char *str, const char *fmt, va_list args)
|
|||
for (i = 0; i < n; i++)
|
||||
write_char (ch);
|
||||
}
|
||||
|
||||
|
||||
while ((c = *fmt++) != 0)
|
||||
{
|
||||
if (c != '%')
|
||||
|
@ -707,12 +677,13 @@ grub_vsprintf (char *str, const char *fmt, va_list args)
|
|||
char tmp[32];
|
||||
char *p;
|
||||
unsigned int format1 = 0;
|
||||
unsigned int format2 = 3;
|
||||
unsigned int format2 = ~ 0U;
|
||||
char zerofill = ' ';
|
||||
int rightfill = 0;
|
||||
int n;
|
||||
int longfmt = 0;
|
||||
int longlongfmt = 0;
|
||||
int unsig = 0;
|
||||
|
||||
if (*fmt && *fmt =='-')
|
||||
{
|
||||
|
@ -734,20 +705,22 @@ grub_vsprintf (char *str, const char *fmt, va_list args)
|
|||
zerofill = '0';
|
||||
format1 = grub_strtoul (s, 0, 10);
|
||||
fmt = p;
|
||||
if (*p && *p == '.')
|
||||
}
|
||||
|
||||
if (*p && *p == '.')
|
||||
{
|
||||
p++;
|
||||
fmt++;
|
||||
while (*p && grub_isdigit (*p))
|
||||
p++;
|
||||
|
||||
if (p > fmt)
|
||||
{
|
||||
p++;
|
||||
fmt++;
|
||||
while (*p && grub_isdigit (*p))
|
||||
p++;
|
||||
|
||||
if (p > fmt)
|
||||
{
|
||||
char fstr[p - fmt];
|
||||
grub_strncpy (fstr, fmt, p - fmt);
|
||||
format2 = grub_strtoul (fstr, 0, 10);
|
||||
fmt = p;
|
||||
}
|
||||
char fstr[p - fmt + 1];
|
||||
grub_strncpy (fstr, fmt, p - fmt);
|
||||
fstr[p - fmt] = 0;
|
||||
format2 = grub_strtoul (fstr, 0, 10);
|
||||
fmt = p;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,9 +742,11 @@ grub_vsprintf (char *str, const char *fmt, va_list args)
|
|||
write_str ("0x");
|
||||
c = 'x';
|
||||
longlongfmt |= (sizeof (void *) == sizeof (long long));
|
||||
/* fall through */
|
||||
/* Fall through. */
|
||||
case 'x':
|
||||
case 'u':
|
||||
unsig = 1;
|
||||
/* Fall through. */
|
||||
case 'd':
|
||||
if (longlongfmt)
|
||||
{
|
||||
|
@ -780,13 +755,25 @@ grub_vsprintf (char *str, const char *fmt, va_list args)
|
|||
ll = va_arg (args, long long);
|
||||
grub_lltoa (tmp, c, ll);
|
||||
}
|
||||
else if (longfmt && unsig)
|
||||
{
|
||||
unsigned long l = va_arg (args, unsigned long);
|
||||
grub_lltoa (tmp, c, l);
|
||||
}
|
||||
else if (longfmt)
|
||||
{
|
||||
long l = va_arg (args, long);
|
||||
grub_lltoa (tmp, c, l);
|
||||
}
|
||||
else if (unsig)
|
||||
{
|
||||
unsigned u = va_arg (args, unsigned);
|
||||
grub_lltoa (tmp, c, u);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (longfmt)
|
||||
n = va_arg (args, long);
|
||||
else
|
||||
n = va_arg (args, int);
|
||||
grub_itoa (tmp, c, n);
|
||||
n = va_arg (args, int);
|
||||
grub_lltoa (tmp, c, n);
|
||||
}
|
||||
if (! rightfill && grub_strlen (tmp) < format1)
|
||||
write_fill (zerofill, format1 - grub_strlen (tmp));
|
||||
|
@ -794,31 +781,18 @@ grub_vsprintf (char *str, const char *fmt, va_list args)
|
|||
if (rightfill && grub_strlen (tmp) < format1)
|
||||
write_fill (zerofill, format1 - grub_strlen (tmp));
|
||||
break;
|
||||
|
||||
|
||||
case 'c':
|
||||
n = va_arg (args, int);
|
||||
write_char (n & 0xff);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
{
|
||||
float f;
|
||||
f = va_arg (args, double);
|
||||
grub_ftoa (tmp, f, format2);
|
||||
if (!rightfill && grub_strlen (tmp) < format1)
|
||||
write_fill (zerofill, format1 - grub_strlen (tmp));
|
||||
write_str (tmp);
|
||||
if (rightfill && grub_strlen (tmp) < format1)
|
||||
write_fill (zerofill, format1 - grub_strlen (tmp));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'C':
|
||||
{
|
||||
grub_uint32_t code = va_arg (args, grub_uint32_t);
|
||||
int shift;
|
||||
unsigned mask;
|
||||
|
||||
|
||||
if (code <= 0x7f)
|
||||
{
|
||||
shift = 0;
|
||||
|
@ -857,7 +831,7 @@ grub_vsprintf (char *str, const char *fmt, va_list args)
|
|||
}
|
||||
|
||||
write_char (mask | (code >> shift));
|
||||
|
||||
|
||||
for (shift -= 6; shift >= 0; shift -= 6)
|
||||
write_char (0x80 | (0x3f & (code >> shift)));
|
||||
}
|
||||
|
@ -867,17 +841,23 @@ grub_vsprintf (char *str, const char *fmt, va_list args)
|
|||
p = va_arg (args, char *);
|
||||
if (p)
|
||||
{
|
||||
if (!rightfill && grub_strlen (p) < format1)
|
||||
write_fill (zerofill, format1 - grub_strlen (p));
|
||||
|
||||
write_str (p);
|
||||
|
||||
if (rightfill && grub_strlen (p) < format1)
|
||||
write_fill (zerofill, format1 - grub_strlen (p));
|
||||
grub_size_t len = 0;
|
||||
while (len < format2 && p[len])
|
||||
len++;
|
||||
|
||||
if (!rightfill && len < format1)
|
||||
write_fill (zerofill, format1 - len);
|
||||
|
||||
grub_size_t i;
|
||||
for (i = 0; i < len; i++)
|
||||
write_char (*p++);
|
||||
|
||||
if (rightfill && len < format1)
|
||||
write_fill (zerofill, format1 - len);
|
||||
}
|
||||
else
|
||||
write_str ("(null)");
|
||||
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -892,7 +872,7 @@ grub_vsprintf (char *str, const char *fmt, va_list args)
|
|||
|
||||
if (count && !str)
|
||||
grub_refresh ();
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -901,7 +881,7 @@ grub_sprintf (char *str, const char *fmt, ...)
|
|||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
|
||||
va_start (ap, fmt);
|
||||
ret = grub_vsprintf (str, fmt, ap);
|
||||
va_end (ap);
|
||||
|
@ -909,90 +889,36 @@ grub_sprintf (char *str, const char *fmt, ...)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Convert UTF-16 to UTF-8. */
|
||||
grub_uint8_t *
|
||||
grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
|
||||
grub_size_t size)
|
||||
{
|
||||
grub_uint32_t code_high = 0;
|
||||
|
||||
while (size--)
|
||||
{
|
||||
grub_uint32_t code = *src++;
|
||||
|
||||
if (code_high)
|
||||
{
|
||||
if (code >= 0xDC00 && code <= 0xDFFF)
|
||||
{
|
||||
/* Surrogate pair. */
|
||||
code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
|
||||
|
||||
*dest++ = (code >> 18) | 0xF0;
|
||||
*dest++ = ((code >> 12) & 0x3F) | 0x80;
|
||||
*dest++ = ((code >> 6) & 0x3F) | 0x80;
|
||||
*dest++ = (code & 0x3F) | 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Error... */
|
||||
*dest++ = '?';
|
||||
}
|
||||
|
||||
code_high = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (code <= 0x007F)
|
||||
*dest++ = code;
|
||||
else if (code <= 0x07FF)
|
||||
{
|
||||
*dest++ = (code >> 6) | 0xC0;
|
||||
*dest++ = (code & 0x3F) | 0x80;
|
||||
}
|
||||
else if (code >= 0xD800 && code <= 0xDBFF)
|
||||
{
|
||||
code_high = code;
|
||||
continue;
|
||||
}
|
||||
else if (code >= 0xDC00 && code <= 0xDFFF)
|
||||
{
|
||||
/* Error... */
|
||||
*dest++ = '?';
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest++ = (code >> 12) | 0xE0;
|
||||
*dest++ = ((code >> 6) & 0x3F) | 0x80;
|
||||
*dest++ = (code & 0x3F) | 0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Convert an UTF-8 string to an UCS-4 string. Return the number of
|
||||
characters converted. DEST must be able to hold at least SIZE
|
||||
characters (when the input is unknown). If an invalid sequence is found,
|
||||
return -1. */
|
||||
grub_ssize_t
|
||||
grub_utf8_to_ucs4 (grub_uint32_t *dest, const grub_uint8_t *src,
|
||||
grub_size_t size)
|
||||
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
|
||||
bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
|
||||
Return the number of characters converted. DEST must be able to hold
|
||||
at least DESTSIZE characters.
|
||||
If SRCEND is not NULL, then *SRCEND is set to the next byte after the
|
||||
last byte used in SRC. */
|
||||
grub_size_t
|
||||
grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
|
||||
const grub_uint8_t *src, grub_size_t srcsize,
|
||||
const grub_uint8_t **srcend)
|
||||
{
|
||||
grub_uint32_t *p = dest;
|
||||
int count = 0;
|
||||
grub_uint32_t code = 0;
|
||||
|
||||
while (size--)
|
||||
|
||||
if (srcend)
|
||||
*srcend = src;
|
||||
|
||||
while (srcsize && destsize)
|
||||
{
|
||||
grub_uint32_t c = *src++;
|
||||
|
||||
if (srcsize != (grub_size_t)-1)
|
||||
srcsize--;
|
||||
if (count)
|
||||
{
|
||||
if ((c & 0xc0) != 0x80)
|
||||
{
|
||||
/* invalid */
|
||||
return -1;
|
||||
code = '?';
|
||||
count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1003,6 +929,9 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, const grub_uint8_t *src,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (c == 0)
|
||||
break;
|
||||
|
||||
if ((c & 0x80) == 0x00)
|
||||
code = c;
|
||||
else if ((c & 0xe0) == 0xc0)
|
||||
|
@ -1031,39 +960,52 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, const grub_uint8_t *src,
|
|||
code = c & 0x01;
|
||||
}
|
||||
else
|
||||
/* invalid */
|
||||
return -1;
|
||||
{
|
||||
/* invalid */
|
||||
code = '?';
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
*p++ = code;
|
||||
{
|
||||
*p++ = code;
|
||||
destsize--;
|
||||
}
|
||||
}
|
||||
|
||||
if (srcend)
|
||||
*srcend = src;
|
||||
return p - dest;
|
||||
}
|
||||
|
||||
void
|
||||
grub_millisleep_generic (grub_uint32_t ms)
|
||||
{
|
||||
grub_uint32_t end_at;
|
||||
|
||||
end_at = grub_get_rtc () + grub_div_roundup (ms * GRUB_TICKS_PER_SECOND, 1000);
|
||||
|
||||
while (grub_get_rtc () < end_at)
|
||||
grub_cpu_idle ();
|
||||
}
|
||||
|
||||
/* Abort GRUB. This function does not return. */
|
||||
void
|
||||
grub_abort (void)
|
||||
{
|
||||
if (grub_term_get_current ())
|
||||
grub_printf ("\nAborted.");
|
||||
|
||||
#ifndef GRUB_UTIL
|
||||
if (grub_term_inputs)
|
||||
#endif
|
||||
{
|
||||
grub_printf ("\nAborted. Press any key to exit.");
|
||||
grub_printf (" Press any key to exit.");
|
||||
grub_getkey ();
|
||||
}
|
||||
|
||||
grub_exit ();
|
||||
}
|
||||
|
||||
#ifndef APPLE_CC
|
||||
/* GCC emits references to abort(). */
|
||||
void abort (void) __attribute__ ((alias ("grub_abort")));
|
||||
#endif
|
||||
|
||||
#ifdef NEED_ENABLE_EXECUTE_STACK
|
||||
/* Some gcc versions generate a call to this function
|
||||
in trampolines for nested functions. */
|
||||
void __enable_execute_stack (void *addr __attribute__ ((unused)))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
132
kern/mm.c
132
kern/mm.c
|
@ -1,7 +1,7 @@
|
|||
/* mm.c - functions for memory manager */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,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
|
||||
|
@ -68,6 +68,7 @@
|
|||
|
||||
#ifdef MM_DEBUG
|
||||
# undef grub_malloc
|
||||
# undef grub_zalloc
|
||||
# undef grub_realloc
|
||||
# undef grub_free
|
||||
# undef grub_memalign
|
||||
|
@ -129,7 +130,7 @@ get_header_from_pointer (void *ptr, grub_mm_header_t *p, grub_mm_region_t *r)
|
|||
|
||||
if (! *r)
|
||||
grub_fatal ("out of range pointer %p", ptr);
|
||||
|
||||
|
||||
*p = (grub_mm_header_t) ptr - 1;
|
||||
if ((*p)->magic != GRUB_MM_ALLOC_MAGIC)
|
||||
grub_fatal ("alloc magic is broken at %p", *p);
|
||||
|
@ -155,7 +156,7 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
|||
r = (grub_mm_region_t) (((grub_addr_t) addr + GRUB_MM_ALIGN - 1)
|
||||
& (~(GRUB_MM_ALIGN - 1)));
|
||||
size -= (char *) r - (char *) addr + sizeof (*r);
|
||||
|
||||
|
||||
h = (grub_mm_header_t) ((char *) r + GRUB_MM_ALIGN);
|
||||
h->next = h;
|
||||
h->magic = GRUB_MM_FREE_MAGIC;
|
||||
|
@ -170,22 +171,26 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
|||
for (p = &base, q = *p; q; p = &(q->next), q = *p)
|
||||
if (q->size > r->size)
|
||||
break;
|
||||
|
||||
|
||||
*p = r;
|
||||
r->next = q;
|
||||
}
|
||||
|
||||
/* Allocate the number of units N with the alignment ALIGN from the ring
|
||||
buffer starting from *FIRST. ALIGN must be a power of two. Return a
|
||||
non-NULL if successful, otherwise return NULL. */
|
||||
buffer starting from *FIRST. ALIGN must be a power of two. Both N and
|
||||
ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful,
|
||||
otherwise return NULL. */
|
||||
static void *
|
||||
grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
|
||||
{
|
||||
grub_mm_header_t p, q;
|
||||
|
||||
/* When everything is allocated side effect is that *first will have alloc
|
||||
magic marked, meaning that there is no room in this region. */
|
||||
if ((*first)->magic == GRUB_MM_ALLOC_MAGIC)
|
||||
return 0;
|
||||
|
||||
/* Try to search free slot for allocation in this memory region. */
|
||||
for (q = *first, p = q->next; ; q = p, p = p->next)
|
||||
{
|
||||
grub_off_t extra;
|
||||
|
@ -204,11 +209,37 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
|
|||
{
|
||||
if (extra == 0 && p->size == n)
|
||||
{
|
||||
/* There is no special alignment requirement and memory block
|
||||
is complete match.
|
||||
|
||||
1. Just mark memory block as allocated and remove it from
|
||||
free list.
|
||||
|
||||
Result:
|
||||
+---------------+ previous block's next
|
||||
| alloc, size=n | |
|
||||
+---------------+ v
|
||||
*/
|
||||
q->next = p->next;
|
||||
p->magic = GRUB_MM_ALLOC_MAGIC;
|
||||
}
|
||||
else if (extra == 0 || p->size == n + extra)
|
||||
{
|
||||
/* There might be alignment requirement, when taking it into
|
||||
account memory block fits in.
|
||||
|
||||
1. Allocate new area at end of memory block.
|
||||
2. Reduce size of available blocks from original node.
|
||||
3. Mark new area as allocated and "remove" it from free
|
||||
list.
|
||||
|
||||
Result:
|
||||
+---------------+
|
||||
| free, size-=n | next --+
|
||||
+---------------+ |
|
||||
| alloc, size=n | |
|
||||
+---------------+ v
|
||||
*/
|
||||
p->size -= n;
|
||||
p += p->size;
|
||||
p->size = n;
|
||||
|
@ -216,13 +247,32 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* There is alignment requirement and there is room in memory
|
||||
block. Split memory block to three pieces.
|
||||
|
||||
1. Create new memory block right after section being
|
||||
allocated. Mark it as free.
|
||||
2. Add new memory block to free chain.
|
||||
3. Mark current memory block having only extra blocks.
|
||||
4. Advance to aligned block and mark that as allocated and
|
||||
"remove" it from free list.
|
||||
|
||||
Result:
|
||||
+------------------------------+
|
||||
| free, size=extra | next --+
|
||||
+------------------------------+ |
|
||||
| alloc, size=n | |
|
||||
+------------------------------+ |
|
||||
| free, size=orig.size-extra-n | <------+, next --+
|
||||
+------------------------------+ v
|
||||
*/
|
||||
grub_mm_header_t r;
|
||||
|
||||
r = p + extra + n;
|
||||
r->magic = GRUB_MM_FREE_MAGIC;
|
||||
r->size = p->size - extra - n;
|
||||
r->next = p->next;
|
||||
|
||||
|
||||
p->size = extra;
|
||||
p->next = r;
|
||||
p += extra;
|
||||
|
@ -230,11 +280,15 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
|
|||
p->magic = GRUB_MM_ALLOC_MAGIC;
|
||||
}
|
||||
|
||||
/* Mark find as a start marker for next allocation to fasten it.
|
||||
This will have side effect of fragmenting memory as small
|
||||
pieces before this will be un-used. */
|
||||
*first = q;
|
||||
|
||||
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
/* Search was completed without result. */
|
||||
if (p == *first)
|
||||
break;
|
||||
}
|
||||
|
@ -249,17 +303,17 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
|||
grub_mm_region_t r;
|
||||
grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1;
|
||||
int count = 0;
|
||||
|
||||
|
||||
align = (align >> GRUB_MM_ALIGN_LOG2);
|
||||
if (align == 0)
|
||||
align = 1;
|
||||
|
||||
again:
|
||||
|
||||
|
||||
for (r = base; r; r = r->next)
|
||||
{
|
||||
void *p;
|
||||
|
||||
|
||||
p = grub_real_malloc (&(r->first), n, align);
|
||||
if (p)
|
||||
return p;
|
||||
|
@ -273,7 +327,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
|||
grub_disk_cache_invalidate_all ();
|
||||
count++;
|
||||
goto again;
|
||||
|
||||
|
||||
case 1:
|
||||
/* Unload unneeded modules. */
|
||||
grub_dl_unload_unneeded ();
|
||||
|
@ -283,7 +337,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
@ -295,6 +349,19 @@ grub_malloc (grub_size_t size)
|
|||
return grub_memalign (0, size);
|
||||
}
|
||||
|
||||
/* Allocate SIZE bytes, clear them and return the pointer. */
|
||||
void *
|
||||
grub_zalloc (grub_size_t size)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
ret = grub_memalign (0, size);
|
||||
if (ret)
|
||||
grub_memset (ret, 0, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Deallocate the pointer PTR. */
|
||||
void
|
||||
grub_free (void *ptr)
|
||||
|
@ -326,12 +393,12 @@ grub_free (void *ptr)
|
|||
}
|
||||
while (q != r->first);
|
||||
#endif
|
||||
|
||||
|
||||
for (q = r->first; q >= p || q->next <= p; q = q->next)
|
||||
{
|
||||
if (q->magic != GRUB_MM_FREE_MAGIC)
|
||||
grub_fatal ("free magic is broken at %p: 0x%x", q, q->magic);
|
||||
|
||||
|
||||
if (q >= q->next && (q < p || q->next > p))
|
||||
break;
|
||||
}
|
||||
|
@ -339,7 +406,7 @@ grub_free (void *ptr)
|
|||
p->magic = GRUB_MM_FREE_MAGIC;
|
||||
p->next = q->next;
|
||||
q->next = p;
|
||||
|
||||
|
||||
if (p + p->size == p->next)
|
||||
{
|
||||
if (p->next == q)
|
||||
|
@ -349,7 +416,7 @@ grub_free (void *ptr)
|
|||
p->size += p->next->size;
|
||||
p->next = p->next->next;
|
||||
}
|
||||
|
||||
|
||||
if (q + q->size == p)
|
||||
{
|
||||
p->magic = 0;
|
||||
|
@ -370,7 +437,7 @@ grub_realloc (void *ptr, grub_size_t size)
|
|||
grub_mm_region_t r;
|
||||
void *q;
|
||||
grub_size_t n;
|
||||
|
||||
|
||||
if (! ptr)
|
||||
return grub_malloc (size);
|
||||
|
||||
|
@ -383,14 +450,14 @@ grub_realloc (void *ptr, grub_size_t size)
|
|||
/* FIXME: Not optimal. */
|
||||
n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1;
|
||||
get_header_from_pointer (ptr, &p, &r);
|
||||
|
||||
|
||||
if (p->size >= n)
|
||||
return ptr;
|
||||
|
||||
|
||||
q = grub_malloc (size);
|
||||
if (! q)
|
||||
return q;
|
||||
|
||||
|
||||
grub_memcpy (q, ptr, size);
|
||||
grub_free (ptr);
|
||||
return q;
|
||||
|
@ -434,7 +501,7 @@ grub_mm_dump (unsigned lineno)
|
|||
for (r = base; r; r = r->next)
|
||||
{
|
||||
grub_mm_header_t p;
|
||||
|
||||
|
||||
for (p = (grub_mm_header_t) ((r->addr + GRUB_MM_ALIGN - 1)
|
||||
& (~(GRUB_MM_ALIGN - 1)));
|
||||
(grub_addr_t) p < r->addr + r->size;
|
||||
|
@ -462,13 +529,26 @@ grub_debug_malloc (const char *file, int line, grub_size_t size)
|
|||
void *ptr;
|
||||
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%s:%d: malloc (0x%x) = ", file, line, size);
|
||||
grub_printf ("%s:%d: malloc (0x%zx) = ", file, line, size);
|
||||
ptr = grub_malloc (size);
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%p\n", ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *
|
||||
grub_debug_zalloc (const char *file, int line, grub_size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%s:%d: zalloc (0x%zx) = ", file, line, size);
|
||||
ptr = grub_zalloc (size);
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%p\n", ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void
|
||||
grub_debug_free (const char *file, int line, void *ptr)
|
||||
{
|
||||
|
@ -481,7 +561,7 @@ void *
|
|||
grub_debug_realloc (const char *file, int line, void *ptr, grub_size_t size)
|
||||
{
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%s:%d: realloc (%p, 0x%x) = ", file, line, ptr, size);
|
||||
grub_printf ("%s:%d: realloc (%p, 0x%zx) = ", file, line, ptr, size);
|
||||
ptr = grub_realloc (ptr, size);
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%p\n", ptr);
|
||||
|
@ -493,9 +573,9 @@ grub_debug_memalign (const char *file, int line, grub_size_t align,
|
|||
grub_size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
|
||||
if (grub_mm_debug)
|
||||
grub_printf ("%s:%d: memalign (0x%x, 0x%x) = ",
|
||||
grub_printf ("%s:%d: memalign (0x%zx, 0x%zx) = ",
|
||||
file, line, align, size);
|
||||
ptr = grub_memalign (align, size);
|
||||
if (grub_mm_debug)
|
||||
|
|
103
kern/parser.c
103
kern/parser.c
|
@ -1,7 +1,7 @@
|
|||
/* parser.c - the part of the parser that can return partial tokens */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -47,8 +47,8 @@ static struct grub_parser_state_transition state_transitions[] =
|
|||
|
||||
{ GRUB_PARSER_STATE_QVAR, GRUB_PARSER_STATE_QVARNAME2, '{', 0},
|
||||
{ GRUB_PARSER_STATE_QVAR, GRUB_PARSER_STATE_QVARNAME, 0, 1},
|
||||
{ GRUB_PARSER_STATE_QVARNAME, GRUB_PARSER_STATE_DQUOTE, ' ', 1},
|
||||
{ GRUB_PARSER_STATE_QVARNAME, GRUB_PARSER_STATE_TEXT, '\"', 0},
|
||||
{ GRUB_PARSER_STATE_QVARNAME, GRUB_PARSER_STATE_DQUOTE, ' ', 1},
|
||||
{ GRUB_PARSER_STATE_QVARNAME2, GRUB_PARSER_STATE_DQUOTE, '}', 0},
|
||||
|
||||
{ 0, 0, 0, 0}
|
||||
|
@ -60,9 +60,7 @@ grub_parser_state_t
|
|||
grub_parser_cmdline_state (grub_parser_state_t state, char c, char *result)
|
||||
{
|
||||
struct grub_parser_state_transition *transition;
|
||||
struct grub_parser_state_transition *next_match = 0;
|
||||
struct grub_parser_state_transition default_transition;
|
||||
int found = 0;
|
||||
|
||||
default_transition.to_state = state;
|
||||
default_transition.keep_value = 1;
|
||||
|
@ -70,26 +68,24 @@ grub_parser_cmdline_state (grub_parser_state_t state, char c, char *result)
|
|||
/* Look for a good translation. */
|
||||
for (transition = state_transitions; transition->from_state; transition++)
|
||||
{
|
||||
if (transition->from_state != state)
|
||||
continue;
|
||||
/* An exact match was found, use it. */
|
||||
if (transition->from_state == state && transition->input == c)
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
if (transition->input == c)
|
||||
break;
|
||||
|
||||
if (transition->input == ' ' && ! grub_isalpha (c)
|
||||
&& ! grub_isdigit (c) && c != '_')
|
||||
break;
|
||||
|
||||
/* A less perfect match was found, use this one if no exact
|
||||
match can be found. */
|
||||
if (transition->from_state == state && transition->input == 0)
|
||||
next_match = transition;
|
||||
if (transition->input == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (! found)
|
||||
{
|
||||
if (next_match)
|
||||
transition = next_match;
|
||||
else
|
||||
transition = &default_transition;
|
||||
}
|
||||
if (! transition->from_state)
|
||||
transition = &default_transition;
|
||||
|
||||
if (transition->keep_value)
|
||||
*result = c;
|
||||
|
@ -100,7 +96,7 @@ grub_parser_cmdline_state (grub_parser_state_t state, char c, char *result)
|
|||
|
||||
|
||||
grub_err_t
|
||||
grub_parser_split_cmdline (const char *cmdline, grub_err_t (*getline) (char **),
|
||||
grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline,
|
||||
int *argc, char ***argv)
|
||||
{
|
||||
grub_parser_state_t state = GRUB_PARSER_STATE_TEXT;
|
||||
|
@ -140,27 +136,30 @@ grub_parser_split_cmdline (const char *cmdline, grub_err_t (*getline) (char **),
|
|||
vp = varname;
|
||||
if (! val)
|
||||
return;
|
||||
|
||||
|
||||
/* Insert the contents of the variable in the buffer. */
|
||||
for (; *val; val++)
|
||||
*(bp++) = *val;
|
||||
}
|
||||
|
||||
*argc = 1;
|
||||
*argc = 0;
|
||||
do
|
||||
{
|
||||
if (! *rd)
|
||||
if (! rd || !*rd)
|
||||
{
|
||||
if (getline)
|
||||
getline (&rd);
|
||||
getline (&rd, 1);
|
||||
else break;
|
||||
}
|
||||
|
||||
if (!rd)
|
||||
break;
|
||||
|
||||
for (; *rd; rd++)
|
||||
{
|
||||
grub_parser_state_t newstate;
|
||||
char use;
|
||||
|
||||
|
||||
newstate = grub_parser_cmdline_state (state, *rd, &use);
|
||||
|
||||
/* If a variable was being processed and this character does
|
||||
|
@ -192,19 +191,23 @@ grub_parser_split_cmdline (const char *cmdline, grub_err_t (*getline) (char **),
|
|||
state = newstate;
|
||||
}
|
||||
} while (state != GRUB_PARSER_STATE_TEXT && !check_varstate (state));
|
||||
*(bp++) = '\0';
|
||||
|
||||
/* A special case for when the last character was part of a
|
||||
variable. */
|
||||
add_var (GRUB_PARSER_STATE_TEXT);
|
||||
|
||||
|
||||
if (bp != buffer && *(bp - 1))
|
||||
{
|
||||
*(bp++) = '\0';
|
||||
(*argc)++;
|
||||
}
|
||||
|
||||
/* Reserve memory for the return values. */
|
||||
args = grub_malloc (bp - buffer);
|
||||
if (! args)
|
||||
return grub_errno;
|
||||
grub_memcpy (args, buffer, bp - buffer);
|
||||
|
||||
|
||||
*argv = grub_malloc (sizeof (char *) * (*argc + 1));
|
||||
if (! *argv)
|
||||
{
|
||||
|
@ -223,7 +226,49 @@ grub_parser_split_cmdline (const char *cmdline, grub_err_t (*getline) (char **),
|
|||
bp++;
|
||||
}
|
||||
|
||||
(*argc)--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct grub_handler_class grub_parser_class =
|
||||
{
|
||||
.name = "parser"
|
||||
};
|
||||
|
||||
grub_err_t
|
||||
grub_parser_execute (char *source)
|
||||
{
|
||||
auto grub_err_t getline (char **line, int cont);
|
||||
grub_err_t getline (char **line, int cont __attribute__ ((unused)))
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (! source)
|
||||
{
|
||||
*line = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = grub_strchr (source, '\n');
|
||||
if (p)
|
||||
*p = 0;
|
||||
|
||||
*line = grub_strdup (source);
|
||||
if (p)
|
||||
*p = '\n';
|
||||
source = p ? p + 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (source)
|
||||
{
|
||||
char *line;
|
||||
grub_parser_t parser;
|
||||
|
||||
getline (&line, 0);
|
||||
parser = grub_parser_get_current ();
|
||||
parser->parse_line (line, getline);
|
||||
grub_free (line);
|
||||
}
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ void
|
|||
grub_partition_map_unregister (grub_partition_map_t partmap)
|
||||
{
|
||||
grub_partition_map_t *p, q;
|
||||
|
||||
|
||||
for (p = &grub_partition_map_list, q = *p; q; p = &(q->next), q = q->next)
|
||||
if (q == partmap)
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ grub_partition_iterate (struct grub_disk *disk,
|
|||
{
|
||||
grub_partition_map_t partmap = 0;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
auto int part_map_iterate (const grub_partition_map_t p);
|
||||
auto int part_map_iterate_hook (grub_disk_t d,
|
||||
const grub_partition_t partition);
|
||||
|
@ -100,15 +100,13 @@ grub_partition_iterate (struct grub_disk *disk,
|
|||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int part_map_iterate (const grub_partition_map_t p)
|
||||
{
|
||||
grub_err_t err;
|
||||
|
||||
grub_dprintf ("partition", "Detecting %s...\n", p->name);
|
||||
err = p->iterate (disk, part_map_iterate_hook);
|
||||
p->iterate (disk, part_map_iterate_hook);
|
||||
|
||||
if (err != GRUB_ERR_NONE)
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
{
|
||||
/* Continue to next partition map type. */
|
||||
grub_dprintf ("partition", "%s detection failed.\n", p->name);
|
||||
|
@ -124,7 +122,7 @@ grub_partition_iterate (struct grub_disk *disk,
|
|||
grub_partition_map_iterate (part_map_iterate);
|
||||
if (partmap)
|
||||
ret = partmap->iterate (disk, hook);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* dl.c - arch-dependent part of loadable module support */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2004,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,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
|
||||
|
@ -26,7 +26,7 @@
|
|||
grub_err_t
|
||||
grub_arch_dl_check_header (void *ehdr)
|
||||
{
|
||||
Elf32_Ehdr *e = ehdr;
|
||||
Elf_Ehdr *e = ehdr;
|
||||
|
||||
/* Check the magic numbers. */
|
||||
if (e->e_ident[EI_CLASS] != ELFCLASS32
|
||||
|
@ -42,28 +42,26 @@ grub_arch_dl_check_header (void *ehdr)
|
|||
grub_err_t
|
||||
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
||||
{
|
||||
Elf32_Ehdr *e = ehdr;
|
||||
Elf32_Shdr *s;
|
||||
Elf32_Sym *symtab;
|
||||
Elf32_Word entsize;
|
||||
Elf_Ehdr *e = ehdr;
|
||||
Elf_Shdr *s;
|
||||
Elf_Word entsize;
|
||||
unsigned i;
|
||||
|
||||
|
||||
/* Find a symbol table. */
|
||||
for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
|
||||
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_SYMTAB)
|
||||
break;
|
||||
|
||||
if (i == e->e_shnum)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
|
||||
|
||||
symtab = (Elf32_Sym *) ((char *) e + s->sh_offset);
|
||||
|
||||
entsize = s->sh_entsize;
|
||||
|
||||
for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
|
||||
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
|
||||
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_RELA)
|
||||
{
|
||||
grub_dl_segment_t seg;
|
||||
|
@ -75,64 +73,64 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
|||
|
||||
if (seg)
|
||||
{
|
||||
Elf32_Rela *rel, *max;
|
||||
|
||||
for (rel = (Elf32_Rela *) ((char *) e + s->sh_offset),
|
||||
Elf_Rela *rel, *max;
|
||||
|
||||
for (rel = (Elf_Rela *) ((char *) e + s->sh_offset),
|
||||
max = rel + s->sh_size / s->sh_entsize;
|
||||
rel < max;
|
||||
rel++)
|
||||
{
|
||||
Elf32_Word *addr;
|
||||
Elf32_Sym *sym;
|
||||
Elf_Word *addr;
|
||||
Elf_Sym *sym;
|
||||
grub_uint32_t value;
|
||||
|
||||
|
||||
if (seg->size < rel->r_offset)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"reloc offset is out of the segment");
|
||||
|
||||
addr = (Elf32_Word *) ((char *) seg->addr + rel->r_offset);
|
||||
sym = (Elf32_Sym *) ((char *) symtab
|
||||
+ entsize * ELF32_R_SYM (rel->r_info));
|
||||
|
||||
|
||||
addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset);
|
||||
sym = (Elf_Sym *) ((char *) mod->symtab
|
||||
+ entsize * ELF_R_SYM (rel->r_info));
|
||||
|
||||
/* On the PPC the value does not have an explicit
|
||||
addend, add it. */
|
||||
value = sym->st_value + rel->r_addend;
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
switch (ELF_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_PPC_ADDR16_LO:
|
||||
*(Elf32_Half *) addr = value;
|
||||
*(Elf_Half *) addr = value;
|
||||
break;
|
||||
|
||||
|
||||
case R_PPC_REL24:
|
||||
{
|
||||
Elf32_Sword delta = value - (Elf32_Word) addr;
|
||||
|
||||
Elf_Sword delta = value - (Elf_Word) addr;
|
||||
|
||||
if (delta << 6 >> 6 != delta)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "Relocation overflow");
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "relocation overflow");
|
||||
*addr = (*addr & 0xfc000003) | (delta & 0x3fffffc);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case R_PPC_ADDR16_HA:
|
||||
*(Elf32_Half *) addr = (value + 0x8000) >> 16;
|
||||
*(Elf_Half *) addr = (value + 0x8000) >> 16;
|
||||
break;
|
||||
|
||||
|
||||
case R_PPC_ADDR32:
|
||||
*addr = value;
|
||||
break;
|
||||
|
||||
|
||||
case R_PPC_REL32:
|
||||
*addr = value - (Elf32_Word) addr;
|
||||
*addr = value - (Elf_Word) addr;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"This relocation (%d) is not implemented yet",
|
||||
ELF32_R_TYPE (rel->r_info));
|
||||
"this relocation (%d) is not implemented yet",
|
||||
ELF_R_TYPE (rel->r_info));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* crt0.S - Startup code for the PowerPC. */
|
||||
/* startup.S - Startup code for the PowerPC. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2004,2005,2007,2008 Free Software Foundation, Inc.
|
||||
|
@ -17,13 +17,31 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/cpu/kernel.h>
|
||||
|
||||
.extern __bss_start
|
||||
.extern _end
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl _start
|
||||
_start:
|
||||
.globl start, _start
|
||||
start:
|
||||
_start:
|
||||
b codestart
|
||||
|
||||
. = _start + GRUB_KERNEL_CPU_PREFIX
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkelfimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_CPU_DATA_END
|
||||
|
||||
codestart:
|
||||
li 2, 0
|
||||
li 13, 0
|
||||
|
||||
|
@ -42,5 +60,5 @@ _start:
|
|||
lis 9, grub_ieee1275_entry_fn@ha
|
||||
stw 5, grub_ieee1275_entry_fn@l(9)
|
||||
|
||||
bl cmain
|
||||
bl grub_main
|
||||
1: b 1b
|
707
kern/rescue.c
707
kern/rescue.c
|
@ -1,707 +0,0 @@
|
|||
/* rescue.c - rescue mode */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,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/kernel.h>
|
||||
#include <grub/rescue.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/parser.h>
|
||||
|
||||
#define GRUB_RESCUE_BUF_SIZE 256
|
||||
#define GRUB_RESCUE_MAX_ARGS 20
|
||||
|
||||
struct grub_rescue_command
|
||||
{
|
||||
const char *name;
|
||||
void (*func) (int argc, char *argv[]);
|
||||
const char *message;
|
||||
struct grub_rescue_command *next;
|
||||
};
|
||||
typedef struct grub_rescue_command *grub_rescue_command_t;
|
||||
|
||||
static char linebuf[GRUB_RESCUE_BUF_SIZE];
|
||||
|
||||
static grub_rescue_command_t grub_rescue_command_list;
|
||||
|
||||
void
|
||||
grub_rescue_register_command (const char *name,
|
||||
void (*func) (int argc, char *argv[]),
|
||||
const char *message)
|
||||
{
|
||||
grub_rescue_command_t cmd;
|
||||
|
||||
cmd = (grub_rescue_command_t) grub_malloc (sizeof (*cmd));
|
||||
if (! cmd)
|
||||
return;
|
||||
|
||||
cmd->name = name;
|
||||
cmd->func = func;
|
||||
cmd->message = message;
|
||||
|
||||
cmd->next = grub_rescue_command_list;
|
||||
grub_rescue_command_list = cmd;
|
||||
}
|
||||
|
||||
void
|
||||
grub_rescue_unregister_command (const char *name)
|
||||
{
|
||||
grub_rescue_command_t *p, q;
|
||||
|
||||
for (p = &grub_rescue_command_list, q = *p; q; p = &(q->next), q = q->next)
|
||||
if (grub_strcmp (name, q->name) == 0)
|
||||
{
|
||||
*p = q->next;
|
||||
grub_free (q);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prompt to input a command and read the line. */
|
||||
static void
|
||||
grub_rescue_get_command_line (const char *prompt)
|
||||
{
|
||||
int c;
|
||||
int pos = 0;
|
||||
|
||||
grub_printf (prompt);
|
||||
grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE);
|
||||
|
||||
while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r')
|
||||
{
|
||||
if (grub_isprint (c))
|
||||
{
|
||||
if (pos < GRUB_RESCUE_BUF_SIZE - 1)
|
||||
{
|
||||
linebuf[pos++] = c;
|
||||
grub_putchar (c);
|
||||
}
|
||||
}
|
||||
else if (c == '\b')
|
||||
{
|
||||
if (pos > 0)
|
||||
{
|
||||
linebuf[--pos] = 0;
|
||||
grub_putchar (c);
|
||||
grub_putchar (' ');
|
||||
grub_putchar (c);
|
||||
}
|
||||
}
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
/* boot */
|
||||
static void
|
||||
grub_rescue_cmd_boot (int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_loader_boot ();
|
||||
}
|
||||
|
||||
/* cat FILE */
|
||||
static void
|
||||
grub_rescue_cmd_cat (int argc, char *argv[])
|
||||
{
|
||||
grub_file_t file;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
grub_ssize_t size;
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||
return;
|
||||
}
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
return;
|
||||
|
||||
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))
|
||||
grub_putchar (c);
|
||||
else
|
||||
{
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
|
||||
grub_printf ("<%x>", (int) c);
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
grub_file_close (file);
|
||||
}
|
||||
|
||||
static int
|
||||
grub_rescue_print_devices (const char *name)
|
||||
{
|
||||
grub_printf ("(%s) ", name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_rescue_print_files (const char *filename, int dir)
|
||||
{
|
||||
grub_printf ("%s%s ", filename, dir ? "/" : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ls [ARG] */
|
||||
static void
|
||||
grub_rescue_cmd_ls (int argc, char *argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
{
|
||||
grub_device_iterate (grub_rescue_print_devices);
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
}
|
||||
else
|
||||
{
|
||||
char *device_name;
|
||||
grub_device_t dev;
|
||||
grub_fs_t fs;
|
||||
char *path;
|
||||
|
||||
device_name = grub_file_get_device_name (argv[0]);
|
||||
dev = grub_device_open (device_name);
|
||||
if (! dev)
|
||||
goto fail;
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
path = grub_strchr (argv[0], ')');
|
||||
if (! path)
|
||||
path = argv[0];
|
||||
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_printf ("(%s): Filesystem is %s.\n",
|
||||
device_name, fs ? fs->name : "unknown");
|
||||
}
|
||||
else if (fs)
|
||||
{
|
||||
(fs->dir) (dev, path, grub_rescue_print_files);
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
fail:
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
grub_free (device_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* help */
|
||||
static void
|
||||
grub_rescue_cmd_help (int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_rescue_command_t p, q;
|
||||
|
||||
/* Sort the commands. This is not a good algorithm, but this is enough,
|
||||
because rescue mode has a small number of commands. */
|
||||
for (p = grub_rescue_command_list; p; p = p->next)
|
||||
for (q = p->next; q; q = q->next)
|
||||
if (grub_strcmp (p->name, q->name) > 0)
|
||||
{
|
||||
struct grub_rescue_command tmp;
|
||||
|
||||
tmp.name = p->name;
|
||||
tmp.func = p->func;
|
||||
tmp.message = p->message;
|
||||
|
||||
p->name = q->name;
|
||||
p->func = q->func;
|
||||
p->message = q->message;
|
||||
|
||||
q->name = tmp.name;
|
||||
q->func = tmp.func;
|
||||
q->message = tmp.message;
|
||||
}
|
||||
|
||||
/* Print them. */
|
||||
for (p = grub_rescue_command_list; p; p = p->next)
|
||||
grub_printf ("%s\t%s\n", p->name, p->message);
|
||||
}
|
||||
|
||||
#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 void
|
||||
grub_rescue_cmd_root (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_env_set ("root", device_name);
|
||||
grub_free (device_name);
|
||||
}
|
||||
|
||||
dev = grub_device_open (0);
|
||||
if (! dev)
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#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 void
|
||||
grub_rescue_cmd_dump (int argc, char *argv[])
|
||||
{
|
||||
grub_uint8_t *addr;
|
||||
grub_size_t size = 4;
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "no address specified");
|
||||
return;
|
||||
}
|
||||
|
||||
addr = (grub_uint8_t *) grub_strtoul (argv[0], 0, 0);
|
||||
if (grub_errno)
|
||||
return;
|
||||
|
||||
if (argc > 1)
|
||||
size = (grub_size_t) grub_strtoul (argv[1], 0, 0);
|
||||
|
||||
while (size--)
|
||||
{
|
||||
grub_printf ("%x%x ", *addr >> 4, *addr & 0xf);
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* insmod MODULE */
|
||||
static void
|
||||
grub_rescue_cmd_insmod (int argc, char *argv[])
|
||||
{
|
||||
char *p;
|
||||
grub_dl_t mod;
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
|
||||
return;
|
||||
}
|
||||
|
||||
p = grub_strchr (argv[0], '/');
|
||||
if (! p)
|
||||
mod = grub_dl_load (argv[0]);
|
||||
else
|
||||
mod = grub_dl_load_file (argv[0]);
|
||||
|
||||
if (mod)
|
||||
grub_dl_ref (mod);
|
||||
}
|
||||
|
||||
/* rmmod MODULE */
|
||||
static void
|
||||
grub_rescue_cmd_rmmod (int argc, char *argv[])
|
||||
{
|
||||
grub_dl_t mod;
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
|
||||
return;
|
||||
}
|
||||
|
||||
mod = grub_dl_get (argv[0]);
|
||||
if (! mod)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "no such module");
|
||||
return;
|
||||
}
|
||||
|
||||
if (grub_dl_unref (mod) <= 0)
|
||||
grub_dl_unload (mod);
|
||||
}
|
||||
|
||||
/* lsmod */
|
||||
static void
|
||||
grub_rescue_cmd_lsmod (int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
auto int print_module (grub_dl_t mod);
|
||||
|
||||
int print_module (grub_dl_t mod)
|
||||
{
|
||||
grub_dl_dep_t dep;
|
||||
|
||||
grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count);
|
||||
for (dep = mod->dep; dep; dep = dep->next)
|
||||
{
|
||||
if (dep != mod->dep)
|
||||
grub_putchar (',');
|
||||
|
||||
grub_printf ("%s", dep->mod->name);
|
||||
}
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_printf ("Name\tRef Count\tDependencies\n");
|
||||
grub_dl_iterate (print_module);
|
||||
}
|
||||
|
||||
/* set ENVVAR=VALUE */
|
||||
static void
|
||||
grub_rescue_cmd_set (int argc, char *argv[])
|
||||
{
|
||||
char *var;
|
||||
char *val;
|
||||
|
||||
auto int print_env (struct grub_env_var *env);
|
||||
|
||||
int print_env (struct grub_env_var *env)
|
||||
{
|
||||
grub_printf ("%s=%s\n", env->name, env->value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
grub_env_iterate (print_env);
|
||||
return;
|
||||
}
|
||||
|
||||
var = argv[0];
|
||||
val = grub_strchr (var, '=');
|
||||
if (! val)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "not an assignment");
|
||||
return;
|
||||
}
|
||||
|
||||
val[0] = 0;
|
||||
grub_env_set (var, val + 1);
|
||||
val[0] = '=';
|
||||
}
|
||||
|
||||
static void
|
||||
grub_rescue_cmd_unset (int argc, char *argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "no environment variable specified");
|
||||
return;
|
||||
}
|
||||
|
||||
grub_env_unset (argv[0]);
|
||||
}
|
||||
|
||||
/* exit */
|
||||
static void
|
||||
grub_rescue_cmd_exit (int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_exit ();
|
||||
}
|
||||
|
||||
static void
|
||||
attempt_normal_mode (void)
|
||||
{
|
||||
grub_rescue_command_t cmd;
|
||||
|
||||
for (cmd = grub_rescue_command_list; cmd; cmd = cmd->next)
|
||||
{
|
||||
if (grub_strcmp ("normal", cmd->name) == 0)
|
||||
{
|
||||
(cmd->func) (0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Enter the rescue mode. */
|
||||
void
|
||||
grub_enter_rescue_mode (void)
|
||||
{
|
||||
auto grub_err_t getline (char **line);
|
||||
|
||||
grub_err_t getline (char **line)
|
||||
{
|
||||
grub_rescue_get_command_line ("> ");
|
||||
*line = linebuf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First of all, attempt to execute the normal mode. */
|
||||
attempt_normal_mode ();
|
||||
|
||||
grub_printf ("Entering into rescue mode...\n");
|
||||
|
||||
grub_rescue_register_command ("boot", grub_rescue_cmd_boot,
|
||||
"boot an operating system");
|
||||
grub_rescue_register_command ("cat", grub_rescue_cmd_cat,
|
||||
"show the contents of a file");
|
||||
grub_rescue_register_command ("help", grub_rescue_cmd_help,
|
||||
"show this message");
|
||||
grub_rescue_register_command ("ls", grub_rescue_cmd_ls,
|
||||
"list devices or files");
|
||||
grub_rescue_register_command ("root", grub_rescue_cmd_root,
|
||||
"set the root device");
|
||||
grub_rescue_register_command ("dump", grub_rescue_cmd_dump,
|
||||
"dump memory");
|
||||
grub_rescue_register_command ("insmod", grub_rescue_cmd_insmod,
|
||||
"insert a module");
|
||||
grub_rescue_register_command ("rmmod", grub_rescue_cmd_rmmod,
|
||||
"remove a module");
|
||||
grub_rescue_register_command ("lsmod", grub_rescue_cmd_lsmod,
|
||||
"show loaded modules");
|
||||
grub_rescue_register_command ("set", grub_rescue_cmd_set,
|
||||
"set an environment variable");
|
||||
grub_rescue_register_command ("unset", grub_rescue_cmd_unset,
|
||||
"remove an environment variable");
|
||||
grub_rescue_register_command ("exit", grub_rescue_cmd_exit,
|
||||
"exit from GRUB");
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *line = linebuf;
|
||||
char *name;
|
||||
int n;
|
||||
grub_rescue_command_t cmd;
|
||||
char **args;
|
||||
|
||||
/* Print an error, if any. */
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
/* Get a command line. */
|
||||
grub_rescue_get_command_line ("grub rescue> ");
|
||||
|
||||
if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0)
|
||||
continue;
|
||||
|
||||
/* In case of an assignment set the environment accordingly
|
||||
instead of calling a function. */
|
||||
if (n == 0 && grub_strchr (line, '='))
|
||||
{
|
||||
char *val = grub_strchr (args[0], '=');
|
||||
val[0] = 0;
|
||||
grub_env_set (args[0], val + 1);
|
||||
val[0] = '=';
|
||||
grub_free (args[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get the command name. */
|
||||
name = args[0];
|
||||
|
||||
/* If nothing is specified, restart. */
|
||||
if (*name == '\0')
|
||||
{
|
||||
grub_free (args[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the command and execute it. */
|
||||
for (cmd = grub_rescue_command_list; cmd; cmd = cmd->next)
|
||||
{
|
||||
if (grub_strcmp (name, cmd->name) == 0)
|
||||
{
|
||||
(cmd->func) (n, &args[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If not found, print an error message. */
|
||||
if (! cmd)
|
||||
{
|
||||
grub_printf ("Unknown command `%s'\n", name);
|
||||
grub_printf ("Try `help' for usage\n");
|
||||
}
|
||||
|
||||
grub_free (args[0]);
|
||||
}
|
||||
}
|
88
kern/rescue_parser.c
Normal file
88
kern/rescue_parser.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/* rescue_parser.c - rescue mode parser */
|
||||
/*
|
||||
* 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/mm.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/parser.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_rescue_parse_line (char *line, grub_reader_getline_t getline)
|
||||
{
|
||||
char *name;
|
||||
int n;
|
||||
grub_command_t cmd;
|
||||
char **args;
|
||||
|
||||
if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0)
|
||||
return grub_errno;
|
||||
|
||||
if (n == 0)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
/* In case of an assignment set the environment accordingly
|
||||
instead of calling a function. */
|
||||
if (n == 1 && grub_strchr (line, '='))
|
||||
{
|
||||
char *val = grub_strchr (args[0], '=');
|
||||
val[0] = 0;
|
||||
grub_env_set (args[0], val + 1);
|
||||
val[0] = '=';
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* Get the command name. */
|
||||
name = args[0];
|
||||
|
||||
/* If nothing is specified, restart. */
|
||||
if (*name == '\0')
|
||||
goto quit;
|
||||
|
||||
cmd = grub_command_find (name);
|
||||
if (cmd)
|
||||
{
|
||||
(cmd->func) (cmd, n - 1, &args[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_printf ("Unknown command `%s'\n", name);
|
||||
if (grub_command_find ("help"))
|
||||
grub_printf ("Try `help' for usage\n");
|
||||
}
|
||||
|
||||
quit:
|
||||
grub_free (args[0]);
|
||||
grub_free (args);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static struct grub_parser grub_rescue_parser =
|
||||
{
|
||||
.name = "rescue",
|
||||
.parse_line = grub_rescue_parse_line
|
||||
};
|
||||
|
||||
void
|
||||
grub_register_rescue_parser (void)
|
||||
{
|
||||
grub_parser_register ("rescue", &grub_rescue_parser);
|
||||
}
|
92
kern/rescue_reader.c
Normal file
92
kern/rescue_reader.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* rescue_reader.c - rescue mode reader */
|
||||
/*
|
||||
* 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/types.h>
|
||||
#include <grub/reader.h>
|
||||
#include <grub/parser.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/mm.h>
|
||||
|
||||
#define GRUB_RESCUE_BUF_SIZE 256
|
||||
|
||||
static char linebuf[GRUB_RESCUE_BUF_SIZE];
|
||||
|
||||
/* Prompt to input a command and read the line. */
|
||||
static grub_err_t
|
||||
grub_rescue_read_line (char **line, int cont)
|
||||
{
|
||||
int c;
|
||||
int pos = 0;
|
||||
|
||||
grub_printf ((cont) ? "> " : "grub rescue> ");
|
||||
grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE);
|
||||
|
||||
while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r')
|
||||
{
|
||||
if (grub_isprint (c))
|
||||
{
|
||||
if (pos < GRUB_RESCUE_BUF_SIZE - 1)
|
||||
{
|
||||
linebuf[pos++] = c;
|
||||
grub_putchar (c);
|
||||
}
|
||||
}
|
||||
else if (c == '\b')
|
||||
{
|
||||
if (pos > 0)
|
||||
{
|
||||
linebuf[--pos] = 0;
|
||||
grub_putchar (c);
|
||||
grub_putchar (' ');
|
||||
grub_putchar (c);
|
||||
}
|
||||
}
|
||||
grub_refresh ();
|
||||
}
|
||||
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
|
||||
*line = grub_strdup (linebuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
grub_rescue_run (void)
|
||||
{
|
||||
grub_printf ("Entering rescue mode...\n");
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *line;
|
||||
|
||||
/* Print an error, if any. */
|
||||
grub_print_error ();
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
grub_rescue_read_line (&line, 0);
|
||||
if (! line || line[0] == '\0')
|
||||
continue;
|
||||
|
||||
grub_parser_get_current ()->parse_line (line, grub_rescue_read_line);
|
||||
grub_free (line);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* cache.S - Flush the processor cache for a specific region. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -27,17 +27,15 @@
|
|||
* void grub_arch_sync_caches (void *address, grub_size_t len)
|
||||
*/
|
||||
FUNCTION(grub_arch_sync_caches)
|
||||
save %o6, -0xC, %o6 ! Get a new register window,
|
||||
! reserve space on stack for
|
||||
! %i0, %i1, %i2
|
||||
brz,pn %i0, return ! Return if address == 0.
|
||||
nop
|
||||
brz,pn %i1, return ! Return if len == 0.
|
||||
clr %i2 ! index = 0.
|
||||
loop: flush %i0 + %i2 ! Flush address + index.
|
||||
cmp %i1, %i2 ! Compare len & index .
|
||||
bpos,a,pt %xcc, loop ! If len > index, loop.
|
||||
add %i2, 8, %i2 ! Go to next doubleword.
|
||||
return: ret ! Restore caller's register
|
||||
restore ! window and return.
|
||||
brz,pn %o1, 2f
|
||||
add %o0, %o1, %o1
|
||||
add %o1, 7, %o1
|
||||
andn %o1, 7, %o1
|
||||
andn %o0, 7, %o0
|
||||
sub %o1, %o0, %o1
|
||||
1: subcc %o1, 8, %o1
|
||||
bne,pt %icc, 1b
|
||||
flush %o0 + %o1
|
||||
2: retl
|
||||
nop
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* dl.c - arch-dependent part of loadable module support */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2004,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,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
|
||||
|
@ -26,7 +26,7 @@
|
|||
grub_err_t
|
||||
grub_arch_dl_check_header (void *ehdr)
|
||||
{
|
||||
Elf64_Ehdr *e = ehdr;
|
||||
Elf_Ehdr *e = ehdr;
|
||||
|
||||
/* Check the magic numbers. */
|
||||
if (e->e_ident[EI_CLASS] != ELFCLASS64
|
||||
|
@ -42,28 +42,26 @@ grub_arch_dl_check_header (void *ehdr)
|
|||
grub_err_t
|
||||
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
||||
{
|
||||
Elf64_Ehdr *e = ehdr;
|
||||
Elf64_Shdr *s;
|
||||
Elf64_Sym *symtab;
|
||||
Elf64_Word entsize;
|
||||
Elf_Ehdr *e = ehdr;
|
||||
Elf_Shdr *s;
|
||||
Elf_Word entsize;
|
||||
unsigned i;
|
||||
|
||||
|
||||
/* Find a symbol table. */
|
||||
for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf64_Shdr *) ((char *) s + e->e_shentsize))
|
||||
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_SYMTAB)
|
||||
break;
|
||||
|
||||
if (i == e->e_shnum)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
|
||||
|
||||
symtab = (Elf64_Sym *) ((char *) e + s->sh_offset);
|
||||
|
||||
entsize = s->sh_entsize;
|
||||
|
||||
for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
|
||||
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf64_Shdr *) ((char *) s + e->e_shentsize))
|
||||
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_RELA)
|
||||
{
|
||||
grub_dl_segment_t seg;
|
||||
|
@ -75,64 +73,70 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
|||
|
||||
if (seg)
|
||||
{
|
||||
Elf64_Rela *rel, *max;
|
||||
|
||||
for (rel = (Elf64_Rela *) ((char *) e + s->sh_offset),
|
||||
Elf_Rela *rel, *max;
|
||||
|
||||
for (rel = (Elf_Rela *) ((char *) e + s->sh_offset),
|
||||
max = rel + s->sh_size / s->sh_entsize;
|
||||
rel < max;
|
||||
rel++)
|
||||
{
|
||||
Elf64_Word *addr;
|
||||
Elf64_Sym *sym;
|
||||
Elf64_Addr value;
|
||||
|
||||
Elf_Word *addr;
|
||||
Elf_Sym *sym;
|
||||
Elf_Addr value;
|
||||
|
||||
if (seg->size < rel->r_offset)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"reloc offset is out of the segment");
|
||||
|
||||
addr = (Elf64_Word *) ((char *) seg->addr + rel->r_offset);
|
||||
sym = (Elf64_Sym *) ((char *) symtab
|
||||
+ entsize * ELF64_R_SYM (rel->r_info));
|
||||
|
||||
addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset);
|
||||
sym = (Elf_Sym *) ((char *) mod->symtab
|
||||
+ entsize * ELF_R_SYM (rel->r_info));
|
||||
|
||||
value = sym->st_value + rel->r_addend;
|
||||
switch (ELF64_R_TYPE (rel->r_info))
|
||||
switch (ELF_R_TYPE (rel->r_info) & 0xff)
|
||||
{
|
||||
case R_SPARC_32: /* 3 V-word32 */
|
||||
if (value & 0xFFFFFFFF00000000)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"Address out of 32 bits range");
|
||||
"address out of 32 bits range");
|
||||
*addr = value;
|
||||
break;
|
||||
case R_SPARC_WDISP30: /* 7 V-disp30 */
|
||||
if (((value - (Elf64_Addr) addr) & 0xFFFFFFFF00000000) &&
|
||||
((value - (Elf64_Addr) addr) & 0xFFFFFFFF00000000
|
||||
!= 0xFFFFFFFF00000000))
|
||||
if (((value - (Elf_Addr) addr) & 0xFFFFFFFF00000000) &&
|
||||
(((value - (Elf_Addr) addr) & 0xFFFFFFFF00000000)
|
||||
!= 0xFFFFFFFF00000000))
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"Displacement out of 30 bits range");
|
||||
"displacement out of 30 bits range");
|
||||
*addr = (*addr & 0xC0000000) |
|
||||
(((grub_int32_t) ((value - (Elf64_Addr) addr) >> 2)) &
|
||||
(((grub_int32_t) ((value - (Elf_Addr) addr) >> 2)) &
|
||||
0x3FFFFFFF);
|
||||
break;
|
||||
case R_SPARC_HI22: /* 9 V-imm22 */
|
||||
if (((grub_int32_t) value) & 0xFF00000000)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"High address out of 22 bits range");
|
||||
"high address out of 22 bits range");
|
||||
*addr = (*addr & 0xFFC00000) | ((value >> 10) & 0x3FFFFF);
|
||||
break;
|
||||
case R_SPARC_LO10: /* 12 T-simm13 */
|
||||
*addr = (*addr & 0xFFFFFC00) | (value & 0x3FF);
|
||||
break;
|
||||
case R_SPARC_64: /* 32 V-xwords64 */
|
||||
*(Elf64_Xword *) addr = value;
|
||||
*(Elf_Xword *) addr = value;
|
||||
break;
|
||||
case R_SPARC_OLO10:
|
||||
*addr = (*addr & ~0x1fff)
|
||||
| (((value & 0x3ff) +
|
||||
(ELF_R_TYPE (rel->r_info) >> 8))
|
||||
& 0x1fff);
|
||||
break;
|
||||
default:
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"This relocation (%d) is not implemented yet",
|
||||
ELF64_R_TYPE (rel->r_info));
|
||||
"this relocation (%d) is not implemented yet",
|
||||
ELF_R_TYPE (rel->r_info));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
77
kern/sparc64/ieee1275/crt0.S
Normal file
77
kern/sparc64/ieee1275/crt0.S
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* crt0.S - Startup code for the Sparc64. */
|
||||
/*
|
||||
* 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/symbol.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.globl _start
|
||||
_start:
|
||||
ba codestart
|
||||
nop
|
||||
|
||||
. = EXT_C(_start) + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
|
||||
|
||||
VARIABLE(grub_total_module_size)
|
||||
.word 0
|
||||
VARIABLE(grub_kernel_image_size)
|
||||
.word 0
|
||||
VARIABLE(grub_compressed_size)
|
||||
.word 0
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = EXT_C(_start) + GRUB_KERNEL_MACHINE_DATA_END
|
||||
|
||||
codestart:
|
||||
/* Copy the modules past the end of the kernel image.
|
||||
* They are currently sitting in the BSS.
|
||||
*/
|
||||
sethi %hi(__bss_start), %o2
|
||||
or %o2, %lo(__bss_start), %o2
|
||||
sethi %hi(_end), %o3
|
||||
or %o3, %lo(_end), %o3
|
||||
sethi %hi(grub_total_module_size), %o4
|
||||
lduw [%o4 + %lo(grub_total_module_size)], %o4
|
||||
1: lduw [%o2], %o5
|
||||
stw %o5, [%o3]
|
||||
subcc %o4, 4, %o4
|
||||
add %o2, 4, %o2
|
||||
bne,pt %icc, 1b
|
||||
add %o3, 4, %o3
|
||||
|
||||
/* Now it's safe to clear out the BSS. */
|
||||
sethi %hi(__bss_start), %o2
|
||||
or %o2, %lo(__bss_start), %o2
|
||||
sethi %hi(_end), %o3
|
||||
or %o3, %lo(_end), %o3
|
||||
1: stx %g0, [%o2]
|
||||
add %o2, 8, %o2
|
||||
cmp %o2, %o3
|
||||
blt,pt %xcc, 1b
|
||||
nop
|
||||
sethi %hi(grub_ieee1275_entry_fn), %o2
|
||||
stx %o0, [%o2 + %lo(grub_ieee1275_entry_fn)]
|
||||
call grub_main
|
||||
nop
|
||||
1: ba,a 1b
|
124
kern/sparc64/ieee1275/ieee1275.c
Normal file
124
kern/sparc64/ieee1275/ieee1275.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* 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/ieee1275/ieee1275.h>
|
||||
#include <grub/types.h>
|
||||
|
||||
/* Sun specific ieee1275 interfaces used by GRUB. */
|
||||
|
||||
int
|
||||
grub_ieee1275_map_physical (grub_addr_t paddr, grub_addr_t vaddr,
|
||||
grub_size_t size, grub_uint32_t mode)
|
||||
{
|
||||
struct map_physical_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_cell_t method;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t mode;
|
||||
grub_ieee1275_cell_t size;
|
||||
grub_ieee1275_cell_t virt;
|
||||
grub_ieee1275_cell_t phys_high;
|
||||
grub_ieee1275_cell_t phys_low;
|
||||
grub_ieee1275_cell_t catch_result;
|
||||
}
|
||||
args;
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 7, 1);
|
||||
args.method = (grub_ieee1275_cell_t) "map";
|
||||
args.ihandle = grub_ieee1275_mmu;
|
||||
args.mode = mode;
|
||||
args.size = size;
|
||||
args.virt = vaddr;
|
||||
args.phys_high = 0;
|
||||
args.phys_low = paddr;
|
||||
args.catch_result = (grub_ieee1275_cell_t) -1;
|
||||
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
return -1;
|
||||
return args.catch_result;
|
||||
}
|
||||
|
||||
int
|
||||
grub_ieee1275_claim_vaddr (grub_addr_t vaddr, grub_size_t size)
|
||||
{
|
||||
struct claim_vaddr_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_cell_t method;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t align;
|
||||
grub_ieee1275_cell_t size;
|
||||
grub_ieee1275_cell_t virt;
|
||||
grub_ieee1275_cell_t catch_result;
|
||||
}
|
||||
args;
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 5, 2);
|
||||
args.method = (grub_ieee1275_cell_t) "claim";
|
||||
args.ihandle = grub_ieee1275_mmu;
|
||||
args.align = 0;
|
||||
args.size = size;
|
||||
args.virt = vaddr;
|
||||
args.catch_result = (grub_ieee1275_cell_t) -1;
|
||||
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
return -1;
|
||||
return args.catch_result;
|
||||
}
|
||||
|
||||
int
|
||||
grub_ieee1275_alloc_physmem (grub_addr_t *paddr, grub_size_t size,
|
||||
grub_uint32_t align)
|
||||
{
|
||||
grub_uint32_t memory_ihandle;
|
||||
struct alloc_physmem_args
|
||||
{
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
grub_ieee1275_cell_t method;
|
||||
grub_ieee1275_cell_t ihandle;
|
||||
grub_ieee1275_cell_t align;
|
||||
grub_ieee1275_cell_t size;
|
||||
grub_ieee1275_cell_t catch_result;
|
||||
grub_ieee1275_cell_t phys_high;
|
||||
grub_ieee1275_cell_t phys_low;
|
||||
}
|
||||
args;
|
||||
grub_ssize_t actual = 0;
|
||||
|
||||
grub_ieee1275_get_property (grub_ieee1275_chosen, "memory",
|
||||
&memory_ihandle, sizeof (memory_ihandle),
|
||||
&actual);
|
||||
if (actual != sizeof (memory_ihandle))
|
||||
return -1;
|
||||
|
||||
if (!align)
|
||||
align = 1;
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 3);
|
||||
args.method = (grub_ieee1275_cell_t) "claim";
|
||||
args.ihandle = memory_ihandle;
|
||||
args.align = (align ? align : 1);
|
||||
args.size = size;
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
return -1;
|
||||
|
||||
*paddr = args.phys_low;
|
||||
|
||||
return args.catch_result;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* init.c -- Initialize GRUB on the Ultra Sprac (sparc64). */
|
||||
/* init.c -- Initialize GRUB on SPARC64. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2004,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,163 +18,111 @@
|
|||
*/
|
||||
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/setjmp.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/machine/console.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/machine/time.h>
|
||||
#include <grub/ieee1275/ofdisk.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
|
||||
/* OpenBoot entry point. */
|
||||
int (*grub_ieee1275_entry_fn) (void *);
|
||||
grub_ieee1275_phandle_t grub_ieee1275_chosen;
|
||||
static grub_uint32_t grub_ieee1275_flags;
|
||||
/* FIXME (sparc64). */
|
||||
static const grub_addr_t grub_heap_start = 0x40000;
|
||||
static grub_addr_t grub_heap_len;
|
||||
|
||||
void
|
||||
_start (uint64_t r0 __attribute__((unused)),
|
||||
uint64_t r1 __attribute__((unused)),
|
||||
uint64_t r2 __attribute__((unused)),
|
||||
uint64_t r3 __attribute__((unused)),
|
||||
uint64_t r4,
|
||||
uint64_t r5 __attribute__((unused)));
|
||||
void
|
||||
_start (uint64_t r0 __attribute__((unused)),
|
||||
uint64_t r1 __attribute__((unused)),
|
||||
uint64_t r2 __attribute__((unused)),
|
||||
uint64_t r3 __attribute__((unused)),
|
||||
uint64_t r4,
|
||||
uint64_t r5 __attribute__((unused)))
|
||||
grub_exit (void)
|
||||
{
|
||||
grub_ieee1275_entry_fn = (int (*)(void *)) r4;
|
||||
|
||||
grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen);
|
||||
|
||||
/* Now invoke the main function. */
|
||||
grub_main ();
|
||||
|
||||
/* Never reached. */
|
||||
grub_ieee1275_exit ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_millisleep (grub_uint32_t ms)
|
||||
static grub_uint64_t
|
||||
ieee1275_get_time_ms (void)
|
||||
{
|
||||
grub_millisleep_generic (ms);
|
||||
grub_uint32_t msecs = 0;
|
||||
|
||||
grub_ieee1275_milliseconds (&msecs);
|
||||
|
||||
return msecs;
|
||||
}
|
||||
|
||||
int
|
||||
grub_ieee1275_test_flag (enum grub_ieee1275_flag flag)
|
||||
grub_uint32_t
|
||||
grub_get_rtc (void)
|
||||
{
|
||||
return (grub_ieee1275_flags & (1 << flag));
|
||||
return ieee1275_get_time_ms ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_ieee1275_set_flag (enum grub_ieee1275_flag flag)
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
grub_ieee1275_flags |= (1 << flag);
|
||||
}
|
||||
|
||||
/* Translate an OF filesystem path (separated by backslashes), into a GRUB
|
||||
path (separated by forward slashes). */
|
||||
static void
|
||||
grub_translate_ieee1275_path (char *filepath)
|
||||
{
|
||||
char *backslash;
|
||||
|
||||
backslash = grub_strchr (filepath, '\\');
|
||||
while (backslash != 0)
|
||||
{
|
||||
*backslash = '/';
|
||||
backslash = grub_strchr (filepath, '\\');
|
||||
}
|
||||
extern char _end[];
|
||||
return (grub_addr_t) _end;
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
{
|
||||
char bootpath[64]; /* XXX check length */
|
||||
char *filename;
|
||||
char *prefix;
|
||||
|
||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath,
|
||||
sizeof (bootpath), 0))
|
||||
if (grub_prefix[0] != '(')
|
||||
{
|
||||
/* Should never happen. */
|
||||
grub_printf ("/chosen/bootpath property missing!\n");
|
||||
grub_env_set ("prefix", "");
|
||||
return;
|
||||
}
|
||||
char bootpath[IEEE1275_MAX_PATH_LEN];
|
||||
char *prefix, *path, *colon;
|
||||
grub_ssize_t actual;
|
||||
|
||||
/* Transform an OF device path to a GRUB path. */
|
||||
|
||||
prefix = grub_ieee1275_encode_devname (bootpath);
|
||||
|
||||
filename = grub_ieee1275_get_filename (bootpath);
|
||||
if (filename)
|
||||
{
|
||||
char *newprefix;
|
||||
char *lastslash = grub_strrchr (filename, '\\');
|
||||
|
||||
/* Truncate at last directory. */
|
||||
if (lastslash)
|
||||
{
|
||||
*lastslash = '\0';
|
||||
grub_translate_ieee1275_path (filename);
|
||||
|
||||
newprefix = grub_malloc (grub_strlen (prefix)
|
||||
+ grub_strlen (filename));
|
||||
grub_sprintf (newprefix, "%s%s", prefix, filename);
|
||||
grub_free (prefix);
|
||||
prefix = newprefix;
|
||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath",
|
||||
&bootpath, sizeof (bootpath), &actual))
|
||||
{
|
||||
/* Should never happen. */
|
||||
grub_printf ("/chosen/bootpath property missing!\n");
|
||||
grub_env_set ("prefix", "");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Transform an OF device path to a GRUB path. */
|
||||
colon = grub_strchr (bootpath, ':');
|
||||
if (colon)
|
||||
{
|
||||
char *part = colon + 1;
|
||||
|
||||
/* Consistently provide numbered partitions to GRUB.
|
||||
OpenBOOT traditionally uses alphabetical partition
|
||||
specifiers. */
|
||||
if (part[0] >= 'a' && part[0] <= 'z')
|
||||
part[0] = '1' + (part[0] - 'a');
|
||||
}
|
||||
prefix = grub_ieee1275_encode_devname (bootpath);
|
||||
|
||||
path = grub_malloc (grub_strlen (grub_prefix)
|
||||
+ grub_strlen (prefix)
|
||||
+ 2);
|
||||
grub_sprintf(path, "%s%s", prefix, grub_prefix);
|
||||
|
||||
grub_strcpy (grub_prefix, path);
|
||||
|
||||
grub_free (path);
|
||||
grub_free (prefix);
|
||||
}
|
||||
|
||||
grub_env_set ("prefix", prefix);
|
||||
|
||||
grub_free (filename);
|
||||
grub_free (prefix);
|
||||
grub_env_set ("prefix", grub_prefix);
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
static void
|
||||
grub_heap_init (void)
|
||||
{
|
||||
char *args;
|
||||
grub_ssize_t length;
|
||||
grub_mm_init_region ((void *)(long)0x4000UL, 0x200000 - 0x4000);
|
||||
}
|
||||
|
||||
grub_console_init ();
|
||||
static void
|
||||
grub_parse_cmdline (void)
|
||||
{
|
||||
grub_ssize_t actual;
|
||||
char args[256];
|
||||
|
||||
/* FIXME (sparc64). */
|
||||
grub_heap_len = (grub_addr_t) &_start - 0x1000 - grub_heap_start;
|
||||
|
||||
if (grub_ieee1275_claim (grub_heap_start, grub_heap_len, 0, 0))
|
||||
grub_fatal ("Failed to claim heap at %p, len 0x%x\n", grub_heap_start,
|
||||
grub_heap_len);
|
||||
grub_mm_init_region ((void *) grub_heap_start, grub_heap_len);
|
||||
|
||||
grub_ofdisk_init ();
|
||||
|
||||
/* Process commandline. */
|
||||
if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootargs",
|
||||
&length) == 0 &&
|
||||
length > 0)
|
||||
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
|
||||
sizeof args, &actual) == 0
|
||||
&& actual > 1)
|
||||
{
|
||||
grub_ssize_t i = 0;
|
||||
int i = 0;
|
||||
|
||||
args = grub_malloc (length);
|
||||
grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", args,
|
||||
length, 0);
|
||||
|
||||
while (i < length)
|
||||
while (i < actual)
|
||||
{
|
||||
char *command = &args[i];
|
||||
char *end;
|
||||
|
@ -182,7 +130,7 @@ grub_machine_init (void)
|
|||
|
||||
end = grub_strchr (command, ';');
|
||||
if (end == 0)
|
||||
i = length; /* No more commands after this one. */
|
||||
i = actual; /* No more commands after this one. */
|
||||
else
|
||||
{
|
||||
*end = '\0';
|
||||
|
@ -200,7 +148,20 @@ grub_machine_init (void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
grub_ieee1275_init ();
|
||||
grub_console_init ();
|
||||
grub_heap_init ();
|
||||
|
||||
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
|
||||
grub_ofdisk_init ();
|
||||
|
||||
grub_parse_cmdline ();
|
||||
grub_install_get_time_ms (ieee1275_get_time_ms);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -209,26 +170,3 @@ grub_machine_fini (void)
|
|||
grub_ofdisk_fini ();
|
||||
grub_console_fini ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_exit (void)
|
||||
{
|
||||
grub_ieee1275_enter ();
|
||||
}
|
||||
|
||||
grub_uint32_t
|
||||
grub_get_rtc (void)
|
||||
{
|
||||
grub_uint32_t msecs;
|
||||
|
||||
if (grub_ieee1275_milliseconds (&msecs))
|
||||
return 0;
|
||||
|
||||
return msecs;
|
||||
}
|
||||
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
return GRUB_IEEE1275_MODULE_BASE;
|
||||
}
|
||||
|
|
|
@ -1,373 +0,0 @@
|
|||
/* openfw.c -- Open firmware support functions. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2004,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/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/machine/kernel.h> /* Needed ? */
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
|
||||
enum grub_ieee1275_parse_type
|
||||
{
|
||||
GRUB_PARSE_FILENAME,
|
||||
GRUB_PARSE_PARTITION,
|
||||
};
|
||||
|
||||
/* Walk children of 'devpath', calling hook for each. */
|
||||
grub_err_t
|
||||
grub_children_iterate (char *devpath,
|
||||
int (*hook) (struct grub_ieee1275_devalias *alias))
|
||||
{
|
||||
grub_ieee1275_phandle_t dev;
|
||||
grub_ieee1275_phandle_t child;
|
||||
|
||||
grub_ieee1275_finddevice (devpath, &dev);
|
||||
if (((signed) dev) == -1)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Unknown device");
|
||||
|
||||
grub_ieee1275_child (dev, &child);
|
||||
if (((signed) child) == -1)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "Device has no children");
|
||||
|
||||
do
|
||||
{
|
||||
/* XXX: Don't use hardcoded path lengths. */
|
||||
char childtype[64];
|
||||
char childpath[64];
|
||||
char childname[64];
|
||||
char fullname[64];
|
||||
struct grub_ieee1275_devalias alias;
|
||||
grub_ssize_t actual;
|
||||
|
||||
grub_ieee1275_get_property (child, "device_type", childtype,
|
||||
sizeof childtype, &actual);
|
||||
if (actual == -1)
|
||||
continue;
|
||||
|
||||
grub_ieee1275_package_to_path (child, childpath, sizeof childpath,
|
||||
&actual);
|
||||
if (actual == -1)
|
||||
continue;
|
||||
|
||||
grub_ieee1275_get_property (child, "name", childname,
|
||||
sizeof childname, &actual);
|
||||
if (actual == -1)
|
||||
continue;
|
||||
|
||||
grub_sprintf (fullname, "%s/%s", devpath, childname);
|
||||
|
||||
alias.type = childtype;
|
||||
alias.path = childpath;
|
||||
alias.name = fullname;
|
||||
hook (&alias);
|
||||
}
|
||||
while (grub_ieee1275_peer (child, &child));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Iterate through all device aliases. This function can be used to
|
||||
find a device of a specific type. */
|
||||
grub_err_t
|
||||
grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
|
||||
{
|
||||
grub_ieee1275_phandle_t devalias;
|
||||
char aliasname[32];
|
||||
grub_ssize_t actual;
|
||||
grub_ieee1275_cell_t flags;
|
||||
struct grub_ieee1275_devalias alias;
|
||||
|
||||
if (grub_ieee1275_finddevice ("/aliases", &devalias))
|
||||
return -1;
|
||||
|
||||
aliasname[0] = '\0';
|
||||
|
||||
while (grub_ieee1275_next_property (devalias, aliasname, aliasname, &flags) != -1
|
||||
&& ((signed) flags) != -1 )
|
||||
{
|
||||
grub_ieee1275_phandle_t dev;
|
||||
grub_ssize_t pathlen, typelen;
|
||||
char *devpath, *devtype;
|
||||
|
||||
grub_dprintf ("devalias", "devalias name = %s\n", aliasname);
|
||||
|
||||
/* The property `name' is a special case we should skip. */
|
||||
if (!grub_strcmp (aliasname, "name"))
|
||||
continue;
|
||||
|
||||
grub_ieee1275_get_property_length (devalias, aliasname, &pathlen);
|
||||
devpath = grub_malloc (pathlen);
|
||||
if (! devpath)
|
||||
return grub_errno;
|
||||
|
||||
if (grub_ieee1275_get_property (devalias, aliasname, devpath, pathlen,
|
||||
&actual))
|
||||
{
|
||||
grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname);
|
||||
grub_free (devpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (grub_ieee1275_finddevice (devpath, &dev) || ((signed) dev) == -1)
|
||||
{
|
||||
grub_dprintf ("devalias", "finddevice (%s) failed\n", devpath);
|
||||
grub_free (devpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
grub_ieee1275_get_property_length (dev, "device_type", &typelen);
|
||||
devtype = grub_malloc (typelen);
|
||||
if (! devtype)
|
||||
{
|
||||
grub_free (devpath);
|
||||
return grub_errno;
|
||||
}
|
||||
if (grub_ieee1275_get_property (dev, "device_type", devtype, typelen, &actual))
|
||||
{
|
||||
grub_dprintf ("devalias", "get device type failed\n");
|
||||
grub_free (devtype);
|
||||
grub_free (devpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
alias.name = aliasname;
|
||||
alias.path= devpath;
|
||||
alias.type = devtype;
|
||||
if((*hook) (&alias))
|
||||
{
|
||||
grub_free (devtype);
|
||||
grub_free (devpath);
|
||||
break;
|
||||
}
|
||||
|
||||
grub_free (devtype);
|
||||
grub_free (devpath);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME (sparc64) */
|
||||
#if 0
|
||||
/* Call the "map" method of /chosen/mmu. */
|
||||
static int
|
||||
grub_map (grub_addr_t phys, grub_addr_t virt, grub_uint32_t size,
|
||||
grub_uint8_t mode)
|
||||
{
|
||||
struct map_args {
|
||||
struct grub_ieee1275_common_hdr common;
|
||||
char *method;
|
||||
grub_ieee1275_ihandle_t ihandle;
|
||||
grub_uint32_t mode;
|
||||
grub_uint32_t size;
|
||||
grub_uint32_t virt;
|
||||
grub_uint32_t phys;
|
||||
int catch_result;
|
||||
} args;
|
||||
grub_ieee1275_ihandle_t mmu;
|
||||
grub_ssize_t len;
|
||||
|
||||
grub_ieee1275_get_integer_property (grub_ieee1275_chosen, "mmu", &mmu, sizeof mmu,
|
||||
&len);
|
||||
if (len != sizeof mmu)
|
||||
return -1;
|
||||
|
||||
INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
|
||||
args.method = "map";
|
||||
args.ihandle = mmu;
|
||||
args.phys = phys;
|
||||
args.virt = virt;
|
||||
args.size = size;
|
||||
args.mode = mode; /* Format is WIMG0PP. */
|
||||
|
||||
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||
return -1;
|
||||
|
||||
return args.catch_result;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
grub_claimmap (grub_addr_t addr, grub_size_t size)
|
||||
{
|
||||
if (grub_ieee1275_claim (addr, size, 0, 0))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the device arguments of the Open Firmware node name `path'. */
|
||||
static char *
|
||||
grub_ieee1275_get_devargs (const char *path)
|
||||
{
|
||||
char *colon = grub_strchr (path, ':');
|
||||
|
||||
if (! colon)
|
||||
return 0;
|
||||
|
||||
return grub_strdup (colon + 1);
|
||||
}
|
||||
|
||||
/* Get the device path of the Open Firmware node name `path'. */
|
||||
static char *
|
||||
grub_ieee1275_get_devname (const char *path)
|
||||
{
|
||||
char *colon = grub_strchr (path, ':');
|
||||
char *newpath = 0;
|
||||
int pathlen = grub_strlen (path);
|
||||
auto int match_alias (struct grub_ieee1275_devalias *alias);
|
||||
|
||||
int match_alias (struct grub_ieee1275_devalias *curalias)
|
||||
{
|
||||
/* briQ firmware can change capitalization in /chosen/bootpath. */
|
||||
if (! grub_strncasecmp (curalias->path, path, pathlen))
|
||||
{
|
||||
newpath = grub_strndup (curalias->name, grub_strlen (curalias->name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (colon)
|
||||
pathlen = (int)(colon - path);
|
||||
|
||||
/* Try to find an alias for this device. */
|
||||
grub_devalias_iterate (match_alias);
|
||||
|
||||
if (! newpath)
|
||||
newpath = grub_strdup (path);
|
||||
|
||||
return newpath;
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
|
||||
{
|
||||
char type[64]; /* XXX check size. */
|
||||
char *device = grub_ieee1275_get_devname (path);
|
||||
char *args = grub_ieee1275_get_devargs (path);
|
||||
char *ret = 0;
|
||||
grub_ieee1275_phandle_t dev;
|
||||
|
||||
if (!args)
|
||||
/* Shouldn't happen. */
|
||||
return 0;
|
||||
|
||||
/* We need to know what type of device it is in order to parse the full
|
||||
file path properly. */
|
||||
if (grub_ieee1275_finddevice (device, &dev))
|
||||
{
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s not found\n", device);
|
||||
goto fail;
|
||||
}
|
||||
if (grub_ieee1275_get_property (dev, "device_type", type, sizeof type, 0))
|
||||
{
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
"Device %s lacks a device_type property\n", device);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!grub_strcmp ("block", type))
|
||||
{
|
||||
/* The syntax of the device arguments is defined in the CHRP and PReP
|
||||
IEEE1275 bindings: "[partition][,[filename]]". */
|
||||
char *comma = grub_strchr (args, ',');
|
||||
|
||||
if (ptype == GRUB_PARSE_FILENAME)
|
||||
{
|
||||
if (comma)
|
||||
{
|
||||
char *filepath = comma + 1;
|
||||
|
||||
ret = grub_malloc (grub_strlen (filepath) + 1);
|
||||
/* Make sure filepath has leading backslash. */
|
||||
if (filepath[0] != '\\')
|
||||
grub_sprintf (ret, "\\%s", filepath);
|
||||
else
|
||||
grub_strcpy (ret, filepath);
|
||||
}
|
||||
}
|
||||
else if (ptype == GRUB_PARSE_PARTITION)
|
||||
{
|
||||
if (!comma)
|
||||
ret = grub_strdup (args);
|
||||
else
|
||||
ret = grub_strndup (args, (grub_size_t)(comma - args));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX Handle net devices by configuring & registering a grub_net_dev
|
||||
here, then return its name?
|
||||
Example path: "net:<server ip>,<file name>,<client ip>,<gateway
|
||||
ip>,<bootp retries>,<tftp retries>". */
|
||||
grub_printf ("Unsupported type %s for device %s\n", type, device);
|
||||
}
|
||||
|
||||
fail:
|
||||
grub_free (device);
|
||||
grub_free (args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
grub_ieee1275_get_filename (const char *path)
|
||||
{
|
||||
return grub_ieee1275_parse_args (path, GRUB_PARSE_FILENAME);
|
||||
}
|
||||
|
||||
/* Convert a device name from IEEE1275 syntax to GRUB syntax. */
|
||||
char *
|
||||
grub_ieee1275_encode_devname (const char *path)
|
||||
{
|
||||
char *device = grub_ieee1275_get_devname (path);
|
||||
char *partition = grub_ieee1275_parse_args (path, GRUB_PARSE_PARTITION);
|
||||
char *encoding;
|
||||
|
||||
if (partition)
|
||||
{
|
||||
unsigned int partno = grub_strtoul (partition, 0, 0);
|
||||
|
||||
/* Assume partno will require less than five bytes to encode. */
|
||||
encoding = grub_malloc (grub_strlen (device) + 3 + 5);
|
||||
grub_sprintf (encoding, "(%s,%d)", device, partno);
|
||||
}
|
||||
else
|
||||
{
|
||||
encoding = grub_malloc (grub_strlen (device) + 2);
|
||||
grub_sprintf (encoding, "(%s)", device);
|
||||
}
|
||||
|
||||
grub_free (partition);
|
||||
grub_free (device);
|
||||
|
||||
return encoding;
|
||||
}
|
||||
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
grub_ieee1275_interpret ("reset-all", 0);
|
||||
}
|
||||
|
||||
void
|
||||
grub_halt (void)
|
||||
{
|
||||
grub_ieee1275_interpret ("power-off", 0);
|
||||
}
|
272
kern/term.c
272
kern/term.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2005,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002,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
|
||||
|
@ -21,125 +21,33 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
/* The list of terminals. */
|
||||
static grub_term_t grub_term_list;
|
||||
struct grub_term_output *grub_term_outputs_disabled;
|
||||
struct grub_term_input *grub_term_inputs_disabled;
|
||||
struct grub_term_output *grub_term_outputs;
|
||||
struct grub_term_input *grub_term_inputs;
|
||||
|
||||
/* The current terminal. */
|
||||
static grub_term_t grub_cur_term;
|
||||
|
||||
/* The amount of lines counted by the pager. */
|
||||
static int grub_more_lines;
|
||||
|
||||
/* If the more pager is active. */
|
||||
static int grub_more;
|
||||
|
||||
/* The current cursor state. */
|
||||
static int cursor_state = 1;
|
||||
|
||||
void
|
||||
grub_term_register (grub_term_t term)
|
||||
{
|
||||
term->next = grub_term_list;
|
||||
grub_term_list = term;
|
||||
}
|
||||
|
||||
void
|
||||
grub_term_unregister (grub_term_t term)
|
||||
{
|
||||
grub_term_t *p, q;
|
||||
|
||||
for (p = &grub_term_list, q = *p; q; p = &(q->next), q = q->next)
|
||||
if (q == term)
|
||||
{
|
||||
*p = q->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_term_iterate (int (*hook) (grub_term_t term))
|
||||
{
|
||||
grub_term_t p;
|
||||
|
||||
for (p = grub_term_list; p; p = p->next)
|
||||
if (hook (p))
|
||||
break;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_term_set_current (grub_term_t term)
|
||||
{
|
||||
if (grub_cur_term && grub_cur_term->fini)
|
||||
if ((grub_cur_term->fini) () != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
if (term->init)
|
||||
if ((term->init) () != GRUB_ERR_NONE)
|
||||
return grub_errno;
|
||||
|
||||
grub_cur_term = term;
|
||||
grub_cls ();
|
||||
grub_setcursor (grub_getcursor ());
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_term_t
|
||||
grub_term_get_current (void)
|
||||
{
|
||||
return grub_cur_term;
|
||||
}
|
||||
void (*grub_newline_hook) (void) = NULL;
|
||||
|
||||
/* Put a Unicode character. */
|
||||
void
|
||||
grub_putcode (grub_uint32_t code)
|
||||
grub_putcode (grub_uint32_t code, struct grub_term_output *term)
|
||||
{
|
||||
int height = grub_getwh () & 255;
|
||||
|
||||
if (code == '\t' && grub_cur_term->getxy)
|
||||
if (code == '\t' && term->getxy)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = 8 - ((grub_getxy () >> 8) & 7);
|
||||
|
||||
n = 8 - ((term->getxy () >> 8) & 7);
|
||||
while (n--)
|
||||
grub_putcode (' ');
|
||||
grub_putcode (' ', term);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
(grub_cur_term->putchar) (code);
|
||||
|
||||
|
||||
(term->putchar) (code);
|
||||
if (code == '\n')
|
||||
{
|
||||
grub_putcode ('\r');
|
||||
|
||||
grub_more_lines++;
|
||||
|
||||
if (grub_more && grub_more_lines == height - 1)
|
||||
{
|
||||
char key;
|
||||
int pos = grub_getxy ();
|
||||
|
||||
/* Show --MORE-- on the lower left side of the screen. */
|
||||
grub_gotoxy (1, height - 1);
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
|
||||
grub_printf ("--MORE--");
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
|
||||
|
||||
key = grub_getkey ();
|
||||
|
||||
/* Remove the message. */
|
||||
grub_gotoxy (1, height - 1);
|
||||
grub_printf (" ");
|
||||
grub_gotoxy (pos >> 8, pos & 0xFF);
|
||||
|
||||
/* Scroll one lines or an entire page, depending on the key. */
|
||||
if (key == '\r' || key =='\n')
|
||||
grub_more_lines--;
|
||||
else
|
||||
grub_more_lines = 0;
|
||||
}
|
||||
}
|
||||
(term->putchar) ('\r');
|
||||
}
|
||||
|
||||
/* Put a character. C is one byte of a UTF-8 stream.
|
||||
|
@ -150,127 +58,101 @@ grub_putchar (int c)
|
|||
static grub_size_t size = 0;
|
||||
static grub_uint8_t buf[6];
|
||||
grub_uint32_t code;
|
||||
grub_ssize_t ret;
|
||||
grub_size_t ret;
|
||||
|
||||
buf[size++] = c;
|
||||
ret = grub_utf8_to_ucs4 (&code, buf, size);
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
size = 0;
|
||||
grub_putcode (code);
|
||||
}
|
||||
else if (ret < 0)
|
||||
{
|
||||
size = 0;
|
||||
grub_putcode ('?');
|
||||
}
|
||||
}
|
||||
ret = grub_utf8_to_ucs4 (&code, 1, buf, size, 0);
|
||||
|
||||
/* Return the number of columns occupied by the character code CODE. */
|
||||
grub_ssize_t
|
||||
grub_getcharwidth (grub_uint32_t code)
|
||||
{
|
||||
return (grub_cur_term->getcharwidth) (code);
|
||||
if (ret != 0)
|
||||
{
|
||||
struct grub_term_output *term;
|
||||
size = 0;
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
grub_putcode (code, term);
|
||||
if (code == '\n' && grub_newline_hook)
|
||||
grub_newline_hook ();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
grub_getkey (void)
|
||||
{
|
||||
return (grub_cur_term->getkey) ();
|
||||
grub_term_input_t term;
|
||||
|
||||
while (1)
|
||||
{
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
{
|
||||
int key = term->checkkey ();
|
||||
if (key != -1)
|
||||
return term->getkey ();
|
||||
}
|
||||
|
||||
grub_cpu_idle ();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
grub_checkkey (void)
|
||||
{
|
||||
return (grub_cur_term->checkkey) ();
|
||||
grub_term_input_t term;
|
||||
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
{
|
||||
int key = term->checkkey ();
|
||||
if (key != -1)
|
||||
return key;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
grub_uint16_t
|
||||
grub_getxy (void)
|
||||
int
|
||||
grub_getkeystatus (void)
|
||||
{
|
||||
return (grub_cur_term->getxy) ();
|
||||
}
|
||||
int status = 0;
|
||||
grub_term_input_t term;
|
||||
|
||||
grub_uint16_t
|
||||
grub_getwh (void)
|
||||
{
|
||||
return (grub_cur_term->getwh) ();
|
||||
}
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
{
|
||||
if (term->getkeystatus)
|
||||
status |= term->getkeystatus ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_gotoxy (grub_uint8_t x, grub_uint8_t y)
|
||||
{
|
||||
(grub_cur_term->gotoxy) (x, y);
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
grub_cls (void)
|
||||
{
|
||||
if ((grub_cur_term->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug")))
|
||||
{
|
||||
grub_putchar ('\n');
|
||||
grub_refresh ();
|
||||
}
|
||||
else
|
||||
(grub_cur_term->cls) ();
|
||||
struct grub_term_output *term;
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
{
|
||||
if ((term->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug")))
|
||||
{
|
||||
grub_putcode ('\n', term);
|
||||
grub_term_refresh (term);
|
||||
}
|
||||
else
|
||||
(term->cls) ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_setcolorstate (grub_term_color_state state)
|
||||
{
|
||||
if (grub_cur_term->setcolorstate)
|
||||
(grub_cur_term->setcolorstate) (state);
|
||||
}
|
||||
|
||||
void
|
||||
grub_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color)
|
||||
{
|
||||
if (grub_cur_term->setcolor)
|
||||
(grub_cur_term->setcolor) (normal_color, highlight_color);
|
||||
}
|
||||
|
||||
void
|
||||
grub_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
|
||||
{
|
||||
if (grub_cur_term->getcolor)
|
||||
(grub_cur_term->getcolor) (normal_color, highlight_color);
|
||||
}
|
||||
|
||||
int
|
||||
grub_setcursor (int on)
|
||||
{
|
||||
int ret = cursor_state;
|
||||
|
||||
if (grub_cur_term->setcursor)
|
||||
{
|
||||
(grub_cur_term->setcursor) (on);
|
||||
cursor_state = on;
|
||||
}
|
||||
struct grub_term_output *term;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
grub_getcursor (void)
|
||||
{
|
||||
return cursor_state;
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
grub_term_setcolorstate (term, state);
|
||||
}
|
||||
|
||||
void
|
||||
grub_refresh (void)
|
||||
{
|
||||
if (grub_cur_term->refresh)
|
||||
(grub_cur_term->refresh) ();
|
||||
}
|
||||
struct grub_term_output *term;
|
||||
|
||||
void
|
||||
grub_set_more (int onoff)
|
||||
{
|
||||
if (onoff == 1)
|
||||
grub_more++;
|
||||
else
|
||||
grub_more--;
|
||||
|
||||
grub_more_lines = 0;
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
grub_term_refresh (term);
|
||||
}
|
||||
|
|
37
kern/time.c
Normal file
37
kern/time.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* time.c - kernel time functions */
|
||||
/*
|
||||
* 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/time.h>
|
||||
|
||||
typedef grub_uint64_t (*get_time_ms_func_t) (void);
|
||||
|
||||
/* Function pointer to the implementation in use. */
|
||||
static get_time_ms_func_t get_time_ms_func;
|
||||
|
||||
grub_uint64_t
|
||||
grub_get_time_ms (void)
|
||||
{
|
||||
return get_time_ms_func ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_install_get_time_ms (get_time_ms_func_t func)
|
||||
{
|
||||
get_time_ms_func = func;
|
||||
}
|
119
kern/x86_64/dl.c
Normal file
119
kern/x86_64/dl.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* dl-x86_64.c - arch-dependent part of loadable module support */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,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/elf.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/err.h>
|
||||
|
||||
/* Check if EHDR is a valid ELF header. */
|
||||
grub_err_t
|
||||
grub_arch_dl_check_header (void *ehdr)
|
||||
{
|
||||
Elf64_Ehdr *e = ehdr;
|
||||
|
||||
/* Check the magic numbers. */
|
||||
if (e->e_ident[EI_CLASS] != ELFCLASS64
|
||||
|| e->e_ident[EI_DATA] != ELFDATA2LSB
|
||||
|| e->e_machine != EM_X86_64)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Relocate symbols. */
|
||||
grub_err_t
|
||||
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
||||
{
|
||||
Elf64_Ehdr *e = ehdr;
|
||||
Elf64_Shdr *s;
|
||||
Elf64_Word entsize;
|
||||
unsigned i;
|
||||
|
||||
/* Find a symbol table. */
|
||||
for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf64_Shdr *) ((char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_SYMTAB)
|
||||
break;
|
||||
|
||||
if (i == e->e_shnum)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
|
||||
|
||||
entsize = s->sh_entsize;
|
||||
|
||||
for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf64_Shdr *) ((char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_RELA)
|
||||
{
|
||||
grub_dl_segment_t seg;
|
||||
|
||||
/* Find the target segment. */
|
||||
for (seg = mod->segment; seg; seg = seg->next)
|
||||
if (seg->section == s->sh_info)
|
||||
break;
|
||||
|
||||
if (seg)
|
||||
{
|
||||
Elf64_Rela *rel, *max;
|
||||
|
||||
for (rel = (Elf64_Rela *) ((char *) e + s->sh_offset),
|
||||
max = rel + s->sh_size / s->sh_entsize;
|
||||
rel < max;
|
||||
rel++)
|
||||
{
|
||||
Elf64_Word *addr32;
|
||||
Elf64_Xword *addr64;
|
||||
Elf64_Sym *sym;
|
||||
|
||||
if (seg->size < rel->r_offset)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"reloc offset is out of the segment");
|
||||
|
||||
addr32 = (Elf64_Word *) ((char *) seg->addr + rel->r_offset);
|
||||
addr64 = (Elf64_Xword *) addr32;
|
||||
sym = (Elf64_Sym *) ((char *) mod->symtab
|
||||
+ entsize * ELF_R_SYM (rel->r_info));
|
||||
|
||||
switch (ELF_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_X86_64_64:
|
||||
*addr64 += rel->r_addend + sym->st_value;
|
||||
break;
|
||||
|
||||
case R_X86_64_PC32:
|
||||
*addr32 += rel->r_addend + sym->st_value -
|
||||
(Elf64_Xword) seg->addr - rel->r_offset;
|
||||
break;
|
||||
|
||||
case R_X86_64_32:
|
||||
case R_X86_64_32S:
|
||||
*addr32 += rel->r_addend + sym->st_value;
|
||||
break;
|
||||
|
||||
default:
|
||||
grub_fatal ("Unrecognized relocation: %d\n", ELF_R_TYPE (rel->r_info));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
116
kern/x86_64/efi/callwrap.S
Normal file
116
kern/x86_64/efi/callwrap.S
Normal file
|
@ -0,0 +1,116 @@
|
|||
/* callwrap.S - wrapper for x86_64 efi calls */
|
||||
/*
|
||||
* 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 <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/boot.h>
|
||||
|
||||
/*
|
||||
* x86_64 uses registry to pass parameters. Unfortunately, gcc and efi use
|
||||
* different call conversion, so we need to do some conversion.
|
||||
*
|
||||
* gcc:
|
||||
* %rdi, %esi, %rdx, %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ...
|
||||
*
|
||||
* efi:
|
||||
* %rcx, %rdx, %r8, %r9, 32(%rsp), 40(%rsp), 48(%rsp), ...
|
||||
*
|
||||
*/
|
||||
|
||||
.file "callwrap.S"
|
||||
.text
|
||||
|
||||
FUNCTION(efi_wrap_0)
|
||||
subq $40, %rsp
|
||||
call *%rdi
|
||||
addq $40, %rsp
|
||||
ret
|
||||
|
||||
FUNCTION(efi_wrap_1)
|
||||
subq $40, %rsp
|
||||
mov %rsi, %rcx
|
||||
call *%rdi
|
||||
addq $40, %rsp
|
||||
ret
|
||||
|
||||
FUNCTION(efi_wrap_2)
|
||||
subq $40, %rsp
|
||||
mov %rsi, %rcx
|
||||
call *%rdi
|
||||
addq $40, %rsp
|
||||
ret
|
||||
|
||||
FUNCTION(efi_wrap_3)
|
||||
subq $40, %rsp
|
||||
mov %rcx, %r8
|
||||
mov %rsi, %rcx
|
||||
call *%rdi
|
||||
addq $40, %rsp
|
||||
ret
|
||||
|
||||
FUNCTION(efi_wrap_4)
|
||||
subq $40, %rsp
|
||||
mov %r8, %r9
|
||||
mov %rcx, %r8
|
||||
mov %rsi, %rcx
|
||||
call *%rdi
|
||||
addq $40, %rsp
|
||||
ret
|
||||
|
||||
FUNCTION(efi_wrap_5)
|
||||
subq $40, %rsp
|
||||
mov %r9, 32(%rsp)
|
||||
mov %r8, %r9
|
||||
mov %rcx, %r8
|
||||
mov %rsi, %rcx
|
||||
call *%rdi
|
||||
addq $40, %rsp
|
||||
ret
|
||||
|
||||
FUNCTION(efi_wrap_6)
|
||||
subq $56, %rsp
|
||||
mov 56+8(%rsp), %rax
|
||||
mov %rax, 40(%rsp)
|
||||
mov %r9, 32(%rsp)
|
||||
mov %r8, %r9
|
||||
mov %rcx, %r8
|
||||
mov %rsi, %rcx
|
||||
call *%rdi
|
||||
addq $56, %rsp
|
||||
ret
|
||||
|
||||
FUNCTION(efi_wrap_10)
|
||||
subq $88, %rsp
|
||||
mov 88+40(%rsp), %rax
|
||||
mov %rax, 72(%rsp)
|
||||
mov 88+32(%rsp), %rax
|
||||
mov %rax, 64(%rsp)
|
||||
mov 88+24(%rsp), %rax
|
||||
mov %rax, 56(%rsp)
|
||||
mov 88+16(%rsp), %rax
|
||||
mov %rax, 48(%rsp)
|
||||
mov 88+8(%rsp), %rax
|
||||
mov %rax, 40(%rsp)
|
||||
mov %r9, 32(%rsp)
|
||||
mov %r8, %r9
|
||||
mov %rcx, %r8
|
||||
mov %rsi, %rcx
|
||||
call *%rdi
|
||||
addq $88, %rsp
|
||||
ret
|
63
kern/x86_64/efi/startup.S
Normal file
63
kern/x86_64/efi/startup.S
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* startup.S - bootstrap GRUB itself */
|
||||
/*
|
||||
* 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 <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/boot.h>
|
||||
|
||||
.file "startup.S"
|
||||
.text
|
||||
.globl start, _start
|
||||
.code64
|
||||
|
||||
start:
|
||||
_start:
|
||||
jmp codestart
|
||||
|
||||
/*
|
||||
* Compatibility version number
|
||||
*
|
||||
* These MUST be at byte offset 6 and 7 of the executable
|
||||
* DO NOT MOVE !!!
|
||||
*/
|
||||
. = _start + 0x6
|
||||
.byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
|
||||
|
||||
/*
|
||||
* This is a special data area 8 bytes from the beginning.
|
||||
*/
|
||||
|
||||
. = _start + 0x8
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + 0x50
|
||||
|
||||
codestart:
|
||||
movq %rcx, EXT_C(grub_efi_image_handle)(%rip)
|
||||
movq %rdx, EXT_C(grub_efi_system_table)(%rip)
|
||||
|
||||
call EXT_C(grub_main)
|
||||
ret
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue