> Date: Mon, 9 Nov 2020 14:18:03 +0000
> From: Stuart Henderson <[email protected]>
> 
> On 2020/11/08 11:42, Benjamin Baier wrote:
> > Forwarding to tech@ by request from  Stuart Henderson
> > This issue came up on misc@
> > https://marc.info/?l=openbsd-misc&m=160477082230840&w=2
> > 
> > Begin forwarded message:
> > 
> > Date: Sat, 7 Nov 2020 22:30:44 +0100
> > From: Benjamin Baier <[email protected]>
> > To: Bruce Lilly <[email protected]>
> > Cc: [email protected]
> > Subject: Re: Hardware UUID discrepancies (dmidecode vs. sysctl) on amd64 
> > multiboot system
> > 
> > 
> > On Sat, 7 Nov 2020 12:36:42 -0500
> > Bruce Lilly <[email protected]> wrote:
> > 
> > > I have a multiboot system with several OSes on the same hardware.
> > > 
> > > Summary: OpenBSD UUID reported by dmidecode and from sysctl differ
> > > significantly w.r.t. byte ordering.  Multiple OSes report the same 
> > > dmidecode
> > > UUID, and most other OSes provide one or more alternate ways of accessing
> > > the UUID which yields results consistent with dmidecode.
> > > 
> > > Details:
> > > dmidecode (after fiddling with kern.allowkmem via /etc/sysctl.conf on 
> > > OpenBSD)
> > > run on each OS that has a dmidecode utility reports the same hardware UUID
> > > (modulo hexadecimal digit case), viz.
> > > 
> > > UUID: 484B1340-D7AA-81E5-3CED-9C5C8E3D6756
> > > 
> > > OpenBSD (6.8) `sysctl hw.uuid` instead reports:
> > > 
> > > hw.uuid=40134b48-aad7-e581-3ced-9c5c8e3d6756
> > > 
> > > Note that the differences are:
> > > 1. case of hexadecimal digits (inconsequential)
> > > 2. byte ordering (but inconsistently so between the initial part
> > >     and the last 64 bits (the latter part's byte ordering is consistent
> > >     with dmidecode))
> > > 
> > According to SMBIOS Reference Specification, you are correct.
> >   7.2.1
> >   Although RFC 4122 recommends network byte order for all fields, the PC 
> > industry (including the ACPI,
> >   UEFI, and Microsoft specifications) has consistently used little-endian 
> > byte encoding for the first three
> >   fields: time_low, time_mid, time_hi_and_version. The same encoding, also 
> > known as wire format, should
> >   also be used for the SMBIOS representation of the UUID.
> >   The UUID {00112233-4455-6677-8899-AABBCCDDEEFF} would thus be represented 
> > as:
> >   33 22 11 00 55 44 77 66 88 99 AA BB CC DD EE FF.
> > 
> > What are the ramifications of a changed UUID?
> > What software depends on hw.uuid not changing? 
> > 
> > Greetings Ben
> > 
> > ---
> 
> I think it would be correct to change our code to follow the spec,
> but reading the manual of current versions of dmidecode it goes a bit
> further;
> 
>     There is some ambiguity about how to interpret the UUID fields
>     prior to SMBIOS specification version 2.6. There was no mention
>     of byte swapping, and RFC 4122 says that no byte swapping should
>     be applied by default.  However, SMBIOS specification version
>     2.6 (and later) explicitly states that the first 3 fields of
>     the UUID should be read as little-endian numbers (byte-swapped).
>     Furthermore, it implies that the same was already true for older
>     versions of the specification, even though it was not mentioned.
>     In practice, many hardware vendors were not byte-swapping the
>     UUID. So, in order to preserve compatibility, it was decided
>     to interpret the UUID fields according to RFC 4122 (no byte
>     swapping) when the SMBIOS version is older than 2.6, and to
>     interpret the first 3 fields as little-endian (byte-swapped)
>     when the SMBIOS version is 2.6 or later. The Linux kernel follows
>     the same logic.
> 
> It would seem sensible to follow that lead here I think? Diff for that
> below.
> 
> I don't think many people will be making existing use of hw.uuid but it
> is possible, I don't think there's much we can do other than mention it
> in upgrade notes.

Given that explanation, I'd argue that we should leave things as-is.
Folks interpreted the standard differently and in the end our
interpretation won.  Adding more code to "fix" this issue doesn't make
a lot of sense to me.  Besides, where in the documentation is it
spelled out that hw.uuid matches the SMBIOS UUID?

> Index: amd64/amd64/bios.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/amd64/bios.c,v
> retrieving revision 1.43
> diff -u -p -u -2 -5 -r1.43 bios.c
> --- amd64/amd64/bios.c        26 Aug 2020 03:29:05 -0000      1.43
> +++ amd64/amd64/bios.c        9 Nov 2020 14:14:18 -0000
> @@ -476,30 +476,45 @@ smbios_info(char *str)
>                       strlcpy(hw_serial, sminfop, infolen);
>       }
>       if (smbios_entry.mjr > 2 || (smbios_entry.mjr == 2 &&
>           smbios_entry.min >= 1)) {
>               /*
>                * If the uuid value is all 0xff the uuid is present but not
>                * set, if its all 0 then the uuid isn't present at all.
>                */
>               uuidf = SMBIOS_UUID_NPRESENT|SMBIOS_UUID_NSET;
>               for (i = 0; i < sizeof(sys->uuid); i++) {
>                       if (sys->uuid[i] != 0xff)
>                               uuidf &= ~SMBIOS_UUID_NSET;
>                       if (sys->uuid[i] != 0)
>                               uuidf &= ~SMBIOS_UUID_NPRESENT;
>               }
>  
>               if (uuidf & SMBIOS_UUID_NPRESENT)
>                       hw_uuid = NULL;
>               else if (uuidf & SMBIOS_UUID_NSET)
>                       hw_uuid = "Not Set";
>               else {
>                       for (i = 0; i < sizeof(sys->uuid); i++)
>                               enqueue_randomness(sys->uuid[i]);
>                       hw_uuid = malloc(SMBIOS_UUID_REPLEN, M_DEVBUF,
>                           M_NOWAIT);
> -                     if (hw_uuid) {
> +                     /*
> +                      * SMBIOS specification 2.6 states that the first 3
> +                      * fields of the UUID should be read as little-endian
> +                      * numbers; earlier versions did not mention this.
> +                      */
> +                     if (hw_uuid && (smbios_entry.mjr > 2 ||
> +                         smbios_entry.min >= 6)) {
> +                             snprintf(hw_uuid, SMBIOS_UUID_REPLEN,
> +                                 SMBIOS_UUID_REP,
> +                                 sys->uuid[3], sys->uuid[2], sys->uuid[1],
> +                                 sys->uuid[0], sys->uuid[5], sys->uuid[4],
> +                                 sys->uuid[7], sys->uuid[6], sys->uuid[8],
> +                                 sys->uuid[9], sys->uuid[10], sys->uuid[11],
> +                                 sys->uuid[12], sys->uuid[13], sys->uuid[14],
> +                                 sys->uuid[15]);
> +                     } else if (hw_uuid) {
>                               snprintf(hw_uuid, SMBIOS_UUID_REPLEN,
>                                   SMBIOS_UUID_REP,
>                                   sys->uuid[0], sys->uuid[1], sys->uuid[2],
>                                   sys->uuid[3], sys->uuid[4], sys->uuid[5],
> Index: arm64/dev/smbios.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/arm64/dev/smbios.c,v
> retrieving revision 1.6
> diff -u -p -r1.6 smbios.c
> --- arm64/dev/smbios.c        26 Aug 2020 03:29:05 -0000      1.6
> +++ arm64/dev/smbios.c        9 Nov 2020 14:10:48 -0000
> @@ -407,7 +407,22 @@ smbios_info(char *str)
>                               enqueue_randomness(sys->uuid[i]);
>                       hw_uuid = malloc(SMBIOS_UUID_REPLEN, M_DEVBUF,
>                           M_NOWAIT);
> -                     if (hw_uuid) {
> +                     /*
> +                      * SMBIOS specification 2.6 states that the first 3
> +                      * fields of the UUID should be read as little-endian
> +                      * numbers; earlier versions did not mention this.
> +                      */
> +                     if (hw_uuid && (smbios_entry.mjr > 2 ||
> +                         smbios_entry.min >= 6)) {
> +                             snprintf(hw_uuid, SMBIOS_UUID_REPLEN,
> +                                 SMBIOS_UUID_REP,
> +                                 sys->uuid[3], sys->uuid[2], sys->uuid[1],
> +                                 sys->uuid[0], sys->uuid[5], sys->uuid[4],
> +                                 sys->uuid[7], sys->uuid[6], sys->uuid[8],
> +                                 sys->uuid[9], sys->uuid[10], sys->uuid[11],
> +                                 sys->uuid[12], sys->uuid[13], sys->uuid[14],
> +                                 sys->uuid[15]);
> +                     } else if (hw_uuid) {
>                               snprintf(hw_uuid, SMBIOS_UUID_REPLEN,
>                                   SMBIOS_UUID_REP,
>                                   sys->uuid[0], sys->uuid[1], sys->uuid[2],
> Index: i386/i386/bios.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/i386/i386/bios.c,v
> retrieving revision 1.126
> diff -u -p -r1.126 bios.c
> --- i386/i386/bios.c  26 Aug 2020 03:29:05 -0000      1.126
> +++ i386/i386/bios.c  9 Nov 2020 14:10:48 -0000
> @@ -1077,7 +1077,22 @@ smbios_info(char *str)
>                               enqueue_randomness(sys->uuid[i]);
>                       hw_uuid = malloc(SMBIOS_UUID_REPLEN, M_DEVBUF,
>                           M_NOWAIT);
> -                     if (hw_uuid) {
> +                     /*
> +                      * SMBIOS specification 2.6 states that the first 3
> +                      * fields of the UUID should be read as little-endian
> +                      * numbers; earlier versions did not mention this.
> +                      */
> +                     if (hw_uuid && (smbios_entry.mjr > 2 ||
> +                         smbios_entry.min >= 6)) {
> +                             snprintf(hw_uuid, SMBIOS_UUID_REPLEN,
> +                                 SMBIOS_UUID_REP,
> +                                 sys->uuid[3], sys->uuid[2], sys->uuid[1],
> +                                 sys->uuid[0], sys->uuid[5], sys->uuid[4],
> +                                 sys->uuid[7], sys->uuid[6], sys->uuid[8],
> +                                 sys->uuid[9], sys->uuid[10], sys->uuid[11],
> +                                 sys->uuid[12], sys->uuid[13], sys->uuid[14],
> +                                 sys->uuid[15]);
> +                     } else if (hw_uuid) {
>                               snprintf(hw_uuid, SMBIOS_UUID_REPLEN,
>                                   SMBIOS_UUID_REP,
>                                   sys->uuid[0], sys->uuid[1], sys->uuid[2],
> 
> 

Reply via email to