Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  pfrut.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Platform Firmware Runtime Update tool to do Management
 * Mode code injection/driver update and telemetry retrieval.
 *
 * This tool uses the interfaces provided by pfr_update and
 * pfr_telemetry drivers. These interfaces are exposed via
 * /dev/pfr_update and /dev/pfr_telemetry. Write operation
 * on the /dev/pfr_update is to load the EFI capsule into
 * kernel space. Mmap/read operations on /dev/pfr_telemetry
 * could be used to read the telemetry data to user space.
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <uuid/uuid.h>
#include PFRUT_HEADER

char *capsule_name;
int action, query_cap, log_type, log_level, log_read, log_getinfo,
 revid, log_revid;
int set_log_level, set_log_type,
 set_revid, set_log_revid;

char *progname;

#define LOG_ERR  0
#define LOG_WARN 1
#define LOG_INFO 2
#define LOG_VERB 4
#define LOG_EXEC_IDX 0
#define LOG_HISTORY_IDX 1
#define REVID_1  1
#define REVID_2  2

static int valid_log_level(int level)
{
 return level == LOG_ERR || level == LOG_WARN ||
        level == LOG_INFO || level == LOG_VERB;
}

static int valid_log_type(int type)
{
 return type == LOG_EXEC_IDX || type == LOG_HISTORY_IDX;
}

static inline int valid_log_revid(int id)
{
 return id == REVID_1 || id == REVID_2;
}

static void help(void)
{
 fprintf(stderr,
  "usage: %s [OPTIONS]\n"
  " code injection:\n"
  " -l, --load\n"
  " -s, --stage\n"
  " -a, --activate\n"
  " -u, --update [stage and activate]\n"
  " -q, --query\n"
  " -d, --revid update\n"
  " telemetry:\n"
  " -G, --getloginfo\n"
  " -T, --type(0:execution, 1:history)\n"
  " -L, --level(0, 1, 2, 4)\n"
  " -R, --read\n"
  " -D, --revid log\n",
  progname);
}

char *option_string = "l:sauqd:GT:L:RD:h";
static struct option long_options[] = {
 {"load", required_argument, 0, 'l'},
 {"stage", no_argument, 0, 's'},
 {"activate", no_argument, 0, 'a'},
 {"update", no_argument, 0, 'u'},
 {"query", no_argument, 0, 'q'},
 {"getloginfo", no_argument, 0, 'G'},
 {"type", required_argument, 0, 'T'},
 {"level", required_argument, 0, 'L'},
 {"read", no_argument, 0, 'R'},
 {"setrev", required_argument, 0, 'd'},
 {"setrevlog", required_argument, 0, 'D'},
 {"help", no_argument, 0, 'h'},
 {}
};

static void parse_options(int argc, char **argv)
{
 int option_index = 0;
 char *pathname, *endptr;
 int opt;

 pathname = strdup(argv[0]);
 progname = basename(pathname);

 while ((opt = getopt_long_only(argc, argv, option_string,
           long_options, &option_index)) != -1) {
  switch (opt) {
  case 'l':
   capsule_name = optarg;
   break;
  case 's':
   action = 1;
   break;
  case 'a':
   action = 2;
   break;
  case 'u':
   action = 3;
   break;
  case 'q':
   query_cap = 1;
   break;
  case 'G':
   log_getinfo = 1;
   break;
  case 'T':
   log_type = strtol(optarg, &endptr, 0);
   if (*endptr || (log_type != 0 && log_type != 1)) {
    printf("Number expected: type(0:execution, 1:history) - Quit.\n");
    exit(1);
   }

   set_log_type = 1;
   break;
  case 'L':
   log_level = strtol(optarg, &endptr, 0);
   if (*endptr ||
       (log_level != 0 && log_level != 1 &&
        log_level != 2 && log_level != 4)) {
    printf("Number expected: level(0, 1, 2, 4) - Quit.\n");
    exit(1);
   }

   set_log_level = 1;
   break;
  case 'R':
   log_read = 1;
   break;
  case 'd':
   revid = atoi(optarg);
   set_revid = 1;
   break;
  case 'D':
   log_revid = atoi(optarg);
   set_log_revid = 1;
   break;
  case 'h':
   help();
   exit(0);
  default:
   break;
  }
 }
}

void print_cap(struct pfru_update_cap_info *cap)
{
 char *uuid;

 uuid = malloc(37);
 if (!uuid) {
  perror("Can not allocate uuid buffer\n");
  exit(1);
 }

 printf("update capability:%d\n", cap->update_cap);

 uuid_unparse(cap->code_type, uuid);
 printf("code injection image type:%s\n", uuid);
 printf("fw_version:%d\n", cap->fw_version);
 printf("code_rt_version:%d\n", cap->code_rt_version);

 uuid_unparse(cap->drv_type, uuid);
 printf("driver update image type:%s\n", uuid);
 printf("drv_rt_version:%d\n", cap->drv_rt_version);
 printf("drv_svn:%d\n", cap->drv_svn);

 uuid_unparse(cap->platform_id, uuid);
 printf("platform id:%s\n", uuid);
 uuid_unparse(cap->oem_id, uuid);
 printf("oem id:%s\n", uuid);
 printf("oem information length:%d\n", cap->oem_info_len);

 free(uuid);
}

int main(int argc, char *argv[])
{
 int fd_update, fd_update_log, fd_capsule;
 struct pfrt_log_data_info data_info;
 struct pfrt_log_info info;
 struct pfru_update_cap_info cap;
 void *addr_map_capsule;
 struct stat st;
 char *log_buf;
 int ret;

 if (getuid() != 0) {
  printf("Please run the tool as root - Exiting.\n");
  return 1;
 }

 parse_options(argc, argv);

 fd_update = open("/dev/acpi_pfr_update0", O_RDWR);
 if (fd_update < 0) {
  printf("PFRU device not supported - Quit...\n");
  return 1;
 }

 fd_update_log = open("/dev/acpi_pfr_telemetry0", O_RDWR);
 if (fd_update_log < 0) {
  printf("PFRT device not supported - Quit...\n");
  return 1;
 }

 if (query_cap) {
  ret = ioctl(fd_update, PFRU_IOC_QUERY_CAP, &cap);
  if (ret)
   perror("Query Update Capability info failed.");
  else
   print_cap(&cap);

  close(fd_update);
  close(fd_update_log);

  return ret;
 }

 if (log_getinfo) {
  ret = ioctl(fd_update_log, PFRT_LOG_IOC_GET_DATA_INFO, &data_info);
  if (ret) {
   perror("Get telemetry data info failed.");
   close(fd_update);
   close(fd_update_log);

   return 1;
  }

  ret = ioctl(fd_update_log, PFRT_LOG_IOC_GET_INFO, &info);
  if (ret) {
   perror("Get telemetry info failed.");
   close(fd_update);
   close(fd_update_log);

   return 1;
  }

  printf("log_level:%d\n", info.log_level);
  printf("log_type:%d\n", info.log_type);
  printf("log_revid:%d\n", info.log_revid);
  printf("max_data_size:%d\n", data_info.max_data_size);
  printf("chunk1_size:%d\n", data_info.chunk1_size);
  printf("chunk2_size:%d\n", data_info.chunk2_size);
  printf("rollover_cnt:%d\n", data_info.rollover_cnt);
  printf("reset_cnt:%d\n", data_info.reset_cnt);

  return 0;
 }

 info.log_level = -1;
 info.log_type = -1;
 info.log_revid = -1;

 if (set_log_level) {
  if (!valid_log_level(log_level)) {
   printf("Invalid log level %d\n",
          log_level);
  } else {
   info.log_level = log_level;
  }
 }

 if (set_log_type) {
  if (!valid_log_type(log_type)) {
   printf("Invalid log type %d\n",
          log_type);
  } else {
   info.log_type = log_type;
  }
 }

 if (set_log_revid) {
  if (!valid_log_revid(log_revid)) {
   printf("Invalid log revid %d, unchanged.\n",
          log_revid);
  } else {
   info.log_revid = log_revid;
  }
 }

 ret = ioctl(fd_update_log, PFRT_LOG_IOC_SET_INFO, &info);
 if (ret) {
  perror("Log information set failed.(log_level, log_type, log_revid)");
  close(fd_update);
  close(fd_update_log);

  return 1;
 }

 if (set_revid) {
  ret = ioctl(fd_update, PFRU_IOC_SET_REV, &revid);
  if (ret) {
   perror("pfru update revid set failed");
   close(fd_update);
   close(fd_update_log);

   return 1;
  }

  printf("pfru update revid set to %d\n", revid);
 }

 if (capsule_name) {
  fd_capsule = open(capsule_name, O_RDONLY);
  if (fd_capsule < 0) {
   perror("Can not open capsule file...");
   close(fd_update);
   close(fd_update_log);

   return 1;
  }

  if (fstat(fd_capsule, &st) < 0) {
   perror("Can not fstat capsule file...");
   close(fd_capsule);
   close(fd_update);
   close(fd_update_log);

   return 1;
  }

  addr_map_capsule = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED,
     fd_capsule, 0);
  if (addr_map_capsule == MAP_FAILED) {
   perror("Failed to mmap capsule file.");
   close(fd_capsule);
   close(fd_update);
   close(fd_update_log);

   return 1;
  }

  ret = write(fd_update, (char *)addr_map_capsule, st.st_size);
  printf("Load %d bytes of capsule file into the system\n",
         ret);

  if (ret == -1) {
   perror("Failed to load capsule file");
   close(fd_capsule);
   close(fd_update);
   close(fd_update_log);

   return 1;
  }

  munmap(addr_map_capsule, st.st_size);
  close(fd_capsule);
  printf("Load done.\n");
 }

 if (action) {
  if (action == 1) {
   ret = ioctl(fd_update, PFRU_IOC_STAGE, NULL);
  } else if (action == 2) {
   ret = ioctl(fd_update, PFRU_IOC_ACTIVATE, NULL);
  } else if (action == 3) {
   ret = ioctl(fd_update, PFRU_IOC_STAGE_ACTIVATE, NULL);
  } else {
   close(fd_update);
   close(fd_update_log);

   return 1;
  }
  printf("Update finished, return %d\n", ret);
 }

 close(fd_update);

 if (log_read) {
  void *p_mmap;
  int max_data_sz;

  ret = ioctl(fd_update_log, PFRT_LOG_IOC_GET_DATA_INFO, &data_info);
  if (ret) {
   perror("Get telemetry data info failed.");
   close(fd_update_log);

   return 1;
  }

  max_data_sz = data_info.max_data_size;
  if (!max_data_sz) {
   printf("No telemetry data available.\n");
   close(fd_update_log);

   return 1;
  }

  log_buf = malloc(max_data_sz + 1);
  if (!log_buf) {
   perror("log_buf allocate failed.");
   close(fd_update_log);

   return 1;
  }

  p_mmap = mmap(NULL, max_data_sz, PROT_READ, MAP_SHARED, fd_update_log, 0);
  if (p_mmap == MAP_FAILED) {
   perror("mmap error.");
   close(fd_update_log);

   return 1;
  }

  memcpy(log_buf, p_mmap, max_data_sz);
  log_buf[max_data_sz] = '\0';
  printf("%s\n", log_buf);
  free(log_buf);

  munmap(p_mmap, max_data_sz);
 }

 close(fd_update_log);

 return 0;
}

Messung V0.5
C=99 H=99 G=98

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge