[PATCH] Add efi getenv command

2017-01-23 Thread Matthew Garrett
Add a command to obtain the contents of EFI firmware variables.
---
 docs/grub.texi  |   7 ++
 grub-core/Makefile.core.def |   7 ++
 grub-core/commands/efi/getenv.c | 153 
 3 files changed, 167 insertions(+)
 create mode 100644 grub-core/commands/efi/getenv.c

diff --git a/docs/grub.texi b/docs/grub.texi
index b9ddb9b..4469638 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3818,6 +3818,7 @@ you forget a command, you can run the command 
@command{help}
 * eval::Evaluate agruments as GRUB commands
 * export::  Export an environment variable
 * false::   Do nothing, unsuccessfully
+* getenv::  Retrieve an EFI firmware variable
 * gettext:: Translate a string
 * gptsync:: Fill an MBR based on GPT entries
 * halt::Shut down your computer
@@ -4258,6 +4259,12 @@ Do nothing, unsuccessfully.  This is mainly useful in 
control constructs
 such as @code{if} and @code{while} (@pxref{Shell-like scripting}).
 @end deffn
 
+@node getenv
+@subsection getenv
+
+@deffn Command getenv [@option{-e}] [@option{-g}] envvar
+Retrieves an EFI variable with the name provided by @option{-e} and the GUID
+provied by @option{-g} and stores it in environment variable @var{envvar}
 
 @node gettext
 @subsection gettext
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 2dfa22a..db77a7f 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -817,6 +817,13 @@ module = {
 };
 
 module = {
+  name = getenv;
+  common = commands/efi/getenv.c;
+  enable = i386_efi;
+  enable = x86_64_efi;
+};
+
+module = {
   name = gptsync;
   common = commands/gptsync.c;
 };
diff --git a/grub-core/commands/efi/getenv.c b/grub-core/commands/efi/getenv.c
new file mode 100644
index 000..5a829f5
--- /dev/null
+++ b/grub-core/commands/efi/getenv.c
@@ -0,0 +1,153 @@
+/* getenv.c - retrieve EFI variables.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *  Copyright (C) 2014  CoreOS, 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 .
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static const struct grub_arg_option options_getenv[] = {
+  {"var-name", 'e', 0,
+   N_("Environment variable to query"),
+   N_("VARNAME"), ARG_TYPE_STRING},
+  {"var-guid", 'g', 0,
+   N_("GUID of environment variable to query"),
+   N_("GUID"), ARG_TYPE_STRING},
+  {"binary", 'b', 0,
+   N_("Read binary data and represent it as hex"),
+   0, ARG_TYPE_NONE},
+  {0, 0, 0, 0, 0, 0}
+};
+
+enum options_getenv
+{
+  GETENV_VAR_NAME,
+  GETENV_VAR_GUID,
+  GETENV_BINARY,
+};
+
+static grub_err_t
+grub_cmd_getenv (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+  struct grub_arg_list *state = ctxt->state;
+  char *envvar = NULL, *guid = NULL, *bindata = NULL, *data = NULL;
+  grub_size_t datasize;
+  grub_efi_guid_t efi_var_guid;
+  grub_efi_boolean_t binary = state[GETENV_BINARY].set;
+  unsigned int i;
+
+  if (!state[GETENV_VAR_NAME].set || !state[GETENV_VAR_GUID].set)
+{
+  grub_error (GRUB_ERR_INVALID_COMMAND, N_("-e and -g are required"));
+  goto done;
+}
+
+  if (argc != 1)
+{
+  grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unexpected arguments"));
+  goto done;
+}
+
+  envvar = state[GETENV_VAR_NAME].arg;
+  guid = state[GETENV_VAR_GUID].arg;
+
+  if (grub_strlen(guid) != 36 ||
+  guid[8] != '-' ||
+  guid[13] != '-' ||
+  guid[18] != '-' ||
+  guid[23] != '-')
+{
+  grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid GUID"));
+  goto done;
+}
+
+  /* Forgive me father for I have sinned */
+  guid[8] = 0;
+  efi_var_guid.data1 = grub_strtoul(guid, NULL, 16);
+  guid[13] = 0;
+  efi_var_guid.data2 = grub_strtoul(guid + 9, NULL, 16);
+  guid[18] = 0;
+  efi_var_guid.data3 = grub_strtoul(guid + 14, NULL, 16);
+  efi_var_guid.data4[7] = grub_strtoul(guid + 34, NULL, 16);
+  guid[34] = 0;
+  efi_var_guid.data4[6] = grub_strtoul(guid + 32, NULL, 16);
+  guid[32] = 0;
+  efi_var_guid.data4[5] = grub_strtoul(guid + 30, NULL, 16);
+  guid[30] = 0;
+  efi_var_guid.data4[4] = grub_strtoul(guid + 28, NULL, 16);
+  guid[28] = 0;
+  efi_var_guid.data

[PATCH] Add fwconfig command

2017-01-23 Thread Matthew Garrett
Add a command to read values from the qemu fwcfg store. This allows data
to be passed from the qemu command line to grub.

Example use:

echo '(hd0,1)' >rootdev
qemu -fw_cfg opt/rootdev,file=rootdev

fwconfig opt/rootdev root
---
 docs/grub.texi|   6 +++
 grub-core/Makefile.core.def   |   6 +++
 grub-core/commands/fwconfig.c | 121 ++
 3 files changed, 133 insertions(+)
 create mode 100644 grub-core/commands/fwconfig.c

diff --git a/docs/grub.texi b/docs/grub.texi
index 4469638..4f8a378 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3818,6 +3818,7 @@ you forget a command, you can run the command 
@command{help}
 * eval::Evaluate agruments as GRUB commands
 * export::  Export an environment variable
 * false::   Do nothing, unsuccessfully
+* fwconfig::Retrieves a value from the qemu fwcfg store
 * getenv::  Retrieve an EFI firmware variable
 * gettext:: Translate a string
 * gptsync:: Fill an MBR based on GPT entries
@@ -4259,6 +4260,11 @@ Do nothing, unsuccessfully.  This is mainly useful in 
control constructs
 such as @code{if} and @code{while} (@pxref{Shell-like scripting}).
 @end deffn
 
+@node fwconfig
+@subsection fwconig
+@deffn Command fwconfig fwpath envvar
+Retrieves @var{fwpath} from the qemu fwcfg store and stores it in @var{envvar}
+
 @node getenv
 @subsection getenv
 
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index db77a7f..f6b6f38 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2362,3 +2362,9 @@ module = {
   common = loader/i386/xen_file64.c;
   extra_dist = loader/i386/xen_fileXX.c;
 };
+
+module = {
+  name = fwconfig;
+  common = commands/fwconfig.c;
+  enable = x86;
+};
diff --git a/grub-core/commands/fwconfig.c b/grub-core/commands/fwconfig.c
new file mode 100644
index 000..289d167
--- /dev/null
+++ b/grub-core/commands/fwconfig.c
@@ -0,0 +1,121 @@
+/* fwconfig.c - command to read config from qemu fwconfig  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2015  CoreOS, 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 .
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define SELECTOR 0x510
+#define DATA 0x511
+
+#define SIGNATURE_INDEX 0x00
+#define DIRECTORY_INDEX 0x19
+
+static grub_extcmd_t cmd_read_fwconfig;
+
+struct grub_qemu_fwcfgfile {
+  grub_uint32_t size;
+  grub_uint16_t select;
+  grub_uint16_t reserved;
+  char name[56];
+};
+
+static const struct grub_arg_option options[] =
+  {
+{0, 'v', 0, N_("Save read value into variable VARNAME."),
+ N_("VARNAME"), ARG_TYPE_STRING},
+{0, 0, 0, 0, 0, 0}
+  };
+
+static grub_err_t
+grub_cmd_fwconfig (grub_extcmd_context_t ctxt, int argc, char **argv)
+{
+  grub_uint32_t i, j, value = 0;
+  struct grub_qemu_fwcfgfile file;
+  char fwsig[4], signature[4] = { 'Q', 'E', 'M', 'U' };
+
+  if (argc != 2)
+return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
+
+  /* Verify that we have meaningful hardware here */
+  grub_outw(SIGNATURE_INDEX, SELECTOR);
+  for (i=0; ihttps://lists.gnu.org/mailman/listinfo/grub-devel


Misc network boot patches

2017-01-23 Thread Matthew Garrett
Various patches that we're using to support network boot in our setup. Only
number 3 is a bugfix.


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH 1/4] Allow non-default ports for HTTP requests

2017-01-23 Thread Matthew Garrett
Add support for passing ports in HTTP requests. This takes the form of:
(http,serverip:portnum)/file
---
 grub-core/net/http.c |  8 ++--
 grub-core/net/net.c  | 10 +-
 include/grub/net.h   |  1 +
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index 5aa4ad3..389a78e 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -309,7 +309,7 @@ http_establish (struct grub_file *file, grub_off_t offset, 
int initial)
 {
   http_data_t data = file->data;
   grub_uint8_t *ptr;
-  int i;
+  int i, port;
   struct grub_net_buff *nb;
   grub_err_t err;
 
@@ -390,8 +390,12 @@ http_establish (struct grub_file *file, grub_off_t offset, 
int initial)
   grub_netbuff_put (nb, 2);
   grub_memcpy (ptr, "\r\n", 2);
 
+  if (file->device->net->port)
+port = file->device->net->port;
+  else
+port = HTTP_PORT;
   data->sock = grub_net_tcp_open (file->device->net->server,
- HTTP_PORT, http_receive,
+ port, http_receive,
  http_err, http_err,
  file);
   if (!data->sock)
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 10773fc..585f4f7 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1261,7 +1261,7 @@ grub_net_open_real (const char *name)
   grub_net_app_level_t proto;
   const char *protname, *server;
   grub_size_t protnamelen;
-  int try;
+  int try, port = 0;
 
   if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
 {
@@ -1278,7 +1278,14 @@ grub_net_open_real (const char *name)
   else
 {
   const char *comma;
+  char *colon;
   comma = grub_strchr (name, ',');
+  colon = grub_strchr (name, ':');
+  if (colon)
+   {
+ port = (int) grub_strtol(colon+1, NULL, 10);
+ *colon = '\0';
+   }
   if (comma)
{
  protnamelen = comma - name;
@@ -1310,6 +1317,7 @@ grub_net_open_real (const char *name)
if (!ret)
  return NULL;
ret->protocol = proto;
+   ret->port = port;
ret->server = grub_strdup (server);
if (!ret->server)
  {
diff --git a/include/grub/net.h b/include/grub/net.h
index 2192fa1..c517509 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -276,6 +276,7 @@ typedef struct grub_net
   grub_fs_t fs;
   int eof;
   int stall;
+  int port;
 } *grub_net_t;
 
 extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);
-- 
2.9.3


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH 2/4] Send a user class identifier in bootp requests and tag it as DHCP discover

2017-01-23 Thread Matthew Garrett
It's helpful to determine that a request was sent by grub in order to permit
the server to provide different information at different stages of the boot
process. Send GRUB2 as a type 77 DHCP option when sending bootp packets in
order to make this possible and tag the request as a DHCP discover to
convince servers to pay attention to it. Add the client architecture for
good measure.
---
 grub-core/net/bootp.c | 42 +-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index 9e2fdb7..0da8e24 100644
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -25,6 +25,24 @@
 #include 
 #include 
 
+#if !defined(GRUB_MACHINE_EFI) && (defined(__i386__) || defined(__x86_64__))
+#define GRUB_NET_BOOTP_ARCH 0x
+#elif defined(GRUB_MACHINE_EFI) && defined(__x86_64__)
+#define GRUB_NET_BOOTP_ARCH 0x0007
+#elif defined(GRUB_MACHINE_EFI) && defined(__aarch64__)
+#define GRUB_NET_BOOTP_ARCH 0x000B
+#else
+#error "unknown bootp architecture"
+#endif
+
+static grub_uint8_t dhcp_option_header[] = {GRUB_NET_BOOTP_RFC1048_MAGIC_0,
+   GRUB_NET_BOOTP_RFC1048_MAGIC_1,
+   GRUB_NET_BOOTP_RFC1048_MAGIC_2,
+   GRUB_NET_BOOTP_RFC1048_MAGIC_3};
+static grub_uint8_t grub_userclass[] = {0x4D, 0x06, 0x05, 'G', 'R', 'U', 'B', 
'2'};
+static grub_uint8_t grub_dhcpdiscover[] = {0x35, 0x01, 0x01};
+static grub_uint8_t grub_dhcptime[] = {0x33, 0x04, 0x00, 0x00, 0x0e, 0x10};
+
 static void
 parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
 {
@@ -499,10 +517,14 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ 
((unused)),
  struct udphdr *udph;
  grub_net_network_level_address_t target;
  grub_net_link_level_address_t ll_target;
+ grub_uint8_t *offset;
 
  if (!ifaces[j].prev)
continue;
- nb = grub_netbuff_alloc (sizeof (*pack) + 64 + 128);
+ nb = grub_netbuff_alloc (sizeof (*pack) + sizeof(dhcp_option_header)
+  + sizeof(grub_userclass)
+  + sizeof(grub_dhcpdiscover)
+  + sizeof(grub_dhcptime) + 64 + 128);
  if (!nb)
{
  grub_netbuff_free (nb);
@@ -536,6 +558,24 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ 
((unused)),
  pack->seconds = grub_cpu_to_be16 (t);
 
  grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); 
+ offset = (grub_uint8_t *)&pack->vendor;
+ grub_memcpy (offset, dhcp_option_header, sizeof(dhcp_option_header));
+ offset += sizeof(dhcp_option_header);
+ grub_memcpy (offset, grub_dhcpdiscover, sizeof(grub_dhcpdiscover));
+ offset += sizeof(grub_dhcpdiscover);
+ grub_memcpy (offset, grub_userclass, sizeof(grub_userclass));
+ offset += sizeof(grub_userclass);
+ grub_memcpy (offset, grub_dhcptime, sizeof(grub_dhcptime));
+
+ /* insert Client System Architecture (option 93) */
+ offset += sizeof(grub_dhcptime);
+ offset[0] = 93;
+ offset[1] = 2;
+ offset[2] = (GRUB_NET_BOOTP_ARCH >> 8);
+ offset[3] = (GRUB_NET_BOOTP_ARCH & 0xFF);
+
+ /* option terminator */
+ offset[4] = 255;
 
  grub_netbuff_push (nb, sizeof (*udph));
 
-- 
2.9.3


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH 4/4] Allow protocol to be separated from host with a semicolon

2017-01-23 Thread Matthew Garrett
Some DHCP servers (such as dnsmasq) tokenise parameters with commas, making
it impossible to pass boot files with commas in them. Allow using a
semicolon to separate the protocol from host if a comma wasn't found.
---
 grub-core/net/net.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 585f4f7..efacb30 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1280,6 +1280,10 @@ grub_net_open_real (const char *name)
   const char *comma;
   char *colon;
   comma = grub_strchr (name, ',');
+  if (!comma)
+   {
+ comma = grub_strchr (name, ';');
+   }
   colon = grub_strchr (name, ':');
   if (colon)
{
-- 
2.9.3


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH 3/4] Don't allocate a new address buffer if we receive multiple DNS responses

2017-01-23 Thread Matthew Garrett
The current logic in the DNS resolution code allocates an address buffer
based on the number of addresses in the response packet. If we receive
multiple response packets in response to a single query packet, this means
that we will reallocate a new buffer large enough for only the addresses in
that specific packet, discarding any previous results in the process. Worse,
we still keep track of the *total* number of addresses resolved in response
to this query, not merely the number in the packet being currently processed.
Use realloc() rather than malloc() to avoid overwriting the existing data,
and allocate a buffer large enough for the total set of addresses rather
than merely the number in this specific response.
---
 grub-core/net/dns.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
index 5d9afe0..5deb1ef 100644
--- a/grub-core/net/dns.c
+++ b/grub-core/net/dns.c
@@ -285,8 +285,8 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ 
((unused)),
   ptr++;
   ptr += 4;
 }
-  *data->addresses = grub_malloc (sizeof ((*data->addresses)[0])
-* grub_be_to_cpu16 (head->ancount));
+  *data->addresses = grub_realloc (*data->addresses, sizeof 
((*data->addresses)[0])
+* (grub_be_to_cpu16 (head->ancount) + *data->naddresses));
   if (!*data->addresses)
 {
   grub_errno = GRUB_ERR_NONE;
-- 
2.9.3


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Support for TPM measurements on UEFI systems

2017-01-23 Thread Matthew Garrett
This patchset adds support for measuring components of grub and what it's
loading into the TPM. It supports both TPM 1.2 and 2.0 devices via the
standard UEFI protocols.


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH 2/7] Rework linux command

2017-01-23 Thread Matthew Garrett
We want a single buffer that contains the entire kernel image in order to
perform a TPM measurement. Allocate one and copy the entire kernel into it
before pulling out the individual blocks later on.
---
 grub-core/loader/i386/linux.c | 34 +-
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index b15b8cc..5e54ec9 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -680,12 +680,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
   grub_file_t file = 0;
   struct linux_kernel_header lh;
   grub_uint8_t setup_sects;
-  grub_size_t real_size, prot_size, prot_file_size;
+  grub_size_t real_size, prot_size, prot_file_size, kernel_offset;
   grub_ssize_t len;
   int i;
   grub_size_t align, min_align;
   int relocatable;
   grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
+  grub_uint8_t *kernel = NULL;
 
   grub_dl_ref (my_mod);
 
@@ -699,7 +700,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
   if (! file)
 goto fail;
 
-  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
+  len = grub_file_size (file);
+  kernel = grub_malloc (len);
+  if (!kernel)
+{
+  grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
+  goto fail;
+}
+
+  if (grub_file_read (file, kernel, len) != len)
 {
   if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -707,6 +716,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   goto fail;
 }
 
+  grub_memcpy (&lh, kernel, sizeof (lh));
+  kernel_offset = sizeof (lh);
+
   if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
 {
   grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
@@ -806,13 +818,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
   linux_params.ps_mouse = linux_params.padding10 =  0;
 
   len = sizeof (linux_params) - sizeof (lh);
-  if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len)
-{
-  if (!grub_errno)
-   grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
-   argv[0]);
-  goto fail;
-}
+
+  grub_memcpy (&linux_params + sizeof (lh), kernel + kernel_offset, len);
+  kernel_offset += len;
 
   linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
 
@@ -871,7 +879,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 
   /* The other parameters are filled when booting.  */
 
-  grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
+  kernel_offset = real_size + GRUB_DISK_SECTOR_SIZE;
 
   grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
(unsigned) real_size, (unsigned) prot_size);
@@ -1016,9 +1024,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
  - (sizeof (LINUX_IMAGE) - 1));
 
   len = prot_file_size;
-  if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
-grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
-   argv[0]);
+  grub_memcpy (prot_mode_mem, kernel + kernel_offset, len);
 
   if (grub_errno == GRUB_ERR_NONE)
 {
@@ -1029,6 +1035,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
 
  fail:
 
+  grub_free (kernel);
+
   if (file)
 grub_file_close (file);
 
-- 
2.9.3


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH 1/7] Core TPM support

2017-01-23 Thread Matthew Garrett
Add support for performing basic TPM measurements. Right now this only
supports extending PCRs statically and only on UEFI and BIOS systems, but
will measure all modules as they're loaded.
---
 grub-core/Makefile.am|   1 +
 grub-core/Makefile.core.def  |   3 +
 grub-core/kern/dl.c  |   4 +
 grub-core/kern/efi/tpm.c | 282 +++
 grub-core/kern/i386/pc/tpm.c | 145 ++
 grub-core/kern/tpm.c |  19 +++
 include/grub/efi/tpm.h   | 153 +++
 include/grub/tpm.h   |  94 +++
 8 files changed, 701 insertions(+)
 create mode 100644 grub-core/kern/efi/tpm.c
 create mode 100644 grub-core/kern/i386/pc/tpm.c
 create mode 100644 grub-core/kern/tpm.c
 create mode 100644 include/grub/efi/tpm.h
 create mode 100644 include/grub/tpm.h

diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 04e9395..23ce9e9 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -92,6 +92,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/tpm.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
 
 if COND_i386_pc
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index f6b6f38..90a43bb 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -126,6 +126,7 @@ kernel = {
   common = kern/rescue_parser.c;
   common = kern/rescue_reader.c;
   common = kern/term.c;
+  common = kern/tpm.c;
 
   noemu = kern/compiler-rt.c;
   noemu = kern/mm.c;
@@ -173,6 +174,7 @@ kernel = {
   efi = term/efi/console.c;
   efi = kern/acpi.c;
   efi = kern/efi/acpi.c;
+  efi = kern/efi/tpm.c;
   i386_coreboot = kern/i386/pc/acpi.c;
   i386_multiboot = kern/i386/pc/acpi.c;
   i386_coreboot = kern/acpi.c;
@@ -219,6 +221,7 @@ kernel = {
 
   i386_pc = kern/i386/pc/init.c;
   i386_pc = kern/i386/pc/mmap.c;
+  i386_pc = kern/i386/pc/tpm.c;
   i386_pc = term/i386/pc/console.c;
 
   i386_qemu = bus/pci.c;
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index e394cd9..29ee00a 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* Platforms where modules are in a readonly area of memory.  */
 #if defined(GRUB_MACHINE_QEMU)
@@ -712,6 +713,9 @@ grub_dl_load_file (const char *filename)
  opens of the same device.  */
   grub_file_close (file);
 
+  grub_tpm_measure(core, size, GRUB_BINARY_PCR, "grub_module", filename);
+  grub_print_error();
+
   mod = grub_dl_load_core (core, size);
   grub_free (core);
   if (! mod)
diff --git a/grub-core/kern/efi/tpm.c b/grub-core/kern/efi/tpm.c
new file mode 100644
index 000..c9fb3c1
--- /dev/null
+++ b/grub-core/kern/efi/tpm.c
@@ -0,0 +1,282 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static grub_efi_guid_t tpm_guid = EFI_TPM_GUID;
+static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID;
+
+static grub_efi_boolean_t grub_tpm_present(grub_efi_tpm_protocol_t *tpm)
+{
+  grub_efi_status_t status;
+  TCG_EFI_BOOT_SERVICE_CAPABILITY caps;
+  grub_uint32_t flags;
+  grub_efi_physical_address_t eventlog, lastevent;
+
+  caps.Size = (grub_uint8_t)sizeof(caps);
+
+  status = efi_call_5(tpm->status_check, tpm, &caps, &flags, &eventlog,
+ &lastevent);
+
+  if (status != GRUB_EFI_SUCCESS || caps.TPMDeactivatedFlag
+  || !caps.TPMPresentFlag)
+return 0;
+
+  return 1;
+}
+
+static grub_efi_boolean_t grub_tpm2_present(grub_efi_tpm2_protocol_t *tpm)
+{
+  grub_efi_status_t status;
+  EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
+
+  caps.Size = (grub_uint8_t)sizeof(caps);
+
+  status = efi_call_2(tpm->get_capability, tpm, &caps);
+
+  if (status != GRUB_EFI_SUCCESS || !caps.TPMPresentFlag)
+return 0;
+
+  return 1;
+}
+
+static grub_efi_boolean_t grub_tpm_handle_find(grub_efi_handle_t *tpm_handle,
+  grub_efi_uint8_t 
*protocol_version)
+{
+  grub_efi_handle_t *handles;
+  grub_efi_uintn_t num_handles;
+
+  handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm_guid, NULL,
+   &num_handles);
+  if (handles && num_handles > 0) {
+*tpm_handle = handles[0];
+*protocol_version = 1;
+return 1;
+  }
+
+  handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm2_guid, NULL,
+   &num_handles);
+  if (handles && num_handles > 0) {
+*tpm_handle = handles[0];
+*protocol_version = 2;
+return 1;
+  }
+
+  return 0;
+}
+
+static grub_err_t
+grub_tpm1_execute(grub_efi_handle_t tpm_handle,
+ PassThroughToTPM_InputParamBlock *inbuf,
+ PassThroughToTPM_OutputParamBlock *outbuf)
+{
+  grub_efi_status_t status;
+  grub_efi

[PATCH 7/7] Measure multiboot images and modules

2017-01-23 Thread Matthew Garrett
---
 grub-core/loader/i386/multiboot_mbi.c | 4 
 grub-core/loader/multiboot.c  | 3 +++
 grub-core/loader/multiboot_mbi2.c | 4 
 3 files changed, 11 insertions(+)

diff --git a/grub-core/loader/i386/multiboot_mbi.c 
b/grub-core/loader/i386/multiboot_mbi.c
index fd7b41b..42372bf 100644
--- a/grub-core/loader/i386/multiboot_mbi.c
+++ b/grub-core/loader/i386/multiboot_mbi.c
@@ -36,6 +36,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef GRUB_MACHINE_EFI
 #include 
@@ -173,6 +174,9 @@ grub_multiboot_load (grub_file_t file, const char *filename)
   return grub_errno;
 }
 
+  grub_tpm_measure((unsigned char*)buffer, len, GRUB_BINARY_PCR, 
"grub_multiboot", filename);
+  grub_print_error();
+
   header = find_header (buffer, len);
 
   if (header == 0)
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index bd9d5b3..a97ed87 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -42,6 +42,7 @@
 #include 
 #include 
 #include 
+#include 
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -424,6 +425,8 @@ grub_cmd_module (grub_command_t cmd __attribute__ 
((unused)),
 }
 
   grub_file_close (file);
+  grub_tpm_measure (module, size, GRUB_BINARY_PCR, "grub_multiboot", argv[0]);
+  grub_print_error();
   return GRUB_ERR_NONE;
 }
 
diff --git a/grub-core/loader/multiboot_mbi2.c 
b/grub-core/loader/multiboot_mbi2.c
index b0679a9..c62ced3 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -36,6 +36,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if defined (GRUB_MACHINE_EFI)
 #include 
@@ -131,6 +132,9 @@ grub_multiboot_load (grub_file_t file, const char *filename)
 
   COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0);
 
+  grub_tpm_measure ((unsigned char *)mld.buffer, len, GRUB_BINARY_PCR, 
"grub_multiboot", filename);
+  grub_print_error();
+
   header = find_header (mld.buffer, len);
 
   if (header == 0)
-- 
2.9.3


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH 4/7] Measure kernel and initrd

2017-01-23 Thread Matthew Garrett
Measure the kernel and initrd at load time
---
 grub-core/loader/i386/linux.c| 6 ++
 grub-core/loader/i386/pc/linux.c | 4 
 grub-core/loader/linux.c | 3 +++
 3 files changed, 13 insertions(+)

diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index 5e54ec9..6d8d3d6 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -35,6 +35,7 @@
 #include 
 #include 
 #include 
+#include 
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -716,7 +717,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
   goto fail;
 }
 
+  grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "grub_linux", "Linux 
Kernel");
+  grub_print_error();
+
   grub_memcpy (&lh, kernel, sizeof (lh));
+
   kernel_offset = sizeof (lh);
 
   if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
@@ -1025,6 +1030,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
 
   len = prot_file_size;
   grub_memcpy (prot_mode_mem, kernel + kernel_offset, len);
+  kernel_offset += len;
 
   if (grub_errno == GRUB_ERR_NONE)
 {
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index 1ac9cd1..c6197a1 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -35,6 +35,7 @@
 #include 
 #include 
 #include 
+#include 
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -160,6 +161,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   goto fail;
 }
 
+  grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "grub_linux16", "BIOS Linux 
Kernel");
+  grub_print_error();
+
   grub_memcpy (&lh, kernel, sizeof (lh));
   kernel_offset = sizeof (lh);
 
diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
index be6fa0f..8b5e6e0 100644
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct newc_head
 {
@@ -288,6 +289,8 @@ grub_initrd_load (struct grub_linux_initrd_context 
*initrd_ctx,
  grub_initrd_close (initrd_ctx);
  return grub_errno;
}
+  grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "grub_initrd", "Linux 
Initrd");
+  grub_print_error();
   ptr += cursize;
 }
   if (newc)
-- 
2.9.3


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH 3/7] Rework linux16 command

2017-01-23 Thread Matthew Garrett
We want a single buffer that contains the entire kernel image in order to
perform a TPM measurement. Allocate one and copy the entire kernel int it
before pulling out the individual blocks later on.
---
 grub-core/loader/i386/pc/linux.c | 34 +-
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index a293b17..1ac9cd1 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -123,13 +123,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
   grub_file_t file = 0;
   struct linux_kernel_header lh;
   grub_uint8_t setup_sects;
-  grub_size_t real_size;
+  grub_size_t real_size, kernel_offset = 0;
   grub_ssize_t len;
   int i;
   char *grub_linux_prot_chunk;
   int grub_linux_is_bzimage;
   grub_addr_t grub_linux_prot_target;
   grub_err_t err;
+  grub_uint8_t *kernel = NULL;
 
   grub_dl_ref (my_mod);
 
@@ -143,7 +144,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
   if (! file)
 goto fail;
 
-  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
+  len = grub_file_size (file);
+  kernel = grub_malloc (len);
+  if (!kernel)
+{
+  grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
+  goto fail;
+}
+
+  if (grub_file_read (file, kernel, len) != len)
 {
   if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -151,6 +160,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   goto fail;
 }
 
+  grub_memcpy (&lh, kernel, sizeof (lh));
+  kernel_offset = sizeof (lh);
+
   if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
 {
   grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
@@ -314,13 +326,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
   grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh));
 
   len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh);
-  if (grub_file_read (file, grub_linux_real_chunk + sizeof (lh), len) != len)
-{
-  if (!grub_errno)
-   grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
-   argv[0]);
-  goto fail;
-}
+  grub_memcpy (grub_linux_real_chunk + sizeof (lh), kernel + kernel_offset,
+  len);
+  kernel_offset += len;
 
   if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
   || grub_le_to_cpu16 (lh.version) < 0x0200)
@@ -355,10 +363,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
   }
 
   len = grub_linux16_prot_size;
-  if (grub_file_read (file, grub_linux_prot_chunk, grub_linux16_prot_size)
-  != (grub_ssize_t) grub_linux16_prot_size && !grub_errno)
-grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
-   argv[0]);
+  grub_memcpy (grub_linux_prot_chunk, kernel + kernel_offset, len);
+  kernel_offset += len;
 
   if (grub_errno == GRUB_ERR_NONE)
 {
@@ -368,6 +374,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 
  fail:
 
+  grub_free (kernel);
+
   if (file)
 grub_file_close (file);
 
-- 
2.9.3


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH 6/7] Measure commands

2017-01-23 Thread Matthew Garrett
From: Matthew Garrett 

Measure each command executed by grub, which includes script execution.
---
 grub-core/script/execute.c | 25 +++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
index a8502d9..cf99410 100644
--- a/grub-core/script/execute.c
+++ b/grub-core/script/execute.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* Max digits for a char is 3 (0xFF is 255), similarly for an int it
is sizeof (int) * 3, and one extra for a possible -ve sign.  */
@@ -929,8 +930,9 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
   grub_err_t ret = 0;
   grub_script_function_t func = 0;
   char errnobuf[18];
-  char *cmdname;
-  int argc;
+  char *cmdname, *cmdstring;
+  int argc, offset = 0, cmdlen = 0;
+  unsigned int i;
   char **args;
   int invert;
   struct grub_script_argv argv = { 0, 0, 0 };
@@ -939,6 +941,25 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
   if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0])
 return grub_errno;
 
+  for (i = 0; i < argv.argc; i++) {
+ cmdlen += grub_strlen (argv.args[i]) + 1;
+  }
+
+  cmdstring = grub_malloc (cmdlen);
+  if (!cmdstring)
+  {
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+N_("cannot allocate command buffer"));
+  }
+
+  for (i = 0; i < argv.argc; i++) {
+ offset += grub_snprintf (cmdstring + offset, cmdlen - offset, "%s ",
+  argv.args[i]);
+  }
+  cmdstring[cmdlen-1]= '\0';
+  grub_tpm_measure ((unsigned char *)cmdstring, cmdlen, GRUB_ASCII_PCR, 
"grub_cmd", cmdstring);
+  grub_print_error();
+  grub_free(cmdstring);
   invert = 0;
   argc = argv.argc - 1;
   args = argv.args + 1;
-- 
2.9.3


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH 5/7] Measure the kernel commandline

2017-01-23 Thread Matthew Garrett
Measure the kernel commandline to ensure that it hasn't been modified
---
 grub-core/lib/cmdline.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c
index d5e10ee..055b7aa 100644
--- a/grub-core/lib/cmdline.c
+++ b/grub-core/lib/cmdline.c
@@ -19,6 +19,7 @@
 
 #include 
 #include 
+#include 
 
 static unsigned int check_arg (char *c, int *has_space)
 {
@@ -67,7 +68,7 @@ int grub_create_loader_cmdline (int argc, char *argv[], char 
*buf,
 {
   int i, space;
   unsigned int arg_size;
-  char *c;
+  char *c, *orig = buf;
 
   for (i = 0; i < argc; i++)
 {
@@ -104,5 +105,8 @@ int grub_create_loader_cmdline (int argc, char *argv[], 
char *buf,
 
   *buf = 0;
 
+  grub_tpm_measure ((void *)orig, grub_strlen (orig), GRUB_BINARY_PCR, 
"grub_kernel_cmdline", "Kernel Commandline");
+  grub_print_error();
+
   return i;
 }
-- 
2.9.3


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH] Add efi getenv command

2017-01-23 Thread SevenBits
As someone who wrote a similar patch several years ago for a personal
project and submitted it to the list, what's the advantage of this patch
over the previous ones that have been submitted (other than, I believe, the
ability to set the GUID)?

On Mon, Jan 23, 2017 at 7:25 PM Matthew Garrett  wrote:

> Add a command to obtain the contents of EFI firmware variables.
>
> ---
>
>  docs/grub.texi  |   7 ++
>
>  grub-core/Makefile.core.def |   7 ++
>
>  grub-core/commands/efi/getenv.c | 153
> 
>
>  3 files changed, 167 insertions(+)
>
>  create mode 100644 grub-core/commands/efi/getenv.c
>
>
>
> diff --git a/docs/grub.texi b/docs/grub.texi
>
> index b9ddb9b..4469638 100644
>
> --- a/docs/grub.texi
>
> +++ b/docs/grub.texi
>
> @@ -3818,6 +3818,7 @@ you forget a command, you can run the command
> @command{help}
>
>  * eval::Evaluate agruments as GRUB commands
>
>  * export::  Export an environment variable
>
>  * false::   Do nothing, unsuccessfully
>
> +* getenv::  Retrieve an EFI firmware variable
>
>  * gettext:: Translate a string
>
>  * gptsync:: Fill an MBR based on GPT entries
>
>  * halt::Shut down your computer
>
> @@ -4258,6 +4259,12 @@ Do nothing, unsuccessfully.  This is mainly useful
> in control constructs
>
>  such as @code{if} and @code{while} (@pxref{Shell-like scripting}).
>
>  @end deffn
>
>
>
> +@node getenv
>
> +@subsection getenv
>
> +
>
> +@deffn Command getenv [@option{-e}] [@option{-g}] envvar
>
> +Retrieves an EFI variable with the name provided by @option{-e} and the
> GUID
>
> +provied by @option{-g} and stores it in environment variable @var{envvar}
>
>
>
>  @node gettext
>
>  @subsection gettext
>
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
>
> index 2dfa22a..db77a7f 100644
>
> --- a/grub-core/Makefile.core.def
>
> +++ b/grub-core/Makefile.core.def
>
> @@ -817,6 +817,13 @@ module = {
>
>  };
>
>
>
>  module = {
>
> +  name = getenv;
>
> +  common = commands/efi/getenv.c;
>
> +  enable = i386_efi;
>
> +  enable = x86_64_efi;
>
> +};
>
> +
>
> +module = {
>
>name = gptsync;
>
>common = commands/gptsync.c;
>
>  };
>
> diff --git a/grub-core/commands/efi/getenv.c
> b/grub-core/commands/efi/getenv.c
>
> new file mode 100644
>
> index 000..5a829f5
>
> --- /dev/null
>
> +++ b/grub-core/commands/efi/getenv.c
>
> @@ -0,0 +1,153 @@
>
> +/* getenv.c - retrieve EFI variables.  */
>
> +/*
>
> + *  GRUB  --  GRand Unified Bootloader
>
> + *  Copyright (C) 2009  Free Software Foundation, Inc.
>
> + *  Copyright (C) 2014  CoreOS, 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 .
>
> + */
>
> +
>
> +#include 
>
> +#include 
>
> +#include 
>
> +#include 
>
> +#include 
>
> +#include 
>
> +#include 
>
> +#include 
>
> +
>
> +GRUB_MOD_LICENSE ("GPLv3+");
>
> +
>
> +static const struct grub_arg_option options_getenv[] = {
>
> +  {"var-name", 'e', 0,
>
> +   N_("Environment variable to query"),
>
> +   N_("VARNAME"), ARG_TYPE_STRING},
>
> +  {"var-guid", 'g', 0,
>
> +   N_("GUID of environment variable to query"),
>
> +   N_("GUID"), ARG_TYPE_STRING},
>
> +  {"binary", 'b', 0,
>
> +   N_("Read binary data and represent it as hex"),
>
> +   0, ARG_TYPE_NONE},
>
> +  {0, 0, 0, 0, 0, 0}
>
> +};
>
> +
>
> +enum options_getenv
>
> +{
>
> +  GETENV_VAR_NAME,
>
> +  GETENV_VAR_GUID,
>
> +  GETENV_BINARY,
>
> +};
>
> +
>
> +static grub_err_t
>
> +grub_cmd_getenv (grub_extcmd_context_t ctxt, int argc, char **args)
>
> +{
>
> +  struct grub_arg_list *state = ctxt->state;
>
> +  char *envvar = NULL, *guid = NULL, *bindata = NULL, *data = NULL;
>
> +  grub_size_t datasize;
>
> +  grub_efi_guid_t efi_var_guid;
>
> +  grub_efi_boolean_t binary = state[GETENV_BINARY].set;
>
> +  unsigned int i;
>
> +
>
> +  if (!state[GETENV_VAR_NAME].set || !state[GETENV_VAR_GUID].set)
>
> +{
>
> +  grub_error (GRUB_ERR_INVALID_COMMAND, N_("-e and -g are required"));
>
> +  goto done;
>
> +}
>
> +
>
> +  if (argc != 1)
>
> +{
>
> +  grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unexpected arguments"));
>
> +  goto done;
>
> +}
>
> +
>
> +  envvar = state[GETENV_VAR_NAME].arg;
>
> +  guid = state[GETENV_VAR_GUID].arg;
>
> +

Re: Support for TPM measurements on UEFI systems

2017-01-23 Thread Vladimir 'phcoder' Serbinenko
For policy reasons we can't put any TPM code into GNU project. Can we use
verifiers framework for this rather than custom hooks? This would allow
your code to be a single module that can be put into a separate repo rather
than a complex patch set. Verifiers framework is in separate branch
verifiers. I didn't look into details of patches. This has to be postponed
after release

On Tue, 24 Jan 2017, 03:39 Matthew Garrett  wrote:

This patchset adds support for measuring components of grub and what it's
loading into the TPM. It supports both TPM 1.2 and 2.0 devices via the
standard UEFI protocols.


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel
___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: Why is stdint.h so little used?

2017-01-23 Thread Vladimir 'phcoder' Serbinenko
All files in posix_wrap are only for porting code to GRUB with little
modification. No GRUB-specific code should use it.

On Wed, 30 Nov 2016, 13:17 Bjørn Forsman  wrote:

> Hi all,
>
> I see that grub has an stdint.h header in
> grub-core/lib/posix_wrap/stdint.h. But hardly any code use it. Why is
> that?
>
> When projects have these custom types (e.g. grub_uint32_t) it just
> makes porting more difficult IMHO. I'm currently working on a xHCI
> driver for GRUB, and I'd like to use stdint.h types (where
> appropriate). Any objections?
>
> Best regards,
> Bjørn Forsman
>
> ___
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
>
___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: Support for TPM measurements on UEFI systems

2017-01-23 Thread Matthew Garrett
On Mon, Jan 23, 2017 at 5:29 PM, Vladimir 'phcoder' Serbinenko
 wrote:
> For policy reasons we can't put any TPM code into GNU project. Can we use
> verifiers framework for this rather than custom hooks? This would allow your
> code to be a single module that can be put into a separate repo rather than
> a complex patch set. Verifiers framework is in separate branch verifiers. I
> didn't look into details of patches. This has to be postponed after release

From https://www.gnu.org/philosophy/can-you-trust.html

"Therefore, we conclude that the “Trusted Platform Modules” available
for PCs are not dangerous, and there is no reason not to include one
in a computer or support it in system software."

There's no problem including TPM support in GNU projects.

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: Unreachable code in mkimagexx (Fwd: New Defects reported by Coverity Scan for GRUB)

2017-01-23 Thread Vladimir 'phcoder' Serbinenko
They're used only for arm (32-bit). So they don't need to work for 64-bit.

On Mon, 14 Mar 2016, 10:01 Andrei Borzenkov  wrote:

> On Sun, Mar 13, 2016 at 10:38 AM, Andrei Borzenkov 
> wrote:
> >
> > We probably need to #ifdef this section for MKIMAGE_ELF64 case only, it
> > makes no sense to compile it for 32 bit target.
> >
>
> Hmm ... why translate_relocation_pe, translate_relocation_raw and
> classify_raw_reloc are not target size specific in the first place?
> They take Elf_Addr parameters so cannot work for both 32 and 64 bit
> targets at the same time.
>
>
>
>
> >
> 
> > *** CID 158599:(DEADCODE)
> > /util/grub-mkimagexx.c: 1317 in translate_relocation_pe()
> > 1311  break;
> > 1312}
> > 1313   break;
> > 1314 case EM_AARCH64:
> > 1315   switch (ELF_R_TYPE (info))
> > 1316{
>  CID 158599:(DEADCODE)
>  Execution cannot reach this statement: "case 257U:".
> > 1317case R_AARCH64_ABS64:
> > 1318  {
> > 1319ctx->current_address
> > 1320  = add_fixup_entry (&ctx->lst,
> > 1321 GRUB_PE32_REL_BASED_DIR64,
> > 1322 addr, 0, ctx->current_address,
> > /util/grub-mkimagexx.c: 1331 in translate_relocation_pe()
> > 1325  break;
> > 1326  /* Relative relocations do not require fixup entries.
> */
> > 1327case R_AARCH64_CALL26:
> > 1328case R_AARCH64_JUMP26:
> > 1329  break;
> > 1330  /* Page-relative relocations do not require fixup
> entries. */
>  CID 158599:(DEADCODE)
>  Execution cannot reach this statement: "case 275U:".
> > 1331case R_AARCH64_ADR_PREL_PG_HI21:
> > 1332  /* We page-align the whole kernel, so no need
> > 1333 for fixup entries.
> > 1334  */
> > 1335case R_AARCH64_ADD_ABS_LO12_NC:
> > 1336case R_AARCH64_LDST64_ABS_LO12_NC:
> > /util/grub-mkimagexx.c: 1335 in translate_relocation_pe()
> > 1329  break;
> > 1330  /* Page-relative relocations do not require fixup
> entries. */
> > 1331case R_AARCH64_ADR_PREL_PG_HI21:
> > 1332  /* We page-align the whole kernel, so no need
> > 1333 for fixup entries.
> > 1334  */
>  CID 158599:(DEADCODE)
>  Execution cannot reach this statement: "case 277U:".
> > 1335case R_AARCH64_ADD_ABS_LO12_NC:
> > 1336case R_AARCH64_LDST64_ABS_LO12_NC:
> > 1337  break;
> > 1338
> > 1339default:
> > 1340  grub_util_error (_("relocation 0x%x is not implemented
> yet"),
> > /util/grub-mkimagexx.c: 1328 in translate_relocation_pe()
> > 1322 addr, 0, ctx->current_address,
> > 1323 image_target);
> > 1324  }
> > 1325  break;
> > 1326  /* Relative relocations do not require fixup entries.
> */
> > 1327case R_AARCH64_CALL26:
>  CID 158599:(DEADCODE)
>  Execution cannot reach this statement: "case 282U:".
> > 1328case R_AARCH64_JUMP26:
> > 1329  break;
> > 1330  /* Page-relative relocations do not require fixup
> entries. */
> > 1331case R_AARCH64_ADR_PREL_PG_HI21:
> > 1332  /* We page-align the whole kernel, so no need
> > 1333 for fixup entries.
> > /util/grub-mkimagexx.c: 1327 in translate_relocation_pe()
> > 1321 GRUB_PE32_REL_BASED_DIR64,
> > 1322 addr, 0, ctx->current_address,
> > 1323 image_target);
> > 1324  }
> > 1325  break;
> > 1326  /* Relative relocations do not require fixup entries.
> */
>  CID 158599:(DEADCODE)
>  Execution cannot reach this statement: "case 283U:".
> > 1327case R_AARCH64_CALL26:
> > 1328case R_AARCH64_JUMP26:
> > 1329  break;
> > 1330  /* Page-relative relocations do not require fixup
> entries. */
> > 1331case R_AARCH64_ADR_PREL_PG_HI21:
> > 1332  /* We page-align the whole kernel, so no need
> > /util/grub-mkimagexx.c: 1336 in translate_relocation_pe()
> > 1330  /* Page-relative relocations do not require fixup
> entries. */
> > 1331case R_AARCH64_ADR_PREL_PG_HI21:
> > 1332  /* We page-align the whole kernel, so no need
> > 1333 for fixup entries.
> > 1334  */
> > 1335case R_AARCH64_ADD_ABS_LO12_NC:
>  CID 158599:(DEADCODE)
>  Execution cannot reach this statement: "case 286U:".
> > 133

Re: Support for TPM measurements on UEFI systems

2017-01-23 Thread Vladimir 'phcoder' Serbinenko
Ok. Good. Still, can we use verifiers framework ? We can adjust it if
needed. Also it's still post-release material

On Tue, 24 Jan 2017, 04:34 Matthew Garrett  wrote:

> On Mon, Jan 23, 2017 at 5:29 PM, Vladimir 'phcoder' Serbinenko
>  wrote:
> > For policy reasons we can't put any TPM code into GNU project. Can we use
> > verifiers framework for this rather than custom hooks? This would allow
> your
> > code to be a single module that can be put into a separate repo rather
> than
> > a complex patch set. Verifiers framework is in separate branch
> verifiers. I
> > didn't look into details of patches. This has to be postponed after
> release
>
> From https://www.gnu.org/philosophy/can-you-trust.html
>
> "Therefore, we conclude that the “Trusted Platform Modules” available
> for PCs are not dangerous, and there is no reason not to include one
> in a computer or support it in system software."
>
> There's no problem including TPM support in GNU projects.
>
> ___
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
>
___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: Support for TPM measurements on UEFI systems

2017-01-23 Thread Matthew Garrett
On Mon, Jan 23, 2017 at 6:03 PM, Vladimir 'phcoder' Serbinenko
 wrote:
> Ok. Good. Still, can we use verifiers framework ? We can adjust it if
> needed. Also it's still post-release material

Where's the branch? I wasn't able to find it on Savannah.

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH 3/4] Don't allocate a new address buffer if we receive multiple DNS responses

2017-01-23 Thread Andrei Borzenkov
24.01.2017 03:36, Matthew Garrett пишет:
> The current logic in the DNS resolution code allocates an address buffer
> based on the number of addresses in the response packet. If we receive
> multiple response packets in response to a single query packet, this means
> that we will reallocate a new buffer large enough for only the addresses in
> that specific packet, discarding any previous results in the process. Worse,
> we still keep track of the *total* number of addresses resolved in response
> to this query, not merely the number in the packet being currently processed.
> Use realloc() rather than malloc() to avoid overwriting the existing data,
> and allocate a buffer large enough for the total set of addresses rather
> than merely the number in this specific response.
> ---
>  grub-core/net/dns.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
> index 5d9afe0..5deb1ef 100644
> --- a/grub-core/net/dns.c
> +++ b/grub-core/net/dns.c
> @@ -285,8 +285,8 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ 
> ((unused)),
>ptr++;
>ptr += 4;
>  }
> -  *data->addresses = grub_malloc (sizeof ((*data->addresses)[0])
> -  * grub_be_to_cpu16 (head->ancount));
> +  *data->addresses = grub_realloc (*data->addresses, sizeof 
> ((*data->addresses)[0])
> +  * (grub_be_to_cpu16 (head->ancount) + *data->naddresses));

If *data->addresses was not NULL, we should not reach this code.

  /* Code apparently assumed that only one packet is received as response.
 We may get multiple responses due to network condition, so check here
 and quit early. */
  if (*data->addresses)
{
  grub_netbuff_free (nb);
  return GRUB_ERR_NONE;
}

This was noted previously by Josef, we discussed it and my position is
that resolver code requires redesign to correctly merge multiple answers
and prioritize A vs  requests.

Do you get actual errors with current master? If yes, could you provide
more information what this patch fixes?

>if (!*data->addresses)
>  {
>grub_errno = GRUB_ERR_NONE;
> 


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH 4/4] Allow protocol to be separated from host with a semicolon

2017-01-23 Thread Andrei Borzenkov
24.01.2017 03:36, Matthew Garrett пишет:
> Some DHCP servers (such as dnsmasq) tokenise parameters with commas, making
> it impossible to pass boot files with commas in them. Allow using a

grub_net_open() operates on devices, not files. Please give more details
about your problem.

> semicolon to separate the protocol from host if a comma wasn't found.
> ---
>  grub-core/net/net.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/grub-core/net/net.c b/grub-core/net/net.c
> index 585f4f7..efacb30 100644
> --- a/grub-core/net/net.c
> +++ b/grub-core/net/net.c
> @@ -1280,6 +1280,10 @@ grub_net_open_real (const char *name)
>const char *comma;
>char *colon;
>comma = grub_strchr (name, ',');
> +  if (!comma)
> + {
> +   comma = grub_strchr (name, ';');
> + }
>colon = grub_strchr (name, ':');
>if (colon)
>   {
> 


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH 2/4] Send a user class identifier in bootp requests and tag it as DHCP discover

2017-01-23 Thread Michael Marineau
On Mon, Jan 23, 2017 at 4:35 PM, Matthew Garrett  wrote:
> It's helpful to determine that a request was sent by grub in order to permit
> the server to provide different information at different stages of the boot
> process. Send GRUB2 as a type 77 DHCP option when sending bootp packets in
> order to make this possible and tag the request as a DHCP discover to
> convince servers to pay attention to it. Add the client architecture for
> good measure.
> ---
>  grub-core/net/bootp.c | 42 +-
>  1 file changed, 41 insertions(+), 1 deletion(-)
>
> diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
> index 9e2fdb7..0da8e24 100644
> --- a/grub-core/net/bootp.c
> +++ b/grub-core/net/bootp.c
> @@ -25,6 +25,24 @@
>  #include 
>  #include 
>
> +#if !defined(GRUB_MACHINE_EFI) && (defined(__i386__) || defined(__x86_64__))
> +#define GRUB_NET_BOOTP_ARCH 0x
> +#elif defined(GRUB_MACHINE_EFI) && defined(__x86_64__)
> +#define GRUB_NET_BOOTP_ARCH 0x0007
> +#elif defined(GRUB_MACHINE_EFI) && defined(__aarch64__)
> +#define GRUB_NET_BOOTP_ARCH 0x000B
> +#else
> +#error "unknown bootp architecture"
> +#endif

This list is woefully incomplete and there aren't even allocated
values for every platform that grub supports so adding the
architecture option will need to be optional.

> +
> +static grub_uint8_t dhcp_option_header[] = {GRUB_NET_BOOTP_RFC1048_MAGIC_0,
> +   GRUB_NET_BOOTP_RFC1048_MAGIC_1,
> +   GRUB_NET_BOOTP_RFC1048_MAGIC_2,
> +   GRUB_NET_BOOTP_RFC1048_MAGIC_3};
> +static grub_uint8_t grub_userclass[] = {0x4D, 0x06, 0x05, 'G', 'R', 'U', 
> 'B', '2'};
> +static grub_uint8_t grub_dhcpdiscover[] = {0x35, 0x01, 0x01};
> +static grub_uint8_t grub_dhcptime[] = {0x33, 0x04, 0x00, 0x00, 0x0e, 0x10};
> +
>  static void
>  parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
>  {
> @@ -499,10 +517,14 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ 
> ((unused)),
>   struct udphdr *udph;
>   grub_net_network_level_address_t target;
>   grub_net_link_level_address_t ll_target;
> + grub_uint8_t *offset;
>
>   if (!ifaces[j].prev)
> continue;
> - nb = grub_netbuff_alloc (sizeof (*pack) + 64 + 128);
> + nb = grub_netbuff_alloc (sizeof (*pack) + sizeof(dhcp_option_header)
> +  + sizeof(grub_userclass)
> +  + sizeof(grub_dhcpdiscover)
> +  + sizeof(grub_dhcptime) + 64 + 128);

Increasing the allocation without also updating grub_netbuff_reserve
and grub_netbuff_push calls doesn't actually influence the amount of
space in the packet. grub_netbuff_alloc and grub_netbuff_reserve
should be given the total size of the packet: ethernet+ip+udp+bootp
while grub_netbuff_push is called for each of those layers. As-is this
happens to work because the existing code included 64 bytes of zeros
at the end of the bootp packet. The new options use 26 of those bytes.
The extra 128 bytes of the reservation is for the lower protocol
headers (ethernet+ip+udp).

I don't now why the original code included 64 bytes of trailing zeros
or allocates 128 for the lower protocols when only 42 will ever be
used I don't know, that seems to be the state of the code on initial
check-in to git.

>   if (!nb)
> {
>   grub_netbuff_free (nb);
> @@ -536,6 +558,24 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ 
> ((unused)),
>   pack->seconds = grub_cpu_to_be16 (t);
>
>   grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6);
> + offset = (grub_uint8_t *)&pack->vendor;
> + grub_memcpy (offset, dhcp_option_header, 
> sizeof(dhcp_option_header));
> + offset += sizeof(dhcp_option_header);
> + grub_memcpy (offset, grub_dhcpdiscover, sizeof(grub_dhcpdiscover));
> + offset += sizeof(grub_dhcpdiscover);
> + grub_memcpy (offset, grub_userclass, sizeof(grub_userclass));
> + offset += sizeof(grub_userclass);
> + grub_memcpy (offset, grub_dhcptime, sizeof(grub_dhcptime));
> +
> + /* insert Client System Architecture (option 93) */
> + offset += sizeof(grub_dhcptime);
> + offset[0] = 93;
> + offset[1] = 2;
> + offset[2] = (GRUB_NET_BOOTP_ARCH >> 8);
> + offset[3] = (GRUB_NET_BOOTP_ARCH & 0xFF);
> +
> + /* option terminator */
> + offset[4] = 255;
>
>   grub_netbuff_push (nb, sizeof (*udph));
>
> --
> 2.9.3
>
>
> ___
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: Why is stdint.h so little used?

2017-01-23 Thread Bjørn Forsman
On 24 January 2017 at 02:33, Vladimir 'phcoder' Serbinenko
 wrote:
> All files in posix_wrap are only for porting code to GRUB with little
> modification. No GRUB-specific code should use it.

That only explains half of it :-)

What is better about writing grub_uint32_t instead of uint32_t? (To me
it looks like a pointless indirection.)

Best regards,
Bjørn Forsman

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: Why is stdint.h so little used?

2017-01-23 Thread Andrei Borzenkov
On Tue, Jan 24, 2017 at 10:08 AM, Bjørn Forsman  wrote:
> On 24 January 2017 at 02:33, Vladimir 'phcoder' Serbinenko
>  wrote:
>> All files in posix_wrap are only for porting code to GRUB with little
>> modification. No GRUB-specific code should use it.
>
> That only explains half of it :-)
>
> What is better about writing grub_uint32_t instead of uint32_t? (To me
> it looks like a pointless indirection.)
>

GRUB boot time code is built without any standard headers at all, so
there is absolutely no difference between defining grub_uint32_t or
uint32_t, in both cases it must be defined in one of grub headers.
There is no indirection at all, because no uint32_t exists. For your
project you can add defines to avoid non-functional changes and then
simply do mass replace ones when porting is complete :)

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel