]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
CMOS support on sparc.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 5 Jul 2011 18:24:20 +0000 (20:24 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 5 Jul 2011 18:24:20 +0000 (20:24 +0200)
* gentpl.py (cmos): Add powerpc and sparc.
* grub-core/Makefile.core.def (datetime): Add lib/ieee1275/cmos.c on
powerpc and sparc.
* grub-core/lib/cmos_datetime.c (grub_get_datetime)
[__powerpc__ || __sparc__]: Rename to grub_get_datetime_cmos.
(grub_set_datetime) [__powerpc__ || __sparc__]: Likewise to
grub_set_datetime_cmos.
* grub-core/lib/ieee1275/cmos.c: New file.
* grub-core/lib/ieee1275/datetime.c (no_ieee1275_rtc): New vaiable.
(find_rtc): Set no_ieee1275_rtc on error.
(grub_get_datetime): Call grub_get_datetime_cmos on error.
(grub_set_datetime): Call grub_set_datetime_cmos on error.
* include/grub/cmos.h (grub_cmos_read): Return grub_err_t since it may
fail. Move value to argument. All users updated
(grub_cmos_write): Likewise.
(grub_cmos_read) [__powerpc__ || __sparc__]: Rewritten.
(grub_cmos_write) [__powerpc__ || __sparc__]: Likewise.
* include/grub/datetime.h [__powerpc__ || __sparc__]: Declare
grub_get_datetime_cmos and grub_set_datetime_cmos.

ChangeLog
gentpl.py
grub-core/Makefile.core.def
grub-core/commands/i386/cmostest.c
grub-core/lib/cmos_datetime.c
grub-core/lib/ieee1275/cmos.c [new file with mode: 0644]
grub-core/lib/ieee1275/datetime.c
include/grub/cmos.h
include/grub/datetime.h

index e091265d4f1deab517d98abe7c8dc319b8259d9e..694a9797266664589d4aff055041c65abc1116ed 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2011-07-05  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       CMOS support on sparc.
+
+       * gentpl.py (cmos): Add powerpc and sparc.
+       * grub-core/Makefile.core.def (datetime): Add lib/ieee1275/cmos.c on
+       powerpc and sparc.
+       * grub-core/lib/cmos_datetime.c (grub_get_datetime)
+       [__powerpc__ || __sparc__]: Rename to grub_get_datetime_cmos.
+       (grub_set_datetime) [__powerpc__ || __sparc__]: Likewise to
+       grub_set_datetime_cmos.
+       * grub-core/lib/ieee1275/cmos.c: New file.
+       * grub-core/lib/ieee1275/datetime.c (no_ieee1275_rtc): New vaiable.
+       (find_rtc): Set no_ieee1275_rtc on error.
+       (grub_get_datetime): Call grub_get_datetime_cmos on error.
+       (grub_set_datetime): Call grub_set_datetime_cmos on error.
+       * include/grub/cmos.h (grub_cmos_read): Return grub_err_t since it may
+       fail. Move value to argument. All users updated
+       (grub_cmos_write): Likewise.
+       (grub_cmos_read) [__powerpc__ || __sparc__]: Rewritten.
+       (grub_cmos_write) [__powerpc__ || __sparc__]: Likewise.
+       * include/grub/datetime.h [__powerpc__ || __sparc__]: Declare
+       grub_get_datetime_cmos and grub_set_datetime_cmos.
+
 2011-07-02  GrĂ©goire Sutre  <gregoire.sutre@gmail.com>
 
        * util/grub-mkconfig.in: Use @PACKAGE@ instead of hardcoded name when
index 6e2df076be9368d0d1a0a096236a7ac04dda7b10..31cde1e819c560c751af92384a7e22dd14be67d9 100644 (file)
--- a/gentpl.py
+++ b/gentpl.py
@@ -30,7 +30,9 @@ GROUPS["ieee1275"]   = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275"
 GROUPS["noemu"]   = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu")
 
 # Groups based on hardware features
-GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi")
+GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips",
+                                     "sparc64_ieee1275", "powerpc_ieee1275"]
+GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi")
 GROUPS["pci"]      = GROUPS["x86"] + ["mips_loongson"]
 GROUPS["usb"]      = GROUPS["pci"]
 
index fd69e9c22624f92767bee9173ab31f989fbc4690..16c940c613253c8aa26b38309cb367038b45b840 100644 (file)
@@ -1192,6 +1192,9 @@ module = {
   efi = lib/efi/datetime.c;
   sparc64_ieee1275 = lib/ieee1275/datetime.c;
   powerpc_ieee1275 = lib/ieee1275/datetime.c;
+  sparc64_ieee1275 = lib/ieee1275/cmos.c;
+  powerpc_ieee1275 = lib/ieee1275/cmos.c;
+
   mips_arc = lib/arc/datetime.c;
   enable = noemu;
 };
index c79bd03876fbd26602c8ad9eecf0abc4a9437d4b..6439159bd02abe7bda5f22f63a28b090528dd083 100644 (file)
@@ -46,12 +46,17 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
 {
   int byte, bit;
   grub_err_t err;
+  grub_uint8_t value;
 
   err = parse_args (argc, argv, &byte, &bit);
   if (err)
     return err;
 
-  if (grub_cmos_read (byte) & (1 << bit))
+  err = grub_cmos_read (byte, &value);
+  if (err)
+    return err;
+
+  if (value & (1 << bit))
     return GRUB_ERR_NONE;
 
   return grub_error (GRUB_ERR_TEST_FAILURE, "false");
@@ -63,13 +68,16 @@ grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)),
 {
   int byte, bit;
   grub_err_t err;
+  grub_uint8_t value;
 
   err = parse_args (argc, argv, &byte, &bit);
+  if (err)
+    return err;
+  err = grub_cmos_read (byte, &value);
   if (err)
     return err;
 
-  grub_cmos_write (byte, grub_cmos_read (byte) & (~(1 << bit)));
-  return GRUB_ERR_NONE;
+  return grub_cmos_write (byte, value & (~(1 << bit)));
 }
 
 static grub_command_t cmd, cmd_clean;
index 73c5a03c0e4df2615b921d55e54dab6a0a8c6ae2..86cd911804281ea24feaa21556e68b6756dcfec0 100644 (file)
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
+#if !defined (__powerpc__) && !defined (__sparc__)
+#define grub_get_datetime_cmos grub_get_datetime
+#define grub_set_datetime_cmos grub_set_datetime
+#endif
+
 grub_err_t
-grub_get_datetime (struct grub_datetime *datetime)
+grub_get_datetime_cmos (struct grub_datetime *datetime)
 {
   int is_bcd, is_12hour;
   grub_uint8_t value, flag;
+  grub_err_t err;
 
-  flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+  err = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B, &flag);
+  if (err)
+    return err;
 
   is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
 
-  value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
+  err = grub_cmos_read (GRUB_CMOS_INDEX_YEAR, &value);
+  if (err)
+    return err;
   if (is_bcd)
     value = grub_bcd_to_num (value);
 
   datetime->year = value;
   datetime->year += (value < 80) ? 2000 : 1900;
 
-  value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH);
+  err = grub_cmos_read (GRUB_CMOS_INDEX_MONTH, &value);
+  if (err)
+    return err;
   if (is_bcd)
     value = grub_bcd_to_num (value);
 
   datetime->month = value;
 
-  value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
+  err = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH, &value);
+  if (err)
+    return err;
   if (is_bcd)
     value = grub_bcd_to_num (value);
 
@@ -54,7 +68,9 @@ grub_get_datetime (struct grub_datetime *datetime)
 
   is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR);
 
-  value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR);
+  err = grub_cmos_read (GRUB_CMOS_INDEX_HOUR, &value);
+  if (err)
+    return err;
   if (is_12hour)
     {
       is_12hour = (value & 0x80);
@@ -71,13 +87,18 @@ grub_get_datetime (struct grub_datetime *datetime)
 
   datetime->hour = value;
 
-  value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE);
+  err = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE, &value);
+  if (err)
+    return err;
+
   if (is_bcd)
     value = grub_bcd_to_num (value);
 
   datetime->minute = value;
 
-  value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND);
+  err = grub_cmos_read (GRUB_CMOS_INDEX_SECOND, &value);
+  if (err)
+    return err;
   if (is_bcd)
     value = grub_bcd_to_num (value);
 
@@ -87,12 +108,15 @@ grub_get_datetime (struct grub_datetime *datetime)
 }
 
 grub_err_t
-grub_set_datetime (struct grub_datetime *datetime)
+grub_set_datetime_cmos (struct grub_datetime *datetime)
 {
   int is_bcd, is_12hour;
   grub_uint8_t value, flag;
+  grub_err_t err;
 
-  flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+  err = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B, &flag);
+  if (err)
+    return err;
 
   is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
 
@@ -102,21 +126,27 @@ grub_set_datetime (struct grub_datetime *datetime)
   if (is_bcd)
     value = grub_num_to_bcd (value);
 
-  grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
+  err = grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
+  if (err)
+    return err;
 
   value = datetime->month;
 
   if (is_bcd)
     value = grub_num_to_bcd (value);
 
-  grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
+  err = grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
+  if (err)
+    return err;
 
   value = datetime->day;
 
   if (is_bcd)
     value = grub_num_to_bcd (value);
 
-  grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
+  err = grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
+  if (err)
+    return err;
 
   value = datetime->hour;
 
@@ -138,21 +168,27 @@ grub_set_datetime (struct grub_datetime *datetime)
   if (is_12hour)
     value |= 0x80;
 
-  grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
+  err = grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
+  if (err)
+    return err;
 
   value = datetime->minute;
 
   if (is_bcd)
     value = grub_num_to_bcd (value);
 
-  grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
+  err = grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
+  if (err)
+    return err;
 
   value = datetime->second;
 
   if (is_bcd)
     value = grub_num_to_bcd (value);
 
-  grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
+  err = grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
+  if (err)
+    return err;
 
   return 0;
 }
diff --git a/grub-core/lib/ieee1275/cmos.c b/grub-core/lib/ieee1275/cmos.c
new file mode 100644 (file)
index 0000000..fa57db9
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2011  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/datetime.h>
+#include <grub/cmos.h>
+#include <grub/dl.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/misc.h>
+
+volatile grub_uint8_t *grub_cmos_port = 0;
+grub_err_t
+grub_cmos_find_port (void)
+{
+  auto int hook (struct grub_ieee1275_devalias *alias);
+  int hook (struct grub_ieee1275_devalias *alias)
+  {
+    grub_ieee1275_phandle_t dev;
+    grub_uint32_t addr[2];
+    grub_ssize_t actual;
+    /* Enough to check if it's "m5819" */
+    char compat[100];
+    if (grub_ieee1275_finddevice (alias->path, &dev))
+      return 0;
+    if (grub_ieee1275_get_property (dev, "compatible", compat, sizeof (compat),
+                                   0))
+      return 0;
+    if (grub_strcmp (compat, "m5819") != 0)
+      return 0;
+    if (grub_ieee1275_get_integer_property (dev, "address",
+                                           addr, sizeof (addr), &actual))
+      return 0;
+    if (actual == 4)
+      {
+       grub_cmos_port = (volatile grub_uint8_t *) (grub_addr_t) addr[0];
+       return 1;
+      }
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+    if (actual == 8)
+      {
+       grub_cmos_port = (volatile grub_uint8_t *) 
+         ((((grub_addr_t) addr[0]) << 32) | addr[1]);
+       return 1;
+      }
+#else
+    if (actual == 8 && addr[0] == 0)
+      {
+       grub_cmos_port = (volatile grub_uint8_t *) addr[1];
+       return 1;
+      }
+#endif
+    return 0;
+  }
+  
+  grub_ieee1275_devices_iterate (hook);
+  if (!grub_cmos_port)
+    return grub_error (GRUB_ERR_IO, "no cmos found");
+  
+  return GRUB_ERR_NONE;
+}
index 4105c639be500101062fba1fe95af5c5ca3e79a2..1947135fe01d1f1ab432c994725a851f732a8a61 100644 (file)
 #include <grub/ieee1275/ieee1275.h>
 #include <grub/misc.h>
 #include <grub/dl.h>
+#if defined (__powerpc__) || defined (__sparc__)
+#include <grub/cmos.h>
+#endif
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
 static char *rtc = 0;
+static int no_ieee1275_rtc = 0;
 
 static void
 find_rtc (void)
@@ -42,6 +46,8 @@ find_rtc (void)
   }
   
   grub_ieee1275_devices_iterate (hook);
+  if (!rtc)
+    no_ieee1275_rtc = 1;
 }
 
 grub_err_t
@@ -64,10 +70,12 @@ grub_get_datetime (struct grub_datetime *datetime)
   int status;
   grub_ieee1275_ihandle_t ihandle;
 
+  if (no_ieee1275_rtc)
+    return grub_get_datetime_cmos (datetime);
   if (!rtc)
     find_rtc ();
   if (!rtc)
-    return grub_error (GRUB_ERR_IO, "no RTC found");
+    return grub_get_datetime_cmos (datetime);
 
   status = grub_ieee1275_open (rtc, &ihandle);
   if (status == -1)
@@ -114,10 +122,12 @@ grub_set_datetime (struct grub_datetime *datetime)
   int status;
   grub_ieee1275_ihandle_t ihandle;
 
+  if (no_ieee1275_rtc)
+    return grub_set_datetime_cmos (datetime);
   if (!rtc)
     find_rtc ();
   if (!rtc)
-    return grub_error (GRUB_ERR_IO, "no RTC found");
+    return grub_set_datetime_cmos (datetime);
 
   status = grub_ieee1275_open (rtc, &ihandle);
   if (status == -1)
index f508e3bf6ec988721c6f0cc0cdd371fce1a7b4bd..331513cd7f21a3de92cda1d033aa6350ff73dd37 100644 (file)
 #define        GRUB_CMOS_H     1
 
 #include <grub/types.h>
+#if !defined (__powerpc__) && !defined (__sparc__)
 #include <grub/cpu/io.h>
 #include <grub/cpu/cmos.h>
+#endif
 
 #define GRUB_CMOS_INDEX_SECOND         0
 #define GRUB_CMOS_INDEX_SECOND_ALARM   1
@@ -55,18 +57,56 @@ grub_num_to_bcd (grub_uint8_t a)
   return (((a / 10) << 4) + (a % 10));
 }
 
-static inline grub_uint8_t
-grub_cmos_read (grub_uint8_t index)
+#if !defined (__powerpc__) && !defined (__sparc__)
+static inline grub_err_t
+grub_cmos_read (grub_uint8_t index, grub_uint8_t *val)
 {
   grub_outb (index, GRUB_CMOS_ADDR_REG);
-  return grub_inb (GRUB_CMOS_DATA_REG);
+  *val = grub_inb (GRUB_CMOS_DATA_REG);
+  return GRUB_ERR_NONE;
 }
 
-static inline void
+static inline grub_err_t
 grub_cmos_write (grub_uint8_t index, grub_uint8_t value)
 {
   grub_outb (index, GRUB_CMOS_ADDR_REG);
   grub_outb (value, GRUB_CMOS_DATA_REG);
+  return GRUB_ERR_NONE;
+}
+#else
+grub_err_t grub_cmos_find_port (void);
+extern volatile grub_uint8_t *grub_cmos_port;
+
+static inline grub_err_t
+grub_cmos_read (grub_uint8_t index, grub_uint8_t *val)
+{
+  if (!grub_cmos_port)
+    {
+      grub_err_t err;
+      err = grub_cmos_find_port ();
+      if (err)
+       return err;
+    }
+  grub_cmos_port[0] = index;
+  *val = grub_cmos_port[1];
+  return GRUB_ERR_NONE;
 }
 
+static inline grub_err_t
+grub_cmos_write (grub_uint8_t index, grub_uint8_t val)
+{
+  if (!grub_cmos_port)
+    {
+      grub_err_t err;
+      err = grub_cmos_find_port ();
+      if (err)
+       return err;
+    }
+  grub_cmos_port[0] = index;
+  grub_cmos_port[1] = val;
+  return GRUB_ERR_NONE;
+}
+
+#endif
+
 #endif /* GRUB_CMOS_H */
index c20fc8c3673c030b665fbf1fbc75dc1fdbc2ab29..dea0f8ea9f8999f21ee36338ba9bda1bbe4e1da7 100644 (file)
@@ -125,4 +125,11 @@ grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix)
   return 1;
 }
 
+#if defined (__powerpc__) || defined (__sparc__)
+grub_err_t
+grub_get_datetime_cmos (struct grub_datetime *datetime);
+grub_err_t
+grub_set_datetime_cmos (struct grub_datetime *datetime);
+#endif
+
 #endif /* ! KERNEL_DATETIME_HEADER */