Skip to contentSkip to conversation

Add a module for retrieving SMBIOS information

PATCH In review David Michael 2 participants 4 messages Feb 20, 2016 – Mar 8, 2016

lore
Share & tools
lore
#0 lore raw

PATCH v5 2/2 Add a module for retrieving SMBIOS information

The following are two use cases from Rajat Jain <[email protected]>:

1) We have a board that boots Linux and this board itself can be plugged into one of different chassis types. We need to pass different parameters to the kernel based on the "CHASSIS_TYPE" information that is passed by the bios in the DMI / SMBIOS tables.

2) We may have a USB stick that can go into multiple boards, and the exact kernel to be loaded depends on the machine information (PRODUCT_NAME etc) passed via the DMI.
---

Changes since v4:

To address points suggested by Andrei Borzenkov:

* Described the returned values' formatting in the documentation.

* Set the copyright year to only the current year in new files.

* Stopped passing a string buffer to the formatting functions.

 docs/grub.texi                       |  75 ++++++++
 grub-core/Makefile.core.def          |  15 ++
 grub-core/commands/efi/smbios.c      |  59 ++++++
 grub-core/commands/i386/pc/smbios.c  |  50 +++++
 grub-core/commands/smbios.c          | 364 +++++++++++++++++++++++++++++++++++
 grub-core/efiemu/i386/pc/cfgtables.c |  15 +-
 include/grub/smbios.h                |  68 +++++++
 7 files changed, 635 insertions(+), 11 deletions(-)
 create mode 100644 grub-core/commands/efi/smbios.c
 create mode 100644 grub-core/commands/i386/pc/smbios.c
 create mode 100644 grub-core/commands/smbios.c
 create mode 100644 include/grub/smbios.h
docs/grub.texi +75 -0
index 82f6fa4..c5bd812 100644
@@ -3850,6 +3850,7 @@ you forget a command, you can run the command @command{help}
 * sha256sum::                   Compute or check SHA256 hash
 * sha512sum::                   Compute or check SHA512 hash
 * sleep::                       Wait for a specified number of seconds
+* smbios::                      Retrieve SMBIOS information
 * source::                      Read a configuration file in same context
 * test::                        Check file types and compare values
 * true::                        Do nothing, successfully
@@ -4972,6 +4973,80 @@ if timeout was interrupted by @key{ESC}.
 @end deffn
 
 
+@node smbios
+@subsection smbios
+
+@deffn Command smbios @
+ [@option{--type} @var{type}] @
+ [@option{--handle} @var{handle}] @
+ [@option{--match} @var{match}] @
+ (@option{--get-byte} | @option{--get-word} | @option{--get-dword} | @
+  @option{--get-qword} | @option{--get-string} | @option{--get-uuid}) @
+ @var{offset} @
+ [@option{--set} @var{variable}]
+Retrieve SMBIOS information.
+
+The @command{smbios} command returns the value of a field in an SMBIOS
+structure.  The following options determine which structure to select.
+
+@itemize @bullet
+@item
+Specifying @option{--type} will select structures with a matching
+@var{type}.  The type can be any integer from 0 to 255.
+@item
+Specifying @option{--handle} will select structures with a matching
+@var{handle}.  The handle can be any integer from 0 to 65535.
+@item
+Specifying @option{--match} will select structure number @var{match} in the
+filtered list of structures; e.g. @code{smbios --type 4 --match 2} will select
+the second Process Information (Type 4) structure.  The list is always ordered
+the same as the hardware's SMBIOS table.  The match number must be a positive
+integer.  If unspecified, the first matching structure will be selected.
+@end itemize
+
+The remaining options determine which field in the selected SMBIOS structure to
+return.  Only one of these options may be specified at a time.
+
+@itemize @bullet
+@item
+When given @option{--get-byte}, return the value of the byte
+at @var{offset} bytes into the selected SMBIOS structure.
+It will be formatted as an unsigned decimal integer.
+@item
+When given @option{--get-word}, return the value of the word (two bytes)
+at @var{offset} bytes into the selected SMBIOS structure.
+It will be formatted as an unsigned decimal integer.
+@item
+When given @option{--get-dword}, return the value of the dword (four bytes)
+at @var{offset} bytes into the selected SMBIOS structure.
+It will be formatted as an unsigned decimal integer.
+@item
+When given @option{--get-qword}, return the value of the qword (eight bytes)
+at @var{offset} bytes into the selected SMBIOS structure.
+It will be formatted as an unsigned decimal integer.
+@item
+When given @option{--get-string}, return the string with its index found
+at @var{offset} bytes into the selected SMBIOS structure.
+@item
+When given @option{--get-uuid}, return the value of the UUID (sixteen bytes)
+at @var{offset} bytes into the selected SMBIOS structure.
+It will be formatted as lower-case hyphenated hexadecimal digits, with the
+first three fields as little-endian, and the rest printed byte-by-byte.
+@end itemize
+
+The default action is to print the value of the requested field to the console,
+but a variable name can be specified with @option{--set} to store the value
+instead of printing it.
+
+For example, this will store and then display the system manufacturer's name.
+
+@example
+smbios --type 1 --get-string 4 --set system_manufacturer
+echo $system_manufacturer
+@end example
+@end deffn
+
+
 @node source
 @subsection source
 
grub-core/Makefile.core.def +15 -0
index 8874501..6de4860 100644
@@ -1014,6 +1014,21 @@ module = {
 };
 
 module = {
+  name = smbios;
+
+  common = commands/smbios.c;
+  efi = commands/efi/smbios.c;
+  i386_pc = commands/i386/pc/smbios.c;
+  i386_coreboot = commands/i386/pc/smbios.c;
+  i386_multiboot = commands/i386/pc/smbios.c;
+
+  enable = efi;
+  enable = i386_pc;
+  enable = i386_coreboot;
+  enable = i386_multiboot;
+};
+
+module = {
   name = suspend;
   ieee1275 = commands/ieee1275/suspend.c;
   enable = i386_ieee1275;
grub-core/commands/efi/smbios.c new file +59 -0

59 lines not on this page · raw message

grub-core/commands/i386/pc/smbios.c new file +50 -0

50 lines not on this page · raw message

grub-core/commands/smbios.c new file +364 -0

364 lines not on this page · raw message

grub-core/efiemu/i386/pc/cfgtables.c +4 -11
index 492c07c..e5fffb7 100644
@@ -22,11 +22,11 @@
 #include <grub/misc.h>
 #include <grub/mm.h>
 #include <grub/acpi.h>
+#include <grub/smbios.h>
 
 grub_err_t
 grub_machine_efiemu_init_tables (void)
 {
-  grub_uint8_t *ptr;
   void *table;
   grub_err_t err;
   grub_efi_guid_t smbios = GRUB_EFI_SMBIOS_TABLE_GUID;
@@ -57,17 +57,10 @@ grub_machine_efiemu_init_tables (void)
       if (err)
 	return err;
     }
-
-  for (ptr = (grub_uint8_t *) 0xf0000; ptr < (grub_uint8_t *) 0x100000;
-       ptr += 16)
-    if (grub_memcmp (ptr, "_SM_", 4) == 0
-	&& grub_byte_checksum (ptr, *(ptr + 5)) == 0)
-      break;
-
-  if (ptr < (grub_uint8_t *) 0x100000)
+  table = grub_smbios_get_eps ();
+  if (table)
     {
-      grub_dprintf ("efiemu", "Registering SMBIOS\n");
-      err = grub_efiemu_register_configuration_table (smbios, 0, 0, ptr);
+      err = grub_efiemu_register_configuration_table (smbios, 0, 0, table);
       if (err)
 	return err;
     }
include/grub/smbios.h new file +68 -0

68 lines not on this page · raw message

Signature · 1 line
2.5.0
#1 lore raw

Two nitpicks otherwise looks good. Thanks!

20.02.2016 22:12, David Michael пишет:
...

Quoted 54 lines
grub-core/commands/smbios.c new file +48 -0
new file mode 100644
index 0000000..80a01a3
@@ -0,0 +1,364 @@
+/* smbios.c - retrieve smbios information. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2016  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/dl.h>
+#include <grub/env.h>
+#include <grub/extcmd.h>
+#include <grub/i18n.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/smbios.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+
+/* Locate the SMBIOS entry point structure depending on the hardware. */
+struct grub_smbios_eps *
+grub_smbios_get_eps (void)
+{
+  static struct grub_smbios_eps *eps = NULL;
+  if (eps != NULL)
+    return eps;
+  eps = grub_machine_smbios_get_eps ();
+  return eps;
+}
+
+/* Locate the SMBIOS3 entry point structure depending on the hardware. */
+struct grub_smbios_eps3 *
+grub_smbios_get_eps3 (void)
+{
+  static struct grub_smbios_eps3 *eps = NULL;
+  if (eps != NULL)
+    return eps;

grub-core/commands/smbios.c line 58

Quoted 10 lines
grub-core/commands/smbios.c new file +10 -0
+  eps = grub_machine_smbios_get_eps3 ();
+  return eps;
+}
+
+/* Abstract useful values found in either the SMBIOS3 or SMBIOS EPS. */
+static struct {
+  grub_addr_t start;
+  grub_addr_t end;
+  grub_uint16_t structures;
+} table_desc = {0, 0, 0};

Static is supposed to be initialized to zero by default.

...

Quoted 36 lines
grub-core/commands/smbios.c new file +36 -0
+static grub_err_t
+grub_cmd_smbios (grub_extcmd_context_t ctxt,
+                 int argc __attribute__ ((unused)),
+                 char **argv __attribute__ ((unused)))
+{
+  struct grub_arg_list *state = ctxt->state;
+
+  grub_int16_t type = -1;
+  grub_int32_t handle = -1;
+  grub_uint16_t match = 0;
+  grub_uint8_t offset = 0;
+
+  const grub_uint8_t *structure;
+  const char *value;
+  grub_int32_t option;
+  grub_int8_t field_type = -1;
+  grub_uint8_t i;
+
+  if (table_desc.start == 0)
+    return grub_error (GRUB_ERR_IO,
+                       N_("the SMBIOS entry point structure was not found"));
+
+  /* Read the given filtering options. */
+  if (state[0].set)
+    {
+      option = grub_strtol (state[0].arg, NULL, 0);
+      if (option < 0 || option > 255)
+        return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                           N_("the type must be between 0 and 255"));
+      type = (grub_int16_t)option;
+    }
+  if (state[1].set)
+    {
+      option = grub_strtol (state[1].arg, NULL, 0);
+      if (option < 0 || option > 65535)
+        return grub_error (GRUB_ERR_BAD_ARGUMENT,

grub-core/commands/smbios.c line 282

Quoted 10 lines
grub-core/commands/smbios.c new file +10 -0
+                           N_("the handle must be between 0 and 65535"));
+      handle = (grub_int32_t)option;
+    }
+  if (state[2].set)
+    {
+      option = grub_strtol (state[2].arg, NULL, 0);
+      if (option <= 0)
+        return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                           N_("the match must be a positive integer"));
+      match = (grub_uint16_t)option;

Should we check that option <= 65535?

#2 lore raw
Quoted 1 line · Andrei Borzenkov

Two nitpicks otherwise looks good. Thanks!

Thanks for reviewing these again. I agree with your suggestions, but do they warrant another updated patch, or can those changes just be squashed onto this commit?

Also, since sending this, Leif Lindholm has proposed a patch for sharing the EFI table lookup code, which is functionality used by this module. Is that something that would be included in 2.02? Should I make a quick update to this to use the new function?

Thanks.

David

#3 lore raw

03.03.2016 07:13, David Michael пишет:

Quoted 7 lines · Andrei Borzenkov
Quoted 1 line

Two nitpicks otherwise looks good. Thanks!

Thanks for reviewing these again. I agree with your suggestions, but do they warrant another updated patch, or can those changes just be squashed onto this commit?

Could you send final version with all changes applied; it makes it easier to review and apply.

Quoted 5 lines

Also, since sending this, Leif Lindholm has proposed a patch for sharing the EFI table lookup code, which is functionality used by this module. Is that something that would be included in 2.02? Should I make a quick update to this to use the new function?

That's probably post-2.02 change.