Reimport nestpart

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-02-06 18:43:37 +01:00
parent bf7fcba2d7
commit 15cb7d433f
26 changed files with 561 additions and 720 deletions

View file

@ -330,6 +330,7 @@ grub_disk_open (const char *name)
void
grub_disk_close (grub_disk_t disk)
{
grub_partition_t part;
grub_dprintf ("disk", "Closing `%s'.\n", disk->name);
if (disk->dev && disk->dev->close)
@ -338,7 +339,13 @@ grub_disk_close (grub_disk_t disk)
/* Reset the timer. */
grub_last_time = grub_get_time_ms ();
grub_free (disk->partition);
while (disk->partition)
{
part = disk->partition->parent;
grub_free (disk->partition->data);
grub_free (disk->partition);
disk->partition = part;
}
grub_free ((void *) disk->name);
grub_free (disk);
}
@ -349,18 +356,19 @@ grub_disk_close (grub_disk_t disk)
- Verify that the range is inside the partition. */
static grub_err_t
grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector,
grub_off_t *offset, grub_size_t size)
grub_off_t *offset, grub_size_t size)
{
grub_partition_t part;
*sector += *offset >> GRUB_DISK_SECTOR_BITS;
*offset &= GRUB_DISK_SECTOR_SIZE - 1;
if (disk->partition)
for (part = disk->partition; part; part = part->parent)
{
grub_disk_addr_t start;
grub_uint64_t len;
start = grub_partition_get_start (disk->partition);
len = grub_partition_get_len (disk->partition);
start = part->start;
len = part->len;
if (*sector >= len
|| len - *sector < ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)

View file

@ -17,6 +17,7 @@
*/
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/partition.h>
#include <grub/disk.h>
@ -54,17 +55,58 @@ grub_partition_map_iterate (int (*hook) (const grub_partition_map_t partmap))
return 0;
}
static grub_partition_t
grub_partition_map_probe (const grub_partition_map_t partmap,
grub_disk_t disk, int partnum)
{
grub_partition_t p = 0;
auto int find_func (grub_disk_t d, const grub_partition_t partition);
int find_func (grub_disk_t d __attribute__ ((unused)),
const grub_partition_t partition)
{
if (partnum == partition->number)
{
p = (grub_partition_t) grub_malloc (sizeof (*p));
if (! p)
return 1;
grub_memcpy (p, partition, sizeof (*p));
return 1;
}
return 0;
}
partmap->iterate (disk, find_func);
if (grub_errno)
goto fail;
return p;
fail:
grub_free (p);
return 0;
}
grub_partition_t
grub_partition_probe (struct grub_disk *disk, const char *str)
{
grub_partition_t part = 0;
grub_partition_t curpart = 0;
grub_partition_t tail;
const char *ptr;
int num;
auto int part_map_probe (const grub_partition_map_t partmap);
int part_map_probe (const grub_partition_map_t partmap)
{
part = partmap->probe (disk, str);
if (part)
disk->partition = part;
curpart = grub_partition_map_probe (partmap, disk, num);
disk->partition = tail;
if (curpart)
return 1;
if (grub_errno == GRUB_ERR_BAD_PART_TABLE)
@ -77,27 +119,54 @@ grub_partition_probe (struct grub_disk *disk, const char *str)
return 1;
}
/* Use the first partition map type found. */
grub_partition_map_iterate (part_map_probe);
part = tail = disk->partition;
for (ptr = str; *ptr;)
{
/* BSD-like partition specification. */
if (*ptr >= 'a' && *ptr <= 'z')
num = *(ptr++) - 'a';
else
num = grub_strtoul (ptr, (char **) &ptr, 0) - 1;
curpart = 0;
/* Use the first partition map type found. */
grub_partition_map_iterate (part_map_probe);
if (! curpart)
{
while (part)
{
curpart = part->parent;
grub_free (part);
part = curpart;
}
return 0;
}
curpart->parent = part;
part = curpart;
if (! ptr || *ptr != ',')
break;
ptr++;
}
return part;
}
int
grub_partition_iterate (struct grub_disk *disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
static grub_partition_map_t
get_partmap (struct grub_disk *disk)
{
grub_partition_map_t partmap = 0;
int ret = 0;
struct grub_partition part;
int found = 0;
auto int part_map_iterate (const grub_partition_map_t p);
auto int part_map_iterate_hook (grub_disk_t d,
const grub_partition_t partition);
int part_map_iterate_hook (grub_disk_t d __attribute__ ((unused)),
const grub_partition_t partition __attribute__ ((unused)))
const grub_partition_t partition)
{
found = 1;
part = *partition;
return 1;
}
@ -106,22 +175,58 @@ grub_partition_iterate (struct grub_disk *disk,
grub_dprintf ("partition", "Detecting %s...\n", p->name);
p->iterate (disk, part_map_iterate_hook);
if (grub_errno != GRUB_ERR_NONE)
if (grub_errno != GRUB_ERR_NONE || ! found)
{
/* Continue to next partition map type. */
grub_dprintf ("partition", "%s detection failed.\n", p->name);
grub_errno = GRUB_ERR_NONE;
return 0;
}
grub_free (part.data);
grub_dprintf ("partition", "%s detection succeeded.\n", p->name);
partmap = p;
return 1;
}
grub_partition_map_iterate (part_map_iterate);
if (partmap)
ret = partmap->iterate (disk, hook);
return partmap;
}
int
grub_partition_iterate (struct grub_disk *disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
int ret = 0;
auto int part_iterate (grub_disk_t dsk, const grub_partition_t p);
int part_iterate (grub_disk_t dsk,
const grub_partition_t partition)
{
struct grub_partition p = *partition;
grub_partition_map_t partmap = 0;
p.parent = dsk->partition;
dsk->partition = 0;
if (hook (dsk, &p))
return 1;
if (p.start != 0)
{
dsk->partition = &p;
partmap = get_partmap (dsk);
if (partmap)
ret = partmap->iterate (dsk, part_iterate);
}
dsk->partition = p.parent;
return ret;
}
{
grub_partition_map_t partmap = 0;
partmap = get_partmap (disk);
if (partmap)
ret = partmap->iterate (disk, part_iterate);
}
return ret;
}
@ -129,5 +234,30 @@ grub_partition_iterate (struct grub_disk *disk,
char *
grub_partition_get_name (const grub_partition_t partition)
{
return partition->partmap->get_name (partition);
char *out = 0;
/* Even on 64-bit machines this buffer is enough to hold longest number. */
char buf[25];
int curlen = 0;
grub_partition_t part;
for (part = partition; part; part = part->parent)
{
int strl;
grub_snprintf (buf, sizeof (buf), "%d", part->number + 1);
strl = grub_strlen (buf);
if (curlen)
{
out = grub_realloc (out, curlen + strl + 2);
grub_memcpy (out + strl + 1, out, curlen);
out[curlen + 1 + strl] = 0;
grub_memcpy (out, buf, strl);
out[strl] = ',';
curlen = curlen + 1 + strl;
}
else
{
curlen = strl;
out = grub_strdup (buf);
}
}
return out;
}