merge mainline into hints
This commit is contained in:
commit
17785932df
448 changed files with 43023 additions and 10176 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,11 +46,7 @@ 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
|
||||
#if DISK_CACHE_STATS
|
||||
static unsigned long grub_disk_cache_hits;
|
||||
static unsigned long grub_disk_cache_misses;
|
||||
|
||||
|
@ -123,13 +119,13 @@ grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id,
|
|||
&& cache->sector == sector)
|
||||
{
|
||||
cache->lock = 1;
|
||||
#if 0
|
||||
#if DISK_CACHE_STATS
|
||||
grub_disk_cache_hits++;
|
||||
#endif
|
||||
return cache->data;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if DISK_CACHE_STATS
|
||||
grub_disk_cache_misses++;
|
||||
#endif
|
||||
|
||||
|
@ -207,10 +203,12 @@ int
|
|||
grub_disk_dev_iterate (int (*hook) (const char *name))
|
||||
{
|
||||
grub_disk_dev_t p;
|
||||
grub_disk_pull_t pull;
|
||||
|
||||
for (p = grub_disk_dev_list; p; p = p->next)
|
||||
if (p->iterate && (p->iterate) (hook))
|
||||
return 1;
|
||||
for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
|
||||
for (p = grub_disk_dev_list; p; p = p->next)
|
||||
if (p->iterate && (p->iterate) (hook, pull))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -247,6 +245,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)
|
||||
|
@ -266,7 +265,6 @@ grub_disk_open (const char *name)
|
|||
if (! disk->name)
|
||||
goto fail;
|
||||
|
||||
|
||||
for (dev = grub_disk_dev_list; dev; dev = dev->next)
|
||||
{
|
||||
if ((dev->open) (raw, disk) == GRUB_ERR_NONE)
|
||||
|
@ -282,6 +280,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;
|
||||
|
||||
|
@ -373,21 +379,113 @@ 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_free (tmp_buf);
|
||||
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 ();
|
||||
grub_free (tmp_buf);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (buf, tmp_buf + offset, size);
|
||||
grub_free (tmp_buf);
|
||||
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)
|
||||
|
@ -399,126 +497,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;
|
||||
}
|
||||
|
@ -528,25 +625,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;
|
||||
|
@ -554,7 +657,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;
|
||||
|
||||
|
@ -565,7 +668,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;
|
||||
|
@ -575,8 +678,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;
|
||||
|
@ -599,6 +702,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;
|
||||
}
|
||||
|
|
|
@ -233,7 +233,7 @@ 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__
|
||||
#if defined (__ia64__) || defined (__powerpc__)
|
||||
grub_size_t tramp;
|
||||
grub_size_t got;
|
||||
#endif
|
||||
|
@ -243,14 +243,14 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
|
|||
i < e->e_shnum;
|
||||
i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
|
||||
{
|
||||
tsize += ALIGN_UP (s->sh_size, s->sh_addralign);
|
||||
tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size;
|
||||
if (talign < s->sh_addralign)
|
||||
talign = s->sh_addralign;
|
||||
}
|
||||
|
||||
#ifdef __ia64__
|
||||
#if defined (__ia64__) || defined (__powerpc__)
|
||||
grub_arch_dl_get_tramp_got_size (e, &tramp, &got);
|
||||
tramp *= GRUB_IA64_DL_TRAMP_SIZE;
|
||||
tramp *= GRUB_ARCH_DL_TRAMP_SIZE;
|
||||
got *= sizeof (grub_uint64_t);
|
||||
tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN);
|
||||
if (talign < GRUB_ARCH_DL_TRAMP_ALIGN)
|
||||
|
@ -269,6 +269,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
|
|||
mod->base = grub_memalign (talign, tsize);
|
||||
if (!mod->base)
|
||||
return grub_errno;
|
||||
mod->sz = tsize;
|
||||
ptr = mod->base;
|
||||
|
||||
#ifdef GRUB_MACHINE_EMU
|
||||
|
@ -316,7 +317,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
|
|||
mod->segment = seg;
|
||||
}
|
||||
}
|
||||
#ifdef __ia64__
|
||||
#if defined (__ia64__) || defined (__powerpc__)
|
||||
ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN);
|
||||
mod->tramp = ptr;
|
||||
ptr += tramp;
|
||||
|
@ -575,15 +576,9 @@ grub_dl_unref (grub_dl_t mod)
|
|||
static void
|
||||
grub_dl_flush_cache (grub_dl_t mod)
|
||||
{
|
||||
grub_dl_segment_t seg;
|
||||
|
||||
for (seg = mod->segment; seg; seg = seg->next) {
|
||||
if (seg->size) {
|
||||
grub_dprintf ("modules", "flushing 0x%lx bytes at %p\n",
|
||||
(unsigned long) seg->size, seg->addr);
|
||||
grub_arch_sync_caches (seg->addr, seg->size);
|
||||
}
|
||||
}
|
||||
grub_dprintf ("modules", "flushing 0x%lx bytes at %p\n",
|
||||
(unsigned long) mod->sz, mod->base);
|
||||
grub_arch_sync_caches (mod->base, mod->sz);
|
||||
}
|
||||
|
||||
/* Load a module from core memory. */
|
||||
|
@ -688,11 +683,9 @@ 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--;
|
||||
return mod;
|
||||
|
@ -704,7 +697,7 @@ grub_dl_load (const char *name)
|
|||
{
|
||||
char *filename;
|
||||
grub_dl_t mod;
|
||||
char *grub_dl_dir = grub_env_get ("prefix");
|
||||
const char *grub_dl_dir = grub_env_get ("prefix");
|
||||
|
||||
mod = grub_dl_get (name);
|
||||
if (mod)
|
||||
|
@ -736,7 +729,6 @@ int
|
|||
grub_dl_unload (grub_dl_t mod)
|
||||
{
|
||||
grub_dl_dep_t dep, depn;
|
||||
grub_dl_segment_t seg, segn;
|
||||
|
||||
if (mod->ref_count > 0)
|
||||
return 0;
|
||||
|
@ -756,13 +748,7 @@ grub_dl_unload (grub_dl_t mod)
|
|||
grub_free (dep);
|
||||
}
|
||||
|
||||
for (seg = mod->segment; seg; seg = segn)
|
||||
{
|
||||
segn = seg->next;
|
||||
grub_free (seg->addr);
|
||||
grub_free (seg);
|
||||
}
|
||||
|
||||
grub_free (mod->base);
|
||||
grub_free (mod->name);
|
||||
#ifdef GRUB_MODULES_MACHINE_READONLY
|
||||
grub_free (mod->symtab);
|
||||
|
|
|
@ -163,18 +163,6 @@ grub_exit (void)
|
|||
for (;;) ;
|
||||
}
|
||||
|
||||
/* On i386, a firmware-independant grub_reboot() is provided by realmode.S. */
|
||||
#ifndef __i386__
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
grub_efi_fini ();
|
||||
efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
|
||||
GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
|
||||
for (;;) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
grub_err_t
|
||||
grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
|
||||
grub_efi_uintn_t descriptor_size,
|
||||
|
@ -218,7 +206,7 @@ grub_get_rtc (void)
|
|||
/* Search the mods section from the PE32/PE32+ image. This code uses
|
||||
a PE32 header, but should work with PE32+ as well. */
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
grub_efi_modules_addr (void)
|
||||
{
|
||||
grub_efi_loaded_image_t *image;
|
||||
struct grub_pe32_header *header;
|
||||
|
@ -746,3 +734,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;
|
||||
}
|
||||
|
|
|
@ -26,9 +26,12 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/kernel.h>
|
||||
|
||||
grub_addr_t grub_modbase;
|
||||
|
||||
void
|
||||
grub_efi_init (void)
|
||||
{
|
||||
grub_modbase = grub_efi_modules_addr ();
|
||||
/* First of all, initialize the console so that GRUB can display
|
||||
messages. */
|
||||
grub_console_init ();
|
||||
|
@ -42,84 +45,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
|
||||
|
|
|
@ -1,967 +0,0 @@
|
|||
/* getroot.c - Get root device */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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-util.h>
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <grub/util/misc.h>
|
||||
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
# include <libdevmapper.h>
|
||||
#endif
|
||||
|
||||
#ifdef __GNU__
|
||||
#include <hurd.h>
|
||||
#include <hurd/lookup.h>
|
||||
#include <hurd/fs.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
# include <sys/types.h>
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
# include <grub/util/libzfs.h>
|
||||
# include <grub/util/libnvpair.h>
|
||||
#endif
|
||||
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/emu/misc.h>
|
||||
#include <grub/emu/hostdisk.h>
|
||||
#include <grub/emu/getroot.h>
|
||||
|
||||
static void
|
||||
strip_extra_slashes (char *dir)
|
||||
{
|
||||
char *p = dir;
|
||||
|
||||
while ((p = strchr (p, '/')) != 0)
|
||||
{
|
||||
if (p[1] == '/')
|
||||
{
|
||||
memmove (p, p + 1, strlen (p));
|
||||
continue;
|
||||
}
|
||||
else if (p[1] == '\0')
|
||||
{
|
||||
if (p > dir)
|
||||
p[0] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
xgetcwd (void)
|
||||
{
|
||||
size_t size = 10;
|
||||
char *path;
|
||||
|
||||
path = xmalloc (size);
|
||||
while (! getcwd (path, size))
|
||||
{
|
||||
size <<= 1;
|
||||
path = xrealloc (path, size);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
struct mountinfo_entry
|
||||
{
|
||||
int id;
|
||||
int major, minor;
|
||||
char enc_root[PATH_MAX], enc_path[PATH_MAX];
|
||||
char fstype[PATH_MAX], device[PATH_MAX];
|
||||
};
|
||||
|
||||
/* Statting something on a btrfs filesystem always returns a virtual device
|
||||
major/minor pair rather than the real underlying device, because btrfs
|
||||
can span multiple underlying devices (and even if it's currently only
|
||||
using a single device it can be dynamically extended onto another). We
|
||||
can't deal with the multiple-device case yet, but in the meantime, we can
|
||||
at least cope with the single-device case by scanning
|
||||
/proc/self/mountinfo. */
|
||||
char *
|
||||
grub_find_root_device_from_mountinfo (const char *dir, char **relroot)
|
||||
{
|
||||
FILE *fp;
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
char *ret = NULL;
|
||||
int entry_len = 0, entry_max = 4;
|
||||
struct mountinfo_entry *entries;
|
||||
struct mountinfo_entry parent_entry = { 0, 0, 0, "", "", "", "" };
|
||||
int i;
|
||||
|
||||
if (! *dir)
|
||||
dir = "/";
|
||||
if (relroot)
|
||||
*relroot = NULL;
|
||||
|
||||
fp = fopen ("/proc/self/mountinfo", "r");
|
||||
if (! fp)
|
||||
return NULL; /* fall through to other methods */
|
||||
|
||||
entries = xmalloc (entry_max * sizeof (*entries));
|
||||
|
||||
/* First, build a list of relevant visible mounts. */
|
||||
while (getline (&buf, &len, fp) > 0)
|
||||
{
|
||||
struct mountinfo_entry entry;
|
||||
int count;
|
||||
size_t enc_path_len;
|
||||
const char *sep;
|
||||
|
||||
if (sscanf (buf, "%d %d %u:%u %s %s%n",
|
||||
&entry.id, &parent_entry.id, &entry.major, &entry.minor,
|
||||
entry.enc_root, entry.enc_path, &count) < 6)
|
||||
continue;
|
||||
|
||||
enc_path_len = strlen (entry.enc_path);
|
||||
/* Check that enc_path is a prefix of dir. The prefix must either be
|
||||
the entire string, or end with a slash, or be immediately followed
|
||||
by a slash. */
|
||||
if (strncmp (dir, entry.enc_path, enc_path_len) != 0 ||
|
||||
(enc_path_len && dir[enc_path_len - 1] != '/' &&
|
||||
dir[enc_path_len] && dir[enc_path_len] != '/'))
|
||||
continue;
|
||||
|
||||
sep = strstr (buf + count, " - ");
|
||||
if (!sep)
|
||||
continue;
|
||||
|
||||
sep += sizeof (" - ") - 1;
|
||||
if (sscanf (sep, "%s %s", entry.fstype, entry.device) != 2)
|
||||
continue;
|
||||
|
||||
/* Using the mount IDs, find out where this fits in the list of
|
||||
visible mount entries we've seen so far. There are three
|
||||
interesting cases. Firstly, it may be inserted at the end: this is
|
||||
the usual case of /foo/bar being mounted after /foo. Secondly, it
|
||||
may be inserted at the start: for example, this can happen for
|
||||
filesystems that are mounted before / and later moved under it.
|
||||
Thirdly, it may occlude part or all of the existing filesystem
|
||||
tree, in which case the end of the list needs to be pruned and this
|
||||
new entry will be inserted at the end. */
|
||||
if (entry_len >= entry_max)
|
||||
{
|
||||
entry_max <<= 1;
|
||||
entries = xrealloc (entries, entry_max * sizeof (*entries));
|
||||
}
|
||||
|
||||
if (!entry_len)
|
||||
{
|
||||
/* Initialise list. */
|
||||
entry_len = 2;
|
||||
entries[0] = parent_entry;
|
||||
entries[1] = entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = entry_len - 1; i >= 0; i--)
|
||||
{
|
||||
if (entries[i].id == parent_entry.id)
|
||||
{
|
||||
/* Insert at end, pruning anything previously above this. */
|
||||
entry_len = i + 2;
|
||||
entries[i + 1] = entry;
|
||||
break;
|
||||
}
|
||||
else if (i == 0 && entries[i].id == entry.id)
|
||||
{
|
||||
/* Insert at start. */
|
||||
entry_len++;
|
||||
memmove (entries + 1, entries,
|
||||
(entry_len - 1) * sizeof (*entries));
|
||||
entries[0] = parent_entry;
|
||||
entries[1] = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now scan visible mounts for the ones we're interested in. */
|
||||
for (i = entry_len - 1; i >= 0; i--)
|
||||
{
|
||||
if (!*entries[i].device)
|
||||
continue;
|
||||
|
||||
ret = strdup (entries[i].device);
|
||||
if (relroot)
|
||||
*relroot = strdup (entries[i].enc_root);
|
||||
break;
|
||||
}
|
||||
|
||||
free (buf);
|
||||
free (entries);
|
||||
fclose (fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
static char *
|
||||
find_root_device_from_libzfs (const char *dir)
|
||||
{
|
||||
char *device = NULL;
|
||||
char *poolname;
|
||||
char *poolfs;
|
||||
|
||||
grub_find_zpool_from_dir (dir, &poolname, &poolfs);
|
||||
if (! poolname)
|
||||
return NULL;
|
||||
|
||||
{
|
||||
zpool_handle_t *zpool;
|
||||
libzfs_handle_t *libzfs;
|
||||
nvlist_t *config, *vdev_tree;
|
||||
nvlist_t **children, **path;
|
||||
unsigned int nvlist_count;
|
||||
unsigned int i;
|
||||
|
||||
libzfs = grub_get_libzfs_handle ();
|
||||
if (! libzfs)
|
||||
return NULL;
|
||||
|
||||
zpool = zpool_open (libzfs, poolname);
|
||||
config = zpool_get_config (zpool, NULL);
|
||||
|
||||
if (nvlist_lookup_nvlist (config, "vdev_tree", &vdev_tree) != 0)
|
||||
error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")");
|
||||
|
||||
if (nvlist_lookup_nvlist_array (vdev_tree, "children", &children, &nvlist_count) != 0)
|
||||
error (1, errno, "nvlist_lookup_nvlist_array (\"children\")");
|
||||
assert (nvlist_count > 0);
|
||||
|
||||
while (nvlist_lookup_nvlist_array (children[0], "children",
|
||||
&children, &nvlist_count) == 0)
|
||||
assert (nvlist_count > 0);
|
||||
|
||||
for (i = 0; i < nvlist_count; i++)
|
||||
{
|
||||
if (nvlist_lookup_string (children[i], "path", &device) != 0)
|
||||
error (1, errno, "nvlist_lookup_string (\"path\")");
|
||||
|
||||
struct stat st;
|
||||
if (stat (device, &st) == 0)
|
||||
{
|
||||
device = xstrdup (device);
|
||||
break;
|
||||
}
|
||||
|
||||
device = NULL;
|
||||
}
|
||||
|
||||
zpool_close (zpool);
|
||||
}
|
||||
|
||||
free (poolname);
|
||||
if (poolfs)
|
||||
free (poolfs);
|
||||
|
||||
return device;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
|
||||
char *
|
||||
grub_find_device (const char *dir __attribute__ ((unused)),
|
||||
dev_t dev __attribute__ ((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif ! defined(__CYGWIN__)
|
||||
|
||||
char *
|
||||
grub_find_device (const char *dir, dev_t dev)
|
||||
{
|
||||
DIR *dp;
|
||||
char *saved_cwd;
|
||||
struct dirent *ent;
|
||||
|
||||
if (! dir)
|
||||
{
|
||||
#ifdef __CYGWIN__
|
||||
return NULL;
|
||||
#else
|
||||
dir = "/dev";
|
||||
#endif
|
||||
}
|
||||
|
||||
dp = opendir (dir);
|
||||
if (! dp)
|
||||
return 0;
|
||||
|
||||
saved_cwd = xgetcwd ();
|
||||
|
||||
grub_util_info ("changing current directory to %s", dir);
|
||||
if (chdir (dir) < 0)
|
||||
{
|
||||
free (saved_cwd);
|
||||
closedir (dp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((ent = readdir (dp)) != 0)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* Avoid:
|
||||
- dotfiles (like "/dev/.tmp.md0") since they could be duplicates.
|
||||
- dotdirs (like "/dev/.static") since they could contain duplicates. */
|
||||
if (ent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
if (lstat (ent->d_name, &st) < 0)
|
||||
/* Ignore any error. */
|
||||
continue;
|
||||
|
||||
if (S_ISLNK (st.st_mode)) {
|
||||
#ifdef __linux__
|
||||
if (strcmp (dir, "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
|
||||
we can get them. */
|
||||
if (stat (ent->d_name, &st) < 0)
|
||||
continue;
|
||||
} else
|
||||
#endif /* __linux__ */
|
||||
/* Don't follow other symbolic links. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR (st.st_mode))
|
||||
{
|
||||
/* Find it recursively. */
|
||||
char *res;
|
||||
|
||||
res = grub_find_device (ent->d_name, dev);
|
||||
|
||||
if (res)
|
||||
{
|
||||
if (chdir (saved_cwd) < 0)
|
||||
grub_util_error ("cannot restore the original directory");
|
||||
|
||||
free (saved_cwd);
|
||||
closedir (dp);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
|
||||
if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
|
||||
#else
|
||||
if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
|
||||
#endif
|
||||
{
|
||||
#ifdef __linux__
|
||||
/* Skip device names like /dev/dm-0, which are short-hand aliases
|
||||
to more descriptive device names, e.g. those under /dev/mapper */
|
||||
if (ent->d_name[0] == 'd' &&
|
||||
ent->d_name[1] == 'm' &&
|
||||
ent->d_name[2] == '-' &&
|
||||
ent->d_name[3] >= '0' &&
|
||||
ent->d_name[3] <= '9')
|
||||
continue;
|
||||
#endif
|
||||
|
||||
/* Found! */
|
||||
char *res;
|
||||
char *cwd;
|
||||
#if defined(__NetBSD__)
|
||||
/* Convert this block device to its character (raw) device. */
|
||||
const char *template = "%s/r%s";
|
||||
#else
|
||||
/* Keep the device name as it is. */
|
||||
const char *template = "%s/%s";
|
||||
#endif
|
||||
|
||||
cwd = xgetcwd ();
|
||||
res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
|
||||
sprintf (res, template, cwd, ent->d_name);
|
||||
strip_extra_slashes (res);
|
||||
free (cwd);
|
||||
|
||||
/* /dev/root is not a real block device keep looking, takes care
|
||||
of situation where root filesystem is on the same partition as
|
||||
grub files */
|
||||
|
||||
if (strcmp(res, "/dev/root") == 0)
|
||||
continue;
|
||||
|
||||
if (chdir (saved_cwd) < 0)
|
||||
grub_util_error ("cannot restore the original directory");
|
||||
|
||||
free (saved_cwd);
|
||||
closedir (dp);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (chdir (saved_cwd) < 0)
|
||||
grub_util_error ("cannot restore the original directory");
|
||||
|
||||
free (saved_cwd);
|
||||
closedir (dp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* __CYGWIN__ */
|
||||
|
||||
/* Read drive/partition serial number from mbr/boot sector,
|
||||
return 0 on read error, ~0 on unknown serial. */
|
||||
static unsigned
|
||||
get_bootsec_serial (const char *os_dev, int mbr)
|
||||
{
|
||||
/* Read boot sector. */
|
||||
int fd = open (os_dev, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
unsigned char buf[0x200];
|
||||
int n = read (fd, buf, sizeof (buf));
|
||||
close (fd);
|
||||
if (n != sizeof(buf))
|
||||
return 0;
|
||||
|
||||
/* Check signature. */
|
||||
if (!(buf[0x1fe] == 0x55 && buf[0x1ff] == 0xaa))
|
||||
return ~0;
|
||||
|
||||
/* Serial number offset depends on boot sector type. */
|
||||
if (mbr)
|
||||
n = 0x1b8;
|
||||
else if (memcmp (buf + 0x03, "NTFS", 4) == 0)
|
||||
n = 0x048;
|
||||
else if (memcmp (buf + 0x52, "FAT32", 5) == 0)
|
||||
n = 0x043;
|
||||
else if (memcmp (buf + 0x36, "FAT", 3) == 0)
|
||||
n = 0x027;
|
||||
else
|
||||
return ~0;
|
||||
|
||||
unsigned serial = *(unsigned *)(buf + n);
|
||||
if (serial == 0)
|
||||
return ~0;
|
||||
return serial;
|
||||
}
|
||||
|
||||
char *
|
||||
grub_find_device (const char *path, dev_t dev)
|
||||
{
|
||||
/* No root device for /cygdrive. */
|
||||
if (dev == (DEV_CYGDRIVE_MAJOR << 16))
|
||||
return 0;
|
||||
|
||||
/* Convert to full POSIX and Win32 path. */
|
||||
char fullpath[PATH_MAX], winpath[PATH_MAX];
|
||||
cygwin_conv_to_full_posix_path (path, fullpath);
|
||||
cygwin_conv_to_full_win32_path (fullpath, winpath);
|
||||
|
||||
/* If identical, this is no real filesystem path. */
|
||||
if (strcmp (fullpath, winpath) == 0)
|
||||
return 0;
|
||||
|
||||
/* Check for floppy drive letter. */
|
||||
if (winpath[0] && winpath[1] == ':' && strchr ("AaBb", winpath[0]))
|
||||
return xstrdup (strchr ("Aa", winpath[0]) ? "/dev/fd0" : "/dev/fd1");
|
||||
|
||||
/* Cygwin returns the partition serial number in stat.st_dev.
|
||||
This is never identical to the device number of the emulated
|
||||
/dev/sdXN device, so above grub_find_device () does not work.
|
||||
Search the partition with the same serial in boot sector instead. */
|
||||
char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia. */
|
||||
int d;
|
||||
for (d = 'a'; d <= 'z'; d++)
|
||||
{
|
||||
sprintf (devpath, "/dev/sd%c", d);
|
||||
if (get_bootsec_serial (devpath, 1) == 0)
|
||||
continue;
|
||||
int p;
|
||||
for (p = 1; p <= 15; p++)
|
||||
{
|
||||
sprintf (devpath, "/dev/sd%c%d", d, p);
|
||||
unsigned ser = get_bootsec_serial (devpath, 0);
|
||||
if (ser == 0)
|
||||
break;
|
||||
if (ser != (unsigned)~0 && dev == (dev_t)ser)
|
||||
return xstrdup (devpath);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
char *
|
||||
grub_guess_root_device (const char *dir)
|
||||
{
|
||||
char *os_dev = NULL;
|
||||
#ifdef __GNU__
|
||||
file_t file;
|
||||
mach_port_t *ports;
|
||||
int *ints;
|
||||
loff_t *offsets;
|
||||
char *data;
|
||||
error_t err;
|
||||
mach_msg_type_number_t num_ports = 0, num_ints = 0, num_offsets = 0, data_len = 0;
|
||||
size_t name_len;
|
||||
|
||||
file = file_name_lookup (dir, 0, 0);
|
||||
if (file == MACH_PORT_NULL)
|
||||
return 0;
|
||||
|
||||
err = file_get_storage_info (file,
|
||||
&ports, &num_ports,
|
||||
&ints, &num_ints,
|
||||
&offsets, &num_offsets,
|
||||
&data, &data_len);
|
||||
|
||||
if (num_ints < 1)
|
||||
grub_util_error ("Storage info for `%s' does not include type", dir);
|
||||
if (ints[0] != STORAGE_DEVICE)
|
||||
grub_util_error ("Filesystem of `%s' is not stored on local disk", dir);
|
||||
|
||||
if (num_ints < 5)
|
||||
grub_util_error ("Storage info for `%s' does not include name", dir);
|
||||
name_len = ints[4];
|
||||
if (name_len < data_len)
|
||||
grub_util_error ("Bogus name length for storage info for `%s'", dir);
|
||||
if (data[name_len - 1] != '\0')
|
||||
grub_util_error ("Storage name for `%s' not NUL-terminated", dir);
|
||||
|
||||
os_dev = xmalloc (strlen ("/dev/") + data_len);
|
||||
memcpy (os_dev, "/dev/", strlen ("/dev/"));
|
||||
memcpy (os_dev + strlen ("/dev/"), data, data_len);
|
||||
|
||||
if (ports && num_ports > 0)
|
||||
{
|
||||
mach_msg_type_number_t i;
|
||||
for (i = 0; i < num_ports; i++)
|
||||
{
|
||||
mach_port_t port = ports[i];
|
||||
if (port != MACH_PORT_NULL)
|
||||
mach_port_deallocate (mach_task_self(), port);
|
||||
}
|
||||
munmap ((caddr_t) ports, num_ports * sizeof (*ports));
|
||||
}
|
||||
|
||||
if (ints && num_ints > 0)
|
||||
munmap ((caddr_t) ints, num_ints * sizeof (*ints));
|
||||
if (offsets && num_offsets > 0)
|
||||
munmap ((caddr_t) offsets, num_offsets * sizeof (*offsets));
|
||||
if (data && data_len > 0)
|
||||
munmap (data, data_len);
|
||||
mach_port_deallocate (mach_task_self (), file);
|
||||
#else /* !__GNU__ */
|
||||
struct stat st;
|
||||
dev_t dev;
|
||||
|
||||
#ifdef __linux__
|
||||
if (!os_dev)
|
||||
os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
|
||||
#endif /* __linux__ */
|
||||
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
if (!os_dev)
|
||||
os_dev = find_root_device_from_libzfs (dir);
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
/* Cygwin specific function. */
|
||||
os_dev = grub_find_device (dir, dev);
|
||||
|
||||
#else
|
||||
|
||||
/* This might be truly slow, but is there any better way? */
|
||||
os_dev = grub_find_device ("/dev", dev);
|
||||
#endif
|
||||
#endif /* !__GNU__ */
|
||||
|
||||
return os_dev;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_util_is_lvm (const char *os_dev)
|
||||
{
|
||||
if ((strncmp ("/dev/mapper/", os_dev, 12) != 0))
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
{
|
||||
struct dm_tree *tree;
|
||||
uint32_t maj, min;
|
||||
struct dm_tree_node *node = NULL;
|
||||
const char *node_uuid;
|
||||
struct stat st;
|
||||
|
||||
if (stat (os_dev, &st) < 0)
|
||||
return 0;
|
||||
|
||||
tree = dm_tree_create ();
|
||||
if (! tree)
|
||||
{
|
||||
grub_printf ("Failed to create tree\n");
|
||||
grub_dprintf ("hostdisk", "dm_tree_create failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
maj = major (st.st_rdev);
|
||||
min = minor (st.st_rdev);
|
||||
|
||||
if (! dm_tree_add_dev (tree, maj, min))
|
||||
{
|
||||
grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n");
|
||||
dm_tree_free (tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = dm_tree_find_node (tree, maj, min);
|
||||
if (! node)
|
||||
{
|
||||
grub_dprintf ("hostdisk", "dm_tree_find_node failed\n");
|
||||
dm_tree_free (tree);
|
||||
return 0;
|
||||
}
|
||||
node_uuid = dm_tree_node_get_uuid (node);
|
||||
if (! node_uuid)
|
||||
{
|
||||
grub_dprintf ("hostdisk", "%s has no DM uuid\n", os_dev);
|
||||
dm_tree_free (tree);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp (node_uuid, "LVM-", 4) != 0)
|
||||
{
|
||||
dm_tree_free (tree);
|
||||
return 0;
|
||||
}
|
||||
dm_tree_free (tree);
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
return 1;
|
||||
#endif /* HAVE_DEVICE_MAPPER */
|
||||
}
|
||||
|
||||
int
|
||||
grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
|
||||
{
|
||||
#ifdef __linux__
|
||||
/* User explicitly claims that this drive is visible by BIOS. */
|
||||
if (grub_util_biosdisk_is_present (os_dev))
|
||||
return GRUB_DEV_ABSTRACTION_NONE;
|
||||
|
||||
/* Check for LVM. */
|
||||
if (grub_util_is_lvm (os_dev))
|
||||
return GRUB_DEV_ABSTRACTION_LVM;
|
||||
|
||||
/* Check for RAID. */
|
||||
if (!strncmp (os_dev, "/dev/md", 7) && ! grub_util_device_is_mapped (os_dev))
|
||||
return GRUB_DEV_ABSTRACTION_RAID;
|
||||
#endif
|
||||
|
||||
/* No abstraction found. */
|
||||
return GRUB_DEV_ABSTRACTION_NONE;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static char *
|
||||
get_mdadm_uuid (const char *os_dev)
|
||||
{
|
||||
int mdadm_pipe[2];
|
||||
pid_t mdadm_pid;
|
||||
char *name = NULL;
|
||||
|
||||
if (pipe (mdadm_pipe) < 0)
|
||||
{
|
||||
grub_util_warn ("Unable to create pipe for mdadm: %s", strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mdadm_pid = fork ();
|
||||
if (mdadm_pid < 0)
|
||||
grub_util_warn ("Unable to fork mdadm: %s", strerror (errno));
|
||||
else if (mdadm_pid == 0)
|
||||
{
|
||||
/* Child. */
|
||||
char *argv[5];
|
||||
|
||||
close (mdadm_pipe[0]);
|
||||
dup2 (mdadm_pipe[1], STDOUT_FILENO);
|
||||
close (mdadm_pipe[1]);
|
||||
|
||||
/* execvp has inconvenient types, hence the casts. None of these
|
||||
strings will actually be modified. */
|
||||
argv[0] = (char *) "mdadm";
|
||||
argv[1] = (char *) "--detail";
|
||||
argv[2] = (char *) "--export";
|
||||
argv[3] = (char *) os_dev;
|
||||
argv[4] = NULL;
|
||||
execvp ("mdadm", argv);
|
||||
exit (127);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Parent. Read mdadm's output. */
|
||||
FILE *mdadm;
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
close (mdadm_pipe[1]);
|
||||
mdadm = fdopen (mdadm_pipe[0], "r");
|
||||
if (! mdadm)
|
||||
{
|
||||
grub_util_warn ("Unable to open stream from mdadm: %s",
|
||||
strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (getline (&buf, &len, mdadm) > 0)
|
||||
{
|
||||
if (strncmp (buf, "MD_UUID=", sizeof ("MD_UUID=") - 1) == 0)
|
||||
{
|
||||
char *name_start, *ptri, *ptro;
|
||||
size_t name_len;
|
||||
|
||||
free (name);
|
||||
name_start = buf + sizeof ("MD_UUID=") - 1;
|
||||
ptro = name = xmalloc (strlen (name_start) + 1);
|
||||
for (ptri = name_start; *ptri && *ptri != '\n' && *ptri != '\r';
|
||||
ptri++)
|
||||
if ((*ptri >= '0' && *ptri <= '9')
|
||||
|| (*ptri >= 'a' && *ptri <= 'f')
|
||||
|| (*ptri >= 'A' && *ptri <= 'F'))
|
||||
*ptro++ = *ptri;
|
||||
*ptro = 0;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
close (mdadm_pipe[0]);
|
||||
waitpid (mdadm_pid, NULL, 0);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
char *
|
||||
grub_util_get_grub_dev (const char *os_dev)
|
||||
{
|
||||
char *grub_dev = NULL;
|
||||
|
||||
switch (grub_util_get_dev_abstraction (os_dev))
|
||||
{
|
||||
case GRUB_DEV_ABSTRACTION_LVM:
|
||||
|
||||
{
|
||||
unsigned short i, len;
|
||||
grub_size_t offset = sizeof ("/dev/mapper/") - 1;
|
||||
|
||||
len = strlen (os_dev) - offset + 1;
|
||||
grub_dev = xmalloc (len);
|
||||
|
||||
for (i = 0; i < len; i++, offset++)
|
||||
{
|
||||
grub_dev[i] = os_dev[offset];
|
||||
if (os_dev[offset] == '-' && os_dev[offset + 1] == '-')
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GRUB_DEV_ABSTRACTION_RAID:
|
||||
|
||||
if (os_dev[7] == '_' && os_dev[8] == 'd')
|
||||
{
|
||||
/* This a partitionable RAID device of the form /dev/md_dNNpMM. */
|
||||
|
||||
char *p, *q;
|
||||
|
||||
p = strdup (os_dev + sizeof ("/dev/md_d") - 1);
|
||||
|
||||
q = strchr (p, 'p');
|
||||
if (q)
|
||||
*q = ',';
|
||||
|
||||
grub_dev = xasprintf ("md%s", p);
|
||||
free (p);
|
||||
}
|
||||
else if (os_dev[7] == '/' && os_dev[8] == 'd')
|
||||
{
|
||||
/* This a partitionable RAID device of the form /dev/md/dNNpMM. */
|
||||
|
||||
char *p, *q;
|
||||
|
||||
p = strdup (os_dev + sizeof ("/dev/md/d") - 1);
|
||||
|
||||
q = strchr (p, 'p');
|
||||
if (q)
|
||||
*q = ',';
|
||||
|
||||
grub_dev = xasprintf ("md%s", p);
|
||||
free (p);
|
||||
}
|
||||
else if (os_dev[7] >= '0' && os_dev[7] <= '9')
|
||||
{
|
||||
char *p , *q;
|
||||
|
||||
p = strdup (os_dev + sizeof ("/dev/md") - 1);
|
||||
|
||||
q = strchr (p, 'p');
|
||||
if (q)
|
||||
*q = ',';
|
||||
|
||||
grub_dev = xasprintf ("md%s", p);
|
||||
free (p);
|
||||
}
|
||||
else if (os_dev[7] == '/' && os_dev[8] >= '0' && os_dev[8] <= '9')
|
||||
{
|
||||
char *p , *q;
|
||||
|
||||
p = strdup (os_dev + sizeof ("/dev/md/") - 1);
|
||||
|
||||
q = strchr (p, 'p');
|
||||
if (q)
|
||||
*q = ',';
|
||||
|
||||
grub_dev = xasprintf ("md%s", p);
|
||||
free (p);
|
||||
}
|
||||
else if (os_dev[7] == '/')
|
||||
{
|
||||
/* mdraid 1.x with a free name. */
|
||||
char *p , *q;
|
||||
|
||||
p = strdup (os_dev + sizeof ("/dev/md/") - 1);
|
||||
|
||||
q = strchr (p, 'p');
|
||||
if (q)
|
||||
*q = ',';
|
||||
|
||||
grub_dev = xasprintf ("md/%s", p);
|
||||
free (p);
|
||||
}
|
||||
else
|
||||
grub_util_error ("unknown kind of RAID device `%s'", os_dev);
|
||||
|
||||
#ifdef __linux__
|
||||
{
|
||||
char *mdadm_name = get_mdadm_uuid (os_dev);
|
||||
struct stat st;
|
||||
|
||||
if (mdadm_name)
|
||||
{
|
||||
const char *q;
|
||||
|
||||
for (q = os_dev + strlen (os_dev) - 1; q >= os_dev
|
||||
&& grub_isdigit (*q); q--);
|
||||
|
||||
if (q >= os_dev && *q == 'p')
|
||||
{
|
||||
free (grub_dev);
|
||||
grub_dev = xasprintf ("mduuid/%s,%s", mdadm_name, q + 1);
|
||||
goto done;
|
||||
}
|
||||
free (grub_dev);
|
||||
grub_dev = xasprintf ("mduuid/%s", mdadm_name);
|
||||
|
||||
done:
|
||||
free (mdadm_name);
|
||||
}
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
break;
|
||||
|
||||
default: /* GRUB_DEV_ABSTRACTION_NONE */
|
||||
grub_dev = grub_util_biosdisk_get_grub_dev (os_dev);
|
||||
}
|
||||
|
||||
return grub_dev;
|
||||
}
|
||||
|
||||
const char *
|
||||
grub_util_check_block_device (const char *blk_dev)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat (blk_dev, &st) < 0)
|
||||
grub_util_error ("cannot stat `%s'", blk_dev);
|
||||
|
||||
if (S_ISBLK (st.st_mode))
|
||||
return (blk_dev);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
grub_util_check_char_device (const char *blk_dev)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat (blk_dev, &st) < 0)
|
||||
grub_util_error ("cannot stat `%s'", blk_dev);
|
||||
|
||||
if (S_ISCHR (st.st_mode))
|
||||
return (blk_dev);
|
||||
else
|
||||
return 0;
|
||||
}
|
|
@ -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. */
|
||||
|
@ -93,10 +94,16 @@ struct hd_geometry
|
|||
# include <sys/disk.h> /* DIOCGMEDIASIZE */
|
||||
# include <sys/param.h>
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/mount.h>
|
||||
#include <libgeom.h>
|
||||
# define MAJOR(dev) major(dev)
|
||||
# define FLOPPY_MAJOR 2
|
||||
#endif
|
||||
|
||||
#if defined (__sun__)
|
||||
# include <sys/dkio.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# include <sys/disk.h>
|
||||
#endif
|
||||
|
@ -105,9 +112,7 @@ struct hd_geometry
|
|||
# include <libdevmapper.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#include <libgeom.h>
|
||||
#elif defined(__NetBSD__)
|
||||
#if defined(__NetBSD__)
|
||||
# define HAVE_DIOCGDINFO
|
||||
# include <sys/ioctl.h>
|
||||
# include <sys/disklabel.h> /* struct disklabel */
|
||||
|
@ -187,6 +192,27 @@ configure_device_driver (int fd)
|
|||
}
|
||||
#endif /* defined(__NetBSD__) */
|
||||
|
||||
static int
|
||||
unescape_cmp (const char *a, const char *b_escaped)
|
||||
{
|
||||
while (*a || *b_escaped)
|
||||
{
|
||||
if (*b_escaped == '\\' && b_escaped[1] != 0)
|
||||
b_escaped++;
|
||||
if (*a < *b_escaped)
|
||||
return -1;
|
||||
if (*a > *b_escaped)
|
||||
return +1;
|
||||
a++;
|
||||
b_escaped++;
|
||||
}
|
||||
if (*a)
|
||||
return +1;
|
||||
if (*b_escaped)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
find_grub_drive (const char *name)
|
||||
{
|
||||
|
@ -195,7 +221,7 @@ find_grub_drive (const char *name)
|
|||
if (name)
|
||||
{
|
||||
for (i = 0; i < ARRAY_SIZE (map); i++)
|
||||
if (map[i].drive && ! strcmp (map[i].drive, name))
|
||||
if (map[i].drive && unescape_cmp (map[i].drive, name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -215,10 +241,14 @@ find_free_slot (void)
|
|||
}
|
||||
|
||||
static int
|
||||
grub_util_biosdisk_iterate (int (*hook) (const char *name))
|
||||
grub_util_biosdisk_iterate (int (*hook) (const char *name),
|
||||
grub_disk_pull_t pull)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (pull != GRUB_DISK_PULL_NONE)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
||||
if (map[i].drive && hook (map[i].drive))
|
||||
return 1;
|
||||
|
@ -226,6 +256,98 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name))
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(__MINGW32__)
|
||||
grub_uint64_t
|
||||
grub_util_get_fd_sectors (int fd, unsigned *log_secsize)
|
||||
{
|
||||
# if defined(__NetBSD__)
|
||||
struct disklabel label;
|
||||
# elif defined (__sun__)
|
||||
struct dk_minfo minfo;
|
||||
#else
|
||||
unsigned long long nr;
|
||||
# endif
|
||||
unsigned sector_size, log_sector_size;
|
||||
struct stat st;
|
||||
|
||||
if (fstat (fd, &st) < 0)
|
||||
grub_util_error (_("fstat failed"));
|
||||
|
||||
#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) \
|
||||
|| defined (__sun__)
|
||||
|
||||
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__)
|
||||
if (! S_ISCHR (st.st_mode))
|
||||
# else
|
||||
if (! S_ISBLK (st.st_mode))
|
||||
# endif
|
||||
goto fail;
|
||||
|
||||
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
if (ioctl (fd, DIOCGMEDIASIZE, &nr))
|
||||
# elif defined(__APPLE__)
|
||||
if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr))
|
||||
# elif defined(__NetBSD__)
|
||||
configure_device_driver (fd);
|
||||
if (ioctl (fd, DIOCGDINFO, &label) == -1)
|
||||
# elif defined (__sun__)
|
||||
if (!ioctl (fd, DKIOCGMEDIAINFO, &minfo))
|
||||
# else
|
||||
if (ioctl (fd, BLKGETSIZE64, &nr))
|
||||
# endif
|
||||
goto fail;
|
||||
|
||||
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
if (ioctl (fd, DIOCGSECTORSIZE, §or_size))
|
||||
goto fail;
|
||||
# elif defined(__sun__)
|
||||
sector_size = minfo.dki_lbsize;
|
||||
# elif defined(__NetBSD__)
|
||||
sector_size = label.d_secsize;
|
||||
# else
|
||||
if (ioctl (fd, BLKSSZGET, §or_size))
|
||||
goto fail;
|
||||
# endif
|
||||
if (sector_size & (sector_size - 1) || !sector_size)
|
||||
goto fail;
|
||||
for (log_sector_size = 0;
|
||||
(1 << log_sector_size) < sector_size;
|
||||
log_sector_size++);
|
||||
|
||||
if (log_secsize)
|
||||
*log_secsize = log_sector_size;
|
||||
|
||||
# if defined (__APPLE__)
|
||||
return nr;
|
||||
# elif defined(__NetBSD__)
|
||||
return label.d_secperunit;
|
||||
# elif defined (__sun__)
|
||||
return minfo.dki_capacity;
|
||||
# else
|
||||
if (nr & ((1 << log_sector_size) - 1))
|
||||
grub_util_error (_("unaligned device size"));
|
||||
|
||||
return (nr >> log_sector_size);
|
||||
# endif
|
||||
|
||||
fail:
|
||||
|
||||
/* In GNU/Hurd, stat() will return the right size. */
|
||||
#elif !defined (__GNU__)
|
||||
# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
|
||||
#endif
|
||||
|
||||
sector_size = 512;
|
||||
log_sector_size = 9;
|
||||
|
||||
if (log_secsize)
|
||||
*log_secsize = 9;
|
||||
|
||||
return st.st_size >> 9;
|
||||
}
|
||||
#endif
|
||||
|
||||
static grub_err_t
|
||||
grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
||||
{
|
||||
|
@ -254,7 +376,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
|||
size = grub_util_get_disk_size (map[drive].device);
|
||||
|
||||
if (size % 512)
|
||||
grub_util_error ("unaligned device size");
|
||||
grub_util_error (_("unaligned device size"));
|
||||
|
||||
disk->total_sectors = size >> 9;
|
||||
|
||||
|
@ -262,77 +384,30 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
|||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
#elif defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
|
||||
#else
|
||||
{
|
||||
# if defined(__NetBSD__)
|
||||
struct disklabel label;
|
||||
# else
|
||||
unsigned long long nr;
|
||||
# endif
|
||||
int fd;
|
||||
|
||||
fd = open (map[drive].device, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot open `%s' while attempting to get disk size", map[drive].device);
|
||||
|
||||
disk->total_sectors = grub_util_get_fd_sectors (fd, &disk->log_sector_size);
|
||||
|
||||
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
|
||||
if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
|
||||
# else
|
||||
if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
|
||||
# endif
|
||||
{
|
||||
close (fd);
|
||||
goto fail;
|
||||
}
|
||||
data->is_disk = 1;
|
||||
|
||||
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
if (ioctl (fd, DIOCGMEDIASIZE, &nr))
|
||||
# elif defined(__APPLE__)
|
||||
if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr))
|
||||
# elif defined(__NetBSD__)
|
||||
configure_device_driver (fd);
|
||||
if (ioctl (fd, DIOCGDINFO, &label) == -1)
|
||||
# else
|
||||
if (ioctl (fd, BLKGETSIZE64, &nr))
|
||||
# endif
|
||||
{
|
||||
close (fd);
|
||||
goto fail;
|
||||
}
|
||||
data->is_disk = 1;
|
||||
|
||||
close (fd);
|
||||
|
||||
# if defined (__APPLE__)
|
||||
disk->total_sectors = nr;
|
||||
# elif defined(__NetBSD__)
|
||||
disk->total_sectors = label.d_secperunit;
|
||||
# else
|
||||
disk->total_sectors = nr / 512;
|
||||
|
||||
if (nr % 512)
|
||||
grub_util_error ("unaligned device size");
|
||||
# endif
|
||||
|
||||
grub_util_info ("the size of %s is %llu", name, disk->total_sectors);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
fail:
|
||||
/* In GNU/Hurd, stat() will return the right size. */
|
||||
#elif !defined (__GNU__)
|
||||
# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
|
||||
#endif
|
||||
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;
|
||||
|
||||
grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -353,11 +428,13 @@ grub_util_device_is_mapped (const char *dev)
|
|||
#endif /* HAVE_DEVICE_MAPPER */
|
||||
}
|
||||
|
||||
|
||||
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
|
||||
/* FIXME: geom actually gives us the whole container hierarchy.
|
||||
It can be used more efficiently than this. */
|
||||
static void
|
||||
follow_geom_up (const char *name, grub_disk_addr_t *off_out, char **name_out)
|
||||
void
|
||||
grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **name_out)
|
||||
{
|
||||
struct gmesh mesh;
|
||||
struct gclass *class;
|
||||
|
@ -368,13 +445,13 @@ follow_geom_up (const char *name, grub_disk_addr_t *off_out, char **name_out)
|
|||
|
||||
error = geom_gettree (&mesh);
|
||||
if (error != 0)
|
||||
grub_util_error ("couldn't open geom");
|
||||
grub_util_error (_("couldn't open geom"));
|
||||
|
||||
LIST_FOREACH (class, &mesh.lg_class, lg_class)
|
||||
if (strcasecmp (class->lg_name, "part") == 0)
|
||||
break;
|
||||
if (!class)
|
||||
grub_util_error ("couldn't open geom part");
|
||||
grub_util_error (_("couldn't open geom part"));
|
||||
|
||||
LIST_FOREACH (geom, &class->lg_geom, lg_geom)
|
||||
{
|
||||
|
@ -387,7 +464,7 @@ follow_geom_up (const char *name, grub_disk_addr_t *off_out, char **name_out)
|
|||
struct gconfig *config;
|
||||
grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name);
|
||||
|
||||
follow_geom_up (name_tmp, &off, name_out);
|
||||
grub_util_follow_gpart_up (name_tmp, &off, name_out);
|
||||
free (name_tmp);
|
||||
LIST_FOREACH (config, &provider->lg_config, lg_config)
|
||||
if (strcasecmp (config->lg_name, "start") == 0)
|
||||
|
@ -410,16 +487,19 @@ find_partition_start (const char *dev)
|
|||
grub_disk_addr_t out;
|
||||
if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0)
|
||||
return 0;
|
||||
follow_geom_up (dev + sizeof ("/dev/") - 1, &out, NULL);
|
||||
grub_util_follow_gpart_up (dev + sizeof ("/dev/") - 1, &out, NULL);
|
||||
|
||||
return out;
|
||||
}
|
||||
#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
|
||||
|
||||
#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined (__sun__)
|
||||
static grub_disk_addr_t
|
||||
find_partition_start (const char *dev)
|
||||
{
|
||||
int fd;
|
||||
# if !defined(HAVE_DIOCGDINFO)
|
||||
#ifdef __sun__
|
||||
struct extpart_info pinfo;
|
||||
# elif !defined(HAVE_DIOCGDINFO)
|
||||
struct hd_geometry hdg;
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
struct disklabel label;
|
||||
|
@ -506,7 +586,9 @@ devmapper_fail:
|
|||
return 0;
|
||||
}
|
||||
|
||||
# if !defined(HAVE_DIOCGDINFO)
|
||||
#if defined(__sun__)
|
||||
if (ioctl (fd, DKIOCEXTPARTINFO, &pinfo))
|
||||
# elif !defined(HAVE_DIOCGDINFO)
|
||||
if (ioctl (fd, HDIO_GETGEO, &hdg))
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
# if defined(__NetBSD__)
|
||||
|
@ -527,7 +609,9 @@ devmapper_fail:
|
|||
|
||||
close (fd);
|
||||
|
||||
# if !defined(HAVE_DIOCGDINFO)
|
||||
#ifdef __sun__
|
||||
return pinfo.p_start;
|
||||
# elif !defined(HAVE_DIOCGDINFO)
|
||||
return hdg.start;
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
if (dev[0])
|
||||
|
@ -567,6 +651,7 @@ linux_find_partition (char *dev, grub_disk_addr_t sector)
|
|||
int i;
|
||||
char real_dev[PATH_MAX];
|
||||
struct linux_partition_cache *cache;
|
||||
int missing = 0;
|
||||
|
||||
strcpy(real_dev, dev);
|
||||
|
||||
|
@ -575,6 +660,12 @@ linux_find_partition (char *dev, grub_disk_addr_t 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;
|
||||
|
@ -605,7 +696,13 @@ linux_find_partition (char *dev, grub_disk_addr_t sector)
|
|||
|
||||
fd = open (real_dev, O_RDONLY);
|
||||
if (fd == -1)
|
||||
continue;
|
||||
{
|
||||
if (missing++ < 10)
|
||||
continue;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
missing = 0;
|
||||
close (fd);
|
||||
|
||||
start = find_partition_start (real_dev);
|
||||
|
@ -632,6 +729,37 @@ linux_find_partition (char *dev, grub_disk_addr_t sector)
|
|||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
#if defined(__linux__) && (!defined(__GLIBC__) || \
|
||||
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
|
||||
/* Maybe libc doesn't have large file support. */
|
||||
grub_err_t
|
||||
grub_util_fd_seek (int fd, const char *name, grub_uint64_t off)
|
||||
{
|
||||
loff_t offset, result;
|
||||
static int _llseek (uint filedes, ulong hi, ulong lo,
|
||||
loff_t *res, uint wh);
|
||||
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
|
||||
loff_t *, res, uint, wh);
|
||||
|
||||
offset = (loff_t) off;
|
||||
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
|
||||
{
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", name);
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
#else
|
||||
grub_err_t
|
||||
grub_util_fd_seek (int fd, const char *name, grub_uint64_t off)
|
||||
{
|
||||
off_t offset = (off_t) off;
|
||||
|
||||
if (lseek (fd, offset, SEEK_SET) != offset)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", name);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||
{
|
||||
|
@ -784,44 +912,20 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
|||
configure_device_driver (fd);
|
||||
#endif /* defined(__NetBSD__) */
|
||||
|
||||
#if defined(__linux__) && (!defined(__GLIBC__) || \
|
||||
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
|
||||
/* Maybe libc doesn't have large file support. */
|
||||
{
|
||||
loff_t offset, result;
|
||||
static int _llseek (uint filedes, ulong hi, ulong lo,
|
||||
loff_t *res, uint wh);
|
||||
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
|
||||
loff_t *, res, uint, wh);
|
||||
|
||||
offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
|
||||
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
|
||||
|
||||
if (lseek (fd, offset, SEEK_SET) != offset)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (grub_util_fd_seek (fd, map[disk->id].device,
|
||||
sector << disk->log_sector_size))
|
||||
{
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
|
||||
error occurs, otherwise return LEN. */
|
||||
static ssize_t
|
||||
nread (int fd, char *buf, size_t len)
|
||||
ssize_t
|
||||
grub_util_fd_read (int fd, char *buf, size_t len)
|
||||
{
|
||||
ssize_t size = len;
|
||||
|
||||
|
@ -904,19 +1008,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 (grub_util_fd_read (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 (grub_util_fd_read (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;
|
||||
|
@ -949,8 +1054,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;
|
||||
|
@ -1048,18 +1153,18 @@ read_device_map (const char *dev_map)
|
|||
continue;
|
||||
|
||||
if (*p != '(')
|
||||
show_error ("No open parenthesis found");
|
||||
show_error (_("No open parenthesis found"));
|
||||
|
||||
p++;
|
||||
/* Find a free slot. */
|
||||
drive = find_free_slot ();
|
||||
if (drive < 0)
|
||||
show_error ("Map table size exceeded");
|
||||
show_error (_("Map table size exceeded"));
|
||||
|
||||
e = p;
|
||||
p = strchr (p, ')');
|
||||
if (! p)
|
||||
show_error ("No close parenthesis found");
|
||||
show_error (_("No close parenthesis found"));
|
||||
|
||||
map[drive].drive = xmalloc (p - e + sizeof ('\0'));
|
||||
strncpy (map[drive].drive, e, p - e + sizeof ('\0'));
|
||||
|
@ -1072,7 +1177,7 @@ read_device_map (const char *dev_map)
|
|||
p++;
|
||||
|
||||
if (*p == '\0')
|
||||
show_error ("No filename found");
|
||||
show_error (_("No filename found"));
|
||||
|
||||
/* NUL-terminate the filename. */
|
||||
e = p;
|
||||
|
@ -1101,7 +1206,7 @@ read_device_map (const char *dev_map)
|
|||
{
|
||||
map[drive].device = xmalloc (PATH_MAX);
|
||||
if (! realpath (p, map[drive].device))
|
||||
grub_util_error ("cannot get the real path of `%s'", p);
|
||||
grub_util_error (_("cannot get the real path of `%s'"), p);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -1142,25 +1247,28 @@ grub_util_biosdisk_fini (void)
|
|||
static char *
|
||||
make_device_name (int drive, int dos_part, int bsd_part)
|
||||
{
|
||||
char *ret;
|
||||
char *dos_part_str = NULL;
|
||||
char *bsd_part_str = NULL;
|
||||
char *ret, *ptr, *end;
|
||||
const char *iptr;
|
||||
|
||||
ret = xmalloc (strlen (map[drive].drive) * 2
|
||||
+ sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
",XXXXXXXXXXXXXXXXXXXXXXXXXX"));
|
||||
end = (ret + strlen (map[drive].drive) * 2
|
||||
+ sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
",XXXXXXXXXXXXXXXXXXXXXXXXXX"));
|
||||
ptr = ret;
|
||||
for (iptr = map[drive].drive; *iptr; iptr++)
|
||||
{
|
||||
if (*iptr == ',')
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = *iptr;
|
||||
}
|
||||
*ptr = 0;
|
||||
if (dos_part >= 0)
|
||||
dos_part_str = xasprintf (",%d", dos_part + 1);
|
||||
|
||||
snprintf (ptr, end - ptr, ",%d", dos_part + 1);
|
||||
ptr += strlen (ptr);
|
||||
if (bsd_part >= 0)
|
||||
bsd_part_str = xasprintf (",%d", bsd_part + 1);
|
||||
|
||||
ret = xasprintf ("%s%s%s", map[drive].drive,
|
||||
dos_part_str ? : "",
|
||||
bsd_part_str ? : "");
|
||||
|
||||
if (dos_part_str)
|
||||
free (dos_part_str);
|
||||
|
||||
if (bsd_part_str)
|
||||
free (bsd_part_str);
|
||||
snprintf (ptr, end - ptr, ",%d", bsd_part + 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1418,7 +1526,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",
|
||||
(major << 8) | minor);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1496,7 +1605,7 @@ devmapper_out:
|
|||
char *out, *out2;
|
||||
if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0)
|
||||
return xstrdup (os_dev);
|
||||
follow_geom_up (os_dev + sizeof ("/dev/") - 1, NULL, &out);
|
||||
grub_util_follow_gpart_up (os_dev + sizeof ("/dev/") - 1, NULL, &out);
|
||||
|
||||
out2 = xasprintf ("/dev/%s", out);
|
||||
free (out);
|
||||
|
@ -1545,12 +1654,37 @@ devmapper_out:
|
|||
}
|
||||
return path;
|
||||
|
||||
#elif defined (__sun__)
|
||||
char *colon = grub_strrchr (os_dev, ':');
|
||||
if (grub_memcmp (os_dev, "/devices", sizeof ("/devices") - 1) == 0
|
||||
&& colon)
|
||||
{
|
||||
char *ret = xmalloc (colon - os_dev + sizeof (":q,raw"));
|
||||
grub_memcpy (ret, os_dev, colon - os_dev);
|
||||
grub_memcpy (ret + (colon - os_dev), ":q,raw", sizeof (":q,raw"));
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return xstrdup (os_dev);
|
||||
#else
|
||||
# warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly."
|
||||
return xstrdup (os_dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__sun__)
|
||||
static int
|
||||
device_is_wholedisk (const char *os_dev)
|
||||
{
|
||||
if (grub_memcmp (os_dev, "/devices/", sizeof ("/devices/") - 1) != 0)
|
||||
return 1;
|
||||
if (grub_memcmp (os_dev + strlen (os_dev) - (sizeof (":q,raw") - 1),
|
||||
":q,raw", (sizeof (":q,raw") - 1)) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__CYGWIN__)
|
||||
static int
|
||||
device_is_wholedisk (const char *os_dev)
|
||||
|
@ -1627,7 +1761,10 @@ find_system_device (const char *os_dev, struct stat *st, int convert, int add)
|
|||
}
|
||||
|
||||
if (!add)
|
||||
return -1;
|
||||
{
|
||||
free (os_disk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE (map))
|
||||
grub_util_error (_("device count exceeds limit"));
|
||||
|
@ -1657,6 +1794,9 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
{
|
||||
struct stat st;
|
||||
int drive;
|
||||
char *sys_disk;
|
||||
|
||||
grub_util_info ("Looking for %s", os_dev);
|
||||
|
||||
if (stat (os_dev, &st) < 0)
|
||||
{
|
||||
|
@ -1674,18 +1814,22 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (grub_strcmp (os_dev,
|
||||
convert_system_partition_to_system_disk (os_dev, &st)) == 0)
|
||||
return make_device_name (drive, -1, -1);
|
||||
sys_disk = convert_system_partition_to_system_disk (os_dev, &st);
|
||||
if (grub_strcmp (os_dev, sys_disk) == 0)
|
||||
{
|
||||
free (sys_disk);
|
||||
return make_device_name (drive, -1, -1);
|
||||
}
|
||||
free (sys_disk);
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__)
|
||||
if (! S_ISCHR (st.st_mode))
|
||||
#else
|
||||
if (! S_ISBLK (st.st_mode))
|
||||
#endif
|
||||
return make_device_name (drive, -1, -1);
|
||||
|
||||
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__sun__)
|
||||
|
||||
/* Linux counts partitions uniformly, whether a BSD partition or a DOS
|
||||
partition, so mapping them to GRUB devices is not trivial.
|
||||
|
@ -1725,7 +1869,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
|
||||
name = make_device_name (drive, -1, -1);
|
||||
|
||||
# if !defined(HAVE_DIOCGDINFO)
|
||||
# if !defined(HAVE_DIOCGDINFO) && !defined(__sun__)
|
||||
if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)
|
||||
return name;
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
|
@ -1788,6 +1932,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
if (partname == NULL)
|
||||
{
|
||||
grub_disk_close (disk);
|
||||
grub_util_info ("cannot find the partition of `%s'", os_dev);
|
||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
"cannot find the partition of `%s'", os_dev);
|
||||
return 0;
|
||||
|
@ -1851,6 +1996,9 @@ grub_util_biosdisk_is_floppy (grub_disk_t disk)
|
|||
struct stat st;
|
||||
int fd;
|
||||
|
||||
if (disk->dev != &grub_util_biosdisk_dev)
|
||||
return 0;
|
||||
|
||||
fd = open (map[disk->id].device, O_RDONLY);
|
||||
/* Shouldn't happen. */
|
||||
if (fd == -1)
|
||||
|
@ -1858,7 +2006,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)
|
||||
|
|
|
@ -49,15 +49,11 @@
|
|||
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;
|
||||
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
grub_addr_t grub_modbase = 0;
|
||||
|
||||
void
|
||||
grub_reboot (void)
|
||||
|
@ -71,11 +67,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
|
||||
|
@ -103,14 +98,14 @@ usage (int status)
|
|||
{
|
||||
if (status)
|
||||
fprintf (stderr,
|
||||
"Try `%s --help' for more information.\n", program_name);
|
||||
_("Try `%s --help' for more information.\n"), program_name);
|
||||
else
|
||||
printf (
|
||||
"Usage: %s [OPTION]...\n"
|
||||
_("Usage: %s [OPTION]...\n"
|
||||
"\n"
|
||||
"GRUB emulator.\n"
|
||||
"\n"
|
||||
" -r, --root-device=DEV use DEV as the root device [default=guessed]\n"
|
||||
" -r, --root-device=DEV use DEV as the root device [default=host]\n"
|
||||
" -m, --device-map=FILE use FILE as the device map [default=%s]\n"
|
||||
" -d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n"
|
||||
" -v, --verbose print verbose messages\n"
|
||||
|
@ -118,7 +113,7 @@ usage (int status)
|
|||
" -h, --help display this message and exit\n"
|
||||
" -V, --version print version information and exit\n"
|
||||
"\n"
|
||||
"Report bugs to <%s>.\n", program_name, DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
|
||||
"Report bugs to <%s>.\n"), program_name, DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -132,22 +127,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;
|
||||
const 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;
|
||||
|
@ -169,13 +166,13 @@ main (int argc, char *argv[])
|
|||
|
||||
if (optind < argc)
|
||||
{
|
||||
fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind]);
|
||||
fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind]);
|
||||
return usage (1);
|
||||
}
|
||||
|
||||
/* Wait until the ARGS.HOLD variable is cleared by an attached debugger. */
|
||||
if (hold && verbosity > 0)
|
||||
printf ("Run \"gdb %s %d\", and set ARGS.HOLD to zero.\n",
|
||||
printf (_("Run \"gdb %s %d\", and set ARGS.HOLD to zero.\n"),
|
||||
program_name, (int) getpid ());
|
||||
while (hold)
|
||||
{
|
||||
|
@ -201,27 +198,9 @@ main (int argc, char *argv[])
|
|||
|
||||
/* Make sure that there is a root device. */
|
||||
if (! root_dev)
|
||||
{
|
||||
char *device_name = grub_guess_root_device (dir);
|
||||
if (! device_name)
|
||||
grub_util_error ("cannot find a device for %s", dir);
|
||||
root_dev = grub_strdup ("host");
|
||||
|
||||
root_dev = grub_util_get_grub_dev (device_name);
|
||||
if (! root_dev)
|
||||
{
|
||||
grub_util_info ("guessing the root device failed, because of `%s'",
|
||||
grub_errmsg);
|
||||
grub_util_error ("cannot guess the root device. Specify the option `--root-device'");
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp (root_dev, "host") == 0)
|
||||
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);
|
||||
dir = xstrdup (dir);
|
||||
|
||||
/* Start GRUB! */
|
||||
if (setjmp (main_env) == 0)
|
||||
|
|
|
@ -46,14 +46,6 @@
|
|||
# include <libdevmapper.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBZFS
|
||||
# include <grub/util/libzfs.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBNVPAIR
|
||||
# include <grub/util/libnvpair.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
@ -125,7 +117,7 @@ xmalloc (grub_size_t size)
|
|||
|
||||
p = malloc (size);
|
||||
if (! p)
|
||||
grub_util_error ("out of memory");
|
||||
grub_util_error (_("out of memory"));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -135,7 +127,7 @@ xrealloc (void *ptr, grub_size_t size)
|
|||
{
|
||||
ptr = realloc (ptr, size);
|
||||
if (! ptr)
|
||||
grub_util_error ("out of memory");
|
||||
grub_util_error (_("out of memory"));
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
@ -193,7 +185,7 @@ xasprintf (const char *fmt, ...)
|
|||
if (vasprintf (&result, fmt, ap) < 0)
|
||||
{
|
||||
if (errno == ENOMEM)
|
||||
grub_util_error ("out of memory");
|
||||
grub_util_error (_("out of memory"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -232,7 +224,11 @@ char *
|
|||
canonicalize_file_name (const char *path)
|
||||
{
|
||||
char *ret;
|
||||
#ifdef PATH_MAX
|
||||
#ifdef __MINGW32__
|
||||
ret = xmalloc (PATH_MAX);
|
||||
if (!_fullpath (ret, path, PATH_MAX))
|
||||
return NULL;
|
||||
#elif defined (PATH_MAX)
|
||||
ret = xmalloc (PATH_MAX);
|
||||
if (!realpath (path, ret))
|
||||
return NULL;
|
||||
|
@ -242,265 +238,6 @@ canonicalize_file_name (const char *path)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
/* Convert POSIX path to Win32 path,
|
||||
remove drive letter, replace backslashes. */
|
||||
static char *
|
||||
get_win32_path (const char *path)
|
||||
{
|
||||
char winpath[PATH_MAX];
|
||||
if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, path, winpath, sizeof(winpath)))
|
||||
grub_util_error ("cygwin_conv_path() failed");
|
||||
|
||||
int len = strlen (winpath);
|
||||
int offs = (len > 2 && winpath[1] == ':' ? 2 : 0);
|
||||
|
||||
int i;
|
||||
for (i = offs; i < len; i++)
|
||||
if (winpath[i] == '\\')
|
||||
winpath[i] = '/';
|
||||
return xstrdup (winpath + offs);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBZFS
|
||||
static libzfs_handle_t *__libzfs_handle;
|
||||
|
||||
static void
|
||||
fini_libzfs (void)
|
||||
{
|
||||
libzfs_fini (__libzfs_handle);
|
||||
}
|
||||
|
||||
libzfs_handle_t *
|
||||
grub_get_libzfs_handle (void)
|
||||
{
|
||||
if (! __libzfs_handle)
|
||||
{
|
||||
__libzfs_handle = libzfs_init ();
|
||||
|
||||
if (__libzfs_handle)
|
||||
atexit (fini_libzfs);
|
||||
}
|
||||
|
||||
return __libzfs_handle;
|
||||
}
|
||||
#endif /* HAVE_LIBZFS */
|
||||
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
/* ZFS has similar problems to those of btrfs (see above). */
|
||||
void
|
||||
grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs)
|
||||
{
|
||||
char *slash;
|
||||
|
||||
*poolname = *poolfs = NULL;
|
||||
|
||||
#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME)
|
||||
/* FreeBSD and GNU/kFreeBSD. */
|
||||
{
|
||||
struct statfs mnt;
|
||||
|
||||
if (statfs (dir, &mnt) != 0)
|
||||
return;
|
||||
|
||||
if (strcmp (mnt.f_fstypename, "zfs") != 0)
|
||||
return;
|
||||
|
||||
*poolname = xstrdup (mnt.f_mntfromname);
|
||||
}
|
||||
#elif defined(HAVE_GETEXTMNTENT)
|
||||
/* Solaris. */
|
||||
{
|
||||
struct stat st;
|
||||
struct extmnttab mnt;
|
||||
|
||||
if (stat (dir, &st) != 0)
|
||||
return;
|
||||
|
||||
FILE *mnttab = fopen ("/etc/mnttab", "r");
|
||||
if (! mnttab)
|
||||
return;
|
||||
|
||||
while (getextmntent (mnttab, &mnt, sizeof (mnt)) == 0)
|
||||
{
|
||||
if (makedev (mnt.mnt_major, mnt.mnt_minor) == st.st_dev
|
||||
&& !strcmp (mnt.mnt_fstype, "zfs"))
|
||||
{
|
||||
*poolname = xstrdup (mnt.mnt_special);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose (mnttab);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! *poolname)
|
||||
return;
|
||||
|
||||
slash = strchr (*poolname, '/');
|
||||
if (slash)
|
||||
{
|
||||
*slash = '\0';
|
||||
*poolfs = xstrdup (slash + 1);
|
||||
}
|
||||
else
|
||||
*poolfs = xstrdup ("");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function never prints trailing slashes (so that its output
|
||||
can be appended a slash unconditionally). */
|
||||
char *
|
||||
grub_make_system_path_relative_to_its_root (const char *path)
|
||||
{
|
||||
struct stat st;
|
||||
char *p, *buf, *buf2, *buf3, *ret;
|
||||
uintptr_t offset = 0;
|
||||
dev_t num;
|
||||
size_t len;
|
||||
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
char *poolfs = NULL;
|
||||
#endif
|
||||
|
||||
/* canonicalize. */
|
||||
p = canonicalize_file_name (path);
|
||||
if (p == NULL)
|
||||
grub_util_error ("failed to get canonical path of %s", path);
|
||||
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
/* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */
|
||||
{
|
||||
char *dummy;
|
||||
grub_find_zpool_from_dir (p, &dummy, &poolfs);
|
||||
}
|
||||
#endif
|
||||
|
||||
len = strlen (p) + 1;
|
||||
buf = xstrdup (p);
|
||||
free (p);
|
||||
|
||||
if (stat (buf, &st) < 0)
|
||||
grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
|
||||
|
||||
buf2 = xstrdup (buf);
|
||||
num = st.st_dev;
|
||||
|
||||
/* This loop sets offset to the number of chars of the root
|
||||
directory we're inspecting. */
|
||||
while (1)
|
||||
{
|
||||
p = strrchr (buf, '/');
|
||||
if (p == NULL)
|
||||
/* This should never happen. */
|
||||
grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)");
|
||||
if (p != buf)
|
||||
*p = 0;
|
||||
else
|
||||
*++p = 0;
|
||||
|
||||
if (stat (buf, &st) < 0)
|
||||
grub_util_error ("cannot stat %s: %s", buf, strerror (errno));
|
||||
|
||||
/* buf is another filesystem; we found it. */
|
||||
if (st.st_dev != num)
|
||||
{
|
||||
/* offset == 0 means path given is the mount point.
|
||||
This works around special-casing of "/" in Un*x. This function never
|
||||
prints trailing slashes (so that its output can be appended a slash
|
||||
unconditionally). Each slash in is considered a preceding slash, and
|
||||
therefore the root directory is an empty string. */
|
||||
if (offset == 0)
|
||||
{
|
||||
free (buf);
|
||||
#ifdef __linux__
|
||||
{
|
||||
char *bind;
|
||||
grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
|
||||
if (bind && bind[0] && bind[1])
|
||||
{
|
||||
buf3 = bind;
|
||||
goto parsedir;
|
||||
}
|
||||
grub_free (bind);
|
||||
}
|
||||
#endif
|
||||
free (buf2);
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
if (poolfs)
|
||||
return xasprintf ("/%s/@", poolfs);
|
||||
#endif
|
||||
return xstrdup ("");
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
offset = p - buf;
|
||||
/* offset == 1 means root directory. */
|
||||
if (offset == 1)
|
||||
{
|
||||
/* Include leading slash. */
|
||||
offset = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free (buf);
|
||||
buf3 = xstrdup (buf2 + offset);
|
||||
buf2[offset] = 0;
|
||||
#ifdef __linux__
|
||||
{
|
||||
char *bind;
|
||||
grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
|
||||
if (bind && bind[0] && bind[1])
|
||||
{
|
||||
char *temp = buf3;
|
||||
buf3 = grub_xasprintf ("%s%s%s", bind, buf3[0] == '/' ?"":"/", buf3);
|
||||
grub_free (temp);
|
||||
}
|
||||
grub_free (bind);
|
||||
}
|
||||
#endif
|
||||
|
||||
free (buf2);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16))
|
||||
{
|
||||
/* Reached some mount point not below /cygdrive.
|
||||
GRUB does not know Cygwin's emulated mounts,
|
||||
convert to Win32 path. */
|
||||
grub_util_info ("Cygwin path = %s\n", buf3);
|
||||
char * temp = get_win32_path (buf3);
|
||||
free (buf3);
|
||||
buf3 = temp;
|
||||
}
|
||||
#endif
|
||||
|
||||
parsedir:
|
||||
/* Remove trailing slashes, return empty string if root directory. */
|
||||
len = strlen (buf3);
|
||||
while (len > 0 && buf3[len - 1] == '/')
|
||||
{
|
||||
buf3[len - 1] = '\0';
|
||||
len--;
|
||||
}
|
||||
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
if (poolfs)
|
||||
{
|
||||
ret = xasprintf ("/%s/@%s", poolfs, buf3);
|
||||
free (buf3);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
ret = buf3;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
static void device_mapper_null_log (int level __attribute__ ((unused)),
|
||||
const char *file __attribute__ ((unused)),
|
||||
|
|
|
@ -77,7 +77,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
|||
#else
|
||||
(void) align;
|
||||
(void) size;
|
||||
grub_util_error ("grub_memalign is not supported");
|
||||
grub_util_error (_("grub_memalign is not supported"));
|
||||
#endif
|
||||
|
||||
if (!p)
|
||||
|
|
|
@ -132,7 +132,7 @@ grub_env_set (const char *name, const char *val)
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
char *
|
||||
const char *
|
||||
grub_env_get (const char *name)
|
||||
{
|
||||
struct grub_env_var *var;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -38,8 +38,9 @@
|
|||
#include <grub/machine/kernel.h>
|
||||
#endif
|
||||
|
||||
extern char _start[];
|
||||
extern char _end[];
|
||||
extern grub_uint8_t _start[];
|
||||
extern grub_uint8_t _end[];
|
||||
extern grub_uint8_t _edata[];
|
||||
|
||||
grub_uint32_t
|
||||
grub_get_rtc (void)
|
||||
|
@ -56,10 +57,18 @@ grub_exit (void)
|
|||
grub_cpu_idle ();
|
||||
}
|
||||
|
||||
#ifdef GRUB_MACHINE_QEMU
|
||||
grub_addr_t grub_modbase;
|
||||
#else
|
||||
grub_addr_t grub_modbase = ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN);
|
||||
#endif
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
#ifdef GRUB_MACHINE_QEMU
|
||||
grub_modbase = grub_core_entry_addr + (_edata - _start);
|
||||
|
||||
grub_qemu_init_cirrus ();
|
||||
#endif
|
||||
/* Initialize the console as early as possible. */
|
||||
|
@ -107,10 +116,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
|
||||
|
@ -119,14 +127,3 @@ grub_machine_fini (void)
|
|||
grub_vga_text_fini ();
|
||||
grub_stop_floppy ();
|
||||
}
|
||||
|
||||
/* Return the end of the core image. */
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
#ifdef GRUB_MACHINE_QEMU
|
||||
return grub_core_entry_addr + grub_kernel_image_size;
|
||||
#else
|
||||
return ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -38,36 +38,6 @@
|
|||
.globl start, _start
|
||||
start:
|
||||
_start:
|
||||
jmp codestart
|
||||
|
||||
/*
|
||||
* This is a special data area at a fixed offset from the beginning.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
/*
|
||||
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
|
||||
*/
|
||||
.p2align 2 /* force 4-byte alignment */
|
||||
multiboot_header:
|
||||
/* magic */
|
||||
.long 0x1BADB002
|
||||
/* flags */
|
||||
.long MULTIBOOT_MEMORY_INFO
|
||||
/* checksum */
|
||||
.long -0x1BADB002 - MULTIBOOT_MEMORY_INFO
|
||||
|
||||
codestart:
|
||||
#ifdef GRUB_MACHINE_MULTIBOOT
|
||||
cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
|
||||
jne 0f
|
||||
|
@ -81,9 +51,22 @@ codestart:
|
|||
/* jump to the main body of C code */
|
||||
jmp EXT_C(grub_main)
|
||||
|
||||
/*
|
||||
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
|
||||
*/
|
||||
.p2align 2 /* force 4-byte alignment */
|
||||
multiboot_header:
|
||||
/* magic */
|
||||
.long 0x1BADB002
|
||||
/* flags */
|
||||
.long MULTIBOOT_MEMORY_INFO
|
||||
/* checksum */
|
||||
.long -0x1BADB002 - MULTIBOOT_MEMORY_INFO
|
||||
|
||||
/*
|
||||
* prot_to_real and associated structures (but NOT real_to_prot, that is
|
||||
* only needed for BIOS gates).
|
||||
*/
|
||||
#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 ();
|
||||
}
|
||||
|
|
|
@ -19,40 +19,12 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/boot.h>
|
||||
|
||||
.file "startup.S"
|
||||
.text
|
||||
.globl start, _start
|
||||
start:
|
||||
_start:
|
||||
jmp codestart
|
||||
|
||||
/*
|
||||
* Compatibility version number
|
||||
*
|
||||
* These MUST be at byte offset 6 and 7 of the executable
|
||||
* DO NOT MOVE !!!
|
||||
*/
|
||||
. = _start + 0x6
|
||||
.byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
|
||||
|
||||
/*
|
||||
* This is a special data area 8 bytes from the beginning.
|
||||
*/
|
||||
|
||||
. = _start + 0x8
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + 0x50
|
||||
|
||||
codestart:
|
||||
/*
|
||||
* EFI_SYSTEM_TABLE * and EFI_HANDLE are passed on the stack.
|
||||
*/
|
||||
|
@ -62,5 +34,3 @@ codestart:
|
|||
movl %eax, EXT_C(grub_efi_system_table)
|
||||
call EXT_C(grub_main)
|
||||
ret
|
||||
|
||||
#include "../realmode.S"
|
||||
|
|
|
@ -36,30 +36,6 @@
|
|||
|
||||
start:
|
||||
_start:
|
||||
jmp codestart
|
||||
|
||||
/*
|
||||
* This is a special data area at a fixed offset from the beginning.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
codestart:
|
||||
movl %eax, EXT_C(grub_ieee1275_entry_fn)
|
||||
jmp EXT_C(grub_main)
|
||||
|
||||
/*
|
||||
* prot_to_real and associated structures (but NOT real_to_prot, that is
|
||||
* only needed for BIOS gates).
|
||||
*/
|
||||
#include "../realmode.S"
|
||||
|
||||
|
|
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
|
||||
|
||||
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
|
||||
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,62 @@ 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);
|
||||
|
||||
/*
|
||||
* return the real time in ticks, of which there are about
|
||||
* 18-20 per second
|
||||
*/
|
||||
grub_uint32_t
|
||||
grub_get_rtc (void)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
|
||||
regs.eax = 0;
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
grub_bios_interrupt (0x1a, ®s);
|
||||
|
||||
return (regs.ecx << 16) | (regs.edx & 0xffff);
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_get_bootlocation (char **device, char **path)
|
||||
{
|
||||
char *ptr;
|
||||
grub_uint8_t boot_drive, dos_part, bsd_part;
|
||||
|
||||
boot_drive = (grub_boot_device >> 24);
|
||||
dos_part = (grub_boot_device >> 16);
|
||||
bsd_part = (grub_boot_device >> 8);
|
||||
|
||||
/* No hardcoded root partition - make it from the boot drive and the
|
||||
partition number encoded at the install time. */
|
||||
if (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", (boot_drive & 0x80) ? 'h' : 'f',
|
||||
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 (dos_part != 0xff)
|
||||
grub_snprintf (ptr, DEV_SIZE - (ptr - *device),
|
||||
",%u", 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 (bsd_part != 0xff)
|
||||
grub_snprintf (ptr, DEV_SIZE - (ptr - *device), ",%u",
|
||||
bsd_part + 1);
|
||||
ptr += grub_strlen (ptr);
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
/* Add a memory region. */
|
||||
|
@ -140,6 +150,9 @@ compact_mem_regions (void)
|
|||
}
|
||||
}
|
||||
|
||||
grub_addr_t grub_modbase;
|
||||
extern grub_uint8_t _start[], _edata[];
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
|
@ -148,6 +161,8 @@ grub_machine_init (void)
|
|||
int grub_lower_mem;
|
||||
#endif
|
||||
|
||||
grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start);
|
||||
|
||||
/* Initialize the console as early as possible. */
|
||||
grub_console_init ();
|
||||
|
||||
|
@ -211,24 +226,9 @@ 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)
|
||||
{
|
||||
grub_console_fini ();
|
||||
grub_stop_floppy ();
|
||||
}
|
||||
|
||||
/* Return the end of the core image. */
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
|
||||
+ (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
|
||||
}
|
||||
|
|
|
@ -1,614 +0,0 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define FIXED_PROPS
|
||||
|
||||
#define LZMA_BASE_SIZE 1846
|
||||
#define LZMA_LIT_SIZE 768
|
||||
|
||||
#define LZMA_PROPERTIES_SIZE 5
|
||||
|
||||
#define kNumTopBits 24
|
||||
#define kTopValue (1 << kNumTopBits)
|
||||
|
||||
#define kNumBitModelTotalBits 11
|
||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||
#define kNumMoveBits 5
|
||||
|
||||
|
||||
#define kNumPosBitsMax 4
|
||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
||||
|
||||
#define kLenNumLowBits 3
|
||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
||||
#define kLenNumMidBits 3
|
||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
||||
#define kLenNumHighBits 8
|
||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
||||
|
||||
#define LenChoice 0
|
||||
#define LenChoice2 (LenChoice + 1)
|
||||
#define LenLow (LenChoice2 + 1)
|
||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
||||
|
||||
|
||||
#define kNumStates 12
|
||||
#define kNumLitStates 7
|
||||
|
||||
#define kStartPosModelIndex 4
|
||||
#define kEndPosModelIndex 14
|
||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
||||
|
||||
#define kNumPosSlotBits 6
|
||||
#define kNumLenToPosStates 4
|
||||
|
||||
#define kNumAlignBits 4
|
||||
#define kAlignTableSize (1 << kNumAlignBits)
|
||||
|
||||
#define kMatchMinLen 2
|
||||
|
||||
#define IsMatch 0
|
||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
||||
#define IsRepG0 (IsRep + kNumStates)
|
||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
||||
#define LenCoder (Align + kAlignTableSize)
|
||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
||||
#define Literal (RepLenCoder + kNumLenProbs)
|
||||
|
||||
#define out_size 8(%ebp)
|
||||
|
||||
#define now_pos -4(%ebp)
|
||||
#define prev_byte -8(%ebp)
|
||||
#define range -12(%ebp)
|
||||
#define code -16(%ebp)
|
||||
#define state -20(%ebp)
|
||||
#define rep0 -24(%ebp)
|
||||
#define rep1 -28(%ebp)
|
||||
#define rep2 -32(%ebp)
|
||||
#define rep3 -36(%ebp)
|
||||
|
||||
#ifdef FIXED_PROPS
|
||||
|
||||
#define FIXED_LC 3
|
||||
#define FIXED_LP 0
|
||||
#define FIXED_PB 2
|
||||
|
||||
#define POS_STATE_MASK ((1 << (FIXED_PB)) - 1)
|
||||
#define LIT_POS_MASK ((1 << (FIXED_LP)) - 1)
|
||||
|
||||
#define LOCAL_SIZE 36
|
||||
|
||||
#else
|
||||
|
||||
#define lc (%ebx)
|
||||
#define lp 4(%ebx)
|
||||
#define pb 8(%ebx)
|
||||
#define probs 12(%ebx)
|
||||
|
||||
#define pos_state_mask -40(%ebp)
|
||||
#define lit_pos_mask -44(%ebp)
|
||||
|
||||
#define LOCAL_SIZE 44
|
||||
|
||||
#endif
|
||||
|
||||
RangeDecoderBitDecode:
|
||||
#ifdef FIXED_PROPS
|
||||
leal (%ebx, %eax, 4), %eax
|
||||
#else
|
||||
shll $2, %eax
|
||||
addl probs, %eax
|
||||
#endif
|
||||
|
||||
movl %eax, %ecx
|
||||
movl (%ecx), %eax
|
||||
|
||||
movl range, %edx
|
||||
shrl $kNumBitModelTotalBits, %edx
|
||||
mull %edx
|
||||
|
||||
cmpl code, %eax
|
||||
jbe 1f
|
||||
|
||||
movl %eax, range
|
||||
movl $kBitModelTotal, %edx
|
||||
subl (%ecx), %edx
|
||||
shrl $kNumMoveBits, %edx
|
||||
addl %edx, (%ecx)
|
||||
clc
|
||||
3:
|
||||
pushf
|
||||
cmpl $kTopValue, range
|
||||
jnc 2f
|
||||
shll $8, code
|
||||
lodsb
|
||||
movb %al, code
|
||||
shll $8, range
|
||||
2:
|
||||
popf
|
||||
ret
|
||||
1:
|
||||
subl %eax, range
|
||||
subl %eax, code
|
||||
movl (%ecx), %edx
|
||||
shrl $kNumMoveBits, %edx
|
||||
subl %edx, (%ecx)
|
||||
stc
|
||||
jmp 3b
|
||||
|
||||
RangeDecoderBitTreeDecode:
|
||||
RangeDecoderReverseBitTreeDecode:
|
||||
movzbl %cl, %ecx
|
||||
xorl %edx, %edx
|
||||
pushl %edx
|
||||
incl %edx
|
||||
pushl %edx
|
||||
|
||||
1:
|
||||
pushl %eax
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
|
||||
addl %edx, %eax
|
||||
call RangeDecoderBitDecode
|
||||
|
||||
popl %edx
|
||||
popl %ecx
|
||||
|
||||
jnc 2f
|
||||
movl 4(%esp), %eax
|
||||
orl %eax, 8(%esp)
|
||||
stc
|
||||
|
||||
2:
|
||||
adcl %edx, %edx
|
||||
popl %eax
|
||||
|
||||
shll $1, (%esp)
|
||||
loop 1b
|
||||
|
||||
popl %ecx
|
||||
subl %ecx, %edx /* RangeDecoderBitTreeDecode */
|
||||
popl %ecx /* RangeDecoderReverseBitTreeDecode */
|
||||
ret
|
||||
|
||||
LzmaLenDecode:
|
||||
pushl %eax
|
||||
addl $LenChoice, %eax
|
||||
call RangeDecoderBitDecode
|
||||
popl %eax
|
||||
jc 1f
|
||||
pushl $0
|
||||
movb $kLenNumLowBits, %cl
|
||||
addl $LenLow, %eax
|
||||
2:
|
||||
movl 12(%esp), %edx
|
||||
shll %cl, %edx
|
||||
addl %edx, %eax
|
||||
3:
|
||||
|
||||
call RangeDecoderBitTreeDecode
|
||||
popl %eax
|
||||
addl %eax, %edx
|
||||
ret
|
||||
|
||||
1:
|
||||
pushl %eax
|
||||
addl $LenChoice2, %eax
|
||||
call RangeDecoderBitDecode
|
||||
popl %eax
|
||||
jc 1f
|
||||
pushl $kLenNumLowSymbols
|
||||
movb $kLenNumMidBits, %cl
|
||||
addl $LenMid, %eax
|
||||
jmp 2b
|
||||
|
||||
1:
|
||||
pushl $(kLenNumLowSymbols + kLenNumMidSymbols)
|
||||
addl $LenHigh, %eax
|
||||
movb $kLenNumHighBits, %cl
|
||||
jmp 3b
|
||||
|
||||
WriteByte:
|
||||
movb %al, prev_byte
|
||||
stosb
|
||||
incl now_pos
|
||||
ret
|
||||
|
||||
/*
|
||||
* int LzmaDecode(CLzmaDecoderState *vs,
|
||||
* const unsigned char *inStream,
|
||||
* unsigned char *outStream,
|
||||
* SizeT outSize);
|
||||
*/
|
||||
|
||||
_LzmaDecodeA:
|
||||
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
subl $LOCAL_SIZE, %esp
|
||||
|
||||
#ifndef ASM_FILE
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
pushl %ebx
|
||||
|
||||
movl %eax, %ebx
|
||||
movl %edx, %esi
|
||||
pushl %ecx
|
||||
#else
|
||||
pushl %edi
|
||||
#endif
|
||||
|
||||
cld
|
||||
|
||||
#ifdef FIXED_PROPS
|
||||
movl %ebx, %edi
|
||||
movl $(Literal + (LZMA_LIT_SIZE << (FIXED_LC + FIXED_LP))), %ecx
|
||||
#else
|
||||
movl $LZMA_LIT_SIZE, %eax
|
||||
movb lc, %cl
|
||||
addb lp, %cl
|
||||
shll %cl, %eax
|
||||
addl $Literal, %eax
|
||||
movl %eax, %ecx
|
||||
movl probs, %edi
|
||||
#endif
|
||||
|
||||
movl $(kBitModelTotal >> 1), %eax
|
||||
|
||||
rep
|
||||
stosl
|
||||
|
||||
popl %edi
|
||||
|
||||
xorl %eax, %eax
|
||||
movl %eax, now_pos
|
||||
movl %eax, prev_byte
|
||||
movl %eax, state
|
||||
|
||||
incl %eax
|
||||
movl %eax, rep0
|
||||
movl %eax, rep1
|
||||
movl %eax, rep2
|
||||
movl %eax, rep3
|
||||
|
||||
#ifndef FIXED_PROPS
|
||||
movl %eax, %edx
|
||||
movb pb, %cl
|
||||
shll %cl, %edx
|
||||
decl %edx
|
||||
movl %edx, pos_state_mask
|
||||
|
||||
movl %eax, %edx
|
||||
movb lp, %cl
|
||||
shll %cl, %edx
|
||||
decl %edx
|
||||
movl %edx, lit_pos_mask;
|
||||
#endif
|
||||
|
||||
/* RangeDecoderInit */
|
||||
negl %eax
|
||||
movl %eax, range
|
||||
|
||||
incl %eax
|
||||
movb $5, %cl
|
||||
|
||||
1:
|
||||
shll $8, %eax
|
||||
lodsb
|
||||
loop 1b
|
||||
|
||||
movl %eax, code
|
||||
|
||||
lzma_decode_loop:
|
||||
movl now_pos, %eax
|
||||
cmpl out_size, %eax
|
||||
|
||||
jb 1f
|
||||
|
||||
#ifndef ASM_FILE
|
||||
xorl %eax, %eax
|
||||
|
||||
popl %ebx
|
||||
popl %edi
|
||||
popl %esi
|
||||
#endif
|
||||
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
1:
|
||||
#ifdef FIXED_PROPS
|
||||
andl $POS_STATE_MASK, %eax
|
||||
#else
|
||||
andl pos_state_mask, %eax
|
||||
#endif
|
||||
pushl %eax /* posState */
|
||||
movl state, %edx
|
||||
shll $kNumPosBitsMax, %edx
|
||||
addl %edx, %eax
|
||||
pushl %eax /* (state << kNumPosBitsMax) + posState */
|
||||
|
||||
call RangeDecoderBitDecode
|
||||
jc 1f
|
||||
|
||||
movl now_pos, %eax
|
||||
|
||||
#ifdef FIXED_PROPS
|
||||
andl $LIT_POS_MASK, %eax
|
||||
shll $FIXED_LC, %eax
|
||||
movl prev_byte, %edx
|
||||
shrl $(8 - FIXED_LC), %edx
|
||||
#else
|
||||
andl lit_pos_mask, %eax
|
||||
movb lc, %cl
|
||||
shll %cl, %eax
|
||||
negb %cl
|
||||
addb $8, %cl
|
||||
movl prev_byte, %edx
|
||||
shrl %cl, %edx
|
||||
#endif
|
||||
|
||||
addl %edx, %eax
|
||||
movl $LZMA_LIT_SIZE, %edx
|
||||
mull %edx
|
||||
addl $Literal, %eax
|
||||
pushl %eax
|
||||
|
||||
incl %edx /* edx = 1 */
|
||||
|
||||
movl rep0, %eax
|
||||
negl %eax
|
||||
pushl (%edi, %eax) /* matchByte */
|
||||
|
||||
cmpb $kNumLitStates, state
|
||||
jb 5f
|
||||
|
||||
/* LzmaLiteralDecodeMatch */
|
||||
|
||||
3:
|
||||
cmpl $0x100, %edx
|
||||
jae 4f
|
||||
|
||||
xorl %eax, %eax
|
||||
shlb $1, (%esp)
|
||||
adcl %eax, %eax
|
||||
|
||||
pushl %eax
|
||||
pushl %edx
|
||||
|
||||
shll $8, %eax
|
||||
leal 0x100(%edx, %eax), %eax
|
||||
addl 12(%esp), %eax
|
||||
call RangeDecoderBitDecode
|
||||
|
||||
setc %al
|
||||
popl %edx
|
||||
adcl %edx, %edx
|
||||
|
||||
popl %ecx
|
||||
cmpb %cl, %al
|
||||
jz 3b
|
||||
|
||||
5:
|
||||
|
||||
/* LzmaLiteralDecode */
|
||||
|
||||
cmpl $0x100, %edx
|
||||
jae 4f
|
||||
|
||||
pushl %edx
|
||||
movl %edx, %eax
|
||||
addl 8(%esp), %eax
|
||||
call RangeDecoderBitDecode
|
||||
popl %edx
|
||||
adcl %edx, %edx
|
||||
jmp 5b
|
||||
|
||||
4:
|
||||
addl $16, %esp
|
||||
|
||||
movb %dl, %al
|
||||
call WriteByte
|
||||
|
||||
movb state, %al
|
||||
cmpb $4, %al
|
||||
jae 2f
|
||||
xorb %al, %al
|
||||
jmp 3f
|
||||
2:
|
||||
subb $3, %al
|
||||
cmpb $7, %al
|
||||
jb 3f
|
||||
subb $3, %al
|
||||
3:
|
||||
movb %al, state
|
||||
jmp lzma_decode_loop
|
||||
|
||||
1:
|
||||
movl state, %eax
|
||||
addl $IsRep, %eax
|
||||
call RangeDecoderBitDecode
|
||||
jnc 1f
|
||||
|
||||
movl state, %eax
|
||||
addl $IsRepG0, %eax
|
||||
call RangeDecoderBitDecode
|
||||
jc 10f
|
||||
|
||||
movl (%esp), %eax
|
||||
addl $IsRep0Long, %eax
|
||||
call RangeDecoderBitDecode
|
||||
jc 20f
|
||||
|
||||
cmpb $7, state
|
||||
movb $9, state
|
||||
jb 100f
|
||||
addb $2, state
|
||||
100:
|
||||
|
||||
movl $1, %ecx
|
||||
|
||||
3:
|
||||
movl rep0, %edx
|
||||
negl %edx
|
||||
|
||||
4:
|
||||
movb (%edi, %edx), %al
|
||||
call WriteByte
|
||||
loop 4b
|
||||
|
||||
popl %eax
|
||||
popl %eax
|
||||
jmp lzma_decode_loop
|
||||
|
||||
10:
|
||||
movl state, %eax
|
||||
addl $IsRepG1, %eax
|
||||
call RangeDecoderBitDecode
|
||||
movl rep1, %edx
|
||||
jnc 100f
|
||||
|
||||
movl state, %eax
|
||||
addl $IsRepG2, %eax
|
||||
call RangeDecoderBitDecode
|
||||
movl rep2, %edx
|
||||
jnc 1000f
|
||||
movl rep2, %edx
|
||||
xchgl rep3, %edx
|
||||
1000:
|
||||
pushl rep1
|
||||
popl rep2
|
||||
100:
|
||||
xchg rep0, %edx
|
||||
movl %edx, rep1
|
||||
20:
|
||||
|
||||
movl $RepLenCoder, %eax
|
||||
call LzmaLenDecode
|
||||
|
||||
cmpb $7, state
|
||||
movb $8, state
|
||||
jb 100f
|
||||
addb $3, state
|
||||
100:
|
||||
jmp 2f
|
||||
|
||||
1:
|
||||
movl rep0, %eax
|
||||
xchgl rep1, %eax
|
||||
xchgl rep2, %eax
|
||||
movl %eax, rep3
|
||||
|
||||
cmpb $7, state
|
||||
movb $7, state
|
||||
jb 10f
|
||||
addb $3, state
|
||||
10:
|
||||
|
||||
movl $LenCoder, %eax
|
||||
call LzmaLenDecode
|
||||
pushl %edx
|
||||
|
||||
movl $(kNumLenToPosStates - 1), %eax
|
||||
cmpl %eax, %edx
|
||||
jbe 100f
|
||||
movl %eax, %edx
|
||||
100:
|
||||
movb $kNumPosSlotBits, %cl
|
||||
shll %cl, %edx
|
||||
leal PosSlot(%edx), %eax
|
||||
call RangeDecoderBitTreeDecode
|
||||
|
||||
movl %edx, rep0
|
||||
cmpl $kStartPosModelIndex, %edx
|
||||
jb 100f
|
||||
|
||||
movl %edx, %ecx
|
||||
shrl $1, %ecx
|
||||
decl %ecx
|
||||
|
||||
movzbl %dl, %eax
|
||||
andb $1, %al
|
||||
orb $2, %al
|
||||
shll %cl, %eax
|
||||
movl %eax, rep0
|
||||
|
||||
cmpl $kEndPosModelIndex, %edx
|
||||
jae 200f
|
||||
movl rep0, %eax
|
||||
addl $(SpecPos - 1), %eax
|
||||
subl %edx, %eax
|
||||
jmp 300f
|
||||
200:
|
||||
|
||||
subb $kNumAlignBits, %cl
|
||||
|
||||
/* RangeDecoderDecodeDirectBits */
|
||||
xorl %edx, %edx
|
||||
|
||||
1000:
|
||||
shrl $1, range
|
||||
shll $1, %edx
|
||||
|
||||
movl range, %eax
|
||||
cmpl %eax, code
|
||||
jb 2000f
|
||||
subl %eax, code
|
||||
orb $1, %dl
|
||||
2000:
|
||||
|
||||
cmpl $kTopValue, %eax
|
||||
jae 3000f
|
||||
shll $8, range
|
||||
shll $8, code
|
||||
lodsb
|
||||
movb %al, code
|
||||
|
||||
3000:
|
||||
loop 1000b
|
||||
|
||||
movb $kNumAlignBits, %cl
|
||||
shll %cl, %edx
|
||||
addl %edx, rep0
|
||||
|
||||
movl $Align, %eax
|
||||
|
||||
300:
|
||||
call RangeDecoderReverseBitTreeDecode
|
||||
addl %ecx, rep0
|
||||
|
||||
100:
|
||||
incl rep0
|
||||
popl %edx
|
||||
|
||||
2:
|
||||
|
||||
addl $kMatchMinLen, %edx
|
||||
movl %edx, %ecx
|
||||
|
||||
jmp 3b
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,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
|
||||
|
@ -43,211 +43,30 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/boot.h>
|
||||
#include <grub/machine/boot.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/console.h>
|
||||
#include <grub/cpu/linux.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/term.h>
|
||||
#include <multiboot.h>
|
||||
#include <multiboot2.h>
|
||||
|
||||
#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
|
||||
|
||||
.file "startup.S"
|
||||
|
||||
.text
|
||||
|
||||
/* Tell GAS to generate 16-bit instructions so that this code works
|
||||
in real mode. */
|
||||
.code16
|
||||
|
||||
.globl start, _start
|
||||
start:
|
||||
_start:
|
||||
LOCAL (base):
|
||||
/*
|
||||
* Guarantee that "main" is loaded at 0x0:0x8200.
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000)
|
||||
#else
|
||||
ljmp $0, $ABS(LOCAL (codestart))
|
||||
#endif
|
||||
/*
|
||||
* Compatibility version number
|
||||
*
|
||||
* These MUST be at byte offset 6 and 7 of the executable
|
||||
* DO NOT MOVE !!!
|
||||
*/
|
||||
. = _start + 0x6
|
||||
.byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
|
||||
|
||||
/*
|
||||
* This is a special data area 8 bytes from the beginning.
|
||||
*/
|
||||
|
||||
. = _start + 0x8
|
||||
|
||||
VARIABLE(grub_total_module_size)
|
||||
.long 0
|
||||
VARIABLE(grub_kernel_image_size)
|
||||
.long 0
|
||||
VARIABLE(grub_compressed_size)
|
||||
.long 0
|
||||
VARIABLE(grub_install_dos_part)
|
||||
.long 0xFFFFFFFF
|
||||
VARIABLE(grub_install_bsd_part)
|
||||
.long 0xFFFFFFFF
|
||||
reed_solomon_redundancy:
|
||||
.long 0
|
||||
|
||||
#ifdef APPLE_CC
|
||||
bss_start:
|
||||
.long 0
|
||||
bss_end:
|
||||
.long 0
|
||||
#endif
|
||||
/*
|
||||
* This is the area for all of the special variables.
|
||||
*/
|
||||
|
||||
VARIABLE(grub_boot_drive)
|
||||
.byte 0
|
||||
|
||||
/* the real mode code continues... */
|
||||
LOCAL (codestart):
|
||||
cli /* we're not safe here! */
|
||||
|
||||
/* set up %ds, %ss, and %es */
|
||||
xorw %ax, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %ss
|
||||
movw %ax, %es
|
||||
|
||||
/* set up the real mode/BIOS stack */
|
||||
movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
|
||||
movl %ebp, %esp
|
||||
|
||||
sti /* we're safe again */
|
||||
|
||||
/* save the boot drive */
|
||||
ADDR32 movb %dl, EXT_C(grub_boot_drive)
|
||||
|
||||
/* reset disk system (%ah = 0) */
|
||||
int $0x13
|
||||
|
||||
/* transition to protected mode */
|
||||
DATA32 call real_to_prot
|
||||
|
||||
/* The ".code32" directive takes GAS out of 16-bit mode. */
|
||||
.code32
|
||||
|
||||
incl %eax
|
||||
call grub_gate_a20
|
||||
|
||||
movl EXT_C(grub_compressed_size), %edx
|
||||
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx
|
||||
movl reed_solomon_redundancy, %ecx
|
||||
leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax
|
||||
call EXT_C (grub_reed_solomon_recover)
|
||||
jmp post_reed_solomon
|
||||
|
||||
#include <rs_decoder.S>
|
||||
|
||||
.text
|
||||
|
||||
. = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART
|
||||
/*
|
||||
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
|
||||
* This uses the a.out kludge to load raw binary to the area starting at 1MB,
|
||||
* and relocates itself after loaded.
|
||||
*/
|
||||
.p2align 2 /* force 4-byte alignment */
|
||||
multiboot_header:
|
||||
/* magic */
|
||||
.long 0x1BADB002
|
||||
/* flags */
|
||||
.long (1 << 16)
|
||||
/* checksum */
|
||||
.long -0x1BADB002 - (1 << 16)
|
||||
/* header addr */
|
||||
.long multiboot_header - _start + 0x100000 + 0x200
|
||||
/* load addr */
|
||||
.long 0x100000
|
||||
/* load end addr */
|
||||
.long 0
|
||||
/* bss end addr */
|
||||
.long 0
|
||||
/* entry addr */
|
||||
.long multiboot_entry - _start + 0x100000 + 0x200
|
||||
|
||||
multiboot_entry:
|
||||
.code32
|
||||
/* obtain the boot device */
|
||||
movl 12(%ebx), %edx
|
||||
|
||||
movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp
|
||||
movl %ebp, %esp
|
||||
|
||||
/* relocate the code */
|
||||
movl $(GRUB_KERNEL_MACHINE_RAW_SIZE + 0x200), %ecx
|
||||
addl EXT_C(grub_compressed_size) - _start + 0x100000 + 0x200, %ecx
|
||||
movl $0x100000, %esi
|
||||
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
|
||||
cld
|
||||
rep
|
||||
movsb
|
||||
/* jump to the real address */
|
||||
movl $multiboot_trampoline, %eax
|
||||
jmp *%eax
|
||||
|
||||
multiboot_trampoline:
|
||||
/* fill the boot information */
|
||||
movl %edx, %eax
|
||||
shrl $8, %eax
|
||||
xorl %ebx, %ebx
|
||||
cmpb $0xFF, %ah
|
||||
je 1f
|
||||
movb %ah, %bl
|
||||
movl %ebx, EXT_C(grub_install_dos_part)
|
||||
1:
|
||||
cmpb $0xFF, %al
|
||||
je 2f
|
||||
movb %al, %bl
|
||||
movl %ebx, EXT_C(grub_install_bsd_part)
|
||||
2:
|
||||
shrl $24, %edx
|
||||
movb $0xFF, %dh
|
||||
/* enter the usual booting */
|
||||
call prot_to_real
|
||||
jmp LOCAL (codestart)
|
||||
|
||||
post_reed_solomon:
|
||||
|
||||
#ifdef ENABLE_LZMA
|
||||
movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
|
||||
movl $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
movl EXT_C(grub_kernel_image_size), %ecx
|
||||
addl EXT_C(grub_total_module_size), %ecx
|
||||
subl $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx
|
||||
pushl %ecx
|
||||
leal (%edi, %ecx), %ebx
|
||||
call _LzmaDecodeA
|
||||
/* _LzmaDecodeA clears DF, so no need to run cld */
|
||||
popl %ecx
|
||||
popl %edi
|
||||
popl %esi
|
||||
#endif
|
||||
movl %ecx, (LOCAL(real_to_prot_addr) - _start) (%esi)
|
||||
movl %edi, (LOCAL(prot_to_real_addr) - _start) (%esi)
|
||||
|
||||
/* copy back the decompressed part (except the modules) */
|
||||
subl EXT_C(grub_total_module_size), %ecx
|
||||
movl $(_edata - _start), %ecx
|
||||
movl $(_start), %edi
|
||||
rep
|
||||
movsb
|
||||
|
||||
movl $LOCAL (cont), %esi
|
||||
jmp *%esi
|
||||
LOCAL(cont):
|
||||
|
||||
#if 0
|
||||
/* copy modules before cleaning out the bss */
|
||||
movl EXT_C(grub_total_module_size), %ecx
|
||||
|
@ -263,24 +82,12 @@ post_reed_solomon:
|
|||
movsb
|
||||
#endif
|
||||
|
||||
#ifdef APPLE_CC
|
||||
/* clean out the bss */
|
||||
bss_start_abs = ABS (bss_start)
|
||||
bss_end_abs = ABS (bss_end)
|
||||
|
||||
movl bss_start_abs, %edi
|
||||
|
||||
/* compute the bss length */
|
||||
movl bss_end_abs, %ecx
|
||||
subl %edi, %ecx
|
||||
#else
|
||||
/* clean out the bss */
|
||||
movl $BSS_START_SYMBOL, %edi
|
||||
|
||||
/* compute the bss length */
|
||||
movl $END_SYMBOL, %ecx
|
||||
subl %edi, %ecx
|
||||
#endif
|
||||
|
||||
/* clean out */
|
||||
xorl %eax, %eax
|
||||
|
@ -288,183 +95,27 @@ post_reed_solomon:
|
|||
rep
|
||||
stosb
|
||||
|
||||
movl %edx, EXT_C(grub_boot_device)
|
||||
|
||||
/*
|
||||
* Call the start of main body of C code.
|
||||
*/
|
||||
call EXT_C(grub_main)
|
||||
|
||||
#include "../realmode.S"
|
||||
|
||||
/*
|
||||
* grub_gate_a20(int on)
|
||||
*
|
||||
* Gate address-line 20 for high memory.
|
||||
*
|
||||
* This routine is probably overconservative in what it does, but so what?
|
||||
*
|
||||
* It also eats any keystrokes in the keyboard buffer. :-(
|
||||
*/
|
||||
|
||||
grub_gate_a20:
|
||||
movl %eax, %edx
|
||||
|
||||
gate_a20_test_current_state:
|
||||
/* first of all, test if already in a good state */
|
||||
call gate_a20_check_state
|
||||
cmpb %al, %dl
|
||||
jnz gate_a20_try_bios
|
||||
ret
|
||||
|
||||
gate_a20_try_bios:
|
||||
/* second, try a BIOS call */
|
||||
pushl %ebp
|
||||
call prot_to_real
|
||||
|
||||
.code16
|
||||
movw $0x2400, %ax
|
||||
testb %dl, %dl
|
||||
jz 1f
|
||||
incw %ax
|
||||
1: int $0x15
|
||||
|
||||
DATA32 call real_to_prot
|
||||
.code32
|
||||
|
||||
popl %ebp
|
||||
call gate_a20_check_state
|
||||
cmpb %al, %dl
|
||||
jnz gate_a20_try_system_control_port_a
|
||||
ret
|
||||
|
||||
gate_a20_try_system_control_port_a:
|
||||
/*
|
||||
* In macbook, the keyboard test would hang the machine, so we move
|
||||
* this forward.
|
||||
*/
|
||||
/* fourth, try the system control port A */
|
||||
inb $0x92
|
||||
andb $(~0x03), %al
|
||||
testb %dl, %dl
|
||||
jz 6f
|
||||
orb $0x02, %al
|
||||
6: outb $0x92
|
||||
|
||||
/* When turning off Gate A20, do not check the state strictly,
|
||||
because a failure is not fatal usually, and Gate A20 is always
|
||||
on some modern machines. */
|
||||
testb %dl, %dl
|
||||
jz 7f
|
||||
call gate_a20_check_state
|
||||
cmpb %al, %dl
|
||||
jnz gate_a20_try_keyboard_controller
|
||||
7: ret
|
||||
|
||||
gate_a20_flush_keyboard_buffer:
|
||||
inb $0x64
|
||||
andb $0x02, %al
|
||||
jnz gate_a20_flush_keyboard_buffer
|
||||
2:
|
||||
inb $0x64
|
||||
andb $0x01, %al
|
||||
jz 3f
|
||||
inb $0x60
|
||||
jmp 2b
|
||||
3:
|
||||
ret
|
||||
|
||||
gate_a20_try_keyboard_controller:
|
||||
/* third, try the keyboard controller */
|
||||
call gate_a20_flush_keyboard_buffer
|
||||
|
||||
movb $0xd1, %al
|
||||
outb $0x64
|
||||
4:
|
||||
inb $0x64
|
||||
andb $0x02, %al
|
||||
jnz 4b
|
||||
|
||||
movb $0xdd, %al
|
||||
testb %dl, %dl
|
||||
jz 5f
|
||||
orb $0x02, %al
|
||||
5: outb $0x60
|
||||
call gate_a20_flush_keyboard_buffer
|
||||
|
||||
/* output a dummy command (USB keyboard hack) */
|
||||
movb $0xff, %al
|
||||
outb $0x64
|
||||
call gate_a20_flush_keyboard_buffer
|
||||
|
||||
call gate_a20_check_state
|
||||
cmpb %al, %dl
|
||||
/* everything failed, so restart from the beginning */
|
||||
jnz gate_a20_try_bios
|
||||
ret
|
||||
|
||||
gate_a20_check_state:
|
||||
/* iterate the checking for a while */
|
||||
movl $100, %ecx
|
||||
1:
|
||||
call 3f
|
||||
cmpb %al, %dl
|
||||
jz 2f
|
||||
loop 1b
|
||||
2:
|
||||
ret
|
||||
3:
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
xorl %eax, %eax
|
||||
/* compare the byte at 0x8000 with that at 0x108000 */
|
||||
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
|
||||
pushl %ebx
|
||||
/* save the original byte in CL */
|
||||
movb (%ebx), %cl
|
||||
/* store the value at 0x108000 in AL */
|
||||
addl $0x100000, %ebx
|
||||
movb (%ebx), %al
|
||||
/* try to set one less value at 0x8000 */
|
||||
popl %ebx
|
||||
movb %al, %ch
|
||||
decb %ch
|
||||
movb %ch, (%ebx)
|
||||
/* serialize */
|
||||
outb %al, $0x80
|
||||
outb %al, $0x80
|
||||
/* obtain the value at 0x108000 in CH */
|
||||
pushl %ebx
|
||||
addl $0x100000, %ebx
|
||||
movb (%ebx), %ch
|
||||
/* this result is 1 if A20 is on or 0 if it is off */
|
||||
subb %ch, %al
|
||||
xorb $1, %al
|
||||
/* restore the original */
|
||||
popl %ebx
|
||||
movb %cl, (%ebx)
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
|
||||
#ifdef ENABLE_LZMA
|
||||
#include "lzma_decode.S"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The code beyond this point is compressed. Assert that the uncompressed
|
||||
* code fits GRUB_KERNEL_MACHINE_RAW_SIZE.
|
||||
*/
|
||||
. = _start + GRUB_KERNEL_MACHINE_RAW_SIZE
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
LOCAL(real_to_prot_addr):
|
||||
.long 0
|
||||
LOCAL(prot_to_real_addr):
|
||||
.long 0
|
||||
|
||||
.macro PROT_TO_REAL
|
||||
movl LOCAL(prot_to_real_addr), %eax
|
||||
call *%eax
|
||||
.endm
|
||||
|
||||
.macro REAL_TO_PROT
|
||||
movl LOCAL(real_to_prot_addr), %eax
|
||||
DATA32 call *%ax
|
||||
.endm
|
||||
|
||||
/*
|
||||
* grub_exit()
|
||||
|
@ -472,403 +123,17 @@ VARIABLE(grub_prefix)
|
|||
* Exit the system.
|
||||
*/
|
||||
FUNCTION(grub_exit)
|
||||
call prot_to_real
|
||||
PROT_TO_REAL
|
||||
.code16
|
||||
/* Tell the BIOS a boot failure. If this does not work, reboot. */
|
||||
int $0x18
|
||||
jmp cold_reboot
|
||||
/* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */
|
||||
xorw %ax, %ax
|
||||
movw $0x0472, %di
|
||||
movw %ax, (%di)
|
||||
ljmp $0xf000, $0xfff0
|
||||
.code32
|
||||
|
||||
/*
|
||||
* void grub_chainloader_real_boot (int drive, void *part_addr)
|
||||
*
|
||||
* This starts another boot loader.
|
||||
*/
|
||||
|
||||
FUNCTION(grub_chainloader_real_boot)
|
||||
pushl %edx
|
||||
pushl %eax
|
||||
|
||||
/* Turn off Gate A20 */
|
||||
xorl %eax, %eax
|
||||
call grub_gate_a20
|
||||
|
||||
/* set up to pass boot drive */
|
||||
popl %edx
|
||||
|
||||
/* ESI must point to a partition table entry */
|
||||
popl %esi
|
||||
|
||||
call prot_to_real
|
||||
.code16
|
||||
ljmp $0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR
|
||||
.code32
|
||||
|
||||
/*
|
||||
* void grub_console_putchar (int c)
|
||||
*
|
||||
* Put the character C on the console. Because GRUB wants to write a
|
||||
* character with an attribute, this implementation is a bit tricky.
|
||||
* If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh
|
||||
* (TELETYPE OUTPUT). Otherwise, save the original position, put a space,
|
||||
* save the current position, restore the original position, write the
|
||||
* character and the attribute, and restore the current position.
|
||||
*
|
||||
* The reason why this is so complicated is that there is no easy way to
|
||||
* get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't
|
||||
* support setting a background attribute.
|
||||
*/
|
||||
FUNCTION(grub_console_putchar)
|
||||
/* Retrieve the base character. */
|
||||
movl 0(%edx), %edx
|
||||
pusha
|
||||
movb EXT_C(grub_console_cur_color), %bl
|
||||
|
||||
call prot_to_real
|
||||
.code16
|
||||
movb %dl, %al
|
||||
xorb %bh, %bh
|
||||
|
||||
/* use teletype output if control character */
|
||||
cmpb $0x7, %al
|
||||
je 1f
|
||||
cmpb $0x8, %al
|
||||
je 1f
|
||||
cmpb $0xa, %al
|
||||
je 1f
|
||||
cmpb $0xd, %al
|
||||
je 1f
|
||||
|
||||
/* save the character and the attribute on the stack */
|
||||
pushw %ax
|
||||
pushw %bx
|
||||
|
||||
/* get the current position */
|
||||
movb $0x3, %ah
|
||||
int $0x10
|
||||
|
||||
/* check the column with the width */
|
||||
cmpb $79, %dl
|
||||
jl 2f
|
||||
|
||||
/* print CR and LF, if next write will exceed the width */
|
||||
movw $0x0e0d, %ax
|
||||
int $0x10
|
||||
movb $0x0a, %al
|
||||
int $0x10
|
||||
|
||||
/* get the current position */
|
||||
movb $0x3, %ah
|
||||
int $0x10
|
||||
|
||||
2:
|
||||
/* restore the character and the attribute */
|
||||
popw %bx
|
||||
popw %ax
|
||||
|
||||
/* write the character with the attribute */
|
||||
movb $0x9, %ah
|
||||
movw $1, %cx
|
||||
int $0x10
|
||||
|
||||
/* move the cursor forward */
|
||||
incb %dl
|
||||
movb $0x2, %ah
|
||||
int $0x10
|
||||
|
||||
jmp 3f
|
||||
|
||||
1: movw $1, %bx
|
||||
movb $0xe, %ah
|
||||
int $0x10
|
||||
|
||||
3: DATA32 call real_to_prot
|
||||
.code32
|
||||
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
LOCAL(bypass_table):
|
||||
.word 0x011b, 0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r'
|
||||
.word 0x1c00 | '\n'
|
||||
LOCAL(bypass_table_end):
|
||||
|
||||
/*
|
||||
* int grub_console_getkey (void)
|
||||
* if there is a character pending, return it; otherwise return -1
|
||||
* BIOS call "INT 16H Function 01H" to check whether a character is pending
|
||||
* Call with %ah = 0x1
|
||||
* Return:
|
||||
* If key waiting to be input:
|
||||
* %ah = keyboard scan code
|
||||
* %al = ASCII character
|
||||
* Zero flag = clear
|
||||
* else
|
||||
* Zero flag = set
|
||||
* BIOS call "INT 16H Function 00H" to read character from keyboard
|
||||
* Call with %ah = 0x0
|
||||
* Return: %ah = keyboard scan code
|
||||
* %al = ASCII character
|
||||
*/
|
||||
|
||||
FUNCTION(grub_console_getkey)
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
|
||||
call prot_to_real
|
||||
.code16
|
||||
|
||||
/*
|
||||
* Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would
|
||||
* cause the machine to hang at the second keystroke. However, we can
|
||||
* work around this problem by ensuring the presence of keystroke with
|
||||
* INT 16/AH = 1 before calling INT 16/AH = 0.
|
||||
*/
|
||||
|
||||
movb $1, %ah
|
||||
int $0x16
|
||||
jz notpending
|
||||
|
||||
movb $0, %ah
|
||||
int $0x16
|
||||
|
||||
xorl %edx, %edx
|
||||
movw %ax, %dx /* real_to_prot uses %eax */
|
||||
|
||||
DATA32 call real_to_prot
|
||||
.code32
|
||||
|
||||
movl $0xff, %eax
|
||||
testl %eax, %edx
|
||||
jz 1f
|
||||
|
||||
andl %edx, %eax
|
||||
cmpl $0x20, %eax
|
||||
jae 2f
|
||||
movl %edx, %eax
|
||||
leal LOCAL(bypass_table), %edi
|
||||
movl $((LOCAL(bypass_table_end) - LOCAL(bypass_table)) >> 1), %ecx
|
||||
repne scasw
|
||||
jz 3f
|
||||
|
||||
andl $0xff, %eax
|
||||
addl $(('a' - 1) | GRUB_TERM_CTRL), %eax
|
||||
jmp 2f
|
||||
3:
|
||||
andl $0xff, %eax
|
||||
jmp 2f
|
||||
|
||||
1: movl %edx, %eax
|
||||
shrl $8, %eax
|
||||
orl $GRUB_TERM_EXTENDED, %eax
|
||||
2:
|
||||
popl %edi
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
notpending:
|
||||
.code16
|
||||
DATA32 call real_to_prot
|
||||
.code32
|
||||
#if GRUB_TERM_NO_KEY != 0
|
||||
#error Fix this asm code
|
||||
#endif
|
||||
jmp 2b
|
||||
|
||||
|
||||
/*
|
||||
* grub_uint16_t grub_console_getxy (void)
|
||||
* BIOS call "INT 10H Function 03h" to get cursor position
|
||||
* Call with %ah = 0x03
|
||||
* %bh = page
|
||||
* Returns %ch = starting scan line
|
||||
* %cl = ending scan line
|
||||
* %dh = row (0 is top)
|
||||
* %dl = column (0 is left)
|
||||
*/
|
||||
|
||||
|
||||
FUNCTION(grub_console_getxy)
|
||||
pushl %ebp
|
||||
pushl %ebx /* save EBX */
|
||||
|
||||
call prot_to_real
|
||||
.code16
|
||||
|
||||
xorb %bh, %bh /* set page to 0 */
|
||||
movb $0x3, %ah
|
||||
int $0x10 /* get cursor position */
|
||||
|
||||
DATA32 call real_to_prot
|
||||
.code32
|
||||
|
||||
movb %dl, %ah
|
||||
movb %dh, %al
|
||||
|
||||
popl %ebx
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* void grub_console_gotoxy(grub_uint8_t x, grub_uint8_t y)
|
||||
* BIOS call "INT 10H Function 02h" to set cursor position
|
||||
* Call with %ah = 0x02
|
||||
* %bh = page
|
||||
* %dh = row (0 is top)
|
||||
* %dl = column (0 is left)
|
||||
*/
|
||||
|
||||
|
||||
FUNCTION(grub_console_gotoxy)
|
||||
pushl %ebp
|
||||
pushl %ebx /* save EBX */
|
||||
|
||||
movb %cl, %dh /* %dh = y */
|
||||
/* %dl = x */
|
||||
|
||||
call prot_to_real
|
||||
.code16
|
||||
|
||||
xorb %bh, %bh /* set page to 0 */
|
||||
movb $0x2, %ah
|
||||
int $0x10 /* set cursor position */
|
||||
|
||||
DATA32 call real_to_prot
|
||||
.code32
|
||||
|
||||
popl %ebx
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* void grub_console_cls (void)
|
||||
* BIOS call "INT 10H Function 09h" to write character and attribute
|
||||
* Call with %ah = 0x09
|
||||
* %al = (character)
|
||||
* %bh = (page number)
|
||||
* %bl = (attribute)
|
||||
* %cx = (number of times)
|
||||
*/
|
||||
|
||||
FUNCTION(grub_console_cls)
|
||||
pushl %ebp
|
||||
pushl %ebx /* save EBX */
|
||||
|
||||
call prot_to_real
|
||||
.code16
|
||||
|
||||
/* move the cursor to the beginning */
|
||||
movb $0x02, %ah
|
||||
xorb %bh, %bh
|
||||
xorw %dx, %dx
|
||||
int $0x10
|
||||
|
||||
/* write spaces to the entire screen */
|
||||
movw $0x0920, %ax
|
||||
movw $0x07, %bx
|
||||
movw $(80 * 25), %cx
|
||||
int $0x10
|
||||
|
||||
/* move back the cursor */
|
||||
movb $0x02, %ah
|
||||
int $0x10
|
||||
|
||||
DATA32 call real_to_prot
|
||||
.code32
|
||||
|
||||
popl %ebx
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* void grub_console_setcursor (int on)
|
||||
* BIOS call "INT 10H Function 01h" to set cursor type
|
||||
* Call with %ah = 0x01
|
||||
* %ch = cursor starting scanline
|
||||
* %cl = cursor ending scanline
|
||||
*/
|
||||
|
||||
console_cursor_state:
|
||||
.byte 1
|
||||
console_cursor_shape:
|
||||
.word 0
|
||||
|
||||
FUNCTION(grub_console_setcursor)
|
||||
pushl %ebp
|
||||
pushl %ebx
|
||||
|
||||
/* push ON */
|
||||
pushl %edx
|
||||
|
||||
/* check if the standard cursor shape has already been saved */
|
||||
movw console_cursor_shape, %ax
|
||||
testw %ax, %ax
|
||||
jne 1f
|
||||
|
||||
call prot_to_real
|
||||
.code16
|
||||
|
||||
movb $0x03, %ah
|
||||
xorb %bh, %bh
|
||||
int $0x10
|
||||
|
||||
DATA32 call real_to_prot
|
||||
.code32
|
||||
|
||||
cmp %cl, %ch
|
||||
jb 3f
|
||||
movw $0x0d0e, %cx
|
||||
3:
|
||||
movw %cx, console_cursor_shape
|
||||
1:
|
||||
/* set %cx to the designated cursor shape */
|
||||
movw $0x2000, %cx
|
||||
popl %eax
|
||||
testl %eax, %eax
|
||||
jz 2f
|
||||
movw console_cursor_shape, %cx
|
||||
2:
|
||||
call prot_to_real
|
||||
.code16
|
||||
|
||||
movb $0x1, %ah
|
||||
int $0x10
|
||||
|
||||
DATA32 call real_to_prot
|
||||
.code32
|
||||
|
||||
popl %ebx
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
/*
|
||||
* grub_get_rtc()
|
||||
* return the real time in ticks, of which there are about
|
||||
* 18-20 per second
|
||||
*/
|
||||
FUNCTION(grub_get_rtc)
|
||||
pushl %ebp
|
||||
|
||||
call prot_to_real /* enter real mode */
|
||||
.code16
|
||||
|
||||
/* %ax is already zero */
|
||||
int $0x1a
|
||||
|
||||
DATA32 call real_to_prot
|
||||
.code32
|
||||
|
||||
movl %ecx, %eax
|
||||
shll $16, %eax
|
||||
movw %dx, %ax
|
||||
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
/*
|
||||
* int grub_pxe_call (int func, void* data, grub_uint32_t pxe_rm_entry);
|
||||
*/
|
||||
|
@ -887,7 +152,7 @@ FUNCTION(grub_pxe_call)
|
|||
shll $16, %edx
|
||||
addl %eax, %edx
|
||||
|
||||
call prot_to_real
|
||||
PROT_TO_REAL
|
||||
.code16
|
||||
|
||||
pushl %ebx
|
||||
|
@ -899,7 +164,7 @@ FUNCTION(grub_pxe_call)
|
|||
addw $10, %sp
|
||||
movw %ax, %cx
|
||||
|
||||
DATA32 call real_to_prot
|
||||
REAL_TO_PROT
|
||||
.code32
|
||||
|
||||
movzwl %cx, %eax
|
||||
|
@ -910,102 +175,8 @@ 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)
|
||||
#include "../int.S"
|
||||
|
||||
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
|
||||
.bss
|
||||
VARIABLE(grub_boot_device)
|
||||
.long 0
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -32,16 +32,6 @@ _start:
|
|||
. = _start + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR
|
||||
VARIABLE(grub_core_entry_addr)
|
||||
.long 0
|
||||
VARIABLE(grub_kernel_image_size)
|
||||
.long 0
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
codestart:
|
||||
/* Relocate to low memory. First we figure out our location.
|
||||
|
@ -53,11 +43,7 @@ codestart:
|
|||
value of `grub_core_entry_addr' in %esi. */
|
||||
xorw %si, %si
|
||||
|
||||
/* ... which allows us to access `grub_kernel_image_size'
|
||||
before relocation. */
|
||||
movl (grub_kernel_image_size - _start)(%esi), %ecx
|
||||
|
||||
|
||||
movl $(_edata - _start), %ecx
|
||||
movl $_start, %edi
|
||||
cld
|
||||
rep
|
||||
|
@ -65,24 +51,12 @@ codestart:
|
|||
ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $1f
|
||||
1:
|
||||
|
||||
#ifdef APPLE_CC
|
||||
/* clean out the bss */
|
||||
bss_start_abs = ABS (bss_start)
|
||||
bss_end_abs = ABS (bss_end)
|
||||
|
||||
movl bss_start_abs, %edi
|
||||
|
||||
/* compute the bss length */
|
||||
movl bss_end_abs, %ecx
|
||||
subl %edi, %ecx
|
||||
#else
|
||||
/* clean out the bss */
|
||||
movl $BSS_START_SYMBOL, %edi
|
||||
|
||||
/* compute the bss length */
|
||||
movl $END_SYMBOL, %ecx
|
||||
subl %edi, %ecx
|
||||
#endif
|
||||
|
||||
/* clean out */
|
||||
xorl %eax, %eax
|
||||
|
|
|
@ -46,11 +46,19 @@
|
|||
* This is the area for all of the special variables.
|
||||
*/
|
||||
|
||||
.p2align 2 /* force 4-byte alignment */
|
||||
.p2align 5 /* force 4-byte alignment */
|
||||
|
||||
protstack:
|
||||
.long GRUB_MEMORY_MACHINE_PROT_STACK
|
||||
|
||||
.macro PROT_TO_REAL
|
||||
call prot_to_real
|
||||
.endm
|
||||
|
||||
.macro REAL_TO_PROT
|
||||
DATA32 call real_to_prot
|
||||
.endm
|
||||
|
||||
/*
|
||||
* This is the Global Descriptor Table
|
||||
*
|
||||
|
@ -71,7 +79,7 @@ protstack:
|
|||
* description.
|
||||
*/
|
||||
|
||||
.p2align 2 /* force 4-byte alignment */
|
||||
.p2align 5 /* force 4-byte alignment */
|
||||
gdt:
|
||||
.word 0, 0
|
||||
.byte 0, 0, 0, 0
|
||||
|
@ -105,6 +113,7 @@ gdt:
|
|||
.byte 0, 0x92, 0, 0
|
||||
|
||||
|
||||
.p2align 5
|
||||
/* this is the GDT descriptor */
|
||||
gdtdesc:
|
||||
.word 0x27 /* limit */
|
||||
|
@ -162,6 +171,25 @@ protcseg:
|
|||
|
||||
/* return on the old (or initialized) stack! */
|
||||
ret
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,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/i386/pc/memory.h>
|
||||
|
||||
prot_to_real:
|
||||
/* just in case, set GDT */
|
||||
|
@ -225,18 +253,3 @@ realcseg:
|
|||
DATA32 ret
|
||||
|
||||
.code32
|
||||
|
||||
/*
|
||||
* grub_reboot()
|
||||
*
|
||||
* Reboot the system. At the moment, rely on BIOS.
|
||||
*/
|
||||
FUNCTION(grub_reboot)
|
||||
call prot_to_real
|
||||
.code16
|
||||
cold_reboot:
|
||||
/* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */
|
||||
movw $0x0472, %di
|
||||
movw %ax, (%di)
|
||||
ljmp $0xf000, $0xfff0
|
||||
.code32
|
||||
|
|
|
@ -104,13 +104,13 @@ add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value)
|
|||
}
|
||||
}
|
||||
|
||||
static grub_uint8_t nopm[5] =
|
||||
static const grub_uint8_t nopm[5] =
|
||||
{
|
||||
/* [MLX] nop.m 0x0 */
|
||||
0x05, 0x00, 0x00, 0x00, 0x01
|
||||
};
|
||||
|
||||
static grub_uint8_t jump[0x20] =
|
||||
static const grub_uint8_t jump[0x20] =
|
||||
{
|
||||
/* ld8 r16=[r15],8 */
|
||||
0x02, 0x80, 0x20, 0x1e, 0x18, 0x14,
|
||||
|
|
|
@ -30,7 +30,6 @@ grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
|
|||
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. */
|
||||
|
@ -43,8 +42,6 @@ grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
|
|||
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)))
|
||||
|
|
|
@ -40,12 +40,6 @@ grub_machine_fini (void)
|
|||
grub_efi_fini ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
{
|
||||
grub_efi_set_prefix ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_arch_sync_caches (void *address, grub_size_t len)
|
||||
{
|
||||
|
|
|
@ -42,13 +42,3 @@ _start:
|
|||
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);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
|
||||
int
|
||||
grub_ieee1275_finddevice (char *name, grub_ieee1275_phandle_t *phandlep)
|
||||
grub_ieee1275_finddevice (const char *name, grub_ieee1275_phandle_t *phandlep)
|
||||
{
|
||||
struct find_device_args
|
||||
{
|
||||
|
@ -532,7 +532,7 @@ grub_ieee1275_release (grub_addr_t addr, grub_size_t size)
|
|||
|
||||
int
|
||||
grub_ieee1275_set_property (grub_ieee1275_phandle_t phandle,
|
||||
const char *propname, void *buf,
|
||||
const char *propname, const void *buf,
|
||||
grub_size_t size, grub_ssize_t *actual)
|
||||
{
|
||||
struct set_property_args
|
||||
|
|
|
@ -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,26 @@ grub_machine_init (void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static grub_uint64_t ieee1275_get_time_ms (void);
|
||||
|
||||
grub_addr_t grub_modbase;
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
grub_modbase = ALIGN_UP((grub_addr_t) _end
|
||||
+ GRUB_KERNEL_MACHINE_MOD_GAP,
|
||||
GRUB_KERNEL_MACHINE_MOD_ALIGN);
|
||||
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);
|
||||
}
|
||||
|
@ -266,9 +298,3 @@ grub_get_rtc (void)
|
|||
{
|
||||
return ieee1275_get_time_ms ();
|
||||
}
|
||||
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
return ALIGN_UP((grub_addr_t) _end + GRUB_KERNEL_MACHINE_MOD_GAP, GRUB_KERNEL_MACHINE_MOD_ALIGN);
|
||||
}
|
||||
|
|
|
@ -22,16 +22,19 @@
|
|||
#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. */
|
||||
int
|
||||
grub_children_iterate (char *devpath,
|
||||
grub_children_iterate (const char *devpath,
|
||||
int (*hook) (struct grub_ieee1275_devalias *alias))
|
||||
{
|
||||
grub_ieee1275_phandle_t dev;
|
||||
|
@ -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,93 @@ 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>". */
|
||||
grub_printf ("Unsupported type %s for device %s\n", type, device);
|
||||
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_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unsupported type %s for device %s", 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)
|
||||
{
|
||||
|
@ -403,10 +446,10 @@ grub_ieee1275_encode_devname (const char *path)
|
|||
/* GRUB partition 1 is OF partition 0. */
|
||||
partno++;
|
||||
|
||||
encoding = grub_xasprintf ("(%s,%d)", device, partno);
|
||||
encoding = grub_xasprintf ("%s,%d", device, partno);
|
||||
}
|
||||
else
|
||||
encoding = grub_xasprintf ("(%s)", device);
|
||||
encoding = grub_strdup (device);
|
||||
|
||||
grub_free (partition);
|
||||
grub_free (device);
|
||||
|
@ -414,16 +457,6 @@ grub_ieee1275_encode_devname (const char *path)
|
|||
return encoding;
|
||||
}
|
||||
|
||||
/* On i386, a firmware-independant grub_reboot() is provided by realmode.S. */
|
||||
#ifndef __i386__
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
grub_ieee1275_interpret ("reset-all", 0);
|
||||
for (;;) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Resolve aliases. */
|
||||
char *
|
||||
grub_ieee1275_canonicalise_devname (const char *path)
|
||||
|
@ -467,3 +500,4 @@ grub_ieee1275_canonicalise_devname (const char *path)
|
|||
grub_free (buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,45 +30,20 @@
|
|||
#include <grub/reader.h>
|
||||
#include <grub/parser.h>
|
||||
|
||||
void
|
||||
grub_module_iterate (int (*hook) (struct grub_module_header *header))
|
||||
{
|
||||
struct grub_module_info *modinfo;
|
||||
struct grub_module_header *header;
|
||||
grub_addr_t modbase;
|
||||
|
||||
modbase = grub_arch_modules_addr ();
|
||||
modinfo = (struct grub_module_info *) modbase;
|
||||
|
||||
/* Check if there are any modules. */
|
||||
if ((modinfo == 0) || modinfo->magic != GRUB_MODULE_MAGIC)
|
||||
return;
|
||||
|
||||
for (header = (struct grub_module_header *) (modbase + modinfo->offset);
|
||||
header < (struct grub_module_header *) (modbase + modinfo->size);
|
||||
header = (struct grub_module_header *) ((char *) header + header->size))
|
||||
{
|
||||
if (hook (header))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct grub_module_info *modinfo;
|
||||
grub_addr_t modbase;
|
||||
|
||||
modbase = grub_arch_modules_addr ();
|
||||
modinfo = (struct grub_module_info *) modbase;
|
||||
modinfo = (struct grub_module_info *) grub_modbase;
|
||||
|
||||
/* Check if there are any modules. */
|
||||
if ((modinfo == 0) || modinfo->magic != GRUB_MODULE_MAGIC)
|
||||
return modbase;
|
||||
return grub_modbase;
|
||||
|
||||
return modbase + modinfo->size;
|
||||
return grub_modbase + modinfo->size;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -76,42 +51,36 @@ grub_modules_get_end (void)
|
|||
static void
|
||||
grub_load_modules (void)
|
||||
{
|
||||
auto int hook (struct grub_module_header *);
|
||||
int hook (struct grub_module_header *header)
|
||||
{
|
||||
/* Not an ELF module, skip. */
|
||||
if (header->type != OBJ_TYPE_ELF)
|
||||
return 0;
|
||||
struct grub_module_header *header;
|
||||
FOR_MODULES (header)
|
||||
{
|
||||
/* Not an ELF module, skip. */
|
||||
if (header->type != OBJ_TYPE_ELF)
|
||||
continue;
|
||||
|
||||
if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header),
|
||||
(header->size - sizeof (struct grub_module_header))))
|
||||
grub_fatal ("%s", grub_errmsg);
|
||||
if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header),
|
||||
(header->size - sizeof (struct grub_module_header))))
|
||||
grub_fatal ("%s", grub_errmsg);
|
||||
|
||||
if (grub_errno)
|
||||
grub_print_error ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_module_iterate (hook);
|
||||
if (grub_errno)
|
||||
grub_print_error ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
grub_load_config (void)
|
||||
{
|
||||
auto int hook (struct grub_module_header *);
|
||||
int hook (struct grub_module_header *header)
|
||||
{
|
||||
/* Not an embedded config, skip. */
|
||||
if (header->type != OBJ_TYPE_CONFIG)
|
||||
return 0;
|
||||
|
||||
grub_parser_execute ((char *) header +
|
||||
sizeof (struct grub_module_header));
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_module_iterate (hook);
|
||||
struct grub_module_header *header;
|
||||
FOR_MODULES (header)
|
||||
{
|
||||
/* Not an embedded config, skip. */
|
||||
if (header->type != OBJ_TYPE_CONFIG)
|
||||
continue;
|
||||
|
||||
grub_parser_execute ((char *) header +
|
||||
sizeof (struct grub_module_header));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write hook for the environment variables of root. Remove surrounding
|
||||
|
@ -129,27 +98,81 @@ 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;
|
||||
char *prefix = NULL;
|
||||
struct grub_module_header *header;
|
||||
|
||||
FOR_MODULES (header)
|
||||
if (header->type == OBJ_TYPE_PREFIX)
|
||||
prefix = (char *) header + sizeof (struct grub_module_header);
|
||||
|
||||
grub_register_variable_hook ("root", 0, grub_env_write_root);
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
|
||||
if (prefix)
|
||||
{
|
||||
char *dev;
|
||||
|
||||
dev = grub_file_get_device_name (prefix);
|
||||
if (dev)
|
||||
char *pptr = NULL;
|
||||
if (prefix[0] == '(')
|
||||
{
|
||||
grub_env_set ("root", dev);
|
||||
grub_free (dev);
|
||||
pptr = grub_strrchr (prefix, ')');
|
||||
if (pptr)
|
||||
{
|
||||
device = grub_strndup (prefix + 1, pptr - prefix - 1);
|
||||
pptr++;
|
||||
}
|
||||
}
|
||||
if (!pptr)
|
||||
pptr = prefix;
|
||||
if (pptr[0])
|
||||
path = grub_strdup (pptr);
|
||||
}
|
||||
if ((!device || device[0] == ',' || !device[0]) || !path)
|
||||
grub_machine_get_bootlocation (&fwdevice, &fwpath);
|
||||
|
||||
if (!device && fwdevice)
|
||||
device = fwdevice;
|
||||
else if (fwdevice && (device[0] == ',' || !device[0]))
|
||||
{
|
||||
/* We have a partition, but still need to fill in the drive. */
|
||||
char *comma, *new_device;
|
||||
|
||||
comma = grub_strchr (fwdevice, ',');
|
||||
if (comma)
|
||||
{
|
||||
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_set;
|
||||
|
||||
prefix_set = grub_xasprintf ("(%s)%s", device, path ? : "");
|
||||
if (prefix_set)
|
||||
{
|
||||
grub_env_set ("prefix", prefix_set);
|
||||
grub_free (prefix_set);
|
||||
}
|
||||
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 +182,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;
|
||||
|
||||
|
@ -167,7 +190,7 @@ grub_load_normal_mode (void)
|
|||
}
|
||||
|
||||
/* The main routine. */
|
||||
void
|
||||
void __attribute__ ((noreturn))
|
||||
grub_main (void)
|
||||
{
|
||||
/* First of all, initialize the machine. */
|
||||
|
@ -187,8 +210,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");
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <grub/term.h>
|
||||
#include <grub/arc/arc.h>
|
||||
#include <grub/offsets.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
const char *type_names[] = {
|
||||
#ifdef GRUB_CPU_WORDS_BIGENDIAN
|
||||
|
@ -125,12 +126,14 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook)
|
|||
}
|
||||
|
||||
extern grub_uint32_t grub_total_modules_size;
|
||||
grub_addr_t grub_modbase;
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
struct grub_arc_memory_descriptor *cur = NULL;
|
||||
|
||||
grub_modbase = GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size;
|
||||
grub_console_init_early ();
|
||||
|
||||
/* FIXME: measure this. */
|
||||
|
@ -164,12 +167,6 @@ grub_machine_init (void)
|
|||
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)
|
||||
{
|
||||
|
@ -182,7 +179,7 @@ grub_halt (void)
|
|||
|
||||
grub_millisleep (1500);
|
||||
|
||||
grub_printf ("Shutdown failed\n");
|
||||
grub_puts_ (N_("Shutdown failed"));
|
||||
grub_refresh ();
|
||||
while (1);
|
||||
}
|
||||
|
@ -194,19 +191,7 @@ grub_exit (void)
|
|||
|
||||
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_puts_ (N_("Exit failed"));
|
||||
grub_refresh ();
|
||||
while (1);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,13 @@
|
|||
subu $t1, $t3, $t2
|
||||
1:
|
||||
cache 1, 0($t0)
|
||||
/* All four ways. */
|
||||
#ifdef GRUB_MACHINE_MIPS_LOONGSON
|
||||
cache 1, 1($t0)
|
||||
cache 1, 2($t0)
|
||||
cache 1, 3($t0)
|
||||
#endif
|
||||
|
||||
addiu $t1, $t1, -0x4
|
||||
bne $t1, $zero, 1b
|
||||
addiu $t0, $t0, 0x4
|
||||
|
|
|
@ -38,7 +38,7 @@ grub_get_rtc (void)
|
|||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
|
||||
char **path __attribute__ ((unused)))
|
||||
{
|
||||
grub_env_set ("prefix", grub_prefix);
|
||||
}
|
||||
|
|
|
@ -30,11 +30,12 @@
|
|||
#include <grub/mips/loongson.h>
|
||||
#include <grub/cs5536.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/machine/ec.h>
|
||||
#include <grub/cpu/memory.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
extern void grub_video_sm712_init (void);
|
||||
extern void grub_video_sis315pro_init (void);
|
||||
extern void grub_video_radeon_fuloong2e_init (void);
|
||||
extern void grub_video_init (void);
|
||||
extern void grub_bitmap_init (void);
|
||||
extern void grub_font_init (void);
|
||||
|
@ -123,6 +124,23 @@ void
|
|||
grub_machine_init (void)
|
||||
{
|
||||
grub_addr_t modend;
|
||||
grub_uint32_t prid;
|
||||
|
||||
asm volatile ("mfc0 %0, " GRUB_CPU_LOONGSON_COP0_PRID : "=r" (prid));
|
||||
|
||||
switch (prid)
|
||||
{
|
||||
/* Loongson 2E. */
|
||||
case 0x6302:
|
||||
grub_arch_machine = GRUB_ARCH_MACHINE_FULOONG2E;
|
||||
break;
|
||||
/* Loongson 2F. */
|
||||
case 0x6303:
|
||||
if (grub_arch_machine != GRUB_ARCH_MACHINE_FULOONG2F
|
||||
&& grub_arch_machine != GRUB_ARCH_MACHINE_YEELOONG)
|
||||
grub_arch_machine = GRUB_ARCH_MACHINE_YEELOONG;
|
||||
break;
|
||||
}
|
||||
|
||||
/* FIXME: measure this. */
|
||||
if (grub_arch_busclock == 0)
|
||||
|
@ -170,7 +188,7 @@ grub_machine_init (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
grub_arch_memsize = (totalmem >> 20);
|
||||
grub_arch_memsize = totalmem;
|
||||
grub_arch_highmemsize = 0;
|
||||
}
|
||||
|
||||
|
@ -189,6 +207,7 @@ grub_machine_init (void)
|
|||
grub_video_init ();
|
||||
grub_video_sm712_init ();
|
||||
grub_video_sis315pro_init ();
|
||||
grub_video_radeon_fuloong2e_init ();
|
||||
grub_bitmap_init ();
|
||||
grub_font_init ();
|
||||
grub_gfxterm_init ();
|
||||
|
@ -213,7 +232,9 @@ grub_halt (void)
|
|||
{
|
||||
switch (grub_arch_machine)
|
||||
{
|
||||
case GRUB_ARCH_MACHINE_FULOONG:
|
||||
case GRUB_ARCH_MACHINE_FULOONG2E:
|
||||
break;
|
||||
case GRUB_ARCH_MACHINE_FULOONG2F:
|
||||
{
|
||||
grub_pci_device_t dev;
|
||||
grub_port_t p;
|
||||
|
@ -234,7 +255,7 @@ grub_halt (void)
|
|||
break;
|
||||
}
|
||||
|
||||
grub_printf ("Shutdown failed\n");
|
||||
grub_puts_ (N_("Shutdown failed"));
|
||||
grub_refresh ();
|
||||
while (1);
|
||||
}
|
||||
|
@ -245,22 +266,6 @@ grub_exit (void)
|
|||
grub_halt ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
grub_write_ec (GRUB_MACHINE_EC_COMMAND_REBOOT);
|
||||
|
||||
grub_millisleep (1500);
|
||||
|
||||
grub_printf ("Reboot failed\n");
|
||||
grub_refresh ();
|
||||
while (1);
|
||||
}
|
||||
|
||||
extern char _end[];
|
||||
grub_addr_t grub_modbase = (grub_addr_t) _end;
|
||||
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
return (grub_addr_t) _end;
|
||||
}
|
||||
|
|
|
@ -7,17 +7,51 @@
|
|||
#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_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;
|
||||
|
||||
|
@ -27,8 +61,22 @@ grub_machine_init (void)
|
|||
|
||||
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
|
||||
|
@ -48,12 +96,6 @@ grub_halt (void)
|
|||
while (1);
|
||||
}
|
||||
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_machine_mmap_iterate (grub_memory_hook_t hook)
|
||||
{
|
||||
|
@ -62,9 +104,5 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook)
|
|||
}
|
||||
|
||||
extern char _end[];
|
||||
grub_addr_t grub_modbase = (grub_addr_t) _end;
|
||||
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
return (grub_addr_t) _end;
|
||||
}
|
||||
|
|
|
@ -40,17 +40,6 @@ start:
|
|||
VARIABLE(grub_total_modules_size)
|
||||
.long 0
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
VARIABLE (grub_arch_busclock)
|
||||
.long 0
|
||||
VARIABLE (grub_arch_cpuclock)
|
||||
|
@ -61,7 +50,7 @@ VARIABLE (grub_arch_highmemsize)
|
|||
.long 0
|
||||
#ifdef GRUB_MACHINE_MIPS_LOONGSON
|
||||
VARIABLE (grub_arch_machine)
|
||||
.long GRUB_ARCH_MACHINE_FULOONG
|
||||
.long GRUB_ARCH_MACHINE_FULOONG2F
|
||||
#endif
|
||||
cont:
|
||||
/* Save our base. */
|
||||
|
|
|
@ -210,11 +210,14 @@ grub_vprintf (const char *fmt, va_list args)
|
|||
buf[PREALLOC_SIZE - 2] = '.';
|
||||
buf[PREALLOC_SIZE - 1] = '.';
|
||||
buf[PREALLOC_SIZE] = 0;
|
||||
curbuf = buf;
|
||||
}
|
||||
else
|
||||
s = grub_vsnprintf_real (curbuf, s, fmt, ap2);
|
||||
}
|
||||
|
||||
va_end (ap2);
|
||||
|
||||
grub_xputs (curbuf);
|
||||
|
||||
if (curbuf != buf)
|
||||
|
@ -311,52 +314,6 @@ grub_strrchr (const char *s, int c)
|
|||
return p;
|
||||
}
|
||||
|
||||
/* Copied from gnulib.
|
||||
Written by Bruno Haible <bruno@clisp.org>, 2005. */
|
||||
char *
|
||||
grub_strstr (const char *haystack, const char *needle)
|
||||
{
|
||||
/* Be careful not to look at the entire extent of haystack or needle
|
||||
until needed. This is useful because of these two cases:
|
||||
- haystack may be very long, and a match of needle found early,
|
||||
- needle may be very long, and not even a short initial segment of
|
||||
needle may be found in haystack. */
|
||||
if (*needle != '\0')
|
||||
{
|
||||
/* Speed up the following searches of needle by caching its first
|
||||
character. */
|
||||
char b = *needle++;
|
||||
|
||||
for (;; haystack++)
|
||||
{
|
||||
if (*haystack == '\0')
|
||||
/* No match. */
|
||||
return NULL;
|
||||
if (*haystack == b)
|
||||
/* The first character matches. */
|
||||
{
|
||||
const char *rhaystack = haystack + 1;
|
||||
const char *rneedle = needle;
|
||||
|
||||
for (;; rhaystack++, rneedle++)
|
||||
{
|
||||
if (*rneedle == '\0')
|
||||
/* Found a match. */
|
||||
return (char *) haystack;
|
||||
if (*rhaystack == '\0')
|
||||
/* No match. */
|
||||
return NULL;
|
||||
if (*rhaystack != *rneedle)
|
||||
/* Nothing in this round. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return (char *) haystack;
|
||||
}
|
||||
|
||||
int
|
||||
grub_strword (const char *haystack, const char *needle)
|
||||
{
|
||||
|
@ -680,10 +637,13 @@ grub_lltoa (char *str, int c, unsigned long long n)
|
|||
}
|
||||
|
||||
static int
|
||||
grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt, va_list args)
|
||||
grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list args_in)
|
||||
{
|
||||
char c;
|
||||
grub_size_t n = 0;
|
||||
grub_size_t count = 0;
|
||||
grub_size_t count_args = 0;
|
||||
const char *fmt;
|
||||
auto void write_char (unsigned char ch);
|
||||
auto void write_str (const char *s);
|
||||
auto void write_fill (const char ch, int n);
|
||||
|
@ -702,209 +662,368 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt, va_list ar
|
|||
write_char (*s++);
|
||||
}
|
||||
|
||||
void write_fill (const char ch, int n)
|
||||
void write_fill (const char ch, int count_fill)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
for (i = 0; i < count_fill; i++)
|
||||
write_char (ch);
|
||||
}
|
||||
|
||||
fmt = fmt0;
|
||||
while ((c = *fmt++) != 0)
|
||||
{
|
||||
if (c != '%')
|
||||
write_char (c);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (*fmt && *fmt =='-')
|
||||
fmt++;
|
||||
|
||||
while (*fmt && grub_isdigit (*fmt))
|
||||
fmt++;
|
||||
|
||||
if (*fmt && *fmt == '$')
|
||||
fmt++;
|
||||
|
||||
if (*fmt && *fmt =='-')
|
||||
fmt++;
|
||||
|
||||
while (*fmt && grub_isdigit (*fmt))
|
||||
fmt++;
|
||||
|
||||
if (*fmt && *fmt =='.')
|
||||
fmt++;
|
||||
|
||||
while (*fmt && grub_isdigit (*fmt))
|
||||
fmt++;
|
||||
|
||||
c = *fmt++;
|
||||
if (c == 'l')
|
||||
{
|
||||
char tmp[32];
|
||||
char *p;
|
||||
unsigned int format1 = 0;
|
||||
unsigned int format2 = ~ 0U;
|
||||
char zerofill = ' ';
|
||||
int rightfill = 0;
|
||||
int n;
|
||||
int longfmt = 0;
|
||||
int longlongfmt = 0;
|
||||
int unsig = 0;
|
||||
c = *fmt++;
|
||||
if (c == 'l')
|
||||
c = *fmt++;
|
||||
}
|
||||
switch (c)
|
||||
{
|
||||
case 'p':
|
||||
case 'x':
|
||||
case 'u':
|
||||
case 'd':
|
||||
case 'c':
|
||||
case 'C':
|
||||
case 's':
|
||||
count_args++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*fmt && *fmt =='-')
|
||||
enum { INT, WCHAR, LONG, LONGLONG, POINTER } types[count_args];
|
||||
union
|
||||
{
|
||||
int i;
|
||||
grub_uint32_t w;
|
||||
long l;
|
||||
long long ll;
|
||||
void *p;
|
||||
} args[count_args];
|
||||
|
||||
grub_memset (types, 0, sizeof (types));
|
||||
|
||||
fmt = fmt0;
|
||||
n = 0;
|
||||
while ((c = *fmt++) != 0)
|
||||
{
|
||||
int longfmt = 0;
|
||||
int longlongfmt = 0;
|
||||
grub_size_t curn;
|
||||
const char *p;
|
||||
|
||||
if (c != '%')
|
||||
continue;
|
||||
|
||||
curn = n++;
|
||||
|
||||
if (*fmt && *fmt =='-')
|
||||
fmt++;
|
||||
|
||||
while (*fmt && grub_isdigit (*fmt))
|
||||
fmt++;
|
||||
|
||||
if (*fmt && *fmt =='.')
|
||||
fmt++;
|
||||
|
||||
while (*fmt && grub_isdigit (*fmt))
|
||||
fmt++;
|
||||
|
||||
p = fmt;
|
||||
|
||||
if (*fmt && *fmt == '$')
|
||||
{
|
||||
curn = grub_strtoull (p, 0, 10) - 1;
|
||||
fmt++;
|
||||
}
|
||||
|
||||
while (*fmt && grub_isdigit (*fmt))
|
||||
fmt++;
|
||||
|
||||
c = *fmt++;
|
||||
if (c == 'l')
|
||||
{
|
||||
c = *fmt++;
|
||||
longfmt = 1;
|
||||
if (c == 'l')
|
||||
{
|
||||
rightfill = 1;
|
||||
fmt++;
|
||||
c = *fmt++;
|
||||
longlongfmt = 1;
|
||||
}
|
||||
}
|
||||
if (curn >= count_args)
|
||||
continue;
|
||||
switch (c)
|
||||
{
|
||||
case 'x':
|
||||
case 'u':
|
||||
case 'd':
|
||||
if (longlongfmt)
|
||||
types[curn] = LONGLONG;
|
||||
else if (longfmt)
|
||||
types[curn] = LONG;
|
||||
else
|
||||
types[curn] = INT;
|
||||
break;
|
||||
case 'p':
|
||||
case 's':
|
||||
types[curn] = POINTER;
|
||||
break;
|
||||
case 'c':
|
||||
types[curn] = INT;
|
||||
break;
|
||||
case 'C':
|
||||
types[curn] = WCHAR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p = (char *) fmt;
|
||||
/* Read formatting parameters. */
|
||||
for (n = 0; n < count_args; n++)
|
||||
switch (types[n])
|
||||
{
|
||||
case WCHAR:
|
||||
args[n].w = va_arg (args_in, grub_uint32_t);
|
||||
break;
|
||||
case POINTER:
|
||||
args[n].p = va_arg (args_in, void *);
|
||||
break;
|
||||
case INT:
|
||||
args[n].i = va_arg (args_in, int);
|
||||
break;
|
||||
case LONG:
|
||||
args[n].l = va_arg (args_in, long);
|
||||
break;
|
||||
case LONGLONG:
|
||||
args[n].ll = va_arg (args_in, long long);
|
||||
break;
|
||||
}
|
||||
|
||||
fmt = fmt0;
|
||||
|
||||
n = 0;
|
||||
while ((c = *fmt++) != 0)
|
||||
{
|
||||
char tmp[32];
|
||||
char *p;
|
||||
unsigned int format1 = 0;
|
||||
unsigned int format2 = ~ 0U;
|
||||
char zerofill = ' ';
|
||||
int rightfill = 0;
|
||||
int longfmt = 0;
|
||||
int longlongfmt = 0;
|
||||
int unsig = 0;
|
||||
grub_size_t curn;
|
||||
|
||||
if (c != '%')
|
||||
{
|
||||
write_char (c);
|
||||
continue;
|
||||
}
|
||||
|
||||
curn = n++;
|
||||
|
||||
rescan:;
|
||||
|
||||
if (*fmt && *fmt =='-')
|
||||
{
|
||||
rightfill = 1;
|
||||
fmt++;
|
||||
}
|
||||
|
||||
p = (char *) fmt;
|
||||
/* Read formatting parameters. */
|
||||
while (*p && grub_isdigit (*p))
|
||||
p++;
|
||||
|
||||
if (p > fmt)
|
||||
{
|
||||
char s[p - fmt + 1];
|
||||
grub_strncpy (s, fmt, p - fmt);
|
||||
s[p - fmt] = 0;
|
||||
if (s[0] == '0')
|
||||
zerofill = '0';
|
||||
format1 = grub_strtoul (s, 0, 10);
|
||||
fmt = p;
|
||||
}
|
||||
|
||||
if (*p && *p == '.')
|
||||
{
|
||||
p++;
|
||||
fmt++;
|
||||
while (*p && grub_isdigit (*p))
|
||||
p++;
|
||||
|
||||
if (p > fmt)
|
||||
{
|
||||
char s[p - fmt + 1];
|
||||
grub_strncpy (s, fmt, p - fmt);
|
||||
s[p - fmt] = 0;
|
||||
if (s[0] == '0')
|
||||
zerofill = '0';
|
||||
format1 = grub_strtoul (s, 0, 10);
|
||||
char fstr[p - fmt + 1];
|
||||
grub_strncpy (fstr, fmt, p - fmt);
|
||||
fstr[p - fmt] = 0;
|
||||
format2 = grub_strtoul (fstr, 0, 10);
|
||||
fmt = p;
|
||||
}
|
||||
}
|
||||
if (*fmt == '$')
|
||||
{
|
||||
curn = format1 - 1;
|
||||
fmt++;
|
||||
format1 = 0;
|
||||
format2 = ~ 0U;
|
||||
zerofill = ' ';
|
||||
rightfill = 0;
|
||||
|
||||
if (*p && *p == '.')
|
||||
{
|
||||
p++;
|
||||
fmt++;
|
||||
while (*p && grub_isdigit (*p))
|
||||
p++;
|
||||
|
||||
if (p > fmt)
|
||||
{
|
||||
char fstr[p - fmt + 1];
|
||||
grub_strncpy (fstr, fmt, p - fmt);
|
||||
fstr[p - fmt] = 0;
|
||||
format2 = grub_strtoul (fstr, 0, 10);
|
||||
fmt = p;
|
||||
}
|
||||
}
|
||||
goto rescan;
|
||||
}
|
||||
|
||||
c = *fmt++;
|
||||
if (c == 'l')
|
||||
{
|
||||
longfmt = 1;
|
||||
c = *fmt++;
|
||||
if (c == 'l')
|
||||
{
|
||||
longfmt = 1;
|
||||
longlongfmt = 1;
|
||||
c = *fmt++;
|
||||
if (c == 'l')
|
||||
{
|
||||
longlongfmt = 1;
|
||||
c = *fmt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'p':
|
||||
write_str ("0x");
|
||||
c = 'x';
|
||||
longlongfmt |= (sizeof (void *) == sizeof (long long));
|
||||
/* Fall through. */
|
||||
case 'x':
|
||||
case 'u':
|
||||
unsig = 1;
|
||||
/* Fall through. */
|
||||
case 'd':
|
||||
if (longlongfmt)
|
||||
{
|
||||
long long ll;
|
||||
if (curn >= count_args)
|
||||
continue;
|
||||
|
||||
ll = va_arg (args, long long);
|
||||
grub_lltoa (tmp, c, ll);
|
||||
}
|
||||
else if (longfmt && unsig)
|
||||
{
|
||||
unsigned long l = va_arg (args, unsigned long);
|
||||
grub_lltoa (tmp, c, l);
|
||||
}
|
||||
else if (longfmt)
|
||||
{
|
||||
long l = va_arg (args, long);
|
||||
grub_lltoa (tmp, c, l);
|
||||
}
|
||||
else if (unsig)
|
||||
{
|
||||
unsigned u = va_arg (args, unsigned);
|
||||
grub_lltoa (tmp, c, u);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = va_arg (args, int);
|
||||
grub_lltoa (tmp, c, n);
|
||||
}
|
||||
if (! rightfill && grub_strlen (tmp) < format1)
|
||||
write_fill (zerofill, format1 - grub_strlen (tmp));
|
||||
write_str (tmp);
|
||||
if (rightfill && grub_strlen (tmp) < format1)
|
||||
write_fill (zerofill, format1 - grub_strlen (tmp));
|
||||
break;
|
||||
switch (c)
|
||||
{
|
||||
case 'p':
|
||||
write_str ("0x");
|
||||
c = 'x';
|
||||
longlongfmt |= (sizeof (void *) == sizeof (long long));
|
||||
/* Fall through. */
|
||||
case 'x':
|
||||
case 'u':
|
||||
unsig = 1;
|
||||
/* Fall through. */
|
||||
case 'd':
|
||||
if (longlongfmt)
|
||||
grub_lltoa (tmp, c, args[curn].ll);
|
||||
else if (longfmt && unsig)
|
||||
grub_lltoa (tmp, c, (unsigned long) args[curn].l);
|
||||
else if (longfmt)
|
||||
grub_lltoa (tmp, c, args[curn].l);
|
||||
else if (unsig)
|
||||
grub_lltoa (tmp, c, (unsigned) args[curn].i);
|
||||
else
|
||||
grub_lltoa (tmp, c, args[curn].i);
|
||||
if (! rightfill && grub_strlen (tmp) < format1)
|
||||
write_fill (zerofill, format1 - grub_strlen (tmp));
|
||||
write_str (tmp);
|
||||
if (rightfill && grub_strlen (tmp) < format1)
|
||||
write_fill (zerofill, format1 - grub_strlen (tmp));
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
n = va_arg (args, int);
|
||||
write_char (n & 0xff);
|
||||
break;
|
||||
case 'c':
|
||||
write_char (args[curn].i & 0xff);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
case 'C':
|
||||
{
|
||||
grub_uint32_t code = args[curn].w;
|
||||
int shift;
|
||||
unsigned mask;
|
||||
|
||||
if (code <= 0x7f)
|
||||
{
|
||||
grub_uint32_t code = va_arg (args, grub_uint32_t);
|
||||
int shift;
|
||||
unsigned mask;
|
||||
|
||||
if (code <= 0x7f)
|
||||
{
|
||||
shift = 0;
|
||||
mask = 0;
|
||||
}
|
||||
else if (code <= 0x7ff)
|
||||
{
|
||||
shift = 6;
|
||||
mask = 0xc0;
|
||||
}
|
||||
else if (code <= 0xffff)
|
||||
{
|
||||
shift = 12;
|
||||
mask = 0xe0;
|
||||
}
|
||||
else if (code <= 0x1fffff)
|
||||
{
|
||||
shift = 18;
|
||||
mask = 0xf0;
|
||||
}
|
||||
else if (code <= 0x3ffffff)
|
||||
{
|
||||
shift = 24;
|
||||
mask = 0xf8;
|
||||
}
|
||||
else if (code <= 0x7fffffff)
|
||||
{
|
||||
shift = 30;
|
||||
mask = 0xfc;
|
||||
}
|
||||
else
|
||||
{
|
||||
code = '?';
|
||||
shift = 0;
|
||||
mask = 0;
|
||||
}
|
||||
|
||||
write_char (mask | (code >> shift));
|
||||
|
||||
for (shift -= 6; shift >= 0; shift -= 6)
|
||||
write_char (0x80 | (0x3f & (code >> shift)));
|
||||
shift = 0;
|
||||
mask = 0;
|
||||
}
|
||||
else if (code <= 0x7ff)
|
||||
{
|
||||
shift = 6;
|
||||
mask = 0xc0;
|
||||
}
|
||||
else if (code <= 0xffff)
|
||||
{
|
||||
shift = 12;
|
||||
mask = 0xe0;
|
||||
}
|
||||
else if (code <= 0x1fffff)
|
||||
{
|
||||
shift = 18;
|
||||
mask = 0xf0;
|
||||
}
|
||||
else if (code <= 0x3ffffff)
|
||||
{
|
||||
shift = 24;
|
||||
mask = 0xf8;
|
||||
}
|
||||
else if (code <= 0x7fffffff)
|
||||
{
|
||||
shift = 30;
|
||||
mask = 0xfc;
|
||||
}
|
||||
else
|
||||
{
|
||||
code = '?';
|
||||
shift = 0;
|
||||
mask = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 's':
|
||||
p = va_arg (args, char *);
|
||||
if (p)
|
||||
{
|
||||
grub_size_t len = 0;
|
||||
while (len < format2 && p[len])
|
||||
len++;
|
||||
write_char (mask | (code >> shift));
|
||||
|
||||
if (!rightfill && len < format1)
|
||||
write_fill (zerofill, format1 - len);
|
||||
for (shift -= 6; shift >= 0; shift -= 6)
|
||||
write_char (0x80 | (0x3f & (code >> shift)));
|
||||
}
|
||||
break;
|
||||
|
||||
grub_size_t i;
|
||||
for (i = 0; i < len; i++)
|
||||
write_char (*p++);
|
||||
case 's':
|
||||
p = args[curn].p;
|
||||
if (p)
|
||||
{
|
||||
grub_size_t len = 0;
|
||||
while (len < format2 && p[len])
|
||||
len++;
|
||||
|
||||
if (rightfill && len < format1)
|
||||
write_fill (zerofill, format1 - len);
|
||||
}
|
||||
else
|
||||
write_str ("(null)");
|
||||
if (!rightfill && len < format1)
|
||||
write_fill (zerofill, format1 - len);
|
||||
|
||||
break;
|
||||
grub_size_t i;
|
||||
for (i = 0; i < len; i++)
|
||||
write_char (*p++);
|
||||
|
||||
default:
|
||||
write_char (c);
|
||||
break;
|
||||
if (rightfill && len < format1)
|
||||
write_fill (zerofill, format1 - len);
|
||||
}
|
||||
else
|
||||
write_str ("(null)");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
write_char (c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -956,6 +1075,9 @@ grub_xvasprintf (const char *fmt, va_list ap)
|
|||
return NULL;
|
||||
|
||||
s = grub_vsnprintf_real (ret, as, fmt, ap2);
|
||||
|
||||
va_end (ap2);
|
||||
|
||||
if (s <= as)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -515,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);
|
||||
|
@ -528,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);
|
||||
|
@ -547,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);
|
||||
|
@ -561,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);
|
||||
|
|
|
@ -123,7 +123,7 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline,
|
|||
|
||||
void add_var (grub_parser_state_t newstate)
|
||||
{
|
||||
char *val;
|
||||
const char *val;
|
||||
|
||||
/* Check if a variable was being read in and the end of the name
|
||||
was reached. */
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
#include <grub/util/misc.h>
|
||||
|
@ -47,7 +48,7 @@ grub_partition_check_containment (const grub_disk_t disk,
|
|||
grub_dprintf ("partition", "sub-partition %s%d of (%s,%s) ends after parent.\n",
|
||||
part->partmap->name, part->number + 1, disk->name, partname);
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)",
|
||||
grub_util_warn (_("Discarding improperly nested partition (%s,%s,%s%d)"),
|
||||
disk->name, partname, part->partmap->name, part->number + 1);
|
||||
#endif
|
||||
grub_free (partname);
|
||||
|
|
|
@ -37,6 +37,65 @@ grub_arch_dl_check_header (void *ehdr)
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
|
||||
grub_size_t *got)
|
||||
{
|
||||
const Elf_Ehdr *e = ehdr;
|
||||
const Elf_Shdr *s;
|
||||
Elf_Word entsize;
|
||||
unsigned i;
|
||||
|
||||
*tramp = 0;
|
||||
*got = 0;
|
||||
|
||||
/* Find a symbol table. */
|
||||
for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_SYMTAB)
|
||||
break;
|
||||
|
||||
if (i == e->e_shnum)
|
||||
return;
|
||||
|
||||
entsize = s->sh_entsize;
|
||||
|
||||
for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_RELA)
|
||||
{
|
||||
const Elf_Rela *rel, *max;
|
||||
|
||||
for (rel = (const Elf_Rela *) ((const char *) e + s->sh_offset),
|
||||
max = rel + s->sh_size / s->sh_entsize;
|
||||
rel < max;
|
||||
rel++)
|
||||
if (ELF_R_TYPE (rel->r_info) == R_PPC_REL24)
|
||||
(*tramp)++;
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* For low-endian reverse lis and addr_high as well as ori and addr_low. */
|
||||
struct trampoline
|
||||
{
|
||||
grub_uint32_t lis;
|
||||
grub_uint32_t ori;
|
||||
grub_uint32_t mtctr;
|
||||
grub_uint32_t bctr;
|
||||
};
|
||||
|
||||
static const struct trampoline trampoline_template =
|
||||
{
|
||||
0x3c000000,
|
||||
0x60000000,
|
||||
0x7c0903a6,
|
||||
0x4e800420,
|
||||
};
|
||||
|
||||
/* Relocate symbols. */
|
||||
grub_err_t
|
||||
|
@ -46,6 +105,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
|||
Elf_Shdr *s;
|
||||
Elf_Word entsize;
|
||||
unsigned i;
|
||||
struct trampoline *tptr = mod->tramp;
|
||||
|
||||
/* Find a symbol table. */
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
|
@ -106,7 +166,20 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
|||
Elf_Sword delta = value - (Elf_Word) addr;
|
||||
|
||||
if (delta << 6 >> 6 != delta)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "relocation overflow");
|
||||
{
|
||||
COMPILE_TIME_ASSERT (sizeof (struct trampoline)
|
||||
== GRUB_ARCH_DL_TRAMP_SIZE);
|
||||
grub_memcpy (tptr, &trampoline_template,
|
||||
sizeof (*tptr));
|
||||
delta = (grub_uint8_t *) tptr - (grub_uint8_t *) addr;
|
||||
tptr->lis |= (((value) >> 16) & 0xffff);
|
||||
tptr->ori |= ((value) & 0xffff);
|
||||
tptr++;
|
||||
}
|
||||
|
||||
if (delta << 6 >> 6 != delta)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"relocation overflow");
|
||||
*addr = (*addr & 0xfc000003) | (delta & 0x3fffffc);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -28,20 +28,6 @@
|
|||
.globl start, _start
|
||||
start:
|
||||
_start:
|
||||
b codestart
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
codestart:
|
||||
li 2, 0
|
||||
li 13, 0
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ grub_rescue_read_line (char **line, int cont)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
void __attribute__ ((noreturn))
|
||||
grub_rescue_run (void)
|
||||
{
|
||||
grub_printf ("Entering rescue mode...\n");
|
||||
|
|
|
@ -111,10 +111,13 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
|||
(((grub_int32_t) ((value - (Elf_Addr) addr) >> 2)) &
|
||||
0x3FFFFFFF);
|
||||
break;
|
||||
case R_SPARC_HH22: /* 9 V-imm22 */
|
||||
*addr = (*addr & 0xFFC00000) | ((value >> 42) & 0x3FFFFF);
|
||||
break;
|
||||
case R_SPARC_HM10: /* 12 T-simm13 */
|
||||
*addr = (*addr & 0xFFFFFC00) | ((value >> 32) & 0x3FF);
|
||||
break;
|
||||
case R_SPARC_HI22: /* 9 V-imm22 */
|
||||
if (((grub_int32_t) value) & 0xFF00000000)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"high address out of 22 bits range");
|
||||
*addr = (*addr & 0xFFC00000) | ((value >> 10) & 0x3FFFFF);
|
||||
break;
|
||||
case R_SPARC_LO10: /* 12 T-simm13 */
|
||||
|
|
|
@ -31,18 +31,6 @@ _start:
|
|||
|
||||
VARIABLE(grub_total_module_size)
|
||||
.word 0
|
||||
VARIABLE(grub_kernel_image_size)
|
||||
.word 0
|
||||
VARIABLE(grub_compressed_size)
|
||||
.word 0
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = EXT_C(_start) + GRUB_KERNEL_MACHINE_PREFIX_END
|
||||
|
||||
codestart:
|
||||
/* Copy the modules past the end of the kernel image.
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -109,7 +109,9 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
|||
break;
|
||||
|
||||
default:
|
||||
grub_fatal ("Unrecognized relocation: %d\n", ELF_R_TYPE (rel->r_info));
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"this relocation (%d) is not implemented yet",
|
||||
ELF_R_TYPE (rel->r_info));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,14 +19,13 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/boot.h>
|
||||
|
||||
/*
|
||||
* x86_64 uses registry to pass parameters. Unfortunately, gcc and efi use
|
||||
* different call conversion, so we need to do some conversion.
|
||||
*
|
||||
* gcc:
|
||||
* %rdi, %esi, %rdx, %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ...
|
||||
* %rdi, %rsi, %rdx, %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ...
|
||||
*
|
||||
* efi:
|
||||
* %rcx, %rdx, %r8, %r9, 32(%rsp), 40(%rsp), 48(%rsp), ...
|
||||
|
@ -95,6 +94,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
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/boot.h>
|
||||
|
||||
.file "startup.S"
|
||||
.text
|
||||
|
@ -28,33 +27,6 @@
|
|||
|
||||
start:
|
||||
_start:
|
||||
jmp codestart
|
||||
|
||||
/*
|
||||
* Compatibility version number
|
||||
*
|
||||
* These MUST be at byte offset 6 and 7 of the executable
|
||||
* DO NOT MOVE !!!
|
||||
*/
|
||||
. = _start + 0x6
|
||||
.byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
|
||||
|
||||
/*
|
||||
* This is a special data area 8 bytes from the beginning.
|
||||
*/
|
||||
|
||||
. = _start + 0x8
|
||||
|
||||
VARIABLE(grub_prefix)
|
||||
/* to be filled by grub-mkimage */
|
||||
|
||||
/*
|
||||
* Leave some breathing room for the prefix.
|
||||
*/
|
||||
|
||||
. = _start + 0x50
|
||||
|
||||
codestart:
|
||||
movq %rcx, EXT_C(grub_efi_image_handle)(%rip)
|
||||
movq %rdx, EXT_C(grub_efi_system_table)(%rip)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue