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.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-07-05 20:24:20 +02:00
parent 77546584e1
commit a07a81b335
9 changed files with 231 additions and 26 deletions

View file

@ -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

View file

@ -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"]

View 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;
};

View 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;

View file

@ -23,30 +23,44 @@
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;
}

View file

@ -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;
}

View file

@ -21,10 +21,14 @@
#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)

View file

@ -20,8 +20,10 @@
#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 */

View 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 */