Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Diverge JSON output from simple serialization of smbios structures? #55

Open
mulark opened this issue Mar 23, 2022 · 3 comments
Open

Diverge JSON output from simple serialization of smbios structures? #55

mulark opened this issue Mar 23, 2022 · 3 comments

Comments

@mulark
Copy link
Collaborator

mulark commented Mar 23, 2022

This is more a documentation of an idea I had.

Essentially, the smbios spec often includes sentinel values to tell you to look at another field. Particularly with memory capacity fields, an example being the recent CacheMemorySize fields. These also can be redundant if the values held fit in the first of the fields (although some of these may be spec violations, the values are present here anyway).

        "maximum_cache_size": {
          "Kilobytes": 32768
        },
        "installed_size": {
          "Kilobytes": 32768
        },
        "maximum_cache_size_2": {
          "Kilobytes": 32768
        },
        "installed_cache_size_2": {
          "Kilobytes": 32768
        }

This application could instead perform such parsing/deduplication tasks prior to outputting.

@jrgerber
Copy link
Owner

The contents of the JSON presented to the user of dmidecode-rs is a very good topic. Today it directly presents the JSON output of smbios-lib. Generally speaking, dmidecode helps present data in a human consumable or at least ready to consume format.

The opposite is true for smbios-lib which has the goal of accurately representing the contents of the raw SMBIOS data, parsed to the SMBIOS standard, without loss of data. By parsing we mean not only breaking a structure into fields of the given data type (byte, word, dword, string, etc.) but also sub-parsing into meanings defined by the standard (e.g. 0xFFFF in this field means refer to the other field). smbios-lib would do a disfavor if it catered only to one consumer or application such as dmidecode-rs because it might limit other use cases of other applications. End user friendliness is a non-goal of smbios-lib and by presenting its JSON output as-is in dmidecode-rs can make some use cases difficult.

A good example to study the difference between the opposing output goals of dmidecode-rs versus smbios-lib is type 17 memory data because it has a complex set of rules to follow to get at the useful data. For example the speed may be 0, indicating an empty slot, in which case you may not want to look further. Beyond that, as you indicate, the deduplication of fields like memory size.

Finally, a very good point you bring up is spec violations. These happen more frequently than the industry likely realizes. Annex A (informative) Conformance Guidelines at the end of the SMBIOS specification outlines what is required in 2.5 and later. These rules can be implemented in code as a validation feature. The user scenario would be someone wants to quickly know the quality of the BIOS table - if the BIOS information they are looking at conforms to the standard. This would be highly useful prior to releasing a firmware update.

@jrgerber
Copy link
Owner

There is another use case for smbios-lib JSON worth mentioning. The JSON output of smbios-lib is a convenient way to quickly write an adapter in another language via FFI (Foreign Function Interface). Essentially, smbios-lib is used to parse a given raw BIOS table into JSON, and then the JSON (as a string or stream) is the sole input to the foreign language, which then queries the desired elements in the JSON and converts to the desired API surface presented in that language.

Second stage JSON refinement might find use outside of dmidecode-rs? If so, perhaps a separate library project that makes smbios-lib easier to consume for end-user oriented goals is in order?

@mulark
Copy link
Collaborator Author

mulark commented Mar 27, 2022

Regarding FFI (although it's not exactly FFI, besides the point), consider the usage of the following memory scenarios:

  3 #[derive(Serialize)]                                                            
  4 pub enum MemExample1 {                                                           
  5     Kilobytes(u64),                                                             
  6     Megabytes(u64),                                                             
  7     Gigabytes(u64),                                                             
  8     Terabytes(u64),                                                             
  9 }                                                                               
 10                                                                                 
 11 #[derive(Serialize)]                                                            
 12 pub struct MemExample2 {                                                        
 13     value: u64,                                                                 
 14     units: Units,                                                               
 15 }                                                                               
 16                                                                                 
 17 #[derive(Serialize)]                                                            
 18 pub enum Units {                                                                
 19     Kilobytes,                                                                  
 20     Megabytes,                                                                  
 21     Gigabytes,                                                                  
 22     Terabytes                                                                   
 23 }                                                                               
 24                                                                                 
 25 #[derive(Serialize)]                                                            
 26 pub struct MemExample3 {                                                        
 27     value: String,                                                              
 28 }
{
  "Kilobytes": 4096
}
{
  "value": 4096,
  "units": "Kilobytes"
}
{
  "value": "4096 kB"
}

Option 1 is roughly the current approach, and is generally(?) the idiomatic approach in Rust. However, not all languages would have such an easy time deserializing this format of data.
Option 2 would likely be a more widely compatible format, albeit somewhat more error prone as well.
Option 3 would be pretty much a translation of the current dmidecode values output into json format. Likely closest to whatever various dmidecode parsers written over the years, but still leaves likely work for the user to do. Might be the easier to maintain since the output values would be formatted in the same way for json/stdout.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants