Merge mainline into yeeloongfw
This commit is contained in:
commit
b7e79e8a6a
155 changed files with 5949 additions and 2562 deletions
49
kern/dl.c
49
kern/dl.c
|
@ -39,31 +39,17 @@
|
|||
|
||||
|
||||
|
||||
struct grub_dl_list
|
||||
{
|
||||
struct grub_dl_list *next;
|
||||
grub_dl_t mod;
|
||||
};
|
||||
typedef struct grub_dl_list *grub_dl_list_t;
|
||||
|
||||
static grub_dl_list_t grub_dl_head;
|
||||
grub_dl_t grub_dl_head = 0;
|
||||
|
||||
static grub_err_t
|
||||
grub_dl_add (grub_dl_t mod)
|
||||
{
|
||||
grub_dl_list_t l;
|
||||
|
||||
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;
|
||||
|
||||
l->mod = mod;
|
||||
l->next = grub_dl_head;
|
||||
grub_dl_head = l;
|
||||
mod->next = grub_dl_head;
|
||||
grub_dl_head = mod;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -71,13 +57,12 @@ grub_dl_add (grub_dl_t mod)
|
|||
static void
|
||||
grub_dl_remove (grub_dl_t mod)
|
||||
{
|
||||
grub_dl_list_t *p, q;
|
||||
grub_dl_t *p, q;
|
||||
|
||||
for (p = &grub_dl_head, q = *p; q; p = &q->next, q = *p)
|
||||
if (q->mod == mod)
|
||||
if (q == mod)
|
||||
{
|
||||
*p = q->next;
|
||||
grub_free (q);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -85,25 +70,15 @@ grub_dl_remove (grub_dl_t mod)
|
|||
grub_dl_t
|
||||
grub_dl_get (const char *name)
|
||||
{
|
||||
grub_dl_list_t l;
|
||||
grub_dl_t l;
|
||||
|
||||
for (l = grub_dl_head; l; l = l->next)
|
||||
if (grub_strcmp (name, l->mod->name) == 0)
|
||||
return l->mod;
|
||||
if (grub_strcmp (name, l->name) == 0)
|
||||
return l;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
grub_dl_iterate (int (*hook) (grub_dl_t mod))
|
||||
{
|
||||
grub_dl_list_t l;
|
||||
|
||||
for (l = grub_dl_head; l; l = l->next)
|
||||
if (hook (l->mod))
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct grub_symbol
|
||||
|
@ -694,11 +669,11 @@ 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;
|
||||
grub_dl_t p = grub_dl_head;
|
||||
|
||||
while (p)
|
||||
{
|
||||
if (grub_dl_unload (p->mod))
|
||||
if (grub_dl_unload (p))
|
||||
{
|
||||
p = grub_dl_head;
|
||||
continue;
|
||||
|
@ -714,13 +689,13 @@ grub_dl_unload_all (void)
|
|||
{
|
||||
while (grub_dl_head)
|
||||
{
|
||||
grub_dl_list_t p;
|
||||
grub_dl_t p;
|
||||
|
||||
grub_dl_unload_unneeded ();
|
||||
|
||||
/* Force to decrement the ref count. This will purge pre-loaded
|
||||
modules and manually inserted modules. */
|
||||
for (p = grub_dl_head; p; p = p->next)
|
||||
p->mod->ref_count--;
|
||||
p->ref_count--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -346,6 +346,7 @@ grub_efi_mm_init (void)
|
|||
grub_efi_uintn_t desc_size;
|
||||
grub_efi_uint64_t total_pages;
|
||||
grub_efi_uint64_t required_pages;
|
||||
int mm_status;
|
||||
|
||||
/* First of all, allocate pages to maintain allocations. */
|
||||
allocated_pages
|
||||
|
@ -361,16 +362,32 @@ grub_efi_mm_init (void)
|
|||
if (! memory_map)
|
||||
grub_fatal ("cannot allocate memory");
|
||||
|
||||
filtered_memory_map = NEXT_MEMORY_DESCRIPTOR (memory_map, MEMORY_MAP_SIZE);
|
||||
|
||||
/* Obtain descriptors for available memory. */
|
||||
map_size = MEMORY_MAP_SIZE;
|
||||
|
||||
if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0)
|
||||
mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0);
|
||||
|
||||
if (mm_status == 0)
|
||||
{
|
||||
grub_efi_free_pages
|
||||
((grub_efi_physical_address_t) ((grub_addr_t) memory_map),
|
||||
2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
|
||||
|
||||
memory_map = grub_efi_allocate_pages (0, 2 * BYTES_TO_PAGES (map_size));
|
||||
if (! memory_map)
|
||||
grub_fatal ("cannot allocate memory");
|
||||
|
||||
mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0,
|
||||
&desc_size, 0);
|
||||
}
|
||||
|
||||
if (mm_status < 0)
|
||||
grub_fatal ("cannot get memory map");
|
||||
|
||||
memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size);
|
||||
|
||||
filtered_memory_map = memory_map_end;
|
||||
|
||||
filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
|
||||
desc_size, memory_map_end);
|
||||
|
||||
|
|
|
@ -80,6 +80,86 @@ xgetcwd (void)
|
|||
return path;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
/* Statting something on a btrfs filesystem always returns a virtual device
|
||||
major/minor pair rather than the real underlying device, because btrfs
|
||||
can span multiple underlying devices (and even if it's currently only
|
||||
using a single device it can be dynamically extended onto another). We
|
||||
can't deal with the multiple-device case yet, but in the meantime, we can
|
||||
at least cope with the single-device case by scanning
|
||||
/proc/self/mountinfo. */
|
||||
static char *
|
||||
find_root_device_from_mountinfo (const char *dir)
|
||||
{
|
||||
FILE *fp;
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
char *ret = NULL;
|
||||
|
||||
fp = fopen ("/proc/self/mountinfo", "r");
|
||||
if (! fp)
|
||||
return NULL; /* fall through to other methods */
|
||||
|
||||
while (getline (&buf, &len, fp) > 0)
|
||||
{
|
||||
int mnt_id, parent_mnt_id;
|
||||
unsigned int major, minor;
|
||||
char enc_root[PATH_MAX], enc_path[PATH_MAX];
|
||||
int count;
|
||||
size_t enc_path_len;
|
||||
const char *sep;
|
||||
char fstype[PATH_MAX], device[PATH_MAX];
|
||||
struct stat st;
|
||||
|
||||
if (sscanf (buf, "%d %d %u:%u %s %s%n",
|
||||
&mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path,
|
||||
&count) < 6)
|
||||
continue;
|
||||
|
||||
if (strcmp (enc_root, "/") != 0)
|
||||
continue; /* only a subtree is mounted */
|
||||
|
||||
enc_path_len = strlen (enc_path);
|
||||
if (strncmp (dir, enc_path, enc_path_len) != 0 ||
|
||||
(dir[enc_path_len] && dir[enc_path_len] != '/'))
|
||||
continue;
|
||||
|
||||
/* This is a parent of the requested directory. /proc/self/mountinfo
|
||||
is in mount order, so it must be the closest parent we've
|
||||
encountered so far. If it's virtual, return its device node;
|
||||
otherwise, carry on to try to find something closer. */
|
||||
|
||||
free (ret);
|
||||
ret = NULL;
|
||||
|
||||
if (major != 0)
|
||||
continue; /* not a virtual device */
|
||||
|
||||
sep = strstr (buf + count, " - ");
|
||||
if (!sep)
|
||||
continue;
|
||||
|
||||
sep += sizeof (" - ") - 1;
|
||||
if (sscanf (sep, "%s %s", fstype, device) != 2)
|
||||
continue;
|
||||
|
||||
if (stat (device, &st) < 0)
|
||||
continue;
|
||||
|
||||
if (!S_ISBLK (st.st_mode))
|
||||
continue; /* not a block device */
|
||||
|
||||
ret = strdup (device);
|
||||
}
|
||||
|
||||
free (buf);
|
||||
fclose (fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
#ifdef __MINGW32__
|
||||
|
||||
static char *
|
||||
|
@ -366,6 +446,12 @@ grub_guess_root_device (const char *dir)
|
|||
#else /* !__GNU__ */
|
||||
struct stat st;
|
||||
|
||||
#ifdef __linux__
|
||||
os_dev = find_root_device_from_mountinfo (dir);
|
||||
if (os_dev)
|
||||
return os_dev;
|
||||
#endif /* __linux__ */
|
||||
|
||||
if (stat (dir, &st) < 0)
|
||||
grub_util_error ("cannot stat `%s'", dir);
|
||||
|
||||
|
|
|
@ -342,7 +342,7 @@ find_partition_start (const char *dev)
|
|||
# endif /* !defined(__NetBSD__) */
|
||||
|
||||
# ifdef HAVE_DEVICE_MAPPER
|
||||
if (device_is_mapped (dev)) {
|
||||
if (grub_device_mapper_supported () && device_is_mapped (dev)) {
|
||||
struct dm_task *task = NULL;
|
||||
grub_uint64_t start, length;
|
||||
char *target_type, *params, *space;
|
||||
|
@ -413,7 +413,11 @@ devmapper_fail:
|
|||
if (fd == -1)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
# if !defined(__NetBSD__)
|
||||
"cannot open `%s' while attempting to get disk geometry", dev);
|
||||
# else /* defined(__NetBSD__) */
|
||||
"cannot open `%s' while attempting to get disk label", dev);
|
||||
# endif /* !defined(__NetBSD__) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -425,7 +429,11 @@ devmapper_fail:
|
|||
# endif /* !defined(__NetBSD__) */
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
# if !defined(__NetBSD__)
|
||||
"cannot get disk geometry of `%s'", dev);
|
||||
# else /* defined(__NetBSD__) */
|
||||
"cannot get disk label of `%s'", dev);
|
||||
# endif /* !defined(__NetBSD__) */
|
||||
close (fd);
|
||||
return 0;
|
||||
}
|
||||
|
@ -984,6 +992,11 @@ grub_util_biosdisk_fini (void)
|
|||
grub_disk_dev_unregister (&grub_util_biosdisk_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: we do not use the new partition naming scheme as dos_part does not
|
||||
* necessarily correspond to an msdos partition. See e.g. the FreeBSD code
|
||||
* in function grub_util_biosdisk_get_grub_dev.
|
||||
*/
|
||||
static char *
|
||||
make_device_name (int drive, int dos_part, int bsd_part)
|
||||
{
|
||||
|
@ -1256,22 +1269,28 @@ devmapper_out:
|
|||
return path;
|
||||
|
||||
#elif defined(__NetBSD__)
|
||||
/* NetBSD uses "/dev/r[wsc]d[0-9]+[a-z]". */
|
||||
/* NetBSD uses "/dev/r[a-z]+[0-9][a-z]". */
|
||||
char *path = xstrdup (os_dev);
|
||||
if (strncmp ("/dev/rwd", path, 8) == 0 ||
|
||||
strncmp ("/dev/rsd", path, 8) == 0 ||
|
||||
strncmp ("/dev/rcd", path, 8) == 0)
|
||||
if (strncmp ("/dev/r", path, sizeof("/dev/r") - 1) == 0 &&
|
||||
(path[sizeof("/dev/r") - 1] >= 'a' && path[sizeof("/dev/r") - 1] <= 'z') &&
|
||||
strncmp ("fd", path + sizeof("/dev/r") - 1, sizeof("fd") - 1) != 0) /* not a floppy device name */
|
||||
{
|
||||
char *q;
|
||||
q = path + strlen(path) - 1; /* last character */
|
||||
if (grub_isalpha(*q) && grub_isdigit(*(q-1)))
|
||||
{
|
||||
int rawpart = -1;
|
||||
char *p;
|
||||
for (p = path + sizeof("/dev/r"); *p >= 'a' && *p <= 'z'; p++);
|
||||
if (grub_isdigit(*p))
|
||||
{
|
||||
p++;
|
||||
if ((*p >= 'a' && *p <= 'z') && (*(p+1) == '\0'))
|
||||
{
|
||||
/* path matches the required regular expression and
|
||||
p points to its last character. */
|
||||
int rawpart = -1;
|
||||
# ifdef HAVE_GETRAWPARTITION
|
||||
rawpart = getrawpartition();
|
||||
rawpart = getrawpartition();
|
||||
# endif /* HAVE_GETRAWPARTITION */
|
||||
if (rawpart >= 0)
|
||||
*q = 'a' + rawpart;
|
||||
if (rawpart >= 0)
|
||||
*p = 'a' + rawpart;
|
||||
}
|
||||
}
|
||||
}
|
||||
return path;
|
||||
|
@ -1386,11 +1405,9 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
For NetBSD, proceed as for Linux, except that the start sector is
|
||||
obtained from the disk label. */
|
||||
{
|
||||
char *name;
|
||||
char *name, *partname;
|
||||
grub_disk_t disk;
|
||||
grub_disk_addr_t start;
|
||||
int dos_part = -1;
|
||||
int bsd_part = -1;
|
||||
auto int find_partition (grub_disk_t dsk,
|
||||
const grub_partition_t partition);
|
||||
|
||||
|
@ -1405,17 +1422,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
|
||||
if (start == part_start)
|
||||
{
|
||||
if (partition->parent)
|
||||
{
|
||||
dos_part = partition->parent->number;
|
||||
bsd_part = partition->number;
|
||||
}
|
||||
else
|
||||
{
|
||||
dos_part = partition->number;
|
||||
bsd_part = -1;
|
||||
}
|
||||
|
||||
partname = grub_partition_get_name (partition);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1429,8 +1436,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
return name;
|
||||
# else /* defined(__NetBSD__) */
|
||||
/* Since os_dev and convert_system_partition_to_system_disk (os_dev) are
|
||||
* different, we know that os_dev is of the form /dev/r[wsc]d[0-9]+[a-z]
|
||||
* and in particular it cannot be a floppy device. */
|
||||
* different, we know that os_dev cannot be a floppy device. */
|
||||
# endif /* !defined(__NetBSD__) */
|
||||
|
||||
start = find_partition_start (os_dev);
|
||||
|
@ -1452,6 +1458,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
if (! disk)
|
||||
return 0;
|
||||
|
||||
partname = NULL;
|
||||
grub_partition_iterate (disk, find_partition);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
{
|
||||
|
@ -1459,7 +1466,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (dos_part < 0)
|
||||
if (partname == NULL)
|
||||
{
|
||||
grub_disk_close (disk);
|
||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
|
@ -1467,7 +1474,9 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
return make_device_name (drive, dos_part, bsd_part);
|
||||
name = grub_xasprintf ("%s,%s", disk->name, partname);
|
||||
free (partname);
|
||||
return name;
|
||||
}
|
||||
|
||||
#elif defined(__GNU__)
|
||||
|
@ -1512,7 +1521,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
for (p = os_dev + 5; *p; ++p)
|
||||
if (grub_isdigit(*p))
|
||||
{
|
||||
p = strchr (p, 's');
|
||||
p = strchr (p, 's'); /* msdos or apple (or ... ?) partition map */
|
||||
if (p)
|
||||
{
|
||||
p++;
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
#include <grub/time.h>
|
||||
#include <grub/emu/misc.h>
|
||||
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
# include <libdevmapper.h>
|
||||
#endif
|
||||
|
||||
int verbosity;
|
||||
|
||||
void
|
||||
|
@ -311,3 +315,38 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
|||
|
||||
return buf3;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
static void device_mapper_null_log (int level __attribute__ ((unused)),
|
||||
const char *file __attribute__ ((unused)),
|
||||
int line __attribute__ ((unused)),
|
||||
int dm_errno __attribute__ ((unused)),
|
||||
const char *f __attribute__ ((unused)),
|
||||
...)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
grub_device_mapper_supported (void)
|
||||
{
|
||||
static int supported = -1;
|
||||
|
||||
if (supported == -1)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
|
||||
/* Suppress annoying log messages. */
|
||||
dm_log_with_errno_init (&device_mapper_null_log);
|
||||
|
||||
dmt = dm_task_create (DM_DEVICE_VERSION);
|
||||
supported = (dmt != NULL);
|
||||
if (dmt)
|
||||
dm_task_destroy (dmt);
|
||||
|
||||
/* Restore the original logger. */
|
||||
dm_log_with_errno_init (NULL);
|
||||
}
|
||||
|
||||
return supported;
|
||||
}
|
||||
#endif /* HAVE_DEVICE_MAPPER */
|
||||
|
|
32
kern/fs.c
32
kern/fs.c
|
@ -27,40 +27,10 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/term.h>
|
||||
|
||||
static grub_fs_t grub_fs_list;
|
||||
grub_fs_t grub_fs_list = 0;
|
||||
|
||||
grub_fs_autoload_hook_t grub_fs_autoload_hook = 0;
|
||||
|
||||
void
|
||||
grub_fs_register (grub_fs_t fs)
|
||||
{
|
||||
fs->next = grub_fs_list;
|
||||
grub_fs_list = fs;
|
||||
}
|
||||
|
||||
void
|
||||
grub_fs_unregister (grub_fs_t fs)
|
||||
{
|
||||
grub_fs_t *p, q;
|
||||
|
||||
for (p = &grub_fs_list, q = *p; q; p = &(q->next), q = q->next)
|
||||
if (q == fs)
|
||||
{
|
||||
*p = q->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grub_fs_iterate (int (*hook) (const grub_fs_t fs))
|
||||
{
|
||||
grub_fs_t p;
|
||||
|
||||
for (p = grub_fs_list; p; p = p->next)
|
||||
if (hook (p))
|
||||
break;
|
||||
}
|
||||
|
||||
grub_fs_t
|
||||
grub_fs_probe (grub_device_t device)
|
||||
{
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/* 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;
|
||||
}
|
|
@ -71,6 +71,9 @@ grub_exit (void)
|
|||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
#ifdef GRUB_MACHINE_QEMU
|
||||
grub_qemu_init_cirrus ();
|
||||
#endif
|
||||
/* Initialize the console as early as possible. */
|
||||
grub_vga_text_init ();
|
||||
|
||||
|
|
|
@ -83,6 +83,14 @@ make_install_device (void)
|
|||
grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix);
|
||||
grub_strcpy (grub_prefix, dev);
|
||||
}
|
||||
else if (grub_prefix[1] == ',' || grub_prefix[1] == ')')
|
||||
{
|
||||
/* We have a prefix, but still need to fill in the boot drive. */
|
||||
grub_snprintf (dev, sizeof (dev),
|
||||
"(%cd%u%s", (grub_boot_drive & 0x80) ? 'h' : 'f',
|
||||
grub_boot_drive & 0x7f, grub_prefix + 1);
|
||||
grub_strcpy (grub_prefix, dev);
|
||||
}
|
||||
|
||||
return grub_prefix;
|
||||
}
|
||||
|
|
152
kern/i386/qemu/init.c
Normal file
152
kern/i386/qemu/init.c
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/pci.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/vga.h>
|
||||
|
||||
static struct {grub_uint8_t r, g, b, a; } colors[] =
|
||||
{
|
||||
// {R, G, B, A}
|
||||
{0x00, 0x00, 0x00, 0xFF}, // 0 = black
|
||||
{0x00, 0x00, 0xA8, 0xFF}, // 1 = blue
|
||||
{0x00, 0xA8, 0x00, 0xFF}, // 2 = green
|
||||
{0x00, 0xA8, 0xA8, 0xFF}, // 3 = cyan
|
||||
{0xA8, 0x00, 0x00, 0xFF}, // 4 = red
|
||||
{0xA8, 0x00, 0xA8, 0xFF}, // 5 = magenta
|
||||
{0xA8, 0x54, 0x00, 0xFF}, // 6 = brown
|
||||
{0xA8, 0xA8, 0xA8, 0xFF}, // 7 = light gray
|
||||
|
||||
{0x54, 0x54, 0x54, 0xFF}, // 8 = dark gray
|
||||
{0x54, 0x54, 0xFE, 0xFF}, // 9 = bright blue
|
||||
{0x54, 0xFE, 0x54, 0xFF}, // 10 = bright green
|
||||
{0x54, 0xFE, 0xFE, 0xFF}, // 11 = bright cyan
|
||||
{0xFE, 0x54, 0x54, 0xFF}, // 12 = bright red
|
||||
{0xFE, 0x54, 0xFE, 0xFF}, // 13 = bright magenta
|
||||
{0xFE, 0xFE, 0x54, 0xFF}, // 14 = yellow
|
||||
{0xFE, 0xFE, 0xFE, 0xFF} // 15 = white
|
||||
};
|
||||
|
||||
#include <ascii.h>
|
||||
|
||||
static void
|
||||
load_font (void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
grub_vga_gr_write (0 << 2, GRUB_VGA_GR_GR6);
|
||||
|
||||
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE);
|
||||
grub_vga_sr_write (1 << GRUB_VGA_TEXT_FONT_PLANE,
|
||||
GRUB_VGA_SR_MAP_MASK_REGISTER);
|
||||
|
||||
grub_vga_gr_write (0, GRUB_VGA_GR_DATA_ROTATE);
|
||||
grub_vga_gr_write (0, GRUB_VGA_GR_MODE);
|
||||
grub_vga_gr_write (0xff, GRUB_VGA_GR_BITMASK);
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
grub_memcpy ((void *) (0xa0000 + 32 * i), ascii_bitmaps + 16 * (0x7f - i), 16);
|
||||
}
|
||||
|
||||
static void
|
||||
load_palette (void)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
grub_outb (i, GRUB_VGA_IO_ARX);
|
||||
grub_outb (i, GRUB_VGA_IO_ARX);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (colors); i++)
|
||||
grub_vga_palette_write (i, colors[i].r, colors[i].g, colors[i].b);
|
||||
}
|
||||
|
||||
void
|
||||
grub_qemu_init_cirrus (void)
|
||||
{
|
||||
auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid);
|
||||
int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)))
|
||||
{
|
||||
grub_pci_address_t addr;
|
||||
grub_uint32_t class;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
|
||||
class = grub_pci_read (addr);
|
||||
|
||||
if (((class >> 16) & 0xffff) != 0x0300)
|
||||
return 0;
|
||||
|
||||
/* FIXME: chooose addresses dynamically. */
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
|
||||
grub_pci_write (addr, 0xf0000000 | GRUB_PCI_ADDR_MEM_PREFETCH
|
||||
| GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32);
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
|
||||
grub_pci_write (addr, 0xf2000000
|
||||
| GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32);
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
|
||||
grub_pci_write (addr, GRUB_PCI_COMMAND_MEM_ENABLED
|
||||
| GRUB_PCI_COMMAND_IO_ENABLED);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_pci_iterate (find_card);
|
||||
|
||||
grub_outb (1, 0x3c2);
|
||||
|
||||
load_font ();
|
||||
|
||||
grub_vga_gr_write (GRUB_VGA_GR_GR6_MMAP_CGA, GRUB_VGA_GR_GR6);
|
||||
grub_vga_gr_write (GRUB_VGA_GR_MODE_ODD_EVEN, GRUB_VGA_GR_MODE);
|
||||
|
||||
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE);
|
||||
|
||||
grub_vga_sr_write ((1 << GRUB_VGA_TEXT_TEXT_PLANE)
|
||||
| (1 << GRUB_VGA_TEXT_ATTR_PLANE),
|
||||
GRUB_VGA_SR_MAP_MASK_REGISTER);
|
||||
|
||||
grub_vga_cr_write (15, GRUB_VGA_CR_CELL_HEIGHT);
|
||||
grub_vga_cr_write (79, GRUB_VGA_CR_WIDTH);
|
||||
grub_vga_cr_write (40, GRUB_VGA_CR_PITCH);
|
||||
|
||||
int vert = 25 * 16;
|
||||
grub_vga_cr_write (vert & 0xff, GRUB_VGA_CR_HEIGHT);
|
||||
grub_vga_cr_write (((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT)
|
||||
& GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK)
|
||||
| ((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT)
|
||||
& GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK),
|
||||
GRUB_VGA_CR_OVERFLOW);
|
||||
|
||||
load_palette ();
|
||||
|
||||
grub_outb (0x10, 0x3c0);
|
||||
grub_outb (0, 0x3c1);
|
||||
grub_outb (0x14, 0x3c0);
|
||||
grub_outb (0, 0x3c1);
|
||||
|
||||
grub_vga_sr_write (GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK,
|
||||
GRUB_VGA_SR_CLOCKING_MODE);
|
||||
|
||||
grub_vga_cr_write (14, GRUB_VGA_CR_CURSOR_START);
|
||||
grub_vga_cr_write (15, GRUB_VGA_CR_CURSOR_END);
|
||||
|
||||
grub_outb (0x20, 0x3c0);
|
||||
}
|
|
@ -27,21 +27,37 @@
|
|||
#define QEMU_CMOS_MEMSIZE_HIGH 0x35
|
||||
#define QEMU_CMOS_MEMSIZE_LOW 0x34
|
||||
|
||||
#define QEMU_CMOS_MEMSIZE2_HIGH 0x31
|
||||
#define QEMU_CMOS_MEMSIZE2_LOW 0x30
|
||||
|
||||
#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;
|
||||
static grub_uint64_t mem_size, above_4g;
|
||||
|
||||
void
|
||||
grub_machine_mmap_init ()
|
||||
{
|
||||
mem_size = grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH) << 24 | grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW) << 16;
|
||||
mem_size = ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH)) << 24
|
||||
| ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW)) << 16;
|
||||
if (mem_size > 0)
|
||||
{
|
||||
/* Don't ask... */
|
||||
mem_size += (16 * 1024 * 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_size
|
||||
= ((((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH)) << 18)
|
||||
| ((grub_uint64_t) (grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW)) << 10))
|
||||
+ 1024 * 1024;
|
||||
}
|
||||
|
||||
/* Don't ask... */
|
||||
mem_size += (16 * 1024 * 1024);
|
||||
above_4g = (((grub_uint64_t) grub_cmos_read (0x5b)) << 16)
|
||||
| (((grub_uint64_t) grub_cmos_read (0x5c)) << 24)
|
||||
| (((grub_uint64_t) grub_cmos_read (0x5d)) << 32);
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
|
@ -57,6 +73,12 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin
|
|||
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;
|
||||
|
||||
/* 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,
|
||||
|
@ -64,10 +86,8 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin
|
|||
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))
|
||||
if (above_4g != 0 && hook (0x100000000ULL, above_4g,
|
||||
GRUB_MACHINE_MEMORY_AVAILABLE))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
|
82
kern/list.c
82
kern/list.c
|
@ -28,18 +28,6 @@ grub_list_push (grub_list_t *head, grub_list_t item)
|
|||
*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)
|
||||
{
|
||||
|
@ -53,51 +41,16 @@ grub_list_remove (grub_list_t *head, grub_list_t item)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
grub_named_list_t item;
|
||||
|
||||
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;
|
||||
}
|
||||
FOR_LIST_ELEMENTS (item, head)
|
||||
if (grub_strcmp (item->name, name) == 0)
|
||||
return item;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_find);
|
||||
return result;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -105,27 +58,30 @@ 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)
|
||||
grub_prio_list_t *p, q;
|
||||
|
||||
for (p = head, q = *p; q; p = &(q->next), q = q->next)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = grub_strcmp (new_item->name, item->name);
|
||||
if (r)
|
||||
return (r < 0);
|
||||
r = grub_strcmp (nitem->name, q->name);
|
||||
if (r < 0)
|
||||
break;
|
||||
if (r > 0)
|
||||
continue;
|
||||
|
||||
if (new_item->prio >= (item->prio & GRUB_PRIO_LIST_PRIO_MASK))
|
||||
if (nitem->prio >= (q->prio & GRUB_PRIO_LIST_PRIO_MASK))
|
||||
{
|
||||
item->prio &= ~GRUB_PRIO_LIST_FLAG_ACTIVE;
|
||||
return 1;
|
||||
q->prio &= ~GRUB_PRIO_LIST_FLAG_ACTIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
inactive = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_list_insert (GRUB_AS_LIST_P (head), GRUB_AS_LIST (nitem),
|
||||
(grub_list_test_t) test);
|
||||
*p = nitem;
|
||||
nitem->next = q;
|
||||
|
||||
if (! inactive)
|
||||
nitem->prio |= GRUB_PRIO_LIST_FLAG_ACTIVE;
|
||||
}
|
||||
|
|
|
@ -191,7 +191,6 @@ grub_main (void)
|
|||
grub_set_root_dev ();
|
||||
|
||||
grub_register_core_commands ();
|
||||
grub_register_rescue_parser ();
|
||||
|
||||
grub_load_config ();
|
||||
grub_load_normal_mode ();
|
||||
|
|
|
@ -230,10 +230,6 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct grub_handler_class grub_parser_class = {
|
||||
.name = "parser"
|
||||
};
|
||||
|
||||
grub_err_t
|
||||
grub_parser_execute (char *source)
|
||||
{
|
||||
|
@ -261,11 +257,9 @@ grub_parser_execute (char *source)
|
|||
while (source)
|
||||
{
|
||||
char *line;
|
||||
grub_parser_t parser;
|
||||
|
||||
getline (&line, 0);
|
||||
parser = grub_parser_get_current ();
|
||||
parser->parse_line (line, getline);
|
||||
grub_rescue_parse_line (line, getline);
|
||||
grub_free (line);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_err_t
|
||||
grub_rescue_parse_line (char *line, grub_reader_getline_t getline)
|
||||
{
|
||||
char *name;
|
||||
|
@ -74,15 +74,3 @@ grub_rescue_parse_line (char *line, grub_reader_getline_t getline)
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ grub_rescue_run (void)
|
|||
if (! line || line[0] == '\0')
|
||||
continue;
|
||||
|
||||
grub_parser_get_current ()->parse_line (line, grub_rescue_read_line);
|
||||
grub_rescue_parse_line (line, grub_rescue_read_line);
|
||||
grub_free (line);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue