merge mainline into 4096

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-06-23 04:08:37 +02:00
commit a5edbcb3a1
393 changed files with 15834 additions and 2186 deletions

View file

@ -37,6 +37,10 @@
#define GRUB_MODULES_MACHINE_READONLY
#endif
#ifdef GRUB_MACHINE_EMU
#include <sys/mman.h>
#endif
grub_dl_t grub_dl_head = 0;
@ -86,6 +90,7 @@ struct grub_symbol
struct grub_symbol *next;
const char *name;
void *addr;
int isfunc;
grub_dl_t mod; /* The module to which this symbol belongs. */
};
typedef struct grub_symbol *grub_symbol_t;
@ -110,21 +115,22 @@ grub_symbol_hash (const char *s)
/* Resolve the symbol name NAME and return the address.
Return NULL, if not found. */
static void *
static grub_symbol_t
grub_dl_resolve_symbol (const char *name)
{
grub_symbol_t sym;
for (sym = grub_symtab[grub_symbol_hash (name)]; sym; sym = sym->next)
if (grub_strcmp (sym->name, name) == 0)
return sym->addr;
return sym;
return 0;
}
/* Register a symbol with the name NAME and the address ADDR. */
grub_err_t
grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod)
grub_dl_register_symbol (const char *name, void *addr, int isfunc,
grub_dl_t mod)
{
grub_symbol_t sym;
unsigned k;
@ -147,6 +153,7 @@ grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod)
sym->addr = addr;
sym->mod = mod;
sym->isfunc = isfunc;
k = grub_symbol_hash (name);
sym->next = grub_symtab[k];
@ -225,6 +232,48 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
{
unsigned i;
Elf_Shdr *s;
grub_size_t tsize = 0, talign = 1;
#ifdef __ia64__
grub_size_t tramp;
grub_size_t got;
#endif
char *ptr;
for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff);
i < e->e_shnum;
i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
{
tsize += ALIGN_UP (s->sh_size, s->sh_addralign);
if (talign < s->sh_addralign)
talign = s->sh_addralign;
}
#ifdef __ia64__
grub_arch_dl_get_tramp_got_size (e, &tramp, &got);
tramp *= GRUB_IA64_DL_TRAMP_SIZE;
got *= sizeof (grub_uint64_t);
tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN);
if (talign < GRUB_ARCH_DL_TRAMP_ALIGN)
talign = GRUB_ARCH_DL_TRAMP_ALIGN;
tsize += ALIGN_UP (got, GRUB_ARCH_DL_GOT_ALIGN);
if (talign < GRUB_ARCH_DL_GOT_ALIGN)
talign = GRUB_ARCH_DL_GOT_ALIGN;
#endif
#ifdef GRUB_MACHINE_EMU
if (talign < 8192 * 16)
talign = 8192 * 16;
tsize = ALIGN_UP (tsize, 8192 * 16);
#endif
mod->base = grub_memalign (talign, tsize);
if (!mod->base)
return grub_errno;
ptr = mod->base;
#ifdef GRUB_MACHINE_EMU
mprotect (mod->base, tsize, PROT_READ | PROT_WRITE | PROT_EXEC);
#endif
for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff);
i < e->e_shnum;
@ -242,12 +291,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
{
void *addr;
addr = grub_memalign (s->sh_addralign, s->sh_size);
if (! addr)
{
grub_free (seg);
return grub_errno;
}
ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign);
addr = ptr;
ptr += s->sh_size;
switch (s->sh_type)
{
@ -270,6 +316,14 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
mod->segment = seg;
}
}
#ifdef __ia64__
ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN);
mod->tramp = ptr;
ptr += tramp;
ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_GOT_ALIGN);
mod->got = ptr;
ptr += got;
#endif
return GRUB_ERR_NONE;
}
@ -320,17 +374,20 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
/* Resolve a global symbol. */
if (sym->st_name != 0 && sym->st_shndx == 0)
{
sym->st_value = (Elf_Addr) grub_dl_resolve_symbol (name);
if (! sym->st_value)
grub_symbol_t nsym = grub_dl_resolve_symbol (name);
if (! nsym)
return grub_error (GRUB_ERR_BAD_MODULE,
"symbol not found: `%s'", name);
sym->st_value = (Elf_Addr) nsym->addr;
if (nsym->isfunc)
sym->st_info = ELF_ST_INFO (bind, STT_FUNC);
}
else
{
sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod,
sym->st_shndx);
if (bind != STB_LOCAL)
if (grub_dl_register_symbol (name, (void *) sym->st_value, mod))
if (grub_dl_register_symbol (name, (void *) sym->st_value, 0, mod))
return grub_errno;
}
break;
@ -338,10 +395,21 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
case STT_FUNC:
sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod,
sym->st_shndx);
#ifdef __ia64__
{
/* FIXME: free descriptor once it's not used anymore. */
char **desc;
desc = grub_malloc (2 * sizeof (char *));
if (!desc)
return grub_errno;
desc[0] = (void *) sym->st_value;
desc[1] = mod->base;
sym->st_value = (grub_addr_t) desc;
}
#endif
if (bind != STB_LOCAL)
if (grub_dl_register_symbol (name, (void *) sym->st_value, mod))
if (grub_dl_register_symbol (name, (void *) sym->st_value, 1, 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)
@ -373,6 +441,38 @@ grub_dl_call_init (grub_dl_t mod)
(mod->init) (mod);
}
/* Me, Vladimir Serbinenko, hereby I add this module check as per new
GNU module policy. Note that this license check is informative only.
Modules have to be licensed under GPLv3 or GPLv3+ (optionally
multi-licensed under other licences as well) independently of the
presence of this check and solely by linking (module loading in GRUB
constitutes linking) and GRUB core being licensed under GPLv3+.
Be sure to understand your license obligations.
*/
static grub_err_t
grub_dl_check_license (Elf_Ehdr *e)
{
Elf_Shdr *s;
const char *str;
unsigned i;
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))
if (grub_strcmp (str + s->sh_name, ".module_license") == 0)
{
if (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0
|| grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0
|| grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0)
return GRUB_ERR_NONE;
}
return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license");
}
static grub_err_t
grub_dl_resolve_name (grub_dl_t mod, Elf_Ehdr *e)
{
@ -519,7 +619,16 @@ grub_dl_load_core (void *addr, grub_size_t size)
mod->ref_count = 1;
grub_dprintf ("modules", "relocating to %p\n", mod);
if (grub_dl_resolve_name (mod, e)
/* Me, Vladimir Serbinenko, hereby I add this module check as per new
GNU module policy. Note that this license check is informative only.
Modules have to be licensed under GPLv3 or GPLv3+ (optionally
multi-licensed under other licences as well) independently of the
presence of this check and solely by linking (module loading in GRUB
constitutes linking) and GRUB core being licensed under GPLv3+.
Be sure to understand your license obligations.
*/
if (grub_dl_check_license (e)
|| grub_dl_resolve_name (mod, e)
|| grub_dl_resolve_dependencies (mod, e)
|| grub_dl_load_segments (mod, e)
|| grub_dl_resolve_symbols (mod, e)
@ -585,7 +694,7 @@ grub_dl_load_file (const char *filename)
return 0;
}
mod->ref_count = 0;
mod->ref_count--;
return mod;
}
@ -642,8 +751,7 @@ grub_dl_unload (grub_dl_t mod)
{
depn = dep->next;
if (! grub_dl_unref (dep->mod))
grub_dl_unload (dep->mod);
grub_dl_unload (dep->mod);
grub_free (dep);
}

View file

@ -24,6 +24,7 @@
#include <grub/efi/console_control.h>
#include <grub/efi/pe32.h>
#include <grub/machine/time.h>
#include <grub/time.h>
#include <grub/term.h>
#include <grub/kernel.h>
#include <grub/mm.h>
@ -193,8 +194,8 @@ grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed");
}
grub_uint32_t
grub_get_rtc (void)
grub_uint64_t
grub_rtc_get_time_ms (void)
{
grub_efi_time_t time;
grub_efi_runtime_services_t *r;
@ -204,9 +205,14 @@ grub_get_rtc (void)
/* What is possible in this case? */
return 0;
return (((time.minute * 60 + time.second) * 1000
+ time.nanosecond / 1000000)
* GRUB_TICKS_PER_SECOND / 1000);
return ((time.minute * 60 + time.second) * 1000
+ time.nanosecond / 1000000);
}
grub_uint32_t
grub_get_rtc (void)
{
return grub_rtc_get_time_ms ();
}
/* Search the mods section from the PE32/PE32+ image. This code uses

View file

@ -23,6 +23,9 @@
#include <grub/file.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/dl.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* Check if EHDR is a valid ELF header. */
static grub_err_t

View file

@ -0,0 +1,13 @@
#if defined(__ia64__)
#include <grub/cache.h>
void __clear_cache (char *beg, char *end);
void
grub_arch_sync_caches (void *address, grub_size_t len)
{
__clear_cache (address, (char *) address + len);
}
#endif

View file

@ -23,6 +23,7 @@ FUNCTION (grub_arch_sync_caches)
.set macro
#elif defined(__powerpc__)
#include "../powerpc/cache.S"
#elif defined(__ia64__)
#else
#error "No target cpu type is defined"
#endif

View file

@ -50,6 +50,15 @@ grub_emu_init (void)
grub_no_autoload = 1;
}
#ifdef __ia64__
void grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)),
grub_size_t *tramp, grub_size_t *got)
{
*tramp = 0;
*got = 0;
}
#endif
#ifdef GRUB_LINKER_HAVE_INIT
void
grub_arch_dl_init_linker (void)

View file

@ -34,6 +34,10 @@
#include <stdint.h>
#include <grub/util/misc.h>
#ifdef HAVE_DEVICE_MAPPER
# include <libdevmapper.h>
#endif
#ifdef __GNU__
#include <hurd.h>
#include <hurd/lookup.h>
@ -98,6 +102,14 @@ xgetcwd (void)
#ifdef __linux__
struct mountinfo_entry
{
int id;
int major, minor;
char enc_root[PATH_MAX], enc_path[PATH_MAX];
char fstype[PATH_MAX], device[PATH_MAX];
};
/* 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
@ -105,75 +117,120 @@ xgetcwd (void)
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)
char *
grub_find_root_device_from_mountinfo (const char *dir, char **relroot)
{
FILE *fp;
char *buf = NULL;
size_t len = 0;
char *ret = NULL;
int entry_len = 0, entry_max = 4;
struct mountinfo_entry *entries;
struct mountinfo_entry parent_entry = { 0, 0, 0, "", "", "", "" };
int i;
if (! *dir)
dir = "/";
if (relroot)
*relroot = NULL;
fp = fopen ("/proc/self/mountinfo", "r");
if (! fp)
return NULL; /* fall through to other methods */
entries = xmalloc (entry_max * sizeof (*entries));
/* First, build a list of relevant visible mounts. */
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];
struct mountinfo_entry entry;
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)
&entry.id, &parent_entry.id, &entry.major, &entry.minor,
entry.enc_root, entry.enc_path, &count) < 6)
continue;
if (strcmp (enc_root, "/") != 0)
continue; /* only a subtree is mounted */
enc_path_len = strlen (enc_path);
enc_path_len = strlen (entry.enc_path);
/* Check that enc_path is a prefix of dir. The prefix must either be
the entire string, or end with a slash, or be immediately followed
by a slash. */
if (strncmp (dir, enc_path, enc_path_len) != 0 ||
if (strncmp (dir, entry.enc_path, enc_path_len) != 0 ||
(enc_path_len && dir[enc_path_len - 1] != '/' &&
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)
if (sscanf (sep, "%s %s", entry.fstype, entry.device) != 2)
continue;
if (stat (device, &st) < 0)
/* Using the mount IDs, find out where this fits in the list of
visible mount entries we've seen so far. There are three
interesting cases. Firstly, it may be inserted at the end: this is
the usual case of /foo/bar being mounted after /foo. Secondly, it
may be inserted at the start: for example, this can happen for
filesystems that are mounted before / and later moved under it.
Thirdly, it may occlude part or all of the existing filesystem
tree, in which case the end of the list needs to be pruned and this
new entry will be inserted at the end. */
if (entry_len >= entry_max)
{
entry_max <<= 1;
entries = xrealloc (entries, entry_max * sizeof (*entries));
}
if (!entry_len)
{
/* Initialise list. */
entry_len = 2;
entries[0] = parent_entry;
entries[1] = entry;
}
else
{
for (i = entry_len - 1; i >= 0; i--)
{
if (entries[i].id == parent_entry.id)
{
/* Insert at end, pruning anything previously above this. */
entry_len = i + 2;
entries[i + 1] = entry;
break;
}
else if (i == 0 && entries[i].id == entry.id)
{
/* Insert at start. */
entry_len++;
memmove (entries + 1, entries,
(entry_len - 1) * sizeof (*entries));
entries[0] = parent_entry;
entries[1] = entry;
break;
}
}
}
}
/* Now scan visible mounts for the ones we're interested in. */
for (i = entry_len - 1; i >= 0; i--)
{
if (!*entries[i].device)
continue;
if (!S_ISBLK (st.st_mode))
continue; /* not a block device */
ret = strdup (device);
ret = strdup (entries[i].device);
if (relroot)
*relroot = strdup (entries[i].enc_root);
break;
}
free (buf);
free (entries);
fclose (fp);
return ret;
}
@ -301,7 +358,7 @@ grub_find_device (const char *dir, dev_t dev)
if (S_ISLNK (st.st_mode)) {
#ifdef __linux__
if (strcmp (dir, "mapper") == 0) {
if (strcmp (dir, "mapper") == 0 || strcmp (dir, "/dev/mapper") == 0) {
/* Follow symbolic links under /dev/mapper/; the canonical name
may be something like /dev/dm-0, but the names under
/dev/mapper/ are more human-readable and so we prefer them if
@ -479,7 +536,7 @@ grub_find_device (const char *path, dev_t dev)
char *
grub_guess_root_device (const char *dir)
{
char *os_dev;
char *os_dev = NULL;
#ifdef __GNU__
file_t file;
mach_port_t *ports;
@ -538,30 +595,49 @@ grub_guess_root_device (const char *dir)
mach_port_deallocate (mach_task_self (), file);
#else /* !__GNU__ */
struct stat st;
dev_t dev;
#ifdef __linux__
os_dev = find_root_device_from_mountinfo (dir);
if (os_dev)
return os_dev;
if (!os_dev)
os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
#endif /* __linux__ */
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
os_dev = find_root_device_from_libzfs (dir);
if (os_dev)
return os_dev;
if (!os_dev)
os_dev = find_root_device_from_libzfs (dir);
#endif
if (os_dev)
{
char *tmp = os_dev;
os_dev = canonicalize_file_name (os_dev);
free (tmp);
}
if (os_dev)
{
if (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) != 0)
return os_dev;
if (stat (os_dev, &st) < 0)
grub_util_error ("cannot stat `%s'", os_dev);
free (os_dev);
dev = st.st_rdev;
return grub_find_device ("/dev/mapper", dev);
}
if (stat (dir, &st) < 0)
grub_util_error ("cannot stat `%s'", dir);
dev = st.st_dev;
#ifdef __CYGWIN__
/* Cygwin specific function. */
os_dev = grub_find_device (dir, st.st_dev);
os_dev = grub_find_device (dir, dev);
#else
/* This might be truly slow, but is there any better way? */
os_dev = grub_find_device ("/dev", st.st_dev);
os_dev = grub_find_device ("/dev", dev);
#endif
#endif /* !__GNU__ */
@ -569,32 +645,65 @@ grub_guess_root_device (const char *dir)
}
static int
grub_util_is_dmraid (const char *os_dev)
grub_util_is_lvm (const char *os_dev)
{
if (! strncmp (os_dev, "/dev/mapper/nvidia_", 19))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/isw_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/hpt37x_", 19))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/hpt45x_", 19))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/via_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/lsi_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/pdc_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/jmicron_", 20))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/asr_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/sil_", 16))
return 1;
else if (! strncmp (os_dev, "/dev/mapper/ddf1_", 17))
return 1;
if ((strncmp ("/dev/mapper/", os_dev, 12) != 0))
return 0;
#ifdef HAVE_DEVICE_MAPPER
{
struct dm_tree *tree;
uint32_t maj, min;
struct dm_tree_node *node = NULL;
const char *node_uuid;
struct stat st;
return 0;
if (stat (os_dev, &st) < 0)
return 0;
tree = dm_tree_create ();
if (! tree)
{
grub_printf ("Failed to create tree\n");
grub_dprintf ("hostdisk", "dm_tree_create failed\n");
return 0;
}
maj = major (st.st_rdev);
min = minor (st.st_rdev);
if (! dm_tree_add_dev (tree, maj, min))
{
grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n");
dm_tree_free (tree);
return 0;
}
node = dm_tree_find_node (tree, maj, min);
if (! node)
{
grub_dprintf ("hostdisk", "dm_tree_find_node failed\n");
dm_tree_free (tree);
return 0;
}
node_uuid = dm_tree_node_get_uuid (node);
if (! node_uuid)
{
grub_dprintf ("hostdisk", "%s has no DM uuid\n", os_dev);
dm_tree_free (tree);
return 0;
}
if (strncmp (node_uuid, "LVM-", 4) != 0)
{
dm_tree_free (tree);
return 0;
}
dm_tree_free (tree);
return 1;
}
#else
return 1;
#endif /* HAVE_DEVICE_MAPPER */
}
int
@ -606,13 +715,11 @@ grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
return GRUB_DEV_ABSTRACTION_NONE;
/* Check for LVM. */
if (!strncmp (os_dev, "/dev/mapper/", 12)
&& ! grub_util_is_dmraid (os_dev)
&& strncmp (os_dev, "/dev/mapper/mpath", 17) != 0)
if (grub_util_is_lvm (os_dev))
return GRUB_DEV_ABSTRACTION_LVM;
/* Check for RAID. */
if (!strncmp (os_dev, "/dev/md", 7))
if (!strncmp (os_dev, "/dev/md", 7) && ! grub_util_device_is_mapped (os_dev))
return GRUB_DEV_ABSTRACTION_RAID;
#endif
@ -622,7 +729,7 @@ grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
#ifdef __linux__
static char *
get_mdadm_name (const char *os_dev)
get_mdadm_uuid (const char *os_dev)
{
int mdadm_pipe[2];
pid_t mdadm_pid;
@ -674,19 +781,21 @@ get_mdadm_name (const char *os_dev)
while (getline (&buf, &len, mdadm) > 0)
{
if (strncmp (buf, "MD_NAME=", sizeof ("MD_NAME=") - 1) == 0)
if (strncmp (buf, "MD_UUID=", sizeof ("MD_UUID=") - 1) == 0)
{
char *name_start, *colon;
char *name_start, *ptri, *ptro;
size_t name_len;
free (name);
name_start = buf + sizeof ("MD_NAME=") - 1;
/* Strip off the homehost if present. */
colon = strchr (name_start, ':');
name = strdup (colon ? colon + 1 : name_start);
name_len = strlen (name);
if (name[name_len - 1] == '\n')
name[name_len - 1] = '\0';
name_start = buf + sizeof ("MD_UUID=") - 1;
ptro = name = xmalloc (strlen (name_start) + 1);
for (ptri = name_start; *ptri && *ptri != '\n' && *ptri != '\r';
ptri++)
if ((*ptri >= '0' && *ptri <= '9')
|| (*ptri >= 'a' && *ptri <= 'f')
|| (*ptri >= 'A' && *ptri <= 'F'))
*ptro++ = *ptri;
*ptro = 0;
}
}
@ -802,19 +911,26 @@ grub_util_get_grub_dev (const char *os_dev)
#ifdef __linux__
{
char *mdadm_name = get_mdadm_name (os_dev);
char *mdadm_name = get_mdadm_uuid (os_dev);
struct stat st;
if (mdadm_name)
{
char *newname;
newname = xasprintf ("/dev/md/%s", mdadm_name);
if (stat (newname, &st) == 0)
const char *q;
for (q = os_dev + strlen (os_dev) - 1; q >= os_dev
&& grub_isdigit (*q); q--);
if (q >= os_dev && *q == 'p')
{
free (grub_dev);
grub_dev = xasprintf ("md/%s", mdadm_name);
grub_dev = xasprintf ("mduuid/%s,%s", mdadm_name, q + 1);
goto done;
}
free (newname);
free (grub_dev);
grub_dev = xasprintf ("mduuid/%s", mdadm_name);
done:
free (mdadm_name);
}
}

View file

@ -24,6 +24,7 @@
#include <grub/err.h>
#include <grub/emu/misc.h>
#include <grub/emu/hostdisk.h>
#include <grub/emu/getroot.h>
#include <grub/misc.h>
#include <grub/i18n.h>
#include <grub/list.h>
@ -139,6 +140,7 @@ struct grub_util_biosdisk_data
char *dev;
int access_mode;
int fd;
int is_disk;
};
#ifdef __linux__
@ -240,6 +242,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
data->dev = NULL;
data->access_mode = 0;
data->fd = -1;
data->is_disk = 0;
/* Get the size. */
#if defined(__MINGW32__)
@ -281,6 +284,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
close (fd);
goto fail;
}
data->is_disk = 1;
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
if (ioctl (fd, DIOCGMEDIASIZE, &nr))
@ -342,18 +346,23 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
return GRUB_ERR_NONE;
}
#ifdef HAVE_DEVICE_MAPPER
static int
device_is_mapped (const char *dev)
int
grub_util_device_is_mapped (const char *dev)
{
#ifdef HAVE_DEVICE_MAPPER
struct stat st;
if (!grub_device_mapper_supported ())
return 0;
if (stat (dev, &st) < 0)
return 0;
return dm_is_dm_major (major (st.st_rdev));
}
#else
return 0;
#endif /* HAVE_DEVICE_MAPPER */
}
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
/* FIXME: geom actually gives us the whole container hierarchy.
@ -429,7 +438,7 @@ find_partition_start (const char *dev)
# endif /* !defined(HAVE_DIOCGDINFO) */
# ifdef HAVE_DEVICE_MAPPER
if (grub_device_mapper_supported () && device_is_mapped (dev)) {
if (grub_util_device_is_mapped (dev)) {
struct dm_task *task = NULL;
grub_uint64_t start, length;
char *target_type, *params, *space;
@ -532,9 +541,12 @@ devmapper_fail:
# if !defined(HAVE_DIOCGDINFO)
return hdg.start;
# else /* defined(HAVE_DIOCGDINFO) */
p_index = dev[strlen(dev) - 1] - 'a';
if (p_index >= label.d_npartitions)
if (dev[0])
p_index = dev[strlen(dev) - 1] - 'a';
else
p_index = -1;
if (p_index >= label.d_npartitions || p_index < 0)
{
grub_error (GRUB_ERR_BAD_DEVICE,
"no disk label entry for `%s'", dev);
@ -558,7 +570,7 @@ struct linux_partition_cache
struct linux_partition_cache *linux_partition_cache_list;
static int
linux_find_partition (char *dev, unsigned long sector)
linux_find_partition (char *dev, grub_disk_addr_t sector)
{
size_t len = strlen (dev);
const char *format;
@ -566,6 +578,7 @@ linux_find_partition (char *dev, unsigned long sector)
int i;
char real_dev[PATH_MAX];
struct linux_partition_cache *cache;
int missing = 0;
strcpy(real_dev, dev);
@ -574,6 +587,12 @@ linux_find_partition (char *dev, unsigned long sector)
p = real_dev + len - 4;
format = "part%d";
}
else if (strncmp (real_dev, "/dev/disk/by-id/",
sizeof ("/dev/disk/by-id/") - 1) == 0)
{
p = real_dev + len;
format = "-part%d";
}
else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9')
{
p = real_dev + len;
@ -604,7 +623,13 @@ linux_find_partition (char *dev, unsigned long sector)
fd = open (real_dev, O_RDONLY);
if (fd == -1)
return 0;
{
if (missing++ < 10)
continue;
else
return 0;
}
missing = 0;
close (fd);
start = find_partition_start (real_dev);
@ -675,7 +700,19 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
{
free (data->dev);
if (data->fd != -1)
close (data->fd);
{
if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
{
fsync (data->fd);
#ifdef __linux__
if (data->is_disk)
ioctl (data->fd, BLKFLSBUF, 0);
#endif
}
close (data->fd);
data->fd = -1;
}
/* Open the partition. */
grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev);
@ -686,10 +723,6 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
return -1;
}
/* Flush the buffer cache to the physical disk.
XXX: This also empties the buffer cache. */
ioctl (fd, BLKFLSBUF, 0);
data->dev = xstrdup (dev);
data->access_mode = (flags & O_ACCMODE);
data->fd = fd;
@ -727,7 +760,18 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
{
free (data->dev);
if (data->fd != -1)
close (data->fd);
{
if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
{
fsync (data->fd);
#ifdef __linux__
if (data->is_disk)
ioctl (data->fd, BLKFLSBUF, 0);
#endif
}
close (data->fd);
data->fd = -1;
}
fd = open (map[disk->id].device, flags);
if (fd >= 0)
@ -888,7 +932,6 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
!= (1 << disk->log_sector_size))
{
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
close (fd);
return grub_errno;
}
@ -938,6 +981,27 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
return grub_errno;
}
grub_err_t
grub_util_biosdisk_flush (struct grub_disk *disk)
{
struct grub_util_biosdisk_data *data = disk->data;
if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID)
return GRUB_ERR_NONE;
if (data->fd == -1)
{
data->fd = open_device (disk, 0, O_RDONLY);
if (data->fd < 0)
return grub_errno;
}
fsync (data->fd);
#ifdef __linux__
if (data->is_disk)
ioctl (data->fd, BLKFLSBUF, 0);
#endif
return GRUB_ERR_NONE;
}
static void
grub_util_biosdisk_close (struct grub_disk *disk)
{
@ -945,7 +1009,11 @@ grub_util_biosdisk_close (struct grub_disk *disk)
free (data->dev);
if (data->fd != -1)
close (data->fd);
{
if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
grub_util_biosdisk_flush (disk);
close (data->fd);
}
free (data);
}
@ -1115,6 +1183,54 @@ make_device_name (int drive, int dos_part, int bsd_part)
return ret;
}
#ifdef HAVE_DEVICE_MAPPER
static int
grub_util_get_dm_node_linear_info (const char *dev,
int *maj, int *min)
{
struct dm_task *dmt;
void *next = NULL;
uint64_t length, start;
char *target, *params;
char *ptr;
int major, minor;
dmt = dm_task_create(DM_DEVICE_TABLE);
if (!dmt)
return 0;
if (!dm_task_set_name(dmt, dev))
return 0;
dm_task_no_open_count(dmt);
if (!dm_task_run(dmt))
return 0;
next = dm_get_next_target(dmt, next, &start, &length,
&target, &params);
if (grub_strcmp (target, "linear") != 0)
return 0;
major = grub_strtoul (params, &ptr, 10);
if (grub_errno)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (*ptr != ':')
return 0;
ptr++;
minor = grub_strtoul (ptr, 0, 10);
if (grub_errno)
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (maj)
*maj = major;
if (min)
*min = minor;
return 1;
}
#endif
static char *
convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
{
@ -1291,9 +1407,40 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
node = NULL;
goto devmapper_out;
}
else if (strncmp (node_uuid, "DMRAID-", 7) != 0)
if (strncmp (node_uuid, "LVM-", 4) == 0)
{
grub_dprintf ("hostdisk", "%s is an LVM\n", path);
node = NULL;
goto devmapper_out;
}
if (strncmp (node_uuid, "mpath-", 6) == 0)
{
/* Multipath partitions have partN-mpath-* UUIDs, and are
linear mappings so are handled by
grub_util_get_dm_node_linear_info. Multipath disks are not
linear mappings and must be handled specially. */
grub_dprintf ("hostdisk", "%s is a multipath disk\n", path);
mapper_name = dm_tree_node_get_name (node);
goto devmapper_out;
}
if (strncmp (node_uuid, "DMRAID-", 7) != 0)
{
int major, minor;
const char *node_name;
grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path);
if ((node_name = dm_tree_node_get_name (node))
&& grub_util_get_dm_node_linear_info (node_name,
&major, &minor))
{
if (tree)
dm_tree_free (tree);
free (path);
char *ret = grub_find_device ("/dev/mapper",
(major << 8) | minor);
return ret;
}
node = NULL;
goto devmapper_out;
}
@ -1530,6 +1677,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
if (stat (os_dev, &st) < 0)
{
grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
grub_util_info ("cannot stat `%s'", os_dev);
return 0;
}
@ -1538,6 +1686,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
{
grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"no mapping exists for `%s'", os_dev);
grub_util_info ("no mapping exists for `%s'", os_dev);
return 0;
}

View file

@ -15,6 +15,8 @@
#include "../mips/dl.c"
#elif defined(__powerpc__)
#include "../powerpc/dl.c"
#elif defined(__ia64__)
#include "../ia64/dl.c"
#else
#error "No target cpu type is defined"
#endif

View file

@ -415,6 +415,18 @@ grub_make_system_path_relative_to_its_root (const char *path)
if (offset == 0)
{
free (buf);
#ifdef __linux__
{
char *bind;
grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
if (bind && bind[0] && bind[1])
{
buf3 = bind;
goto parsedir;
}
grub_free (bind);
}
#endif
free (buf2);
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
if (poolfs)
@ -437,6 +449,21 @@ grub_make_system_path_relative_to_its_root (const char *path)
}
free (buf);
buf3 = xstrdup (buf2 + offset);
buf2[offset] = 0;
#ifdef __linux__
{
char *bind;
grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
if (bind && bind[0] && bind[1])
{
char *temp = buf3;
buf3 = grub_xasprintf ("%s%s%s", bind, buf3[0] == '/' ?"":"/", buf3);
grub_free (temp);
}
grub_free (bind);
}
#endif
free (buf2);
#ifdef __CYGWIN__
@ -452,6 +479,7 @@ grub_make_system_path_relative_to_its_root (const char *path)
}
#endif
parsedir:
/* Remove trailing slashes, return empty string if root directory. */
len = strlen (buf3);
while (len > 0 && buf3[len - 1] == '/')

View file

@ -68,7 +68,7 @@ grub_file_open (const char *name)
goto fail;
/* Get the file part of NAME. */
file_name = grub_strchr (name, ')');
file_name = (name[0] == '(') ? grub_strchr (name, ')') : NULL;
if (file_name)
file_name++;
else

276
grub-core/kern/ia64/dl.c Normal file
View file

@ -0,0 +1,276 @@
/* dl.c - arch-dependent part of loadable module support */
/*
* GRUB -- GRand Unified Bootloader
* 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
* 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>
#include <grub/mm.h>
/* Check if EHDR is a valid ELF header. */
grub_err_t
grub_arch_dl_check_header (void *ehdr)
{
Elf_Ehdr *e = ehdr;
/* Check the magic numbers. */
if (e->e_ident[EI_CLASS] != ELFCLASS64
|| e->e_ident[EI_DATA] != ELFDATA2LSB
|| e->e_machine != EM_IA_64)
return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
return GRUB_ERR_NONE;
}
#define MASK20 ((1 << 20) - 1)
#define MASK19 ((1 << 19) - 1)
struct unaligned_uint32
{
grub_uint32_t val;
} __attribute__ ((packed));
static void
add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value)
{
struct unaligned_uint32 *p;
switch (addr & 3)
{
case 0:
p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2);
p->val = ((((((p->val >> 2) & MASK20) + value) & MASK20) << 2)
| (p->val & ~(MASK20 << 2)));
break;
case 1:
p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7);
p->val = ((((((p->val >> 3) & MASK20) + value) & MASK20) << 3)
| (p->val & ~(MASK20 << 3)));
break;
case 2:
p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12);
p->val = ((((((p->val >> 4) & MASK20) + value) & MASK20) << 4)
| (p->val & ~(MASK20 << 4)));
break;
}
}
#define MASKF21 ( ((1 << 23) - 1) & ~((1 << 7) | (1 << 8)) )
static grub_uint32_t
add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value)
{
grub_uint32_t high, mid, low, c;
low = (a & 0x00007f);
mid = (a & 0x7fc000) >> 7;
high = (a & 0x003e00) << 7;
c = (low | mid | high) + value;
return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 7) & 0x0003e00); //0x003e00
}
static void
add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value)
{
struct unaligned_uint32 *p;
switch (addr & 3)
{
case 0:
p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2);
p->val = ((add_value_to_slot_21_real (((p->val >> 2) & MASKF21), value) & MASKF21) << 2) | (p->val & ~(MASKF21 << 2));
break;
case 1:
p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7);
p->val = ((add_value_to_slot_21_real (((p->val >> 3) & MASKF21), value) & MASKF21) << 3) | (p->val & ~(MASKF21 << 3));
break;
case 2:
p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12);
p->val = ((add_value_to_slot_21_real (((p->val >> 4) & MASKF21), value) & MASKF21) << 4) | (p->val & ~(MASKF21 << 4));
break;
}
}
static grub_uint8_t nopm[5] =
{
/* [MLX] nop.m 0x0 */
0x05, 0x00, 0x00, 0x00, 0x01
};
static grub_uint8_t jump[0x20] =
{
/* ld8 r16=[r15],8 */
0x02, 0x80, 0x20, 0x1e, 0x18, 0x14,
/* mov r14=r1;; */
0xe0, 0x00, 0x04, 0x00, 0x42, 0x00,
/* nop.i 0x0 */
0x00, 0x00, 0x04, 0x00,
/* ld8 r1=[r15] */
0x11, 0x08, 0x00, 0x1e, 0x18, 0x10,
/* mov b6=r16 */
0x60, 0x80, 0x04, 0x80, 0x03, 0x00,
/* br.few b6;; */
0x60, 0x00, 0x80, 0x00
};
struct ia64_trampoline
{
/* nop.m */
grub_uint8_t nop[5];
/* movl r15 = addr*/
grub_uint8_t addr_hi[6];
grub_uint8_t e0;
grub_uint8_t addr_lo[4];
grub_uint8_t jump[0x20];
};
static void
make_trampoline (struct ia64_trampoline *tr, grub_uint64_t addr)
{
COMPILE_TIME_ASSERT (sizeof (struct ia64_trampoline)
== GRUB_IA64_DL_TRAMP_SIZE);
grub_memcpy (tr->nop, nopm, sizeof (tr->nop));
tr->addr_hi[0] = ((addr & 0xc00000) >> 16);
tr->addr_hi[1] = (addr >> 24) & 0xff;
tr->addr_hi[2] = (addr >> 32) & 0xff;
tr->addr_hi[3] = (addr >> 40) & 0xff;
tr->addr_hi[4] = (addr >> 48) & 0xff;
tr->addr_hi[5] = (addr >> 56) & 0xff;
tr->e0 = 0xe0;
tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01;
tr->addr_lo[1] = (((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11)
| ((addr & 0x200000) >> 17));
tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19);
tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60;
grub_memcpy (tr->jump, jump, sizeof (tr->jump));
}
/* Relocate symbols. */
grub_err_t
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
{
Elf_Ehdr *e = ehdr;
Elf_Shdr *s;
Elf_Word entsize;
unsigned i;
grub_uint64_t *gp, *gpptr;
struct ia64_trampoline *tr;
gp = (grub_uint64_t *) mod->base;
gpptr = (grub_uint64_t *) mod->got;
tr = mod->tramp;
/* Find a symbol table. */
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
i < e->e_shnum;
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");
entsize = s->sh_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))
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)
{
Elf_Rela *rel, *max;
for (rel = (Elf_Rela *) ((char *) e + s->sh_offset),
max = rel + s->sh_size / s->sh_entsize;
rel < max;
rel++)
{
grub_addr_t addr;
Elf_Sym *sym;
grub_uint64_t value;
if (seg->size < (rel->r_offset & ~3))
return grub_error (GRUB_ERR_BAD_MODULE,
"reloc offset is out of the segment");
addr = (grub_addr_t) 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 (ELF_R_TYPE (rel->r_info))
{
case R_IA64_PCREL21B:
{
grub_uint64_t noff;
make_trampoline (tr, value);
noff = ((char *) tr - (char *) (addr & ~3)) >> 4;
tr++;
if (noff & ~MASK19)
return grub_error (GRUB_ERR_BAD_OS,
"trampoline offset too big (%lx)", noff);
add_value_to_slot_20b (addr, noff);
}
break;
case R_IA64_SEGREL64LSB:
*(grub_uint64_t *) addr += value - (grub_addr_t) seg->addr;
break;
case R_IA64_FPTR64LSB:
case R_IA64_DIR64LSB:
*(grub_uint64_t *) addr += value;
break;
case R_IA64_PCREL64LSB:
*(grub_uint64_t *) addr += value - addr;
break;
case R_IA64_GPREL22:
add_value_to_slot_21 (addr, value - (grub_addr_t) gp);
break;
case R_IA64_LTOFF22X:
case R_IA64_LTOFF22:
if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
value = *(grub_uint64_t *) sym->st_value + rel->r_addend;
case R_IA64_LTOFF_FPTR22:
*gpptr = value;
add_value_to_slot_21 (addr, (grub_addr_t) gpptr - (grub_addr_t) gp);
gpptr++;
break;
/* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
case R_IA64_LDXMOV:
break;
default:
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"this relocation (0x%x) is not implemented yet",
ELF_R_TYPE (rel->r_info));
}
}
}
}
return GRUB_ERR_NONE;
}

View file

@ -0,0 +1,73 @@
/* dl.c - arch-dependent part of loadable module support */
/*
* GRUB -- GRand Unified Bootloader
* 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
* 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>
#include <grub/mm.h>
void
grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
grub_size_t *got)
{
const Elf64_Ehdr *e = ehdr;
grub_size_t cntt = 0, cntg = 0;;
const Elf64_Shdr *s;
Elf64_Word entsize;
unsigned i;
/* Find a symbol table. */
for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff));
i < grub_le_to_cpu16 (e->e_shnum);
i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize)))
if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB)
break;
if (i == grub_le_to_cpu16 (e->e_shnum))
return;
entsize = s->sh_entsize;
for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff));
i < grub_le_to_cpu16 (e->e_shnum);
i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize)))
if (grub_le_to_cpu32 (s->sh_type) == SHT_RELA)
{
Elf64_Rela *rel, *max;
for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu32 (s->sh_offset)),
max = rel + grub_le_to_cpu32 (s->sh_size) / grub_le_to_cpu16 (s->sh_entsize);
rel < max; rel++)
switch (ELF64_R_TYPE (grub_le_to_cpu32 (rel->r_info)))
{
case R_IA64_PCREL21B:
cntt++;
break;
case R_IA64_LTOFF_FPTR22:
case R_IA64_LTOFF22X:
case R_IA64_LTOFF22:
cntg++;
break;
}
}
*tramp = cntt;
*got = cntg;
}

View file

@ -0,0 +1,60 @@
/* init.c - initialize an ia64-based EFI system */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/cache.h>
#include <grub/kernel.h>
#include <grub/efi/efi.h>
void
grub_machine_init (void)
{
grub_efi_init ();
grub_install_get_time_ms (grub_rtc_get_time_ms);
}
void
grub_machine_fini (void)
{
grub_efi_fini ();
}
void
grub_machine_set_prefix (void)
{
grub_efi_set_prefix ();
}
void
grub_arch_sync_caches (void *address, grub_size_t len)
{
/* Cache line length is at least 32. */
grub_uint64_t a = (grub_uint64_t)address & ~0x1f;
/* Flush data. */
for (len = (len + 31) & ~0x1f; len > 0; len -= 0x20, a += 0x20)
asm volatile ("fc.i %0" : : "r" (a));
/* Sync and serialize. Maybe extra. */
asm volatile (";; sync.i;; srlz.i;;");
}

View file

@ -0,0 +1,54 @@
/*
* 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 <config.h>
#include <grub/symbol.h>
#include <grub/offsets.h>
.text
.psr abi64
.psr lsb
.lsb
.global _start
.proc _start
_start:
alloc loc0=ar.pfs,2,4,0,0
mov loc1=rp
addl loc2=@gprel(grub_efi_image_handle),gp
addl loc3=@gprel(grub_efi_system_table),gp
;;
st8 [loc2]=in0
st8 [loc3]=in1
br.call.sptk.few rp=grub_main
;;
mov ar.pfs=loc0
mov rp=loc1
;;
br.ret.sptk.few rp
.endp _start
. = _start + GRUB_KERNEL_MACHINE_PREFIX
VARIABLE(grub_prefix)
.byte 0
/* to be filled by grub-mkimage */
/*
* Leave some breathing room for the prefix.
*/
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END

View file

@ -53,8 +53,8 @@ grub_module_iterate (int (*hook) (struct grub_module_header *header))
}
}
/* This is actualy platform-independant but used only on yeeloong and sparc. */
#if defined (GRUB_MACHINE_MIPS_YEELOONG) || defined (GRUB_MACHINE_SPARC64)
/* This is actualy platform-independant but used only on loongson and sparc. */
#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_SPARC64)
grub_addr_t
grub_modules_get_end (void)
{

View file

@ -0,0 +1,213 @@
/*
* 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/kernel.h>
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/time.h>
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/machine/kernel.h>
#include <grub/machine/memory.h>
#include <grub/arc/console.h>
#include <grub/cpu/memory.h>
#include <grub/cpu/time.h>
#include <grub/memory.h>
#include <grub/term.h>
#include <grub/arc/arc.h>
#include <grub/offsets.h>
const char *type_names[] = {
#ifdef GRUB_CPU_WORDS_BIGENDIAN
NULL,
#endif
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
"eisa", "tc", "scsi", "dti", "multi", "disk", "tape", "cdrom", "worm",
"serial", "net", "video", "par", "point", "key", "audio", "other",
"rdisk", "fdisk", "tape", "modem", "monitor", "print", "pointer",
"keyboard", "term", "other", "line", "network", NULL
};
static int
iterate_rec (const char *prefix, const struct grub_arc_component *parent,
int (*hook) (const char *name,
const struct grub_arc_component *comp),
int alt_names)
{
const struct grub_arc_component *comp;
FOR_ARC_CHILDREN(comp, parent)
{
char *name;
const char *cname = NULL;
if (comp->type < ARRAY_SIZE (type_names))
cname = type_names[comp->type];
if (!cname)
cname = "unknown";
if (alt_names)
name = grub_xasprintf ("%s/%s%lu", prefix, cname, comp->key);
else
name = grub_xasprintf ("%s%s(%lu)", prefix, cname, comp->key);
if (!name)
return 1;
if (hook (name, comp))
{
grub_free (name);
return 1;
}
if (iterate_rec ((parent ? name : prefix), comp, hook, alt_names))
{
grub_free (name);
return 1;
}
grub_free (name);
}
return 0;
}
int
grub_arc_iterate_devs (int (*hook) (const char *name,
const struct grub_arc_component *comp),
int alt_names)
{
return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, alt_names);
}
grub_err_t
grub_machine_mmap_iterate (grub_memory_hook_t hook)
{
struct grub_arc_memory_descriptor *cur = NULL;
while (1)
{
grub_memory_type_t type;
cur = GRUB_ARC_FIRMWARE_VECTOR->getmemorydescriptor (cur);
if (!cur)
return GRUB_ERR_NONE;
switch (cur->type)
{
case GRUB_ARC_MEMORY_EXCEPTION_BLOCK:
case GRUB_ARC_MEMORY_SYSTEM_PARAMETER_BLOCK:
case GRUB_ARC_MEMORY_FW_PERMANENT:
default:
type = GRUB_MEMORY_RESERVED;
break;
case GRUB_ARC_MEMORY_FW_TEMPORARY:
case GRUB_ARC_MEMORY_FREE:
case GRUB_ARC_MEMORY_LOADED:
case GRUB_ARC_MEMORY_FREE_CONTIGUOUS:
type = GRUB_MEMORY_AVAILABLE;
break;
case GRUB_ARC_MEMORY_BADRAM:
type = GRUB_MEMORY_BADRAM;
break;
}
if (hook (((grub_uint64_t) cur->start_page) << 12,
((grub_uint64_t) cur->num_pages) << 12, type))
return GRUB_ERR_NONE;
}
}
extern grub_uint32_t grub_total_modules_size;
void
grub_machine_init (void)
{
struct grub_arc_memory_descriptor *cur = NULL;
grub_console_init_early ();
/* FIXME: measure this. */
grub_arch_cpuclock = 64000000;
grub_install_get_time_ms (grub_rtc_get_time_ms);
while (1)
{
grub_uint64_t start, end;
cur = GRUB_ARC_FIRMWARE_VECTOR->getmemorydescriptor (cur);
if (!cur)
break;
if (cur->type != GRUB_ARC_MEMORY_FREE
&& cur->type != GRUB_ARC_MEMORY_LOADED
&& cur->type != GRUB_ARC_MEMORY_FREE_CONTIGUOUS)
continue;
start = ((grub_uint64_t) cur->start_page) << 12;
end = ((grub_uint64_t) cur->num_pages) << 12;
end += start;
if ((grub_uint64_t) end > ((GRUB_KERNEL_MIPS_ARC_LINK_ADDR
- grub_total_modules_size) & 0x1fffffff))
end = ((GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size)
& 0x1fffffff);
if (end > start)
grub_mm_init_region ((void *) (grub_addr_t) (start | 0x80000000),
end - start);
}
grub_console_init_lately ();
grub_arcdisk_init ();
}
grub_addr_t
grub_arch_modules_addr (void)
{
return GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size;
}
void
grub_machine_fini (void)
{
}
void
grub_halt (void)
{
GRUB_ARC_FIRMWARE_VECTOR->powerdown ();
grub_millisleep (1500);
grub_printf ("Shutdown failed\n");
grub_refresh ();
while (1);
}
void
grub_exit (void)
{
GRUB_ARC_FIRMWARE_VECTOR->exit ();
grub_millisleep (1500);
grub_printf ("Exit failed\n");
grub_refresh ();
while (1);
}
void
grub_reboot (void)
{
GRUB_ARC_FIRMWARE_VECTOR->restart ();
grub_millisleep (1500);
grub_printf ("Reboot failed\n");
grub_refresh ();
while (1);
}

View file

@ -8,3 +8,38 @@ FUNCTION (grub_cpu_flush_cache)
FUNCTION (grub_arch_sync_caches)
#include "cache_flush.S"
j $ra
FUNCTION (grub_arch_sync_dma_caches)
move $t2, $a0
addu $t3, $a0, $a1
srl $t2, $t2, 5
sll $t2, $t2, 5
addu $t3, $t3, 0x1f
srl $t3, $t3, 5
sll $t3, $t3, 5
move $t0, $t2
subu $t1, $t3, $t2
1:
cache 1, 0($t0)
addiu $t1, $t1, 0xffff
bne $t1, $zero, 1b
addiu $t0, $t0, 0x1
sync
move $t0, $t2
subu $t1, $t3, $t2
2:
cache 0, 0($t0)
addiu $t1, $t1, 0xffff
bne $t1, $zero, 2b
addiu $t0, $t0, 0x1
sync
move $t0, $t2
subu $t1, $t3, $t2
2:
cache 23, 0($t0)
addiu $t1, $t1, 0xffff
bne $t1, $zero, 2b
addiu $t0, $t0, 0x1
sync
jr $ra

View file

@ -9,15 +9,15 @@
subu $t1, $t3, $t2
1:
cache 1, 0($t0)
addiu $t1, $t1, 0xffff
addiu $t1, $t1, -0x4
bne $t1, $zero, 1b
addiu $t0, $t0, 0x1
addiu $t0, $t0, 0x4
sync
move $t0, $t2
subu $t1, $t3, $t2
2:
cache 0, 0($t0)
addiu $t1, $t1, 0xffff
addiu $t1, $t1, -0x4
bne $t1, $zero, 2b
addiu $t0, $t0, 0x1
addiu $t0, $t0, 0x4
sync

View file

@ -34,7 +34,7 @@ grub_arch_dl_check_header (void *ehdr)
Elf_Ehdr *e = ehdr;
/* Check the magic numbers. */
#ifdef WORDS_BIGENDIAN
#ifdef GRUB_CPU_WORDS_BIGENDIAN
if (e->e_ident[EI_CLASS] != ELFCLASS32
|| e->e_ident[EI_DATA] != ELFDATA2MSB
|| e->e_machine != EM_MIPS)
@ -144,14 +144,14 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
rel < max;
rel++)
{
Elf_Word *addr;
grub_uint8_t *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 = (Elf_Word *) ((char *) seg->addr + rel->r_offset);
addr = (grub_uint8_t *) ((char *) seg->addr + rel->r_offset);
sym = (Elf_Sym *) ((char *) mod->symtab
+ entsize * ELF_R_SYM (rel->r_info));
if (sym->st_value == (grub_addr_t) &__gnu_local_gp_dummy)
@ -163,7 +163,11 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
{
grub_uint32_t value;
Elf_Rel *rel2;
#ifdef GRUB_CPU_WORDS_BIGENDIAN
addr += 2;
#endif
/* Handle partner lo16 relocation. Lower part is
treated as signed. Hence add 0x8000 to compensate.
*/
@ -175,13 +179,20 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
&& ELF_R_TYPE (rel2->r_info) == R_MIPS_LO16)
{
value += *(grub_int16_t *)
((char *) seg->addr + rel2->r_offset);
((char *) seg->addr + rel2->r_offset
#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ 2
#endif
);
break;
}
*(grub_uint16_t *) addr = (value >> 16) & 0xffff;
}
break;
case R_MIPS_LO16:
#ifdef GRUB_CPU_WORDS_BIGENDIAN
addr += 2;
#endif
*(grub_uint16_t *) addr += (sym->st_value) & 0xffff;
break;
case R_MIPS_32:
@ -208,11 +219,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
case R_MIPS_GOT16:
case R_MIPS_CALL16:
/* FIXME: reuse*/
#ifdef GRUB_CPU_WORDS_BIGENDIAN
addr += 2;
#endif
*gpptr = sym->st_value + *(grub_uint16_t *) addr;
*(grub_uint16_t *) addr
= sizeof (grub_uint32_t) * (gpptr - gp);
gpptr++;
break;
case R_MIPS_JALR:
break;
default:
{
grub_free (gp);
@ -232,6 +248,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
void
grub_arch_dl_init_linker (void)
{
grub_dl_register_symbol ("__gnu_local_gp", &__gnu_local_gp_dummy, 0);
grub_dl_register_symbol ("__gnu_local_gp", &__gnu_local_gp_dummy, 0, 0);
}

View file

@ -18,17 +18,27 @@
#include <grub/kernel.h>
#include <grub/env.h>
#include <grub/cpu/time.h>
#include <grub/cpu/mips.h>
/* FIXME: use interrupt to count high. */
grub_uint64_t
grub_get_rtc (void)
{
static grub_uint32_t high = 0;
static grub_uint32_t last = 0;
grub_uint32_t low;
asm volatile ("mfc0 %0, " GRUB_CPU_MIPS_COP0_TIMER_COUNT : "=r" (low));
if (low < last)
high++;
last = low;
return (((grub_uint64_t) high) << 32) | low;
}
void
grub_machine_set_prefix (void)
{
grub_env_set ("prefix", grub_prefix);
}
extern char _end[];
grub_addr_t
grub_arch_modules_addr (void)
{
return (grub_addr_t) _end;
}

View file

@ -31,8 +31,10 @@
#include <grub/cs5536.h>
#include <grub/term.h>
#include <grub/machine/ec.h>
#include <grub/cpu/memory.h>
extern void grub_video_sm712_init (void);
extern void grub_video_sis315pro_init (void);
extern void grub_video_init (void);
extern void grub_bitmap_init (void);
extern void grub_font_init (void);
@ -43,22 +45,6 @@ extern void grub_terminfo_init (void);
extern void grub_keylayouts_init (void);
extern void grub_boot_init (void);
/* FIXME: use interrupt to count high. */
grub_uint64_t
grub_get_rtc (void)
{
static grub_uint32_t high = 0;
static grub_uint32_t last = 0;
grub_uint32_t low;
asm volatile ("mfc0 %0, " GRUB_CPU_LOONGSON_COP0_TIMER_COUNT : "=r" (low));
if (low < last)
high++;
last = low;
return (((grub_uint64_t) high) << 32) | low;
}
grub_err_t
grub_machine_mmap_iterate (grub_memory_hook_t hook)
{
@ -79,7 +65,7 @@ init_pci (void)
/* FIXME: autoscan for BARs and devices. */
switch (pciid)
{
case GRUB_YEELOONG_OHCI_PCIID:
case GRUB_LOONGSON_OHCI_PCIID:
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
grub_pci_write (addr, 0x5025000);
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
@ -91,7 +77,7 @@ init_pci (void)
addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS);
grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES);
break;
case GRUB_YEELOONG_EHCI_PCIID:
case GRUB_LOONGSON_EHCI_PCIID:
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
grub_pci_write (addr, 0x5026000);
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
@ -163,7 +149,7 @@ grub_machine_init (void)
if (err)
grub_fatal ("Couldn't init SMBus: %s\n", grub_errmsg);
/* Yeeloong has only one memory slot. */
/* Yeeloong and Fuloong have only one memory slot. */
err = grub_cs5536_read_spd (smbbase, GRUB_SMB_RAM_START_ADDR, &spd);
if (err)
grub_fatal ("Couldn't read SPD: %s\n", grub_errmsg);
@ -202,12 +188,14 @@ grub_machine_init (void)
relies on a working heap. */
grub_video_init ();
grub_video_sm712_init ();
grub_video_sis315pro_init ();
grub_bitmap_init ();
grub_font_init ();
grub_gfxterm_init ();
grub_keylayouts_init ();
grub_at_keyboard_init ();
if (grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG)
grub_at_keyboard_init ();
grub_terminfo_init ();
grub_serial_init ();
@ -223,10 +211,28 @@ grub_machine_fini (void)
void
grub_halt (void)
{
grub_outb (grub_inb (GRUB_CPU_LOONGSON_GPIOCFG)
& ~GRUB_CPU_LOONGSON_SHUTDOWN_GPIO, GRUB_CPU_LOONGSON_GPIOCFG);
grub_millisleep (1500);
switch (grub_arch_machine)
{
case GRUB_ARCH_MACHINE_FULOONG:
{
grub_pci_device_t dev;
grub_port_t p;
if (grub_cs5536_find (&dev))
{
p = (grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_GPIO_BAR)
& GRUB_CS5536_LBAR_ADDR_MASK) + GRUB_MACHINE_PCI_IO_BASE;
grub_outl ((1 << 13), p + 4);
grub_outl ((1 << 29), p);
grub_millisleep (5000);
}
}
break;
case GRUB_ARCH_MACHINE_YEELOONG:
grub_outb (grub_inb (GRUB_CPU_LOONGSON_GPIOCFG)
& ~GRUB_CPU_YEELOONG_SHUTDOWN_GPIO, GRUB_CPU_LOONGSON_GPIOCFG);
grub_millisleep (1500);
break;
}
grub_printf ("Shutdown failed\n");
grub_refresh ();
@ -251,3 +257,10 @@ grub_reboot (void)
while (1);
}
extern char _end[];
grub_addr_t
grub_arch_modules_addr (void)
{
return (grub_addr_t) _end;
}

View file

@ -6,25 +6,29 @@
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/machine/kernel.h>
#include <grub/machine/memory.h>
#include <grub/cpu/kernel.h>
#include <grub/cpu/memory.h>
#include <grub/memory.h>
#define RAMSIZE (*(grub_uint32_t *) ((16 << 20) - 264))
grub_uint32_t
grub_get_rtc (void)
{
static int calln = 0;
return calln++;
}
extern void grub_serial_init (void);
extern void grub_terminfo_init (void);
void
grub_machine_init (void)
{
grub_mm_init_region ((void *) GRUB_MACHINE_MEMORY_USABLE,
RAMSIZE - (GRUB_MACHINE_MEMORY_USABLE & 0x7fffffff));
grub_addr_t modend;
/* FIXME: measure this. */
grub_arch_cpuclock = 64000000;
modend = grub_modules_get_end ();
grub_mm_init_region ((void *) modend, grub_arch_memsize
- (modend - GRUB_ARCH_LOWMEMVSTART));
grub_install_get_time_ms (grub_rtc_get_time_ms);
grub_terminfo_init ();
grub_serial_init ();
}
void
@ -53,6 +57,14 @@ grub_reboot (void)
grub_err_t
grub_machine_mmap_iterate (grub_memory_hook_t hook)
{
hook (0, RAMSIZE, GRUB_MEMORY_AVAILABLE);
hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE);
return GRUB_ERR_NONE;
}
extern char _end[];
grub_addr_t
grub_arch_modules_addr (void)
{
return (grub_addr_t) _end;
}

View file

@ -20,6 +20,7 @@
#include <grub/symbol.h>
#include <grub/offsets.h>
#include <grub/machine/memory.h>
#include <grub/machine/kernel.h>
#include <grub/offsets.h>
#define BASE_ADDR 8
@ -35,8 +36,8 @@ start:
bal cont
nop
. = _start + GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE
total_module_size:
. = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
VARIABLE(grub_total_modules_size)
.long 0
. = _start + GRUB_KERNEL_MACHINE_PREFIX
@ -50,7 +51,6 @@ VARIABLE(grub_prefix)
*/
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
#ifdef GRUB_MACHINE_MIPS_YEELOONG
VARIABLE (grub_arch_busclock)
.long 0
VARIABLE (grub_arch_cpuclock)
@ -59,21 +59,32 @@ VARIABLE (grub_arch_memsize)
.long 0
VARIABLE (grub_arch_highmemsize)
.long 0
#ifdef GRUB_MACHINE_MIPS_LOONGSON
VARIABLE (grub_arch_machine)
.long GRUB_ARCH_MACHINE_FULOONG
#endif
cont:
/* Save our base. */
move $s0, $ra
#ifdef GRUB_MACHINE_MIPS_YEELOONG
#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
lui $t1, %hi(grub_arch_busclock)
addiu $t1, %lo(grub_arch_busclock)
sw $s4, 8($t1)
#endif
#ifdef GRUB_MACHINE_MIPS_LOONGSON
lui $t1, %hi(grub_arch_busclock)
addiu $t1, %lo(grub_arch_busclock)
sw $s2, 0($t1)
sw $s3, 4($t1)
sw $s4, 8($t1)
sw $s5, 12($t1)
sw $s7, 16($t1)
#endif
/* Move the modules out of BSS. */
#ifndef GRUB_MACHINE_ARC
lui $t2, %hi(__bss_start)
addiu $t2, %lo(__bss_start)
@ -103,6 +114,7 @@ modulesmovcont:
b modulesmovcont
addiu $t3, $t3, -1
modulesmovdone:
#endif
/* Clean BSS. */

View file

@ -597,23 +597,23 @@ grub_reverse (char *str)
/* 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)
grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
{
/* This algorithm is typically implemented by hardware. The idea
is to get the highest bit in N, 64 times, by keeping
upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
upper(N * 2^i) = (Q * D + M), where upper
represents the high 64 bits in 128-bits space. */
unsigned bits = 64;
unsigned long long q = 0;
unsigned m = 0;
grub_uint64_t q = 0;
grub_uint64_t m = 0;
/* Skip the slow computation if 32-bit arithmetic is possible. */
if (n < 0xffffffff)
if (n < 0xffffffff && d < 0xffffffff)
{
if (r)
*r = ((grub_uint32_t) n) % d;
*r = ((grub_uint32_t) n) % (grub_uint32_t) d;
return ((grub_uint32_t) n) / d;
return ((grub_uint32_t) n) / (grub_uint32_t) d;
}
while (bits--)
@ -666,7 +666,7 @@ grub_lltoa (char *str, int c, unsigned long long n)
/* BASE == 10 */
do
{
unsigned m;
grub_uint64_t m;
n = grub_divmod64 (n, 10, &m);
*p++ = m + '0';

View file

@ -311,11 +311,13 @@ grub_memalign (grub_size_t align, grub_size_t size)
count++;
goto again;
#if 0
case 1:
/* Unload unneeded modules. */
grub_dl_unload_unneeded ();
count++;
goto again;
#endif
default:
break;

View file

@ -37,80 +37,80 @@
.text
FUNCTION(efi_wrap_0)
subq $40, %rsp
subq $48, %rsp
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_1)
subq $40, %rsp
subq $48, %rsp
mov %rsi, %rcx
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_2)
subq $40, %rsp
subq $48, %rsp
mov %rsi, %rcx
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_3)
subq $40, %rsp
subq $48, %rsp
mov %rcx, %r8
mov %rsi, %rcx
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_4)
subq $40, %rsp
subq $48, %rsp
mov %r8, %r9
mov %rcx, %r8
mov %rsi, %rcx
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_5)
subq $40, %rsp
subq $48, %rsp
mov %r9, 32(%rsp)
mov %r8, %r9
mov %rcx, %r8
mov %rsi, %rcx
call *%rdi
addq $40, %rsp
addq $48, %rsp
ret
FUNCTION(efi_wrap_6)
subq $56, %rsp
mov 56+8(%rsp), %rax
subq $64, %rsp
mov 64+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
addq $64, %rsp
ret
FUNCTION(efi_wrap_10)
subq $88, %rsp
mov 88+40(%rsp), %rax
subq $96, %rsp
mov 96+40(%rsp), %rax
mov %rax, 72(%rsp)
mov 88+32(%rsp), %rax
mov 96+32(%rsp), %rax
mov %rax, 64(%rsp)
mov 88+24(%rsp), %rax
mov 96+24(%rsp), %rax
mov %rax, 56(%rsp)
mov 88+16(%rsp), %rax
mov 96+16(%rsp), %rax
mov %rax, 48(%rsp)
mov 88+8(%rsp), %rax
mov 96+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
addq $96, %rsp
ret