mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 18:47:22 +00:00
mc: guid: Implement encoding autodetection
With this commit the GUID encoding is now by default detected automatically based on the validity of the version field, and the timestamp (for time-based version 1 GUIDs). The version is considered valid if it is 1 through 5. The timestamp is considered valid if the year is past UNIX Epoch and before the current year. Resolves ipmitool/ipmitool#25 Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
This commit is contained in:
parent
0b6abe8cd9
commit
40d52b5fa1
@ -2023,11 +2023,35 @@ Display the Management Controller Globally Unique IDentifier.
|
||||
|
||||
.RS
|
||||
.TP
|
||||
\fIsmbios\fP
|
||||
\fIauto\fP
|
||||
.br
|
||||
|
||||
This is the default behavior for ipmitool for the sake of compatibility
|
||||
with old versions and broken BMC implementations whose number is legion.
|
||||
This is the default behavior for
|
||||
.BR ipmitool (1).
|
||||
|
||||
Try to automatically detect the encoding based on the value of the
|
||||
version field and (for version 1) the timestamp. The version is
|
||||
considered valid if it is 1 through 5, and the timestamp is valid
|
||||
if the year is past or equal to UNIX Epoch (1970) and is before or
|
||||
equal to the current year.
|
||||
|
||||
If multiple encodings happen to have valid version fields, then
|
||||
precedence takes the one with version 1 and a valid timestamp. If
|
||||
neither one has that, then the precedence order is as follows:
|
||||
\fIsmbios\fP, \fIipmi\fP, \fIrfc4122\fP.
|
||||
|
||||
If neither encoding yields a valid version field, then
|
||||
.BR ipmitool (1)
|
||||
defaults to \fIdump\fP mode.
|
||||
|
||||
If this option is in use, then
|
||||
.BR ipmitool (1)
|
||||
will also print out the detected encoding and warn
|
||||
regarding IPMI specification violation if the encoding isn't \fIipmi\fP.
|
||||
|
||||
.TP
|
||||
\fIsmbios\fP
|
||||
.br
|
||||
|
||||
Decode GUID as if it was sent by BMC as prescribed by SMBIOS specification.
|
||||
|
||||
@ -2035,6 +2059,13 @@ Decode GUID as if it was sent by BMC as prescribed by SMBIOS specification.
|
||||
it this way. If your BMC's GUID is shown correctly using this option, you
|
||||
may want to inform your BMC manufacturer that they have a bug.
|
||||
|
||||
.TP
|
||||
\fIipmi\fP
|
||||
.br
|
||||
|
||||
Decode GUID according to IPMI specification. It MUST show the correct GUID.
|
||||
If it doesn't, try other options and inform your BMC manufacturer of the bug.
|
||||
|
||||
.TP
|
||||
\fIrfc4122\fP or \fIrfc\fP
|
||||
.br
|
||||
@ -2045,13 +2076,6 @@ Decode GUID as if it was sent by BMC as prescribed by RFC4122 specification.
|
||||
If your BMC's GUID is shown correctly using this option, you
|
||||
may want to inform your BMC manufacturer that they have a bug.
|
||||
|
||||
.TP
|
||||
\fIipmi\fP
|
||||
.br
|
||||
|
||||
Decode GUID according to IPMI specification. It MUST show the correct GUID.
|
||||
If it doesn't, try other options above and inform your BMC manufacturer of the bug.
|
||||
|
||||
.TP
|
||||
\fIdump\fP
|
||||
.br
|
||||
|
@ -33,6 +33,8 @@
|
||||
#ifndef IPMI_MC_H
|
||||
#define IPMI_MC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/helper.h>
|
||||
#include <ipmitool/ipmi_strings.h>
|
||||
@ -100,12 +102,28 @@ struct ipm_devid_rsp {
|
||||
/* There are lots of BMC implementations that don't follow the IPMI
|
||||
* specification for GUID encoding. Some send data encoded as in
|
||||
* RFC4122, some follow SMBIOS specification. We support all users
|
||||
* of those buggy implementations here */
|
||||
* of those buggy implementations here.
|
||||
*
|
||||
* Most implementations like AMI MegaRAC do it the SMBIOS way.
|
||||
* This is the legacy behavior we don't want to break yet.
|
||||
* That's why the last real mode is GUID_SMBIOS. If automatic
|
||||
* detection finds more than one possible candidate, and
|
||||
* GUID_SMBIOS is one of them, then it will take precedence.
|
||||
*
|
||||
* For the same reason GUID_IPMI is right before GUID_SMBIOS.
|
||||
* If both RFC4122 and IPMI encodings have a valid version
|
||||
* field, then IPMI takes precedence.
|
||||
*/
|
||||
typedef enum {
|
||||
/* Real modes, in reverse precedence order */
|
||||
GUID_RFC4122,
|
||||
GUID_IPMI,
|
||||
GUID_SMBIOS,
|
||||
GUID_RFC4122,
|
||||
GUID_DUMP
|
||||
GUID_REAL_MODES, /* Real mode count*/
|
||||
/* Pseudo modes start here */
|
||||
GUID_AUTO = GUID_REAL_MODES, /* Automatically detect mode */
|
||||
GUID_DUMP, /* Just dump the data */
|
||||
GUID_TOTAL_MODES
|
||||
} ipmi_guid_mode_t;
|
||||
|
||||
#define GUID_NODE_SZ 6
|
||||
@ -129,12 +147,17 @@ typedef enum {
|
||||
GUID_VERSION_COUNT /* The number of supported versions */
|
||||
} guid_version_t;
|
||||
|
||||
static inline bool is_guid_version_valid(guid_version_t ver)
|
||||
{
|
||||
return (ver > GUID_VERSION_UNKNOWN) && (ver <= GUID_VERSION_MAX);
|
||||
}
|
||||
|
||||
/* The structure follows IPMI v2.0, rev 1.1
|
||||
* See section 20.8 */
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct ipmi_guid_t {
|
||||
typedef struct {
|
||||
uint8_t node[GUID_NODE_SZ]; /* Byte 0 is LSB */
|
||||
union {
|
||||
struct {
|
||||
@ -146,7 +169,7 @@ struct ipmi_guid_t {
|
||||
uint16_t time_hi_and_version; /* timestamp high field and version number */
|
||||
uint16_t time_mid; /* timestamp middle field */
|
||||
uint32_t time_low; /* timestamp low field */
|
||||
} ATTRIBUTE_PACKING;
|
||||
} ATTRIBUTE_PACKING ipmi_guid_t;
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(0)
|
||||
#endif
|
||||
@ -156,7 +179,7 @@ struct ipmi_guid_t {
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct rfc_guid_t {
|
||||
typedef struct {
|
||||
uint32_t time_low; /* timestamp low field */
|
||||
uint16_t time_mid; /* timestamp middle field */
|
||||
uint16_t time_hi_and_version; /* timestamp high field and version number */
|
||||
@ -168,12 +191,28 @@ struct rfc_guid_t {
|
||||
uint16_t clock_seq_and_rsvd;
|
||||
};
|
||||
uint8_t node[GUID_NODE_SZ]; /* Byte 0 is MSB */
|
||||
} ATTRIBUTE_PACKING;
|
||||
} ATTRIBUTE_PACKING rfc_guid_t;
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(0)
|
||||
#endif
|
||||
|
||||
int _ipmi_mc_get_guid(struct ipmi_intf *, struct ipmi_guid_t *);
|
||||
/* Parsed GUID structure */
|
||||
typedef struct {
|
||||
uint8_t node[GUID_NODE_SZ]; /* MSB first */
|
||||
/* These are architecture-specific for easy output with printf() */
|
||||
uint16_t clock_seq_and_rsvd;
|
||||
uint64_t time_hi_and_version;
|
||||
uint64_t time_mid;
|
||||
uint64_t time_low;
|
||||
/* These are the parsed values */
|
||||
time_t time;
|
||||
ipmi_guid_mode_t mode;
|
||||
guid_version_t ver; /* Version from time_hi_and_version, if valid */
|
||||
} parsed_guid_t;
|
||||
|
||||
parsed_guid_t ipmi_parse_guid(void *guid, ipmi_guid_mode_t guid_mode);
|
||||
|
||||
int _ipmi_mc_get_guid(struct ipmi_intf *intf, ipmi_guid_t *guid);
|
||||
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
#pragma pack(1)
|
||||
|
314
lib/ipmi_mc.c
314
lib/ipmi_mc.c
@ -186,7 +186,7 @@ printf_mc_usage(void)
|
||||
struct bitfield_data * bf;
|
||||
lprintf(LOG_NOTICE, "MC Commands:");
|
||||
lprintf(LOG_NOTICE, " reset <warm|cold>");
|
||||
lprintf(LOG_NOTICE, " guid [smbios|rfc4122|ipmi|dump]");
|
||||
lprintf(LOG_NOTICE, " guid [auto|smbios|ipmi|rfc4122|dump]");
|
||||
lprintf(LOG_NOTICE, " info");
|
||||
lprintf(LOG_NOTICE, " watchdog <get|reset|off>");
|
||||
lprintf(LOG_NOTICE, " selftest");
|
||||
@ -495,7 +495,7 @@ ipmi_mc_get_deviceid(struct ipmi_intf * intf)
|
||||
* returns - negative number means error, positive is a ccode.
|
||||
*/
|
||||
int
|
||||
_ipmi_mc_get_guid(struct ipmi_intf *intf, struct ipmi_guid_t *guid)
|
||||
_ipmi_mc_get_guid(struct ipmi_intf *intf, ipmi_guid_t *guid)
|
||||
{
|
||||
struct ipmi_rs *rsp;
|
||||
struct ipmi_rq req;
|
||||
@ -503,7 +503,7 @@ _ipmi_mc_get_guid(struct ipmi_intf *intf, struct ipmi_guid_t *guid)
|
||||
return (-3);
|
||||
}
|
||||
|
||||
memset(guid, 0, sizeof(struct ipmi_guid_t));
|
||||
memset(guid, 0, sizeof(ipmi_guid_t));
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.msg.netfn = IPMI_NETFN_APP;
|
||||
req.msg.cmd = BMC_GET_GUID;
|
||||
@ -514,13 +514,188 @@ _ipmi_mc_get_guid(struct ipmi_intf *intf, struct ipmi_guid_t *guid)
|
||||
} else if (rsp->ccode) {
|
||||
return rsp->ccode;
|
||||
} else if (rsp->data_len != 16
|
||||
|| rsp->data_len != sizeof(struct ipmi_guid_t)) {
|
||||
|| rsp->data_len != sizeof(ipmi_guid_t)) {
|
||||
return (-2);
|
||||
}
|
||||
memcpy(guid, &rsp->data[0], sizeof(struct ipmi_guid_t));
|
||||
memcpy(guid, &rsp->data[0], sizeof(ipmi_guid_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* A helper function to convert GUID time to time_t */
|
||||
static time_t _guid_time(uint64_t t_low, uint64_t t_mid, uint64_t t_hi)
|
||||
{
|
||||
/* GUID time-stamp is a 60-bit value representing the
|
||||
* count of 100ns intervals since 00:00:00.00, 15 Oct 1582 */
|
||||
|
||||
const uint64_t t100ns_in_sec = 10000000LL;
|
||||
|
||||
/* Seconds from 15 Oct 1582 to 1 Jan 1970 00:00:00 */
|
||||
uint64_t epoch_since_gregorian = 12219292800;
|
||||
|
||||
/* 100ns intervals since 15 Oct 1582 00:00:00 */
|
||||
uint64_t gregorian = (GUID_TIME_HI(t_hi) << 48)
|
||||
| (t_mid << 32)
|
||||
| t_low;
|
||||
time_t unixtime; /* We need timestamp in seconds since UNIX epoch */
|
||||
|
||||
gregorian /= t100ns_in_sec; /* Convert to seconds */
|
||||
unixtime = gregorian - epoch_since_gregorian;
|
||||
|
||||
return unixtime;
|
||||
}
|
||||
|
||||
#define TM_YEAR_BASE 1900
|
||||
#define EPOCH_YEAR 1970
|
||||
static bool _is_time_valid(time_t t)
|
||||
{
|
||||
time_t t_now = time(NULL);
|
||||
struct tm tm;
|
||||
struct tm now;
|
||||
|
||||
gmtime_r(&t, &tm);
|
||||
gmtime_r(&t_now, &now);
|
||||
|
||||
/* It's enought to check that the year fits in [Epoch .. now] interval */
|
||||
|
||||
if (tm.tm_year + TM_YEAR_BASE < EPOCH_YEAR)
|
||||
return false;
|
||||
|
||||
if (tm.tm_year > now.tm_year) {
|
||||
/* GUID timestamp can't be in future */
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** ipmi_mc_parse_guid - print-out given BMC GUID
|
||||
*
|
||||
* The function parses the raw guid data according to the requested encoding
|
||||
* mode. If GUID_AUTO mode is requested, then automatic detection of encoding
|
||||
* is attempted using the version nibble of the time_hi_and_version field of
|
||||
* each of the supported encodings.
|
||||
*
|
||||
* Considering the rather random nature of GUIDs, it may happen that the
|
||||
* version nibble is valid for multiple encodings at the same time. That's why
|
||||
* if the version is 1 (time-based), the function will also check validity of
|
||||
* the time stamp. If a valid time stamp is found for a given mode, the mode is
|
||||
* considered detected and no further checks are performed. Otherwise other
|
||||
* encodings are probed the same way. If in neither encoding the valid version
|
||||
* nibble happened to indicate time-based version or no valid time-stamp has
|
||||
* been found, then the last probed encoding with valid version nibble is
|
||||
* considered detected. If none of the probed encodings indicated a valid
|
||||
* version nibble, then fall back to GUID_DUMP
|
||||
*
|
||||
* @param[in] guid - The original GUID data as received from BMC
|
||||
* @param[in] mode - The requested mode/encoding
|
||||
*
|
||||
* @returns parsed GUID
|
||||
*/
|
||||
parsed_guid_t ipmi_parse_guid(void *guid, ipmi_guid_mode_t guid_mode)
|
||||
{
|
||||
ipmi_guid_mode_t i;
|
||||
ipmi_guid_t *ipmi_guid = guid;
|
||||
rfc_guid_t *rfc_guid = guid;
|
||||
parsed_guid_t parsed_guid = { 0 };
|
||||
uint32_t t_low[GUID_REAL_MODES];
|
||||
uint16_t t_mid[GUID_REAL_MODES];
|
||||
uint16_t t_hi[GUID_REAL_MODES];
|
||||
uint16_t clk[GUID_REAL_MODES];
|
||||
time_t seconds[GUID_REAL_MODES];
|
||||
bool detect = false;
|
||||
|
||||
/* Unless another mode is detected, default to dumping */
|
||||
if (GUID_AUTO == guid_mode) {
|
||||
detect = true;
|
||||
guid_mode = GUID_DUMP;
|
||||
}
|
||||
|
||||
/* Try to convert time using all possible methods to use
|
||||
* the result later if GUID_AUTO is requested */
|
||||
|
||||
/* For IPMI all fields are little-endian (LSB first) */
|
||||
t_hi[GUID_IPMI] = ipmi16toh(&ipmi_guid->time_hi_and_version);
|
||||
t_mid[GUID_IPMI] = ipmi16toh(&ipmi_guid->time_mid);
|
||||
t_low[GUID_IPMI] = ipmi32toh(&ipmi_guid->time_low);
|
||||
clk[GUID_IPMI] = ipmi16toh(&ipmi_guid->clock_seq_and_rsvd);
|
||||
|
||||
/* For RFC4122 all fields are in network byte order (MSB first) */
|
||||
t_hi[GUID_RFC4122] = ntohs(rfc_guid->time_hi_and_version);
|
||||
t_mid[GUID_RFC4122] = ntohs(rfc_guid->time_mid);
|
||||
t_low[GUID_RFC4122] = ntohl(rfc_guid->time_low);
|
||||
clk[GUID_RFC4122] = ntohs(rfc_guid->clock_seq_and_rsvd);
|
||||
|
||||
/* For SMBIOS time fields are little-endian (as in IPMI), the rest is
|
||||
* in network order (as in RFC4122) */
|
||||
t_hi[GUID_SMBIOS] = ipmi16toh(&rfc_guid->time_hi_and_version);
|
||||
t_mid[GUID_SMBIOS] = ipmi16toh(&rfc_guid->time_mid);
|
||||
t_low[GUID_SMBIOS] = ipmi32toh(&rfc_guid->time_low);
|
||||
clk[GUID_SMBIOS] = ntohs(rfc_guid->clock_seq_and_rsvd);
|
||||
|
||||
/* Using 0 here to allow for reordering of modes in ipmi_guid_mode_t */
|
||||
for (i = 0; i < GUID_REAL_MODES; ++i) {
|
||||
seconds[i] = _guid_time(t_low[i], t_mid[i], t_hi[i]);
|
||||
|
||||
/* If autodetection was initially requested and mode
|
||||
* hasn't been detected yet */
|
||||
if (detect) {
|
||||
guid_version_t ver = GUID_VERSION(t_hi[i]);
|
||||
if (is_guid_version_valid(ver)) {
|
||||
guid_mode = i;
|
||||
if (GUID_VERSION_TIME == ver && _is_time_valid(seconds[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (guid_mode >= GUID_REAL_MODES) {
|
||||
guid_mode = GUID_DUMP;
|
||||
/* The endianness and field order are irrelevant for dump mode */
|
||||
memcpy(&parsed_guid, guid, sizeof(ipmi_guid_t));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return only a valid version in the parsed version field.
|
||||
* If one needs the raw value, they still may use
|
||||
* GUID_VERSION(parsed_guid.time_hi_and_version)
|
||||
*/
|
||||
parsed_guid.ver = GUID_VERSION(t_hi[guid_mode]);
|
||||
if (parsed_guid.ver > GUID_VERSION_MAX) {
|
||||
parsed_guid.ver = GUID_VERSION_UNKNOWN;
|
||||
}
|
||||
|
||||
if (GUID_VERSION_TIME == parsed_guid.ver) {
|
||||
parsed_guid.time = seconds[guid_mode];
|
||||
}
|
||||
|
||||
if (GUID_IPMI == guid_mode) {
|
||||
/*
|
||||
* In IPMI all fields are little-endian (LSB first)
|
||||
* That is, first byte last. Hence, swap before copying.
|
||||
*/
|
||||
memcpy(parsed_guid.node,
|
||||
array_byteswap(ipmi_guid->node, GUID_NODE_SZ),
|
||||
GUID_NODE_SZ);
|
||||
} else {
|
||||
/*
|
||||
* For RFC4122 and SMBIOS the node field is in network byte order.
|
||||
* That is first byte first. Hence, copy as is.
|
||||
*/
|
||||
memcpy(parsed_guid.node, rfc_guid->node, GUID_NODE_SZ);
|
||||
}
|
||||
|
||||
parsed_guid.time_low = t_low[guid_mode];
|
||||
parsed_guid.time_mid = t_mid[guid_mode];
|
||||
parsed_guid.time_hi_and_version = t_hi[guid_mode];
|
||||
parsed_guid.clock_seq_and_rsvd = clk[guid_mode];
|
||||
|
||||
out:
|
||||
parsed_guid.mode = guid_mode;
|
||||
return parsed_guid;
|
||||
}
|
||||
|
||||
/* ipmi_mc_print_guid - print-out given BMC GUID
|
||||
*
|
||||
* @param[in] intf - The IPMI interface to request GUID from
|
||||
@ -533,18 +708,12 @@ _ipmi_mc_get_guid(struct ipmi_intf *intf, struct ipmi_guid_t *guid)
|
||||
static int
|
||||
ipmi_mc_print_guid(struct ipmi_intf *intf, ipmi_guid_mode_t guid_mode)
|
||||
{
|
||||
/* Field order is different for RFC4122/SMBIOS and for IPMI */
|
||||
struct ipmi_guid_t ipmi_guid;
|
||||
struct rfc_guid_t *rfc_guid; /* Alias pointer */
|
||||
/* Allocate a byte array for ease of use in dump mode */
|
||||
uint8_t guid_data[sizeof(ipmi_guid_t)];
|
||||
|
||||
uint8_t node[GUID_NODE_SZ]; /* MSB first */
|
||||
/* These are host architecture specific */
|
||||
uint16_t clock_seq_and_rsvd;
|
||||
uint64_t time_hi_and_version;
|
||||
uint64_t time_mid;
|
||||
uint64_t time_low;
|
||||
parsed_guid_t guid;
|
||||
|
||||
guid_version_t guid_ver;
|
||||
const char *guid_ver_str[GUID_VERSION_COUNT] = {
|
||||
[GUID_VERSION_UNKNOWN] = "Unknown/unsupported",
|
||||
[GUID_VERSION_TIME] = "Time-based",
|
||||
@ -554,95 +723,70 @@ ipmi_mc_print_guid(struct ipmi_intf *intf, ipmi_guid_mode_t guid_mode)
|
||||
[GUID_VERSION_SHA1] = "Name-based using SHA-1"
|
||||
};
|
||||
|
||||
const char *guid_mode_str[GUID_TOTAL_MODES] = {
|
||||
[GUID_IPMI] = "IPMI",
|
||||
[GUID_RFC4122] = "RFC4122",
|
||||
[GUID_SMBIOS] = "SMBIOS",
|
||||
[GUID_AUTO] = "Automatic (if you see this, report a bug)",
|
||||
[GUID_DUMP] = "Unknown (data dumped)"
|
||||
};
|
||||
|
||||
char tbuf[40] = { 0 };
|
||||
struct tm *tm;
|
||||
int rc;
|
||||
|
||||
rc = _ipmi_mc_get_guid(intf, &ipmi_guid);
|
||||
rc = _ipmi_mc_get_guid(intf, (ipmi_guid_t *)guid_data);
|
||||
if (eval_ccode(rc) != 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
printf("System GUID : ");
|
||||
if (GUID_DUMP == guid_mode) {
|
||||
printf("System GUID : ");
|
||||
|
||||
guid = ipmi_parse_guid(guid_data, guid_mode);
|
||||
if (GUID_DUMP == guid.mode) {
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(ipmi_guid); ++i) {
|
||||
printf("%02X", ((uint8_t *)&ipmi_guid)[i]);
|
||||
for (i = 0; i < sizeof(guid_data); ++i) {
|
||||
printf("%02X", guid_data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GUID_IPMI == guid_mode) {
|
||||
/* In IPMI all fields are little-endian (LSB first) */
|
||||
memcpy(node,
|
||||
array_byteswap(ipmi_guid.node, GUID_NODE_SZ),
|
||||
GUID_NODE_SZ);
|
||||
clock_seq_and_rsvd = ipmi16toh(&ipmi_guid.clock_seq_and_rsvd);
|
||||
time_low = ipmi32toh(&ipmi_guid.time_low);
|
||||
time_mid = ipmi16toh(&ipmi_guid.time_mid);
|
||||
time_hi_and_version = ipmi16toh(&ipmi_guid.time_hi_and_version);
|
||||
} else {
|
||||
/* For RFC4122 all fields are in network byte order (MSB first) */
|
||||
rfc_guid = (struct rfc_guid_t *)(&ipmi_guid);
|
||||
memcpy(node,
|
||||
rfc_guid->node,
|
||||
GUID_NODE_SZ);
|
||||
clock_seq_and_rsvd = ntohs(rfc_guid->clock_seq_and_rsvd);
|
||||
if (GUID_RFC4122 == guid_mode) {
|
||||
time_low = ntohl(rfc_guid->time_low);
|
||||
time_mid = ntohs(rfc_guid->time_mid);
|
||||
time_hi_and_version = ntohs(rfc_guid->time_hi_and_version);
|
||||
} else {
|
||||
/* For SMBIOS time fields are little-endian (as in IPMI) */
|
||||
time_low = ipmi32toh(&rfc_guid->time_low);
|
||||
time_mid = ipmi16toh(&rfc_guid->time_mid);
|
||||
time_hi_and_version = ipmi16toh(&rfc_guid->time_hi_and_version);
|
||||
}
|
||||
}
|
||||
|
||||
printf("%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n",
|
||||
(int)time_low, (int)time_mid, (int)time_hi_and_version,
|
||||
clock_seq_and_rsvd,
|
||||
node[0], node[1], node[2], node[3], node[4], node[5]);
|
||||
(int)guid.time_low,
|
||||
(int)guid.time_mid,
|
||||
(int)guid.time_hi_and_version,
|
||||
guid.clock_seq_and_rsvd,
|
||||
guid.node[0], guid.node[1], guid.node[2],
|
||||
guid.node[3], guid.node[4], guid.node[5]);
|
||||
|
||||
guid_ver = GUID_VERSION(time_hi_and_version);
|
||||
|
||||
if (guid_ver > GUID_VERSION_MAX) {
|
||||
/* Reset any unsupported value fto UNKNOWN */
|
||||
guid_ver = GUID_VERSION_UNKNOWN;
|
||||
if (GUID_AUTO == guid_mode) {
|
||||
/* ipmi_parse_guid() returns only valid modes in guid.ver */
|
||||
printf("GUID Encoding : %s", guid_mode_str[guid.mode]);
|
||||
if (GUID_IPMI != guid.mode) {
|
||||
printf(" (WARNING: IPMI Specification violation!)");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("GUID Version : %s", guid_ver_str[guid_ver]);
|
||||
if (GUID_VERSION_UNKNOWN == guid_ver)
|
||||
printf(" (%d)", GUID_VERSION((int)time_hi_and_version));
|
||||
printf("\n");
|
||||
|
||||
if (GUID_VERSION_TIME == guid_ver) {
|
||||
/* GUID time-stamp is a 60-bit value representing the
|
||||
* count of 100ns intervals since 00:00:00.00, 15 Oct 1582 */
|
||||
|
||||
const uint64_t t100ns_in_sec = 10000000LL;
|
||||
|
||||
/* Seconds from 15 Oct 1582 to 1 Jan 1970 00:00:00 */
|
||||
uint64_t epoch_since_gregorian = 12219292800;
|
||||
|
||||
/* 100ns intervals since 15 Oct 1582 00:00:00 */
|
||||
uint64_t gregorian = (GUID_TIME_HI(time_hi_and_version) << 48)
|
||||
| (time_mid << 32)
|
||||
| time_low;
|
||||
time_t unixtime; /* We need timestamp in seconds since UNIX epoch */
|
||||
|
||||
gregorian /= t100ns_in_sec; /* Convert to seconds */
|
||||
unixtime = gregorian - epoch_since_gregorian;
|
||||
printf("GUID Version : %s", guid_ver_str[guid.ver]);
|
||||
|
||||
switch (guid.ver) {
|
||||
case GUID_VERSION_UNKNOWN:
|
||||
printf(" (%d)\n", GUID_VERSION((int)guid.time_hi_and_version));
|
||||
break;
|
||||
case GUID_VERSION_TIME:
|
||||
if(time_in_utc)
|
||||
tm = gmtime(&unixtime);
|
||||
tm = gmtime(&guid.time);
|
||||
else
|
||||
tm = localtime(&unixtime);
|
||||
tm = localtime(&guid.time);
|
||||
strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", tm);
|
||||
printf("Timestamp : %s\n", tbuf);
|
||||
printf("\nTimestamp : %s\n", tbuf);
|
||||
break;
|
||||
default:
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1177,18 +1321,22 @@ ipmi_mc_main(struct ipmi_intf * intf, int argc, char ** argv)
|
||||
rc = ipmi_mc_get_deviceid(intf);
|
||||
}
|
||||
else if (strncmp(argv[0], "guid", 4) == 0) {
|
||||
/* Most implementations like AMI MegaRAC do it the SMBIOS way.
|
||||
* This is the legacy behavior we don't want to break yet. */
|
||||
ipmi_guid_mode_t guid_mode = GUID_SMBIOS;
|
||||
ipmi_guid_mode_t guid_mode = GUID_AUTO;
|
||||
|
||||
/* Allow for 'rfc' and 'rfc4122' */
|
||||
if (argc > 1) {
|
||||
if (!strncmp(argv[1], "rfc", 3)) {
|
||||
guid_mode = GUID_RFC4122;
|
||||
}
|
||||
else if (!strcmp(argv[1], "smbios")) {
|
||||
guid_mode = GUID_SMBIOS;
|
||||
}
|
||||
else if (!strcmp(argv[1], "ipmi")) {
|
||||
guid_mode = GUID_IPMI;
|
||||
}
|
||||
else if (!strcmp(argv[1], "auto")) {
|
||||
guid_mode = GUID_AUTO;
|
||||
}
|
||||
else if (!strcmp(argv[1], "dump")) {
|
||||
guid_mode = GUID_DUMP;
|
||||
}
|
||||
|
@ -1143,7 +1143,7 @@ ipmi_pef2_get_info(struct ipmi_intf *intf)
|
||||
{
|
||||
struct pef_capabilities pcap;
|
||||
struct pef_cfgparm_system_guid psys_guid;
|
||||
struct ipmi_guid_t guid;
|
||||
ipmi_guid_t guid;
|
||||
int rc;
|
||||
uint8_t *guid_ptr = NULL;
|
||||
uint8_t policy_table_size;
|
||||
|
Loading…
x
Reference in New Issue
Block a user