[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Add support for (pxe[:server_ip[:gateway_ip]]) and export pxe pa
From: |
Vladimir 'φ-coder/phcoder' Serbinenko |
Subject: |
[PATCH] Add support for (pxe[:server_ip[:gateway_ip]]) and export pxe parameteres into grub environment |
Date: |
Sun, 20 Dec 2009 20:26:01 +0100 |
User-agent: |
Mozilla-Thunderbird 2.0.0.22 (X11/20091109) |
Any other DHCP options needed?
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
=== added file 'ChangeLog.pxeenv'
--- ChangeLog.pxeenv 1970-01-01 00:00:00 +0000
+++ ChangeLog.pxeenv 2009-12-20 19:23:11 +0000
@@ -0,0 +1,36 @@
+2009-12-19 Vladimir Serbinenko <address@hidden>
+
+ Support for (pxe[:server[:gateway]]) syntax and
+ use environment variable for PXE.
+
+ * commands/i386/pc/pxecmd.c (options): Removed.
+ (print_ip): Removed.
+ (grub_cmd_pxe): Removed
+ (grub_cmd_pxe_unload): New function.
+ * fs/i386/pc/pxe.c (grub_pxe_disk_data): New structure.
+ (grub_pxe_your_ip): Made static.
+ (grub_pxe_default_server_ip): Likewise.
+ (grub_pxe_default_gateway_ip): Likewise.
+ (grub_pxe_blksize): Likewise.
+ (parse_ip): New function.
+ (grub_pxe_open): Support server and gateway specification.
+ (grub_pxe_close): Free disk->data.
+ (grub_pxefs_open): Use disk->data.
+ (grub_pxefs_read): Likewise.
+ (grub_env_write_readonly): New function.
+ (set_mac_env): Likewise.
+ (set_env_limn_ro): Likewise.
+ (parse_dhcp_vendor): Likewise.
+ (grub_pxe_detect): Set the environment variables.
+ (set_ip_env): New function.
+ (write_ip_env): Likewise.
+ (grub_env_write_pxe_default_server): Likewise.
+ (grub_env_write_pxe_default_gateway): Likewise.
+ (grub_env_write_pxe_blocksize): Likewise.
+ (GRUB_MOD_INIT(pxe)): Set environment variables.
+ * include/grub/i386/pc/pxe.h (grub_pxe_mac_addr): Rename to ...
+ (grub_pxe_mac_addr_t): ... this. All users updated.
+ (grub_pxe_your_ip): Removed.
+ (grub_pxe_server_ip): Likewise.
+ (grub_pxe_gateway_ip): Likewise.
+ (grub_pxe_blksize): Likewise.
=== modified file 'commands/i386/pc/pxecmd.c'
--- commands/i386/pc/pxecmd.c 2009-05-04 03:49:08 +0000
+++ commands/i386/pc/pxecmd.c 2009-12-20 19:05:53 +0000
@@ -1,7 +1,7 @@
/* pxe.c - command to control the pxe driver */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2008 Free Software Foundation, Inc.
+ * Copyright (C) 2008,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
@@ -21,79 +21,31 @@
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/machine/pxe.h>
-#include <grub/extcmd.h>
-
-static const struct grub_arg_option options[] =
-{
- {"info", 'i', 0, "show PXE information.", 0, 0},
- {"bsize", 'b', 0, "set PXE block size", 0, ARG_TYPE_INT},
- {"unload", 'u', 0, "unload PXE stack.", 0, 0},
- {0, 0, 0, 0, 0, 0}
- };
-
-static void
-print_ip (grub_uint32_t ip)
-{
- int i;
-
- for (i = 0; i < 3; i++)
- {
- grub_printf ("%d.", ip & 0xFF);
- ip >>= 8;
- }
- grub_printf ("%d", ip);
-}
+#include <grub/command.h>
static grub_err_t
-grub_cmd_pxe (grub_extcmd_t cmd, int argc __attribute__ ((unused)),
- char **args __attribute__ ((unused)))
+grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
{
- struct grub_arg_list *state = cmd->state;
-
if (! grub_pxe_pxenv)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment");
- if (state[1].set)
- {
- int size;
-
- size = grub_strtoul (state[1].arg, 0, 0);
- if (size < GRUB_PXE_MIN_BLKSIZE)
- size = GRUB_PXE_MIN_BLKSIZE;
- else if (size > GRUB_PXE_MAX_BLKSIZE)
- size = GRUB_PXE_MAX_BLKSIZE;
-
- grub_pxe_blksize = size;
- }
-
- if (state[0].set)
- {
- grub_printf ("blksize : %d\n", grub_pxe_blksize);
- grub_printf ("client ip : ");
- print_ip (grub_pxe_your_ip);
- grub_printf ("\nserver ip : ");
- print_ip (grub_pxe_server_ip);
- grub_printf ("\ngateway ip : ");
- print_ip (grub_pxe_gateway_ip);
- grub_printf ("\n");
- }
-
- if (state[2].set)
- grub_pxe_unload ();
+ grub_pxe_unload ();
return 0;
}
-static grub_extcmd_t cmd;
+static grub_command_t cmd;
GRUB_MOD_INIT(pxecmd)
{
- cmd = grub_register_extcmd ("pxe", grub_cmd_pxe, GRUB_COMMAND_FLAG_BOTH,
- "pxe [-i|-b|-u]",
- "Command to control the PXE device.", options);
+ cmd = grub_register_command ("pxe_unload", grub_cmd_pxe_unload,
+ "pxe_unload",
+ "Unload PXE environment.");
}
GRUB_MOD_FINI(pxecmd)
{
- grub_unregister_extcmd (cmd);
+ grub_unregister_command (cmd);
}
=== modified file 'fs/i386/pc/pxe.c'
--- fs/i386/pc/pxe.c 2009-12-20 13:09:16 +0000
+++ fs/i386/pc/pxe.c 2009-12-20 19:05:53 +0000
@@ -1,7 +1,7 @@
/* pxe.c - Driver to provide access to the pxe filesystem */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2008 Free Software Foundation, Inc.
+ * Copyright (C) 2008,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
@@ -24,6 +24,7 @@
#include <grub/file.h>
#include <grub/misc.h>
#include <grub/bufio.h>
+#include <grub/env.h>
#include <grub/machine/pxe.h>
#include <grub/machine/memory.h>
@@ -33,11 +34,17 @@
#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x))
#define LINEAR(x) (void *) (((x >> 16) <<4) + (x & 0xFFFF))
+struct grub_pxe_disk_data
+{
+ grub_uint32_t server_ip;
+ grub_uint32_t gateway_ip;
+};
+
struct grub_pxenv *grub_pxe_pxenv;
-grub_uint32_t grub_pxe_your_ip;
-grub_uint32_t grub_pxe_server_ip;
-grub_uint32_t grub_pxe_gateway_ip;
-int grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE;
+static grub_uint32_t grub_pxe_your_ip;
+static grub_uint32_t grub_pxe_default_server_ip;
+static grub_uint32_t grub_pxe_default_gateway_ip;
+static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE;
static grub_file_t curr_file = 0;
@@ -57,23 +64,82 @@ grub_pxe_iterate (int (*hook) (const cha
}
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++;
+ }
+ *ip = newip;
+ if (rest)
+ *rest = ptr - 1;
+ return 0;
+}
+
+static grub_err_t
grub_pxe_open (const char *name, grub_disk_t disk)
{
- if (grub_strcmp (name, "pxe"))
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a pxe disk");
+ struct grub_pxe_disk_data *data;
+
+ if (grub_strcmp (name, "pxe") != 0
+ && grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) != 0)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a pxe disk");
+
+ data = grub_malloc (sizeof (*data));
+ if (!data)
+ return grub_errno;
+
+ if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
+ {
+ const char *ptr;
+ grub_err_t err;
+
+ ptr = name + sizeof ("pxe:") - 1;
+ err = parse_ip (ptr, &(data->server_ip), &ptr);
+ if (err)
+ return err;
+ if (*ptr == ':')
+ {
+ err = parse_ip (ptr + 1, &(data->server_ip), 0);
+ if (err)
+ return err;
+ }
+ else
+ data->gateway_ip = grub_pxe_default_gateway_ip;
+ }
+ else
+ {
+ data->server_ip = grub_pxe_default_server_ip;
+ data->gateway_ip = grub_pxe_default_gateway_ip;
+ }
disk->total_sectors = 0;
- disk->id = (unsigned long) "pxe";
+ disk->id = (unsigned long) data;
disk->has_partitions = 0;
- disk->data = 0;
+ disk->data = data;
return GRUB_ERR_NONE;
}
static void
-grub_pxe_close (grub_disk_t disk __attribute((unused)))
+grub_pxe_close (grub_disk_t disk)
{
+ grub_free (disk->data);
}
static grub_err_t
@@ -125,6 +191,7 @@ grub_pxefs_open (struct grub_file *file,
struct grub_pxenv_tftp_open c2;
} c;
struct grub_pxe_data *data;
+ struct grub_pxe_disk_data *disk_data = file->device->disk->data;
grub_file_t file_int, bufio;
if (curr_file != 0)
@@ -133,8 +200,8 @@ grub_pxefs_open (struct grub_file *file,
curr_file = 0;
}
- c.c1.server_ip = grub_pxe_server_ip;
- c.c1.gateway_ip = grub_pxe_gateway_ip;
+ c.c1.server_ip = disk_data->server_ip;
+ c.c1.gateway_ip = disk_data->gateway_ip;
grub_strcpy ((char *)&c.c1.filename[0], name);
grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1);
if (c.c1.status)
@@ -184,6 +251,7 @@ grub_pxefs_read (grub_file_t file, char
{
struct grub_pxenv_tftp_read c;
struct grub_pxe_data *data;
+ struct grub_pxe_disk_data *disk_data = file->device->disk->data;
grub_uint32_t pn, r;
data = file->data;
@@ -203,8 +271,8 @@ grub_pxefs_read (grub_file_t file, char
if (curr_file != 0)
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o);
- o.server_ip = grub_pxe_server_ip;
- o.gateway_ip = grub_pxe_gateway_ip;
+ o.server_ip = disk_data->server_ip;
+ o.gateway_ip = disk_data->gateway_ip;
grub_strcpy ((char *)&o.filename[0], data->filename);
o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
o.packet_size = grub_pxe_blksize;
@@ -272,6 +340,99 @@ static struct grub_fs grub_pxefs_fs =
.next = 0
};
+static char *
+grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val __attribute__ ((unused)))
+{
+ return NULL;
+}
+
+static void
+set_mac_env (grub_uint8_t *mac_addr, grub_size_t mac_len)
+{
+ char buf[(sizeof ("XX:") - 1) * mac_len + 1];
+ char *ptr = buf;
+ unsigned i;
+
+ for (i = 0; i < mac_len; i++)
+ {
+ grub_sprintf (ptr, "%02x:", mac_addr[i] & 0xff);
+ ptr += (sizeof ("XX:") - 1);
+ }
+ if (mac_len)
+ *(ptr - 1) = 0;
+ else
+ buf[0] = 0;
+
+ grub_env_set ("net_pxe_mac", buf);
+ /* XXX: Is it possible to change MAC in PXE? */
+ grub_register_variable_hook ("net_pxe_mac", 0, grub_env_write_readonly);
+}
+
+static void
+set_env_limn_ro (const char *varname, char *value, grub_size_t len)
+{
+ char c;
+ c = value[len];
+ value[len] = 0;
+ grub_env_set (varname, value);
+ value[len] = c;
+ grub_register_variable_hook (varname, 0, grub_env_write_readonly);
+}
+
+static void
+parse_dhcp_vendor (void *vend, int limit)
+{
+ grub_uint8_t *ptr, *ptr0;
+
+ ptr = ptr0 = vend;
+
+ if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) != 0x63825363)
+ return;
+ ptr = ptr + sizeof (grub_uint32_t);
+ while (ptr - ptr0 < limit)
+ {
+ grub_uint8_t tagtype;
+ grub_uint8_t taglength;
+
+ tagtype = *ptr++;
+
+ /* Pad tag. */
+ if (tagtype == 0)
+ continue;
+
+ /* End tag. */
+ if (tagtype == 0xff)
+ return;
+
+ taglength = *ptr++;
+
+ switch (tagtype)
+ {
+ case 12:
+ set_env_limn_ro ("net_pxe_hostname", (char *) ptr, taglength);
+ break;
+
+ case 15:
+ set_env_limn_ro ("net_pxe_domain", (char *) ptr, taglength);
+ break;
+
+ case 17:
+ set_env_limn_ro ("net_pxe_rootpath", (char *) ptr, taglength);
+ break;
+
+ case 18:
+ set_env_limn_ro ("net_pxe_extensionspath", (char *) ptr, taglength);
+ break;
+
+ /* If you need any other options please contact GRUB
+ developpement team. */
+ }
+
+ ptr += taglength;
+ }
+}
+
static void
grub_pxe_detect (void)
{
@@ -293,9 +454,15 @@ grub_pxe_detect (void)
bp = LINEAR (ci.buffer);
grub_pxe_your_ip = bp->your_ip;
- grub_pxe_server_ip = bp->server_ip;
- grub_pxe_gateway_ip = bp->gateway_ip;
-
+ grub_pxe_default_server_ip = bp->server_ip;
+ grub_pxe_default_gateway_ip = bp->gateway_ip;
+ set_mac_env (bp->mac_addr, bp->hw_len < sizeof (bp->mac_addr) ? bp->hw_len
+ : sizeof (bp->mac_addr));
+ set_env_limn_ro ("net_pxe_boot_file", (char *) bp->boot_file,
+ sizeof (bp->boot_file));
+ set_env_limn_ro ("net_pxe_dhcp_server_name", (char *) bp->server_name,
+ sizeof (bp->server_name));
+ parse_dhcp_vendor (&bp->vendor, sizeof (bp->vendor));
grub_pxe_pxenv = pxenv;
}
@@ -311,11 +478,110 @@ grub_pxe_unload (void)
}
}
+static void
+set_ip_env (char *varname, grub_uint32_t ip)
+{
+ char buf[sizeof ("XXX.XXX.XXX.XXX")];
+
+ grub_sprintf (buf, "%d.%d.%d.%d", (ip & 0xff),
+ (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);
+ grub_env_set (varname, buf);
+}
+
+static char *
+write_ip_env (grub_uint32_t *ip, const char *val)
+{
+ char *buf;
+ grub_err_t err;
+ grub_uint32_t newip;
+
+ err = parse_ip (val, &newip, 0);
+ if (err)
+ return 0;
+
+ /* Normalize the IP. */
+ buf = grub_malloc (sizeof ("XXX.XXX.XXX.XXX"));
+ if (!buf)
+ return 0;
+
+ *ip = newip;
+
+ grub_sprintf (buf, "%d.%d.%d.%d", (newip & 0xff), (newip >> 8) & 0xff,
+ (newip >> 16) & 0xff, (newip >> 24) & 0xff);
+
+ return buf;
+}
+
+static char *
+grub_env_write_pxe_default_server (struct grub_env_var *var
+ __attribute__ ((unused)),
+ const char *val)
+{
+ return write_ip_env (&grub_pxe_default_server_ip, val);
+}
+
+static char *
+grub_env_write_pxe_default_gateway (struct grub_env_var *var
+ __attribute__ ((unused)),
+ const char *val)
+{
+ return write_ip_env (&grub_pxe_default_gateway_ip, val);
+}
+
+static char *
+grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__
((unused)),
+ const char *val)
+{
+ unsigned size;
+ char *buf;
+
+ size = grub_strtoul (val, 0, 0);
+ if (grub_errno)
+ return 0;
+
+ if (size < GRUB_PXE_MIN_BLKSIZE)
+ size = GRUB_PXE_MIN_BLKSIZE;
+ else if (size > GRUB_PXE_MAX_BLKSIZE)
+ size = GRUB_PXE_MAX_BLKSIZE;
+
+ buf = grub_malloc (sizeof ("XXXXXX XXXXXX"));
+ if (!buf)
+ return 0;
+
+ grub_sprintf (buf, "%d", size);
+ grub_pxe_blksize = size;
+
+ return buf;
+}
+
+
GRUB_MOD_INIT(pxe)
{
grub_pxe_detect ();
if (grub_pxe_pxenv)
{
+ char *buf;
+
+ buf = grub_malloc (sizeof ("XXXXXX XXXXXX"));
+ if (buf)
+ {
+ grub_sprintf (buf, "%d", grub_pxe_blksize);
+ grub_env_set ("net_pxe_blksize", buf);
+ }
+
+ set_ip_env ("pxe_default_server", grub_pxe_default_server_ip);
+ set_ip_env ("pxe_default_gateway", grub_pxe_default_gateway_ip);
+ set_ip_env ("net_pxe_ip", grub_pxe_your_ip);
+ grub_register_variable_hook ("net_pxe_default_server", 0,
+ grub_env_write_pxe_default_server);
+ grub_register_variable_hook ("net_pxe_default_gateway", 0,
+ grub_env_write_pxe_default_gateway);
+
+ /* XXX: Is it possible to change IP in PXE? */
+ grub_register_variable_hook ("net_pxe_ip", 0,
+ grub_env_write_readonly);
+ grub_register_variable_hook ("net_pxe_blksize", 0,
+ grub_env_write_pxe_blocksize);
grub_disk_dev_register (&grub_pxe_dev);
grub_fs_register (&grub_pxefs_fs);
}
=== modified file 'include/grub/i386/pc/pxe.h'
--- include/grub/i386/pc/pxe.h 2008-08-05 15:15:59 +0000
+++ include/grub/i386/pc/pxe.h 2009-12-20 19:05:53 +0000
@@ -201,7 +201,7 @@ struct grub_pxenv_get_cached_info
#define GRUB_PXE_MAC_ADDR_LEN 16
-typedef grub_uint8_t grub_pxe_mac_addr[GRUB_PXE_MAC_ADDR_LEN];
+typedef grub_uint8_t grub_pxe_mac_addr_t[GRUB_PXE_MAC_ADDR_LEN];
struct grub_pxenv_boot_player
{
@@ -216,7 +216,7 @@ struct grub_pxenv_boot_player
grub_uint32_t your_ip;
grub_uint32_t server_ip;
grub_uint32_t gateway_ip;
- grub_pxe_mac_addr mac_addr;
+ grub_pxe_mac_addr_t mac_addr;
grub_uint8_t server_name[64];
grub_uint8_t boot_file[128];
union
@@ -306,10 +306,6 @@ struct grub_pxenv * EXPORT_FUNC(grub_pxe
int EXPORT_FUNC(grub_pxe_call) (int func, void * data);
extern struct grub_pxenv *grub_pxe_pxenv;
-extern grub_uint32_t grub_pxe_your_ip;
-extern grub_uint32_t grub_pxe_server_ip;
-extern grub_uint32_t grub_pxe_gateway_ip;
-extern int grub_pxe_blksize;
void grub_pxe_unload (void);
signature.asc
Description: OpenPGP digital signature
- [PATCH] Add support for (pxe[:server_ip[:gateway_ip]]) and export pxe parameteres into grub environment,
Vladimir 'φ-coder/phcoder' Serbinenko <=