merge mainline into lazy

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-07-07 12:21:53 +02:00
commit 00542307eb
326 changed files with 18667 additions and 4092 deletions

View file

@ -26,6 +26,8 @@
#include <grub/env.h>
#include <grub/partition.h>
grub_net_t (*grub_net_open) (const char *name) = NULL;
grub_device_t
grub_device_open (const char *name)
{
@ -35,7 +37,7 @@ grub_device_open (const char *name)
if (! name)
{
name = grub_env_get ("root");
if (*name == '\0')
if (name == NULL || *name == '\0')
{
grub_error (GRUB_ERR_BAD_DEVICE, "no device is set");
goto fail;
@ -46,15 +48,19 @@ grub_device_open (const char *name)
if (! dev)
goto fail;
dev->net = NULL;
/* Try to open a disk. */
disk = grub_disk_open (name);
if (! disk)
goto fail;
dev->disk = grub_disk_open (name);
if (dev->disk)
return dev;
if (grub_net_open && grub_errno == GRUB_ERR_UNKNOWN_DEVICE)
{
grub_errno = GRUB_ERR_NONE;
dev->net = grub_net_open (name);
}
dev->disk = disk;
dev->net = 0; /* FIXME */
return dev;
if (dev->net)
return dev;
fail:
if (disk)
@ -71,6 +77,12 @@ grub_device_close (grub_device_t device)
if (device->disk)
grub_disk_close (device->disk);
if (device->net)
{
grub_free (device->net->server);
grub_free (device->net);
}
grub_free (device);
return grub_errno;

View file

@ -46,10 +46,6 @@ 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;
@ -254,6 +250,7 @@ grub_disk_open (const char *name)
disk = (grub_disk_t) grub_zalloc (sizeof (*disk));
if (! disk)
return 0;
disk->log_sector_size = GRUB_DISK_SECTOR_BITS;
p = find_part_sep (name);
if (p)
@ -293,6 +290,14 @@ grub_disk_open (const char *name)
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such disk");
goto fail;
}
if (disk->log_sector_size > GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS
|| disk->log_sector_size < GRUB_DISK_SECTOR_BITS)
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"sector sizes of %d bytes aren't supported yet",
(1 << disk->log_sector_size));
goto fail;
}
disk->dev = dev;
@ -384,21 +389,110 @@ grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector,
*sector += start;
}
if (disk->total_sectors <= *sector
|| ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
>> GRUB_DISK_SECTOR_BITS) > disk->total_sectors - *sector)
if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN
&& ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector
|| ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
>> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors
<< (disk->log_sector_size
- GRUB_DISK_SECTOR_BITS)) - *sector))
return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk");
return GRUB_ERR_NONE;
}
static inline grub_disk_addr_t
transform_sector (grub_disk_t disk, grub_disk_addr_t sector)
{
return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
}
/* Small read (less than cache size and not pass across cache unit boundaries).
sector is already adjusted and is divisible by cache unit size.
*/
static grub_err_t
grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, void *buf)
{
char *data;
char *tmp_buf;
/* Fetch the cache. */
data = grub_disk_cache_fetch (disk->dev->id, disk->id, sector);
if (data)
{
/* Just copy it! */
grub_memcpy (buf, data + offset, size);
grub_disk_cache_unlock (disk->dev->id, disk->id, sector);
return GRUB_ERR_NONE;
}
/* Allocate a temporary buffer. */
tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
if (! tmp_buf)
return grub_errno;
/* Otherwise read data from the disk actually. */
if (disk->total_sectors == GRUB_DISK_SIZE_UNKNOWN
|| sector + GRUB_DISK_CACHE_SIZE
< (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)))
{
grub_err_t err;
err = (disk->dev->read) (disk, transform_sector (disk, sector),
1 << (GRUB_DISK_CACHE_BITS
+ GRUB_DISK_SECTOR_BITS
- disk->log_sector_size), tmp_buf);
if (!err)
{
/* Copy it and store it in the disk cache. */
grub_memcpy (buf, tmp_buf + offset, size);
grub_disk_cache_store (disk->dev->id, disk->id,
sector, tmp_buf);
grub_free (tmp_buf);
return GRUB_ERR_NONE;
}
}
grub_errno = GRUB_ERR_NONE;
{
/* Uggh... Failed. Instead, just read necessary data. */
unsigned num;
grub_disk_addr_t aligned_sector;
sector += (offset >> GRUB_DISK_SECTOR_BITS);
offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1);
aligned_sector = (sector & ~((1 << (disk->log_sector_size
- GRUB_DISK_SECTOR_BITS))
- 1));
offset += ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS);
num = ((size + offset + (1 << (disk->log_sector_size))
- 1) >> (disk->log_sector_size));
tmp_buf = grub_malloc (num << disk->log_sector_size);
if (!tmp_buf)
return grub_errno;
if ((disk->dev->read) (disk, transform_sector (disk, aligned_sector),
num, tmp_buf))
{
grub_error_push ();
grub_dprintf ("disk", "%s read failed\n", disk->name);
grub_error_pop ();
return grub_errno;
}
grub_memcpy (buf, tmp_buf + offset, size);
return GRUB_ERR_NONE;
}
}
/* 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, void *buf)
{
char *tmp_buf;
unsigned real_offset;
grub_off_t real_offset;
grub_disk_addr_t real_sector;
grub_size_t real_size;
/* First of all, check if the region is within the disk. */
if (grub_disk_adjust_range (disk, &sector, &offset, size) != GRUB_ERR_NONE)
@ -410,126 +504,125 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
return grub_errno;
}
real_sector = sector;
real_offset = offset;
real_size = size;
/* Allocate a temporary buffer. */
tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
if (! tmp_buf)
return grub_errno;
/* Until SIZE is zero... */
while (size)
/* First read until first cache boundary. */
if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1)))
{
char *data;
grub_disk_addr_t start_sector;
grub_size_t len;
grub_size_t pos;
grub_err_t err;
grub_size_t len;
/* For reading bulk data. */
start_sector = sector & ~(GRUB_DISK_CACHE_SIZE - 1);
pos = (sector - start_sector) << GRUB_DISK_SECTOR_BITS;
len = ((GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS)
- pos - real_offset);
- pos - offset);
if (len > size)
len = size;
/* Fetch the cache. */
data = grub_disk_cache_fetch (disk->dev->id, disk->id, start_sector);
if (data)
{
/* Just copy it! */
grub_memcpy (buf, data + pos + real_offset, len);
grub_disk_cache_unlock (disk->dev->id, disk->id, start_sector);
}
else
{
/* Otherwise read data from the disk actually. */
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. */
unsigned num;
char *p;
grub_errno = GRUB_ERR_NONE;
num = ((size + real_offset + GRUB_DISK_SECTOR_SIZE - 1)
>> GRUB_DISK_SECTOR_BITS);
p = grub_realloc (tmp_buf, num << GRUB_DISK_SECTOR_BITS);
if (!p)
goto finish;
tmp_buf = p;
if ((disk->dev->read) (disk, sector, num, tmp_buf))
{
grub_error_push ();
grub_dprintf ("disk", "%s read failed\n", disk->name);
grub_error_pop ();
goto finish;
}
grub_memcpy (buf, tmp_buf + real_offset, size);
/* Call the read hook, if any. */
if (disk->read_hook)
while (size)
{
grub_size_t to_read = (size > GRUB_DISK_SECTOR_SIZE) ? GRUB_DISK_SECTOR_SIZE : size;
(disk->read_hook) (sector, real_offset,
to_read);
if (grub_errno != GRUB_ERR_NONE)
goto finish;
sector++;
size -= to_read - real_offset;
real_offset = 0;
}
/* This must be the end. */
goto finish;
}
/* Copy it and store it in the disk cache. */
grub_memcpy (buf, tmp_buf + pos + real_offset, len);
grub_disk_cache_store (disk->dev->id, disk->id,
start_sector, tmp_buf);
}
/* Call the read hook, if any. */
if (disk->read_hook)
{
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;
err = grub_disk_read_small (disk, start_sector,
offset + pos, len, buf);
if (err)
return err;
buf = (char *) buf + len;
size -= len;
real_offset = 0;
offset += len;
sector += (offset >> GRUB_DISK_SECTOR_BITS);
offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1);
}
finish:
/* Until SIZE is zero... */
while (size >= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS))
{
char *data = NULL;
grub_disk_addr_t agglomerate;
grub_err_t err;
grub_free (tmp_buf);
/* agglomerate read until we find a first cached entry. */
for (agglomerate = 0; agglomerate
< (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS));
agglomerate++)
{
data = grub_disk_cache_fetch (disk->dev->id, disk->id,
sector + (agglomerate
<< GRUB_DISK_CACHE_BITS));
if (data)
break;
}
if (data)
{
grub_memcpy ((char *) buf
+ (agglomerate << (GRUB_DISK_CACHE_BITS
+ GRUB_DISK_SECTOR_BITS)),
data, GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
grub_disk_cache_unlock (disk->dev->id, disk->id,
sector + (agglomerate
<< GRUB_DISK_CACHE_BITS));
}
if (agglomerate)
{
grub_disk_addr_t i;
err = (disk->dev->read) (disk, transform_sector (disk, sector),
agglomerate << (GRUB_DISK_CACHE_BITS
+ GRUB_DISK_SECTOR_BITS
- disk->log_sector_size),
buf);
if (err)
return err;
for (i = 0; i < agglomerate; i ++)
grub_disk_cache_store (disk->dev->id, disk->id,
sector + (i << GRUB_DISK_CACHE_BITS),
(char *) buf
+ (i << (GRUB_DISK_CACHE_BITS
+ GRUB_DISK_SECTOR_BITS)));
sector += agglomerate << GRUB_DISK_CACHE_BITS;
size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
buf = (char *) buf
+ (agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS));
}
if (data)
{
sector += GRUB_DISK_CACHE_SIZE;
buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS);
}
}
/* And now read the last part. */
if (size)
{
grub_err_t err;
err = grub_disk_read_small (disk, sector, 0, size, buf);
if (err)
return err;
}
/* Call the read hook, if any. */
if (disk->read_hook)
{
grub_disk_addr_t s = real_sector;
grub_size_t l = real_size;
grub_off_t o = real_offset;
while (l)
{
(disk->read_hook) (s, o,
((l > GRUB_DISK_SECTOR_SIZE)
? GRUB_DISK_SECTOR_SIZE
: l));
s++;
l -= GRUB_DISK_SECTOR_SIZE - o;
o = 0;
}
}
return grub_errno;
}
@ -539,25 +632,31 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, const void *buf)
{
unsigned real_offset;
grub_disk_addr_t aligned_sector;
grub_dprintf ("disk", "Writing `%s'...\n", disk->name);
if (grub_disk_adjust_range (disk, &sector, &offset, size) != GRUB_ERR_NONE)
return -1;
real_offset = offset;
aligned_sector = (sector & ~((1 << (disk->log_sector_size
- GRUB_DISK_SECTOR_BITS)) - 1));
real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS);
sector = aligned_sector;
while (size)
{
if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0))
if (real_offset != 0 || (size < (1U << disk->log_sector_size)
&& size != 0))
{
char tmp_buf[GRUB_DISK_SECTOR_SIZE];
char tmp_buf[1 << disk->log_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)
if (grub_disk_read (disk, sector,
0, (1 << disk->log_sector_size), tmp_buf)
!= GRUB_ERR_NONE)
{
disk->partition = part;
@ -565,7 +664,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
}
disk->partition = part;
len = GRUB_DISK_SECTOR_SIZE - real_offset;
len = (1 << disk->log_sector_size) - real_offset;
if (len > size)
len = size;
@ -576,7 +675,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE)
goto finish;
sector++;
sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS));
buf = (char *) buf + len;
size -= len;
real_offset = 0;
@ -586,8 +685,8 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t len;
grub_size_t n;
len = size & ~(GRUB_DISK_SECTOR_SIZE - 1);
n = size >> GRUB_DISK_SECTOR_BITS;
len = size & ~((1 << disk->log_sector_size) - 1);
n = size >> disk->log_sector_size;
if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE)
goto finish;
@ -610,6 +709,8 @@ grub_disk_get_size (grub_disk_t disk)
{
if (disk->partition)
return grub_partition_get_len (disk->partition);
else if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN)
return disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
else
return disk->total_sectors;
return GRUB_DISK_SIZE_UNKNOWN;
}

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)
@ -620,13 +688,11 @@ grub_dl_load_file (const char *filename)
grub_file_close (file);
mod = grub_dl_load_core (core, size);
grub_free (core);
if (! mod)
{
grub_free (core);
return 0;
}
return 0;
mod->ref_count = 0;
mod->ref_count--;
return mod;
}
@ -683,8 +749,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
@ -740,3 +746,51 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
dp = (grub_efi_device_path_t *) ((char *) dp + len);
}
}
/* Compare device paths. */
int
grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
const grub_efi_device_path_t *dp2)
{
if (! dp1 || ! dp2)
/* Return non-zero. */
return 1;
while (1)
{
grub_efi_uint8_t type1, type2;
grub_efi_uint8_t subtype1, subtype2;
grub_efi_uint16_t len1, len2;
int ret;
type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
if (type1 != type2)
return (int) type2 - (int) type1;
subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
if (subtype1 != subtype2)
return (int) subtype1 - (int) subtype2;
len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
if (len1 != len2)
return (int) len1 - (int) len2;
ret = grub_memcmp (dp1, dp2, len1);
if (ret != 0)
return ret;
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
break;
dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
}
return 0;
}

View file

@ -42,84 +42,28 @@ grub_efi_init (void)
grub_efidisk_init ();
}
void (*grub_efi_net_config) (grub_efi_handle_t hnd,
char **device,
char **path);
void
grub_efi_set_prefix (void)
grub_machine_get_bootlocation (char **device, char **path)
{
grub_efi_loaded_image_t *image = NULL;
char *device = NULL;
char *path = NULL;
char *p;
{
char *pptr = NULL;
if (grub_prefix[0] == '(')
{
pptr = grub_strrchr (grub_prefix, ')');
if (pptr)
{
device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1);
pptr++;
}
}
if (!pptr)
pptr = grub_prefix;
if (pptr[0])
path = grub_strdup (pptr);
}
image = grub_efi_get_loaded_image (grub_efi_image_handle);
if (!image)
return;
*device = grub_efidisk_get_device_name (image->device_handle);
*path = grub_efi_get_filename (image->file_path);
if (!*device && grub_efi_net_config)
grub_efi_net_config (image->device_handle, device, path);
if ((!device || device[0] == ',' || !device[0]) || !path)
image = grub_efi_get_loaded_image (grub_efi_image_handle);
if (image)
{
if (!device)
device = grub_efidisk_get_device_name (image->device_handle);
else if (device[0] == ',' || !device[0])
{
/* We have a partition, but still need to fill in the drive. */
char *image_device, *comma, *new_device;
image_device = grub_efidisk_get_device_name (image->device_handle);
comma = grub_strchr (image_device, ',');
if (comma)
{
char *drive = grub_strndup (image_device, comma - image_device);
new_device = grub_xasprintf ("%s%s", drive, device);
grub_free (drive);
}
else
new_device = grub_xasprintf ("%s%s", image_device, device);
grub_free (image_device);
grub_free (device);
device = new_device;
}
}
if (image && !path)
{
char *p;
path = grub_efi_get_filename (image->file_path);
/* Get the directory. */
p = grub_strrchr (path, '/');
if (p)
*p = '\0';
}
if (device && path)
{
char *prefix;
prefix = grub_xasprintf ("(%s)%s", device, path);
if (prefix)
{
grub_env_set ("prefix", prefix);
grub_free (prefix);
}
}
grub_free (device);
grub_free (path);
/* Get the directory. */
p = grub_strrchr (*path, '/');
if (p)
*p = '\0';
}
void

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

@ -220,9 +220,6 @@ grub_find_root_device_from_mountinfo (const char *dir, char **relroot)
/* Now scan visible mounts for the ones we're interested in. */
for (i = entry_len - 1; i >= 0; i--)
{
if (entries[i].major != 0)
continue; /* not a virtual device */
if (!*entries[i].device)
continue;
@ -361,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
@ -612,20 +609,31 @@ grub_guess_root_device (const char *dir)
if (os_dev)
{
if (stat (os_dev, &st) >= 0)
dev = st.st_rdev;
else
grub_util_error ("cannot stat `%s'", os_dev);
free (os_dev);
}
else
{
if (stat (dir, &st) >= 0)
dev = st.st_dev;
else
grub_util_error ("cannot stat `%s'", dir);
char *tmp = os_dev;
os_dev = canonicalize_file_name (os_dev);
free (tmp);
}
if (os_dev)
{
int dm = (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) == 0);
int root = (strcmp (os_dev, "/dev/root") == 0);
if (!dm && !root)
return os_dev;
if (stat (os_dev, &st) >= 0)
{
free (os_dev);
dev = st.st_rdev;
return grub_find_device (dm ? "/dev/mapper" : "/dev", dev);
}
free (os_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, dev);

View file

@ -43,6 +43,7 @@
#ifdef __linux__
# include <sys/ioctl.h> /* ioctl */
# include <sys/mount.h>
# if !defined(__GLIBC__) || \
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
/* Maybe libc doesn't have large file support. */
@ -269,6 +270,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk,
# else
unsigned long long nr;
# endif
int sector_size;
int fd;
fd = open (map[drive].device, O_RDONLY);
@ -301,16 +303,28 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk,
goto fail;
}
if (ioctl (fd, BLKSSZGET, &sector_size))
{
close (fd);
goto fail;
}
close (fd);
if (sector_size & (sector_size - 1) || !sector_size)
goto fail;
for (disk->log_sector_size = 0;
(1 << disk->log_sector_size) < sector_size;
disk->log_sector_size++);
# if defined (__APPLE__)
disk->total_sectors = nr;
# elif defined(__NetBSD__)
disk->total_sectors = label.d_secperunit;
# else
disk->total_sectors = nr / 512;
disk->total_sectors = nr >> disk->log_sector_size;
if (nr % 512)
if (nr & ((1 << disk->log_sector_size) - 1))
grub_util_error ("unaligned device size");
# endif
@ -327,7 +341,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk,
if (stat (map[drive].device, &st) < 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device);
disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
disk->total_sectors = st.st_size >> disk->log_sector_size;
grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
@ -558,7 +572,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 +580,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 +589,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 +625,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);
@ -686,6 +713,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
}
close (data->fd);
data->fd = -1;
}
/* Open the partition. */
@ -744,6 +772,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
#endif
}
close (data->fd);
data->fd = -1;
}
fd = open (map[disk->id].device, flags);
@ -791,7 +820,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
loff_t *, res, uint, wh);
offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
offset = (loff_t) sector << disk->log_sector_size;
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
{
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
@ -801,7 +830,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
}
#else
{
off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
off_t offset = (off_t) sector << disk->log_sector_size;
if (lseek (fd, offset, SEEK_SET) != offset)
{
@ -901,19 +930,20 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
sectors that are read together with the MBR in one read. It
should only remap the MBR, so we split the read in two
parts. -jochen */
if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
if (nread (fd, buf, (1 << disk->log_sector_size))
!= (1 << disk->log_sector_size))
{
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
return grub_errno;
}
buf += GRUB_DISK_SECTOR_SIZE;
buf += (1 << disk->log_sector_size);
size--;
}
#endif /* __linux__ */
if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
if (nread (fd, buf, size << disk->log_sector_size)
!= (ssize_t) (size << disk->log_sector_size))
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
return grub_errno;
@ -946,8 +976,8 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
if (fd < 0)
return grub_errno;
if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
if (nwrite (fd, buf, size << disk->log_sector_size)
!= (ssize_t) (size << disk->log_sector_size))
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
return grub_errno;
@ -1408,7 +1438,8 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
if (tree)
dm_tree_free (tree);
free (path);
char *ret = grub_find_device (NULL, (major << 8) | minor);
char *ret = grub_find_device ("/dev/mapper",
(major << 8) | minor);
return ret;
}
@ -1837,7 +1868,12 @@ grub_util_biosdisk_is_floppy (grub_disk_t disk)
/* Shouldn't happen either. */
if (fstat (fd, &st) < 0)
return 0;
{
close (fd);
return 0;
}
close (fd);
#if defined(__NetBSD__)
if (major(st.st_rdev) == RAW_FLOPPY_MAJOR)

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

@ -49,7 +49,7 @@
static jmp_buf main_env;
/* Store the prefix specified by an argument. */
static char *prefix = NULL;
static char *root_dev = NULL, *dir = NULL;
int grub_no_autoload;
@ -71,11 +71,10 @@ grub_machine_init (void)
}
void
grub_machine_set_prefix (void)
grub_machine_get_bootlocation (char **device, char **path)
{
grub_env_set ("prefix", prefix);
free (prefix);
prefix = 0;
*device = root_dev;
*path = dir;
}
void
@ -84,6 +83,8 @@ grub_machine_fini (void)
grub_console_fini ();
}
char grub_prefix[64] = "";
static struct option options[] =
@ -132,22 +133,24 @@ void grub_emu_init (void);
int
main (int argc, char *argv[])
{
char *root_dev = 0;
char *dir = DEFAULT_DIRECTORY;
char *dev_map = DEFAULT_DEVICE_MAP;
volatile int hold = 0;
int opt;
set_program_name (argv[0]);
dir = xstrdup (DEFAULT_DIRECTORY);
while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1)
switch (opt)
{
case 'r':
root_dev = optarg;
free (root_dev);
root_dev = xstrdup (optarg);
break;
case 'd':
dir = optarg;
free (dir);
dir = xstrdup (optarg);
break;
case 'm':
dev_map = optarg;
@ -219,9 +222,6 @@ main (int argc, char *argv[])
dir = xstrdup (dir);
else
dir = grub_make_system_path_relative_to_its_root (dir);
prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1);
sprintf (prefix, "(%s)%s", root_dev, dir);
free (dir);
/* Start GRUB! */
if (setjmp (main_env) == 0)

View file

@ -86,6 +86,8 @@ grub_util_raid_getmembers (const char *name, int bootable)
devicelist[j] = NULL;
close (fd);
return devicelist;
}

View file

@ -20,10 +20,13 @@
#include <grub/misc.h>
#include <grub/err.h>
#include <grub/file.h>
#include <grub/net.h>
#include <grub/mm.h>
#include <grub/fs.h>
#include <grub/device.h>
void (*EXPORT_VAR (grub_grubnet_fini)) (void);
grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX];
@ -148,7 +151,6 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len)
if (len == 0)
return 0;
res = (file->fs->read) (file, buf, len);
if (res > 0)
file->offset += res;
@ -179,8 +181,9 @@ 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;
}

View file

@ -94,7 +94,7 @@ grub_fs_probe (grub_device_t device)
count--;
}
}
else if (device->net->fs)
else if (device->net && device->net->fs)
return device->net->fs;
grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem");

View file

@ -107,10 +107,9 @@ grub_machine_init (void)
}
void
grub_machine_set_prefix (void)
grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
char **path __attribute__ ((unused)))
{
/* Initialize the prefix. */
grub_env_set ("prefix", grub_prefix);
}
void

View file

@ -87,3 +87,4 @@ codestart:
*/
#include "../realmode.S"
#include "../int.S"

View file

@ -39,9 +39,3 @@ grub_machine_fini (void)
{
grub_efi_fini ();
}
void
grub_machine_set_prefix (void)
{
grub_efi_set_prefix ();
}

140
grub-core/kern/i386/int.S Normal file
View file

@ -0,0 +1,140 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010,2011 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/>.
*/
FUNCTION(grub_bios_interrupt)
pushf
cli
#ifndef GRUB_MACHINE_PCBIOS
sidt protidt
#endif
popf
pushl %ebp
pushl %ecx
pushl %eax
pushl %ebx
pushl %esi
pushl %edi
pushl %edx
movb %al, intno
movl (%edx), %eax
movl %eax, LOCAL(bios_register_eax)
movw 4(%edx), %ax
movw %ax, LOCAL(bios_register_es)
movw 6(%edx), %ax
movw %ax, LOCAL(bios_register_ds)
movw 8(%edx), %ax
movw %ax, LOCAL(bios_register_flags)
movl 12(%edx), %ebx
movl 16(%edx), %ecx
movl 20(%edx), %edi
movl 24(%edx), %esi
movl 28(%edx), %edx
call prot_to_real
.code16
pushf
cli
#ifndef GRUB_MACHINE_PCBIOS
lidt realidt
#endif
mov %ds, %ax
push %ax
/* movw imm16, %ax*/
.byte 0xb8
LOCAL(bios_register_es):
.short 0
movw %ax, %es
/* movw imm16, %ax*/
.byte 0xb8
LOCAL(bios_register_ds):
.short 0
movw %ax, %ds
/* movw imm16, %ax*/
.byte 0xb8
LOCAL(bios_register_flags):
.short 0
push %ax
popf
/* movl imm32, %eax*/
.byte 0x66, 0xb8
LOCAL(bios_register_eax):
.long 0
/* int imm8. */
.byte 0xcd
intno:
.byte 0
movl %eax, %cs:LOCAL(bios_register_eax)
movw %ds, %ax
movw %ax, %cs:LOCAL(bios_register_ds)
pop %ax
mov %ax, %ds
pushf
pop %ax
movw %ax, LOCAL(bios_register_flags)
mov %es, %ax
movw %ax, LOCAL(bios_register_es)
popf
DATA32 call real_to_prot
.code32
popl %eax
movl %ebx, 12(%eax)
movl %ecx, 16(%eax)
movl %edi, 20(%eax)
movl %esi, 24(%eax)
movl %edx, 28(%eax)
movl %eax, %edx
movl LOCAL(bios_register_eax), %eax
movl %eax, (%edx)
movw LOCAL(bios_register_es), %ax
movw %ax, 4(%edx)
movw LOCAL(bios_register_ds), %ax
movw %ax, 6(%edx)
movw LOCAL(bios_register_flags), %ax
movw %ax, 8(%edx)
popl %edi
popl %esi
popl %ebx
popl %eax
popl %ecx
popl %ebp
#ifndef GRUB_MACHINE_PCBIOS
lidt protidt
#endif
ret
#ifndef GRUB_MACHINE_PCBIOS
realidt:
.word 0x100
.long 0
protidt:
.word 0
.long 0
#endif

View file

@ -45,52 +45,41 @@ struct mem_region
static struct mem_region mem_regions[MAX_REGIONS];
static int num_regions;
static char *
make_install_device (void)
void (*grub_pc_net_config) (char **device, char **path);
void
grub_machine_get_bootlocation (char **device, char **path)
{
char *ptr;
/* No hardcoded root partition - make it from the boot drive and the
partition number encoded at the install time. */
if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL)
{
if (grub_pc_net_config)
grub_pc_net_config (device, path);
return;
}
/* XXX: This should be enough. */
char dev[100], *ptr = dev;
#define DEV_SIZE 100
*device = grub_malloc (DEV_SIZE);
ptr = *device;
grub_snprintf (*device, DEV_SIZE,
"%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f',
grub_boot_drive & 0x7f);
ptr += grub_strlen (ptr);
if (grub_prefix[0] != '(')
{
/* No hardcoded root partition - make it from the boot drive and the
partition number encoded at the install time. */
if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL)
{
grub_strcpy (dev, "(pxe");
ptr += sizeof ("(pxe") - 1;
}
else
{
grub_snprintf (dev, sizeof (dev),
"(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f',
grub_boot_drive & 0x7f);
ptr += grub_strlen (ptr);
if (grub_install_dos_part >= 0)
grub_snprintf (ptr, DEV_SIZE - (ptr - *device),
",%u", grub_install_dos_part + 1);
ptr += grub_strlen (ptr);
if (grub_install_dos_part >= 0)
grub_snprintf (ptr, sizeof (dev) - (ptr - dev),
",%u", grub_install_dos_part + 1);
ptr += grub_strlen (ptr);
if (grub_install_bsd_part >= 0)
grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u",
grub_install_bsd_part + 1);
ptr += grub_strlen (ptr);
}
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;
if (grub_install_bsd_part >= 0)
grub_snprintf (ptr, DEV_SIZE - (ptr - *device), ",%u",
grub_install_bsd_part + 1);
ptr += grub_strlen (ptr);
*ptr = 0;
}
/* Add a memory region. */
@ -211,13 +200,6 @@ grub_machine_init (void)
grub_tsc_init ();
}
void
grub_machine_set_prefix (void)
{
/* Initialize the prefix. */
grub_env_set ("prefix", make_install_device ());
}
void
grub_machine_fini (void)
{

View file

@ -910,102 +910,4 @@ FUNCTION(grub_pxe_call)
popl %ebp
ret
FUNCTION(grub_bios_interrupt)
pushl %ebp
pushl %ecx
pushl %eax
pushl %ebx
pushl %esi
pushl %edi
pushl %edx
movb %al, intno
movl (%edx), %eax
movl %eax, LOCAL(bios_register_eax)
movw 4(%edx), %ax
movw %ax, LOCAL(bios_register_es)
movw 6(%edx), %ax
movw %ax, LOCAL(bios_register_ds)
movw 8(%edx), %ax
movw %ax, LOCAL(bios_register_flags)
movl 12(%edx), %ebx
movl 16(%edx), %ecx
movl 20(%edx), %edi
movl 24(%edx), %esi
movl 28(%edx), %edx
call prot_to_real
.code16
mov %ds, %ax
push %ax
/* movw imm16, %ax*/
.byte 0xb8
LOCAL(bios_register_es):
.short 0
movw %ax, %es
/* movw imm16, %ax*/
.byte 0xb8
LOCAL(bios_register_ds):
.short 0
movw %ax, %ds
/* movw imm16, %ax*/
.byte 0xb8
LOCAL(bios_register_flags):
.short 0
push %ax
popf
/* movl imm32, %eax*/
.byte 0x66, 0xb8
LOCAL(bios_register_eax):
.long 0
/* int imm8. */
.byte 0xcd
intno:
.byte 0
movl %eax, %cs:LOCAL(bios_register_eax)
movw %ds, %ax
movw %ax, %cs:LOCAL(bios_register_ds)
pop %ax
mov %ax, %ds
pushf
pop %ax
movw %ax, LOCAL(bios_register_flags)
mov %es, %ax
movw %ax, LOCAL(bios_register_es)
DATA32 call real_to_prot
.code32
popl %eax
movl %ebx, 12(%eax)
movl %ecx, 16(%eax)
movl %edi, 20(%eax)
movl %esi, 24(%eax)
movl %edx, 28(%eax)
movl %eax, %edx
movl LOCAL(bios_register_eax), %eax
movl %eax, (%edx)
movw LOCAL(bios_register_es), %ax
movw %ax, 4(%edx)
movw LOCAL(bios_register_ds), %ax
movw %ax, 6(%edx)
movw LOCAL(bios_register_flags), %ax
movw %ax, 8(%edx)
popl %edi
popl %esi
popl %ebx
popl %eax
popl %ecx
popl %ebp
ret
#include "../int.S"

View file

@ -41,8 +41,11 @@ static grub_uint64_t mem_size, above_4g;
void
grub_machine_mmap_init ()
{
mem_size = ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH)) << 24
| ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW)) << 16;
grub_uint8_t high, low, b, c, d;
grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH, &high);
grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW, &low);
mem_size = ((grub_uint64_t) high) << 24
| ((grub_uint64_t) low) << 16;
if (mem_size > 0)
{
/* Don't ask... */
@ -50,15 +53,19 @@ grub_machine_mmap_init ()
}
else
{
grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH, &high);
grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW, &low);
mem_size
= ((((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH)) << 18)
| ((grub_uint64_t) (grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW)) << 10))
= ((((grub_uint64_t) high) << 18) | (((grub_uint64_t) low) << 10))
+ 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_cmos_read (0x5b, &b);
grub_cmos_read (0x5c, &c);
grub_cmos_read (0x5d, &d);
above_4g = (((grub_uint64_t) b) << 16)
| (((grub_uint64_t) c) << 24)
| (((grub_uint64_t) d) << 32);
}
grub_err_t

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,54 @@
/* 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_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

@ -60,6 +60,10 @@ grub_ieee1275_find_options (void)
int is_olpc = 0;
int is_qemu = 0;
#ifdef __sparc__
grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
#endif
grub_ieee1275_finddevice ("/", &root);
grub_ieee1275_finddevice ("/options", &options);
grub_ieee1275_finddevice ("/openprom", &openprom);

View file

@ -31,8 +31,12 @@
#include <grub/ieee1275/console.h>
#include <grub/ieee1275/ofdisk.h>
#include <grub/ieee1275/ieee1275.h>
#include <grub/net.h>
#include <grub/offsets.h>
#include <grub/memory.h>
#ifdef __sparc__
#include <grub/machine/kernel.h>
#endif
/* The minimal heap size we can live with. */
#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024)
@ -47,6 +51,10 @@
extern char _start[];
extern char _end[];
#ifdef __sparc__
grub_addr_t grub_ieee1275_original_stack;
#endif
void
grub_exit (void)
{
@ -68,37 +76,51 @@ grub_translate_ieee1275_path (char *filepath)
}
}
void (*grub_ieee1275_net_config) (const char *dev,
char **device,
char **path);
void
grub_machine_set_prefix (void)
grub_machine_get_bootlocation (char **device, char **path)
{
char bootpath[64]; /* XXX check length */
char *filename;
char *prefix;
if (grub_prefix[0])
{
grub_env_set ("prefix", grub_prefix);
/* Prefix is hardcoded in the core image. */
return;
}
char *type;
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath,
sizeof (bootpath), 0))
{
/* Should never happen. */
grub_printf ("/chosen/bootpath property missing!\n");
grub_env_set ("prefix", "");
return;
}
/* Transform an OF device path to a GRUB path. */
prefix = grub_ieee1275_encode_devname (bootpath);
type = grub_ieee1275_get_device_type (bootpath);
if (type && grub_strcmp (type, "network") == 0)
{
char *dev, *canon;
char *ptr;
dev = grub_ieee1275_get_aliasdevname (bootpath);
canon = grub_ieee1275_canonicalise_devname (dev);
ptr = canon + grub_strlen (canon) - 1;
while (ptr > canon && (*ptr == ',' || *ptr == ':'))
ptr--;
ptr++;
*ptr = 0;
if (grub_ieee1275_net_config)
grub_ieee1275_net_config (canon, device, path);
grub_free (dev);
grub_free (canon);
}
else
*device = grub_ieee1275_encode_devname (bootpath);
grub_free (type);
filename = grub_ieee1275_get_filename (bootpath);
if (filename)
{
char *newprefix;
char *lastslash = grub_strrchr (filename, '\\');
/* Truncate at last directory. */
@ -107,23 +129,22 @@ grub_machine_set_prefix (void)
*lastslash = '\0';
grub_translate_ieee1275_path (filename);
newprefix = grub_xasprintf ("%s%s", prefix, filename);
if (newprefix)
{
grub_free (prefix);
prefix = newprefix;
}
*path = filename;
}
}
grub_env_set ("prefix", prefix);
grub_free (filename);
grub_free (prefix);
}
/* Claim some available memory in the first /memory node. */
static void grub_claim_heap (void)
#ifdef __sparc__
static void
grub_claim_heap (void)
{
grub_mm_init_region ((void *) (grub_modules_get_end ()
+ GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000);
}
#else
static void
grub_claim_heap (void)
{
unsigned long total = 0;
@ -191,23 +212,14 @@ static void grub_claim_heap (void)
else
grub_machine_mmap_iterate (heap_init);
}
#endif
static grub_uint64_t ieee1275_get_time_ms (void);
void
grub_machine_init (void)
static void
grub_parse_cmdline (void)
{
char args[256];
grub_ssize_t actual;
char args[256];
grub_ieee1275_init ();
grub_console_init_early ();
grub_claim_heap ();
grub_console_init_lately ();
grub_ofdisk_init ();
/* Process commandline. */
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
sizeof args, &actual) == 0
&& actual > 1)
@ -240,6 +252,21 @@ grub_machine_init (void)
}
}
}
}
static grub_uint64_t ieee1275_get_time_ms (void);
void
grub_machine_init (void)
{
grub_ieee1275_init ();
grub_console_init_early ();
grub_claim_heap ();
grub_console_init_lately ();
grub_ofdisk_init ();
grub_parse_cmdline ();
grub_install_get_time_ms (ieee1275_get_time_ms);
}

View file

@ -22,11 +22,14 @@
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/ieee1275/ieee1275.h>
#include <grub/net.h>
enum grub_ieee1275_parse_type
{
GRUB_PARSE_FILENAME,
GRUB_PARSE_PARTITION,
GRUB_PARSE_DEVICE,
GRUB_PARSE_DEVICE_TYPE
};
/* Walk children of 'devpath', calling hook for each. */
@ -317,14 +320,9 @@ 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))
@ -339,48 +337,92 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
goto fail;
}
if (!grub_strcmp ("block", type))
switch (ptype)
{
/* The syntax of the device arguments is defined in the CHRP and PReP
IEEE1275 bindings: "[partition][,[filename]]". */
char *comma = grub_strchr (args, ',');
case GRUB_PARSE_DEVICE:
ret = grub_strdup (device);
break;
case GRUB_PARSE_DEVICE_TYPE:
ret = grub_strdup (type);
break;
case GRUB_PARSE_FILENAME:
{
char *comma;
char *args;
if (ptype == GRUB_PARSE_FILENAME)
{
if (comma)
{
char *filepath = comma + 1;
if (grub_strcmp ("block", type) != 0)
goto unknown;
/* Make sure filepath has leading backslash. */
if (filepath[0] != '\\')
ret = grub_xasprintf ("\\%s", filepath);
else
ret = grub_strdup (filepath);
args = grub_ieee1275_get_devargs (path);
if (!args)
/* Shouldn't happen. */
return 0;
/* The syntax of the device arguments is defined in the CHRP and PReP
IEEE1275 bindings: "[partition][,[filename]]". */
comma = grub_strchr (args, ',');
if (comma)
{
char *filepath = comma + 1;
/* Make sure filepath has leading backslash. */
if (filepath[0] != '\\')
ret = grub_xasprintf ("\\%s", filepath);
else
ret = grub_strdup (filepath);
}
grub_free (args);
}
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>". */
break;
case GRUB_PARSE_PARTITION:
{
char *comma;
char *args;
if (grub_strcmp ("block", type) != 0)
goto unknown;
args = grub_ieee1275_get_devargs (path);
if (!args)
/* Shouldn't happen. */
return 0;
comma = grub_strchr (args, ',');
if (!comma)
ret = grub_strdup (args);
else
ret = grub_strndup (args, (grub_size_t)(comma - args));
/* Consistently provide numbered partitions to GRUB.
OpenBOOT traditionally uses alphabetical partition
specifiers. */
if (ret[0] >= 'a' && ret[0] <= 'z')
ret[0] = '1' + (ret[0] - 'a');
grub_free (args);
}
break;
default:
unknown:
grub_printf ("Unsupported type %s for device %s\n", type, device);
}
fail:
grub_free (device);
grub_free (args);
return ret;
}
char *
grub_ieee1275_get_device_type (const char *path)
{
return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE_TYPE);
}
char *
grub_ieee1275_get_aliasdevname (const char *path)
{
return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE);
}
char *
grub_ieee1275_get_filename (const char *path)
{
@ -467,3 +509,4 @@ grub_ieee1275_canonicalise_devname (const char *path)
grub_free (buf);
return NULL;
}

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)
{
@ -129,27 +129,74 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
return grub_strdup (val);
}
/* Set the root device according to the dl prefix. */
static void
grub_set_root_dev (void)
grub_set_prefix_and_root (void)
{
const char *prefix;
char *device = NULL;
char *path = NULL;
char *fwdevice = NULL;
char *fwpath = NULL;
grub_register_variable_hook ("root", 0, grub_env_write_root);
prefix = grub_env_get ("prefix");
{
char *pptr = NULL;
if (grub_prefix[0] == '(')
{
pptr = grub_strrchr (grub_prefix, ')');
if (pptr)
{
device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1);
pptr++;
}
}
if (!pptr)
pptr = grub_prefix;
if (pptr[0])
path = grub_strdup (pptr);
}
if ((!device || device[0] == ',' || !device[0]) || !path)
grub_machine_get_bootlocation (&fwdevice, &fwpath);
if (prefix)
if (!device && fwdevice)
device = fwdevice;
else if (fwdevice && (device[0] == ',' || !device[0]))
{
char *dev;
/* We have a partition, but still need to fill in the drive. */
char *comma, *new_device;
dev = grub_file_get_device_name (prefix);
if (dev)
comma = grub_strchr (fwdevice, ',');
if (comma)
{
grub_env_set ("root", dev);
grub_free (dev);
char *drive = grub_strndup (fwdevice, comma - fwdevice);
new_device = grub_xasprintf ("%s%s", drive, device);
grub_free (drive);
}
else
new_device = grub_xasprintf ("%s%s", fwdevice, device);
grub_free (fwdevice);
grub_free (device);
device = new_device;
}
if (fwpath && !path)
path = fwpath;
if (device)
{
char *prefix;
prefix = grub_xasprintf ("(%s)%s", device, path ? : "");
if (prefix)
{
grub_env_set ("prefix", prefix);
grub_free (prefix);
}
grub_env_set ("root", device);
}
grub_free (device);
grub_free (path);
grub_print_error ();
}
/* Load the normal mode module and execute the normal mode if possible. */
@ -159,7 +206,7 @@ grub_load_normal_mode (void)
/* Load the module. */
grub_dl_load ("normal");
/* Something went wrong. Print errors here to let user know why we're entering rescue mode. */
/* Print errors if any. */
grub_print_error ();
grub_errno = 0;
@ -187,8 +234,7 @@ grub_main (void)
/* It is better to set the root device as soon as possible,
for convenience. */
grub_machine_set_prefix ();
grub_set_root_dev ();
grub_set_prefix_and_root ();
grub_env_export ("root");
grub_env_export ("prefix");

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_machine_get_bootlocation (char **device __attribute__ ((unused)),
char **path __attribute__ ((unused)))
{
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

@ -1,58 +0,0 @@
#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/cpu/kernel.h>
#define RAMSIZE (*(grub_uint32_t *) ((16 << 20) - 264))
grub_uint32_t
grub_get_rtc (void)
{
static int calln = 0;
return calln++;
}
void
grub_machine_init (void)
{
grub_mm_init_region ((void *) GRUB_MACHINE_MEMORY_USABLE,
RAMSIZE - (GRUB_MACHINE_MEMORY_USABLE & 0x7fffffff));
grub_install_get_time_ms (grub_rtc_get_time_ms);
}
void
grub_machine_fini (void)
{
}
void
grub_exit (void)
{
while (1);
}
void
grub_halt (void)
{
while (1);
}
void
grub_reboot (void)
{
while (1);
}
grub_err_t
grub_machine_mmap_iterate (grub_memory_hook_t hook)
{
hook (0, RAMSIZE, GRUB_MEMORY_AVAILABLE);
return GRUB_ERR_NONE;
}

View file

@ -0,0 +1,121 @@
#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/memory.h>
#include <grub/machine/kernel.h>
#include <grub/cpu/memory.h>
#include <grub/memory.h>
extern void grub_serial_init (void);
extern void grub_terminfo_init (void);
extern void grub_at_keyboard_init (void);
extern void grub_video_init (void);
extern void grub_bitmap_init (void);
extern void grub_font_init (void);
extern void grub_gfxterm_init (void);
extern void grub_at_keyboard_init (void);
extern void grub_serial_init (void);
extern void grub_terminfo_init (void);
extern void grub_keylayouts_init (void);
extern void grub_boot_init (void);
extern void grub_vga_text_init (void);
static inline int
probe_mem (grub_addr_t addr)
{
volatile grub_uint8_t *ptr = (grub_uint8_t *) (0xa0000000 | addr);
grub_uint8_t c = *ptr;
*ptr = 0xAA;
if (*ptr != 0xAA)
return 0;
*ptr = 0x55;
if (*ptr != 0x55)
return 0;
*ptr = c;
return 1;
}
void
grub_machine_init (void)
{
grub_addr_t modend;
if (grub_arch_memsize == 0)
{
int i;
for (i = 27; i >= 0; i--)
if (probe_mem (grub_arch_memsize | (1 << i)))
grub_arch_memsize |= (1 << i);
grub_arch_memsize++;
}
/* 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_video_init ();
grub_bitmap_init ();
grub_font_init ();
grub_keylayouts_init ();
grub_at_keyboard_init ();
grub_qemu_init_cirrus ();
grub_vga_text_init ();
grub_terminfo_init ();
grub_serial_init ();
grub_boot_init ();
grub_gfxterm_init ();
}
void
grub_machine_fini (void)
{
}
void
grub_exit (void)
{
while (1);
}
void
grub_halt (void)
{
while (1);
}
void
grub_reboot (void)
{
while (1);
}
grub_err_t
grub_machine_mmap_iterate (grub_memory_hook_t hook)
{
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,7 +597,7 @@ grub_reverse (char *str)
/* Divide N by D, return the quotient, and store the remainder in *R. */
grub_uint64_t
grub_divmod64_full (grub_uint64_t n, grub_uint64_t d, grub_uint64_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
@ -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;
@ -513,7 +515,7 @@ grub_debug_malloc (const char *file, int line, grub_size_t size)
void *ptr;
if (grub_mm_debug)
grub_printf ("%s:%d: malloc (0x%zx) = ", file, line, size);
grub_printf ("%s:%d: malloc (0x%" PRIxGRUB_SIZE ") = ", file, line, size);
ptr = grub_malloc (size);
if (grub_mm_debug)
grub_printf ("%p\n", ptr);
@ -526,7 +528,7 @@ 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);
grub_printf ("%s:%d: zalloc (0x%" PRIxGRUB_SIZE ") = ", file, line, size);
ptr = grub_zalloc (size);
if (grub_mm_debug)
grub_printf ("%p\n", ptr);
@ -545,7 +547,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%zx) = ", file, line, ptr, size);
grub_printf ("%s:%d: realloc (%p, 0x%" PRIxGRUB_SIZE ") = ", file, line, ptr, size);
ptr = grub_realloc (ptr, size);
if (grub_mm_debug)
grub_printf ("%p\n", ptr);
@ -559,8 +561,8 @@ grub_debug_memalign (const char *file, int line, grub_size_t align,
void *ptr;
if (grub_mm_debug)
grub_printf ("%s:%d: memalign (0x%zx, 0x%zx) = ",
file, line, align, size);
grub_printf ("%s:%d: memalign (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE
") = ", file, line, align, size);
ptr = grub_memalign (align, size);
if (grub_mm_debug)
grub_printf ("%p\n", ptr);

View file

@ -1,174 +0,0 @@
/* init.c -- Initialize GRUB on 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/kernel.h>
#include <grub/mm.h>
#include <grub/env.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/time.h>
#include <grub/machine/boot.h>
#include <grub/ieee1275/console.h>
#include <grub/machine/kernel.h>
#include <grub/machine/time.h>
#include <grub/ieee1275/ofdisk.h>
#include <grub/ieee1275/ieee1275.h>
grub_addr_t grub_ieee1275_original_stack;
void
grub_exit (void)
{
grub_ieee1275_exit ();
}
static grub_uint64_t
ieee1275_get_time_ms (void)
{
grub_uint32_t msecs = 0;
grub_ieee1275_milliseconds (&msecs);
return msecs;
}
grub_uint32_t
grub_get_rtc (void)
{
return ieee1275_get_time_ms ();
}
grub_addr_t
grub_arch_modules_addr (void)
{
extern char _end[];
return (grub_addr_t) _end;
}
void
grub_machine_set_prefix (void)
{
if (grub_prefix[0] != '(')
{
char bootpath[IEEE1275_MAX_PATH_LEN];
char *prefix, *path, *colon;
grub_ssize_t actual;
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_xasprintf("%s%s", prefix, grub_prefix);
grub_strcpy (grub_prefix, path);
grub_free (path);
grub_free (prefix);
}
grub_env_set ("prefix", grub_prefix);
}
static void
grub_heap_init (void)
{
grub_mm_init_region ((void *) (grub_modules_get_end ()
+ GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000);
}
static void
grub_parse_cmdline (void)
{
grub_ssize_t actual;
char args[256];
if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
sizeof args, &actual) == 0
&& actual > 1)
{
int i = 0;
while (i < actual)
{
char *command = &args[i];
char *end;
char *val;
end = grub_strchr (command, ';');
if (end == 0)
i = actual; /* No more commands after this one. */
else
{
*end = '\0';
i += end - command + 1;
while (grub_isspace(args[i]))
i++;
}
/* Process command. */
val = grub_strchr (command, '=');
if (val)
{
*val = '\0';
grub_env_set (command, val + 1);
}
}
}
}
void
grub_machine_init (void)
{
grub_ieee1275_init ();
grub_console_init_early ();
grub_heap_init ();
grub_console_init_lately ();
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
grub_machine_fini (void)
{
grub_ofdisk_fini ();
grub_console_fini ();
}

View file

@ -29,6 +29,7 @@ struct grub_term_output *grub_term_outputs;
struct grub_term_input *grub_term_inputs;
void (*grub_term_poll_usb) (void) = NULL;
void (*grub_net_poll_cards_idle) (void) = NULL;
/* Put a Unicode character. */
static void
@ -91,6 +92,9 @@ grub_checkkey (void)
if (grub_term_poll_usb)
grub_term_poll_usb ();
if (grub_net_poll_cards_idle)
grub_net_poll_cards_idle ();
FOR_ACTIVE_TERM_INPUTS(term)
{
pending_key = term->getkey (term);

View file

@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
* Copyright (C) 2010,2011 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,7 +16,9 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __mips__
#include <grub/pci.h>
#endif
#include <grub/machine/kernel.h>
#include <grub/misc.h>
#include <grub/vga.h>
@ -43,7 +45,17 @@ static struct {grub_uint8_t r, g, b, a; } colors[] =
{0xFE, 0xFE, 0xFE, 0xFF} // 15 = white
};
#ifdef __mips__
extern unsigned char ascii_bitmaps[];
#else
#include <ascii.h>
#endif
#ifdef __mips__
#define VGA_ADDR 0xb00a0000
#else
#define VGA_ADDR 0xa0000
#endif
static void
load_font (void)
@ -61,7 +73,7 @@ load_font (void)
grub_vga_gr_write (0xff, GRUB_VGA_GR_BITMASK);
for (i = 0; i < 128; i++)
grub_memcpy ((void *) (0xa0000 + 32 * i), ascii_bitmaps + 16 * i, 16);
grub_memcpy ((void *) (VGA_ADDR + 32 * i), ascii_bitmaps + 16 * i, 16);
}
static void
@ -78,6 +90,7 @@ load_palette (void)
void
grub_qemu_init_cirrus (void)
{
#ifndef __mips__
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)))
{
@ -106,8 +119,10 @@ grub_qemu_init_cirrus (void)
}
grub_pci_iterate (find_card);
#endif
grub_outb (GRUB_VGA_IO_MISC_COLOR, GRUB_VGA_IO_MISC_WRITE);
grub_outb (GRUB_VGA_IO_MISC_COLOR,
GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_MISC_WRITE);
load_font ();
@ -143,5 +158,5 @@ grub_qemu_init_cirrus (void)
grub_vga_cr_write (14, GRUB_VGA_CR_CURSOR_START);
grub_vga_cr_write (15, GRUB_VGA_CR_CURSOR_END);
grub_outb (0x20, 0x3c0);
grub_outb (0x20, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX);
}

View file

@ -95,6 +95,20 @@ FUNCTION(efi_wrap_6)
addq $64, %rsp
ret
FUNCTION(efi_wrap_7)
subq $96, %rsp
mov 96+16(%rsp), %rax
mov %rax, 48(%rsp)
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 $96, %rsp
ret
FUNCTION(efi_wrap_10)
subq $96, %rsp
mov 96+40(%rsp), %rax