On 9/2/22 01:52, Simon Glass wrote:
Hi Heinrich,


On Thu, 1 Sept 2022 at 14:44, Heinrich Schuchardt
<heinrich.schucha...@canonical.com> wrote:

We need to support multiple digits in the parts of the UEFI verision
number. E.g.

     EFI_SPECIFICATION_VERSION = (123 << 16) | 456

must be printed as

     123.45.6

Signed-off-by: Heinrich Schuchardt <heinrich.schucha...@canonical.com>
---
  lib/efi_loader/helloworld.c | 66 ++++++++++++++++++++++++++++++-------
  1 file changed, 54 insertions(+), 12 deletions(-)

Gosh, I'm not sure what to make of this! Could uint2dec() use strtoul()?

This is standalone code. We cannot call any library functions here and we convert unsigned to wide string and not string to unsigned.

Best regards

Heinrich


Regards,
Simon



diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c
index 10666dc0f2..d565f32745 100644
--- a/lib/efi_loader/helloworld.c
+++ b/lib/efi_loader/helloworld.c
@@ -29,24 +29,66 @@ static struct efi_system_table *systable;
  static struct efi_boot_services *boottime;
  static struct efi_simple_text_output_protocol *con_out;

+/*
+ * Print an unsigned 32bit value as decimal number to an u16 string
+ *
+ * @value:     value to be printed
+ * @buf:       pointer to buffer address
+ *             on return position of terminating zero word
+ */
+static void uint2dec(u32 value, u16 **buf)
+{
+       u16 *pos = *buf;
+       int i;
+       u16 c;
+       u64 f;
+
+       /*
+        * Increment by .5 and multiply with
+        * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
+        * to move the first digit to bit 60-63.
+        */
+       f = 0x225C17D0;
+       f += (0x9B5A52DULL * value) >> 28;
+       f += 0x44B82FA0ULL * value;
+
+       for (i = 0; i < 10; ++i) {
+               /* Write current digit */
+               c = f >> 60;
+               if (c || pos != *buf)
+                       *pos++ = c + '0';
+               /* Eliminate current digit */
+               f &= 0xfffffffffffffff;
+               /* Get next digit */
+               f *= 0xaULL;
+       }
+       if (pos == *buf)
+               *pos++ = '0';
+       *pos = 0;
+       *buf = pos;
+}
+
  /**
   * print_uefi_revision() - print UEFI revision number
   */
  static void print_uefi_revision(void)
  {
-       u16 rev[] = u"0.0.0";
-
-       rev[0] = (systable->hdr.revision >> 16) + '0';
-       rev[4] = systable->hdr.revision & 0xffff;
-       for (; rev[4] >= 10;) {
-               rev[4] -= 10;
-               ++rev[2];
+       u16 rev[13] = {0};
+       u16 *buf = rev;
+       u16 digit;
+
+       uint2dec(systable->hdr.revision >> 16, &buf);
+       *buf++ = '.';
+       uint2dec(systable->hdr.revision & 0xffff, &buf);
+
+       /* Minor revision is only to be shown if non-zero */
+       digit = *--buf;
+       if (digit == '0') {
+               *buf = 0;
+       } else {
+               *buf++ = '.';
+               *buf = digit;
         }
-       /* Third digit is only to be shown if non-zero */
-       if (rev[4])
-               rev[4] += '0';
-       else
-               rev[3] = 0;

         con_out->output_string(con_out, u"Running on UEFI ");
         con_out->output_string(con_out, rev);
--
2.37.2

Reply via email to