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.

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