dmidecode-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [dmidecode] [RFC] dmioem: Decode HPE OEM Record 242


From: Jean Delvare
Subject: Re: [dmidecode] [RFC] dmioem: Decode HPE OEM Record 242
Date: Fri, 30 Sep 2022 14:51:19 +0200

Hi Jerry,

On Mon, 26 Sep 2022 23:40:25 -0600, Jerry Hoemann wrote:
> From: Jerry Hoemann <jerry.hoemann@hpe.com>
> 
> Decode HPE OEM Record 242: Hard Drive Inventory Record

You added "RFC" to the subject. Is there anything in this patch that
you think needs do be discussed?

> Signed-off-by: Jerry Hoemann <jerry.hoemann@hpe.com>
> ---
>  dmioem.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 117 insertions(+)
> 
> diff --git a/dmioem.c b/dmioem.c
> index 6000e1c..250c2c6 100644
> --- a/dmioem.c
> +++ b/dmioem.c
> @@ -466,6 +466,44 @@ static void dmi_hp_238_speed(const char *fname, unsigned 
> int code)
>       pr_attr(fname, "%s", str);
>  }
>  
> +static void dmi_hp_242_hdd_type(u8 code)
> +{
> +     const char *str = "Reserved";
> +     static const char * const type[] = {
> +             "Undetermined", /* 0x00 */
> +             "NVMe SSD",
> +             "SATA",
> +             "SAS",
> +             "SATA SSD",
> +             "NVMe Manged by VROC/VMD", /* 0x05 */
> +     };
> +     if (code < ARRAY_SIZE(type))
> +             str = type[code];
> +
> +     pr_attr("Hard Drive Type", "%s", str);
> +}
> +
> +static void dmi_hp_242_ff(u8 code)

Please spell out form_factor for clarity.

> +{
> +     const char *str = "Reserved";
> +     static const char * const form[] = {
> +             "Reserved", /* 0x00 */
> +             "Reserved",
> +             "3.5\" form factor",
> +             "2.5\" form factor",
> +             "1.8\" form factor",
> +             "less than 1.8\" form factor",

"Less" (uppercase L) for consistency.

> +             "mSATA",
> +             "M.2",
> +             "MicroSSD",
> +             "CFast", /* 0x09 */
> +     };
> +     if (code < ARRAY_SIZE(form))
> +             str = form[code];
> +
> +     pr_attr("Hard Drive Form Factor", "%s", str);

Isn't "Hard Drive" already pretty much implied by the record type?

> +}
> +
>  static int dmi_decode_hp(const struct dmi_header *h)
>  {
>       u8 *data = h->data;
> @@ -944,6 +982,85 @@ static int dmi_decode_hp(const struct dmi_header *h)
>                               pr_attr("Lowest Supported Version", "Not 
> Available");
>                       break;
>  
> +             case 242:
> +                     /*
> +                      * Vendor Specific: HPE Hard Drive Inventory Record
> +                      *
> +                      * This record provides a mechanism for software to 
> gather information for
> +                      * NVMe and SATA drives that are directly attached to 
> the system. This record
> +                      * does not contain drive information for drive 
> attached to a HBA (i.e. a

"drives" (plural)?

> +                      * SmartArray controller). This record will only 
> contain information for a
> +                      * hard drive detected by the BIOS during POST and does 
> not comprehend a hot
> +                      * plug event after the system has booted.
> +                      *
> +                      * Offset |  Name      | Width | Description
> +                      * ---------------------------------------
> +                      *  0x00  | Type       | BYTE  | 0xF2, HPE Hard Drive 
> Inventory Record
> +                      *  0x01  | Length     | BYTE  | Length of structure
> +                      *  0x02  | Handle     | WORD  | Unique handle
> +                      *  0x04  | Hndl Assoc | WORD  | Handle to map to Type 
> 203
> +                      *  0x06  | HDD Type   | BYTE  | Hard drive type
> +                      *  0x07  | HDD Uniq ID| QWORD | SATA-> WWID.  NVMe -> 
> IEEE Ext Uniq ID.
> +                      *  0x0F  | Capacity   | DWORD | Drive Capacity in 
> Mbytes
> +                      *  0x13  | Hours      | 16BYTE| Number of poweron hours
> +                      *  0x23  | Reserved   | BYTE  | Reserved
> +                      *  0x24  | Power      | BTYE  | Wattage
> +                      *  0x25  | Form Factor| BYTE  | HDD Form Factor
> +                      *  0x26  | Health     | BYTE  | Hard Drive Health 
> Status
> +                      *  0x27  | Serial Num | STRING| NVMe/SATA Serial Number
> +                      *  0x28  | Model Num  | STRING| NVMe/SATA Model Number
> +                      *  0x29  | FW Rev     | STRING| Firmware revision
> +                      *  0x2A  | Location   | STRING| Drive location
> +                      *  0x2B  | Crypt Stat | BYTE  | Drive encryption 
> status from BIOS
> +                      *  0x2C  | Capacity   | QWORD | Hard Drive capacity in 
> bytes
> +                      *  0x34  | Block Size | DWORD | Logical Block Size in 
> bytes
> +                      *  0x38  | Rot Speed  | WORD  | Nominal Rotational 
> Speed (rpm)

"RPM" (uppercase).

> +                      *  0x3A  | Neg Speed  | WORD  | Current negotiated bus 
> speed
> +                      *  0x3C  | Cap Speed  | WORD  | Fastest Capable Bus 
> Speed of drive
> +                      */
> +                     if (gen < G10) return 0;
> +                     pr_handle_name("%s ProLiant Hard Drive Inventory 
> Record", company);
> +                     if (h->length < 0x2c) break;
> +                     if (!(opt.flags & FLAG_QUIET))
> +                             pr_attr("Associated Handle", "0x%04X", 
> WORD(data + 0x4));
> +                     dmi_hp_242_hdd_type(data[0x06]);
> +                     pr_attr("ID", "%lx", QWORD(data + 0x07));
> +                     pr_attr("Capacity", "%d MB", DWORD(data + 0x0f));

%u

> +                     // NB: Poweron upper QWORD not needed for 
> 2,104,351,365,926,255 years

Please stick to /* legacy C comment style */.

I admit I was surprised to see 16 bytes allocated to store the power-on
hours value ;-)

> +                     pr_attr("Poweron", "%ld hours", QWORD(data + 0x13));

QWORD returns a struct. I doubt this can be reliably passed to printf?
TBH I'm surprised gcc doesn't complain. Maybe it's OK...

> +                     if (data[0x24])
> +                             pr_attr("Power Wattage", "%d", data[0x24]);

%hhu

> +                     else
> +                             pr_attr("Power Wattage", "%s", "Unknown");

In which unit is this value expressed? On my sample, the value is 25,
for a NVMe SSD. I've never seen a mechanical drive consuming more than
13 W, and I'd expect a SSD to consume under 5 W. So 25 W seems a lot.
But then again I'm not too much into enterprise server hardware, so I
could be wrong.

> +                     dmi_hp_242_ff(data[0x25]);
> +                     feat = data[0x26];
> +                     pr_attr("Health Status", "%s", (feat == 0x00) ? "OK" :
> +                                                     (feat == 0x01) ? 
> "Warning" :
> +                                                     (feat == 0x02) ? 
> "Critical" :
> +                                                     (feat == 0xFF) ? 
> "Unknown" : "Reserved");

Any reason why you do not introduce a helper function for that one, as
we typically do for such enumerated fields?

> +                     pr_attr("Serial Number", dmi_string(h, data[0x27]));
> +                     pr_attr("Model Number", dmi_string(h, data[0x28]));
> +                     pr_attr("Firmware Revsion", dmi_string(h, data[0x29]));
> +                     pr_attr("Hard Drive LOCATION", dmi_string(h, 
> data[0x2A]));

Case: "Location". I'd also strip "Hard Drive" as it is implied.

> +                     feat = data[0x2B];
> +                     pr_attr("Encryption Status", "%s", (feat == 0) ? "Not 
> Encrypted" :
> +                                                     (feat == 1) ? 
> "Encrypted" :
> +                                                     (feat == 2) ? "Uknown" 
> :  
> +                                                     (feat == 3) ? "Not 
> Supported" : "Reserved");

Same question here.

> +                     if (h->length < 0x3e) break;
> +                     pr_attr("Capacity", "%lu bytes", QWORD(data + 0x2C));

This field is redundant with the field at offset 0x0F. Does your
specification clarify what to do when both fields are present? I
don't think we want to print both values.

There is a similar situation for memory sizes (DMI type 16, fields 0x07
and 0x0F, as well as DMI type 17, fields 0x0C and 0x1C). I think we
should handle the situation in the same way here.

It might also make sense to use dmi_print_memory_size() to display the
value in a more human-friendly way. I'm not sure if disk sizes are
usually a power of 2 (or a multiple of some large power of 2) as memory
modules tend to be. I guess not, then we could print both the exact
value, and a rounded value using the most suitable unit.

> +                     pr_attr("Black Size", "%u bytes", DWORD(data + 0x34));

It might make sense to print this in a human-friendly unit.

> +                     if (data[0x38] > 1)

Hmm, so 2 RPM is OK, but 1 RPM is not? Odd.

> +                             pr_attr("Rotational Speed", "%d rpm", 
> data[0x38]);

Case: "RPM".

I also think you want to use %u instead of %d. In case it spins
realllly fast :-D

> +                     if (WORD(data + 0x3A))
> +                             pr_attr("Negotiated Speed", "%d Gbit/s", 
> WORD(data + 0x3A));

%h is preferred for short-size variables. %hu in this case as it can't
be negative.

> +                     else
> +                             pr_attr("Negotiated Speed", "%s", "Uknown");

Typo: "Unknown".

> +                     if (WORD(data + 0x3C))
> +                             pr_attr("Capable Speed", "%d Gbit/s", WORD(data 
> + 0x3C));

%hu

> +                     else
> +                             pr_attr("Capable Speed", "%s", "Unknown");

It might make sense to introduce a helper function for Negotiated Speed
and Capable Speed, as the code is pretty much the same for both.

> +                     break;
>               default:
>                       return 0;
>       }

You use a mix of lowercase and uppercase letters in your hexadecimal
numbers. Please stick to uppercase everywhere for consistency.

Also note that I don't have any sample implementing the second part of
type 242. If you could share a dump with from a system where this is
implemented, I'd be happy to add it to my test suite.

Thanks,
-- 
Jean Delvare
SUSE L3 Support



reply via email to

[Prev in Thread] Current Thread [Next in Thread]