root/tools/wmi/dell-smbios-example.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. show_buffer
  2. run_wmi_smbios_cmd
  3. find_token
  4. token_is_active
  5. query_token
  6. activate_token
  7. query_buffer_size
  8. main

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  Sample application for SMBIOS communication over WMI interface
   4  *  Performs the following:
   5  *  - Simple cmd_class/cmd_select lookup for TPM information
   6  *  - Simple query of known tokens and their values
   7  *  - Simple activation of a token
   8  *
   9  *  Copyright (C) 2017 Dell, Inc.
  10  */
  11 
  12 #include <errno.h>
  13 #include <fcntl.h>
  14 #include <stdio.h>
  15 #include <stdlib.h>
  16 #include <sys/ioctl.h>
  17 #include <unistd.h>
  18 
  19 /* if uapi header isn't installed, this might not yet exist */
  20 #ifndef __packed
  21 #define __packed __attribute__((packed))
  22 #endif
  23 #include <linux/wmi.h>
  24 
  25 /* It would be better to discover these using udev, but for a simple
  26  * application they're hardcoded
  27  */
  28 static const char *ioctl_devfs = "/dev/wmi/dell-smbios";
  29 static const char *token_sysfs =
  30                         "/sys/bus/platform/devices/dell-smbios.0/tokens";
  31 
  32 static void show_buffer(struct dell_wmi_smbios_buffer *buffer)
  33 {
  34         printf("Call: %x/%x [%x,%x,%x,%x]\nResults: [%8x,%8x,%8x,%8x]\n",
  35         buffer->std.cmd_class, buffer->std.cmd_select,
  36         buffer->std.input[0], buffer->std.input[1],
  37         buffer->std.input[2], buffer->std.input[3],
  38         buffer->std.output[0], buffer->std.output[1],
  39         buffer->std.output[2], buffer->std.output[3]);
  40 }
  41 
  42 static int run_wmi_smbios_cmd(struct dell_wmi_smbios_buffer *buffer)
  43 {
  44         int fd;
  45         int ret;
  46 
  47         fd = open(ioctl_devfs, O_NONBLOCK);
  48         ret = ioctl(fd, DELL_WMI_SMBIOS_CMD, buffer);
  49         close(fd);
  50         return ret;
  51 }
  52 
  53 static int find_token(__u16 token, __u16 *location, __u16 *value)
  54 {
  55         char location_sysfs[60];
  56         char value_sysfs[57];
  57         char buf[4096];
  58         FILE *f;
  59         int ret;
  60 
  61         ret = sprintf(value_sysfs, "%s/%04x_value", token_sysfs, token);
  62         if (ret < 0) {
  63                 printf("sprintf value failed\n");
  64                 return 2;
  65         }
  66         f = fopen(value_sysfs, "rb");
  67         if (!f) {
  68                 printf("failed to open %s\n", value_sysfs);
  69                 return 2;
  70         }
  71         fread(buf, 1, 4096, f);
  72         fclose(f);
  73         *value = (__u16) strtol(buf, NULL, 16);
  74 
  75         ret = sprintf(location_sysfs, "%s/%04x_location", token_sysfs, token);
  76         if (ret < 0) {
  77                 printf("sprintf location failed\n");
  78                 return 1;
  79         }
  80         f = fopen(location_sysfs, "rb");
  81         if (!f) {
  82                 printf("failed to open %s\n", location_sysfs);
  83                 return 2;
  84         }
  85         fread(buf, 1, 4096, f);
  86         fclose(f);
  87         *location = (__u16) strtol(buf, NULL, 16);
  88 
  89         if (*location)
  90                 return 0;
  91         return 2;
  92 }
  93 
  94 static int token_is_active(__u16 *location, __u16 *cmpvalue,
  95                            struct dell_wmi_smbios_buffer *buffer)
  96 {
  97         int ret;
  98 
  99         buffer->std.cmd_class = CLASS_TOKEN_READ;
 100         buffer->std.cmd_select = SELECT_TOKEN_STD;
 101         buffer->std.input[0] = *location;
 102         ret = run_wmi_smbios_cmd(buffer);
 103         if (ret != 0 || buffer->std.output[0] != 0)
 104                 return ret;
 105         ret = (buffer->std.output[1] == *cmpvalue);
 106         return ret;
 107 }
 108 
 109 static int query_token(__u16 token, struct dell_wmi_smbios_buffer *buffer)
 110 {
 111         __u16 location;
 112         __u16 value;
 113         int ret;
 114 
 115         ret = find_token(token, &location, &value);
 116         if (ret != 0) {
 117                 printf("unable to find token %04x\n", token);
 118                 return 1;
 119         }
 120         return token_is_active(&location, &value, buffer);
 121 }
 122 
 123 static int activate_token(struct dell_wmi_smbios_buffer *buffer,
 124                    __u16 token)
 125 {
 126         __u16 location;
 127         __u16 value;
 128         int ret;
 129 
 130         ret = find_token(token, &location, &value);
 131         if (ret != 0) {
 132                 printf("unable to find token %04x\n", token);
 133                 return 1;
 134         }
 135         buffer->std.cmd_class = CLASS_TOKEN_WRITE;
 136         buffer->std.cmd_select = SELECT_TOKEN_STD;
 137         buffer->std.input[0] = location;
 138         buffer->std.input[1] = 1;
 139         ret = run_wmi_smbios_cmd(buffer);
 140         return ret;
 141 }
 142 
 143 static int query_buffer_size(__u64 *buffer_size)
 144 {
 145         FILE *f;
 146 
 147         f = fopen(ioctl_devfs, "rb");
 148         if (!f)
 149                 return -EINVAL;
 150         fread(buffer_size, sizeof(__u64), 1, f);
 151         fclose(f);
 152         return EXIT_SUCCESS;
 153 }
 154 
 155 int main(void)
 156 {
 157         struct dell_wmi_smbios_buffer *buffer;
 158         int ret;
 159         __u64 value = 0;
 160 
 161         ret = query_buffer_size(&value);
 162         if (ret == EXIT_FAILURE || !value) {
 163                 printf("Unable to read buffer size\n");
 164                 goto out;
 165         }
 166         printf("Detected required buffer size %lld\n", value);
 167 
 168         buffer = malloc(value);
 169         if (buffer == NULL) {
 170                 printf("failed to alloc memory for ioctl\n");
 171                 ret = -ENOMEM;
 172                 goto out;
 173         }
 174         buffer->length = value;
 175 
 176         /* simple SMBIOS call for looking up TPM info */
 177         buffer->std.cmd_class = CLASS_FLASH_INTERFACE;
 178         buffer->std.cmd_select = SELECT_FLASH_INTERFACE;
 179         buffer->std.input[0] = 2;
 180         ret = run_wmi_smbios_cmd(buffer);
 181         if (ret) {
 182                 printf("smbios ioctl failed: %d\n", ret);
 183                 ret = EXIT_FAILURE;
 184                 goto out;
 185         }
 186         show_buffer(buffer);
 187 
 188         /* query some tokens */
 189         ret = query_token(CAPSULE_EN_TOKEN, buffer);
 190         printf("UEFI Capsule enabled token is: %d\n", ret);
 191         ret = query_token(CAPSULE_DIS_TOKEN, buffer);
 192         printf("UEFI Capsule disabled token is: %d\n", ret);
 193 
 194         /* activate UEFI capsule token if disabled */
 195         if (ret) {
 196                 printf("Enabling UEFI capsule token");
 197                 if (activate_token(buffer, CAPSULE_EN_TOKEN)) {
 198                         printf("activate failed\n");
 199                         ret = -1;
 200                         goto out;
 201                 }
 202         }
 203         ret = EXIT_SUCCESS;
 204 out:
 205         free(buffer);
 206         return ret;
 207 }

/* [<][>][^][v][top][bottom][index][help] */