Added support to netdisk specified in the form (net,protocol,server_ip,username,password)

an to list its information with command ls.

* fs/ieee1275/ofnet.c (grub_ofnet_open): parse parameters to determine netdisk data
* fs/ieee1275/ofnet.c (grub_ofnet_close): dealloc netdisk data
* include/grub/disk.h: added struct grub_netdisk_data
* include/grub/ieee1275/ofnet.h: added newline
* kern/disk.c (grub_disk_open): ignore partition check for netdisk
* normal/misc.c (grub_normal_print_device_info): added support to list netdisk information
This commit is contained in:
Paulo de Rezende Pinatti 2010-07-13 11:22:35 -03:00
parent 3ec6213b17
commit f8795693f1
5 changed files with 213 additions and 7 deletions

View file

@ -42,6 +42,85 @@
//static grub_ieee1275_ihandle_t handle = 0; //static grub_ieee1275_ihandle_t handle = 0;
static const char *
find_sep (const char *name)
{
const char *p = name;
char c = *p;
if (c == '\0')
return NULL;
do
{
if (c == '\\' && *p == ',')
p++;
else if (c == ',')
return p - 1;
} while ((c = *p++) != '\0');
return p - 1;
}
static grub_err_t
retrieve_field(const char *src, char **field, const char **rest)
{
const char *p;
grub_size_t len;
p = find_sep(src);
if (! p)
{
*field = NULL;
*rest = src;
return 0;
}
len = p - src;
*field = grub_malloc (len + 1);
if (! *field)
{
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory");
}
grub_memcpy (*field, src, len);
(*field)[len] = '\0';
if (*p == '\0')
*rest = p;
else
*rest = p + 1;
return 0;
}
static grub_err_t
parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
{
grub_uint32_t newip = 0;
unsigned long t;
int i;
const char *ptr = val;
for (i = 0; i < 4; i++)
{
t = grub_strtoul (ptr, (char **) &ptr, 0);
if (grub_errno)
return grub_errno;
if (t & ~0xff)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
newip >>= 8;
newip |= (t << 24);
if (i != 3 && *ptr != '.')
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
ptr++;
}
ptr = ptr - 1;
if ( *ptr != '\0' && *ptr != ',')
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
*ip = newip;
if (rest)
*rest = ptr;
return 0;
}
static int static int
grub_ofnet_iterate (int (*hook) (const char *name)) grub_ofnet_iterate (int (*hook) (const char *name))
@ -54,23 +133,93 @@ grub_ofnet_iterate (int (*hook) (const char *name))
static grub_err_t static grub_err_t
grub_ofnet_open (const char *name, grub_disk_t disk) grub_ofnet_open (const char *name, grub_disk_t disk)
{ {
grub_err_t err;
const char *p1, *p2;
char *user = NULL, *pwd = NULL;
grub_netdisk_data_t data;
grub_netdisk_protocol_t proto;
grub_uint32_t server_ip = 0;
if (grub_strcmp (name, "net")) if (grub_strcmp (name, "net"))
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk");
disk->total_sectors = U64MAXSIZE; p1 = find_sep(disk->name);
if (! p1 || *p1 == '\0')
return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments missing");
p1++;
// parse protocol
p2 = find_sep(p1);
if (! p2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no protocol specified");
if ((p2 - p1 == 4) && (! grub_strncasecmp(p1, "tftp", p2 - p1)))
proto = GRUB_NETDISK_PROTOCOL_TFTP;
else
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid protocol specified");
// parse server ip
if ( *p2 == '\0')
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no server ip specified");
p1 = p2 + 1;
err = parse_ip(p1, &server_ip, &p2);
if (err)
return err;
// parse username (optional)
if ( *p2 == ',')
p2++;
err = retrieve_field(p2, &user, &p1);
if (err)
return err;
if (user)
{
// parse password (optional)
err = retrieve_field(p1, &pwd, &p2);
if (err)
{
grub_free(user);
return err;
}
}
if (! disk->data)
{
data = grub_malloc (sizeof(*data));
disk->data = data;
}
else
{
data = disk->data;
if (data->username)
grub_free(data->username);
if (data->password)
grub_free(data->password);
}
data->protocol = proto;
data->server_ip = server_ip;
data->username = user;
data->password = pwd;
disk->total_sectors = 0;
disk->id = (unsigned long) "net"; disk->id = (unsigned long) "net";
disk->has_partitions = 0; disk->has_partitions = 0;
disk->data = 0;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
static void static void
grub_ofnet_close (grub_disk_t disk __attribute((unused))) grub_ofnet_close (grub_disk_t disk)
{ {
grub_netdisk_data_t data = disk->data;
if (data)
{
if (data->username)
grub_free(data->username);
if (data->password)
grub_free(data->password);
grub_free(data);
}
} }
static grub_err_t static grub_err_t

View file

@ -119,6 +119,23 @@ struct grub_disk
}; };
typedef struct grub_disk *grub_disk_t; typedef struct grub_disk *grub_disk_t;
/* Net Disk */
enum grub_netdisk_protocol
{
GRUB_NETDISK_PROTOCOL_TFTP
};
typedef enum grub_netdisk_protocol grub_netdisk_protocol_t;
struct grub_netdisk_data
{
grub_netdisk_protocol_t protocol;
grub_uint32_t server_ip;
grub_uint32_t port;
char *username;
char *password;
};
typedef struct grub_netdisk_data *grub_netdisk_data_t;
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
struct grub_disk_memberlist struct grub_disk_memberlist
{ {

View file

@ -25,6 +25,7 @@
extern void grub_ofnet_init(void); extern void grub_ofnet_init(void);
extern void grub_ofnet_fini(void); extern void grub_ofnet_fini(void);
/* /*
struct grub_net; struct grub_net;

View file

@ -281,7 +281,7 @@ grub_disk_open (const char *name)
goto fail; goto fail;
} }
if (p && ! disk->has_partitions) if (p && ! disk->has_partitions && grub_strcmp (raw, "net"))
{ {
grub_error (GRUB_ERR_BAD_DEVICE, "no partition on this disk"); grub_error (GRUB_ERR_BAD_DEVICE, "no partition on this disk");
goto fail; goto fail;
@ -289,7 +289,7 @@ grub_disk_open (const char *name)
disk->dev = dev; disk->dev = dev;
if (p) if (p && grub_strcmp (raw, "net"))
{ {
disk->partition = grub_partition_probe (disk, p + 1); disk->partition = grub_partition_probe (disk, p + 1);
if (! disk->partition) if (! disk->partition)

View file

@ -32,8 +32,47 @@ grub_err_t
grub_normal_print_device_info (const char *name) grub_normal_print_device_info (const char *name)
{ {
grub_device_t dev; grub_device_t dev;
grub_netdisk_data_t data;
char *p; char *p;
if ((! grub_strcmp(name, "net")) || (! grub_strncmp(name, "net,", 4)))
{
grub_printf_ (N_("Device network:"));
grub_putchar (' ');
dev = grub_device_open (name);
if (! dev || ! dev->disk || ! dev->disk->data)
grub_printf ("%s", _("Network information not available"));
else
{
data = dev->disk->data;
grub_putchar ('\n');
grub_putchar ('\t');
if (data->protocol == GRUB_NETDISK_PROTOCOL_TFTP)
grub_printf_(N_("Protocol: %s"), "TFTP");
else
grub_printf_(N_("Protocol: %s"), "Unknown");
grub_putchar ('\n');
grub_putchar ('\t');
grub_printf_(N_("Server IP: %d.%d.%d.%d"), data->server_ip & 0xff, data->server_ip >> 8 & 0xff, data->server_ip >> 16 & 0xff, data->server_ip >> 24 & 0xff);
if (data->username)
{
grub_putchar ('\n');
grub_putchar ('\t');
grub_printf_(N_("Username: %s"), data->username);
if (data->password)
{
grub_putchar ('\n');
grub_putchar ('\t');
grub_printf_(N_("Password: %s"), data->password);
}
}
}
grub_putchar ('\n');
return GRUB_ERR_NONE;
}
p = grub_strchr (name, ','); p = grub_strchr (name, ',');
if (p) if (p)
{ {