merge mainline into lazy
This commit is contained in:
commit
00542307eb
326 changed files with 18667 additions and 4092 deletions
|
@ -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;
|
||||
|
|
|
@ -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, §or, &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, §or, &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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
13
grub-core/kern/emu/cache.c
Normal file
13
grub-core/kern/emu/cache.c
Normal 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
|
||||
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, §or_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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -86,6 +86,8 @@ grub_util_raid_getmembers (const char *name, int bootable)
|
|||
|
||||
devicelist[j] = NULL;
|
||||
|
||||
close (fd);
|
||||
|
||||
return devicelist;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -87,3 +87,4 @@ codestart:
|
|||
*/
|
||||
#include "../realmode.S"
|
||||
|
||||
#include "../int.S"
|
||||
|
|
|
@ -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
140
grub-core/kern/i386/int.S
Normal 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
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
276
grub-core/kern/ia64/dl.c
Normal 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;
|
||||
}
|
73
grub-core/kern/ia64/dl_helper.c
Normal file
73
grub-core/kern/ia64/dl_helper.c
Normal 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;
|
||||
}
|
||||
|
54
grub-core/kern/ia64/efi/init.c
Normal file
54
grub-core/kern/ia64/efi/init.c
Normal 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;;");
|
||||
}
|
54
grub-core/kern/ia64/efi/startup.S
Normal file
54
grub-core/kern/ia64/efi/startup.S
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
213
grub-core/kern/mips/arc/init.c
Normal file
213
grub-core/kern/mips/arc/init.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
121
grub-core/kern/mips/qemu_mips/init.c
Normal file
121
grub-core/kern/mips/qemu_mips/init.c
Normal 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;
|
||||
}
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ();
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue