* 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-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
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"]
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;
};
{
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");
{
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;
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);
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);
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);
}
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);
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;
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;
}
--- /dev/null
+/*
+ * 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;
+}
#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)
}
grub_ieee1275_devices_iterate (hook);
+ if (!rtc)
+ no_ieee1275_rtc = 1;
}
grub_err_t
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)
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)
#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
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 */
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 */