uboot/common/cmd_date.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24/*
  25 * RTC, Date & Time support: get and set date & time
  26 */
  27#include <common.h>
  28#include <command.h>
  29#include <rtc.h>
  30#include <i2c.h>
  31
  32DECLARE_GLOBAL_DATA_PTR;
  33
  34const char *weekdays[] = {
  35        "Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
  36};
  37
  38#ifdef CONFIG_RELOC_FIXUP_WORKS
  39#define RELOC(a)        a
  40#else
  41#define RELOC(a)        ((typeof(a))((unsigned long)(a) + gd->reloc_off))
  42#endif
  43
  44int mk_date (char *, struct rtc_time *);
  45
  46int do_date (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  47{
  48        struct rtc_time tm;
  49        int rcode = 0;
  50        int old_bus;
  51
  52        /* switch to correct I2C bus */
  53        old_bus = I2C_GET_BUS();
  54        I2C_SET_BUS(CONFIG_SYS_RTC_BUS_NUM);
  55
  56        switch (argc) {
  57        case 2:                 /* set date & time */
  58                if (strcmp(argv[1],"reset") == 0) {
  59                        puts ("Reset RTC...\n");
  60                        rtc_reset ();
  61                } else {
  62                        /* initialize tm with current time */
  63                        rcode = rtc_get (&tm);
  64
  65                        if(!rcode) {
  66                                /* insert new date & time */
  67                                if (mk_date (argv[1], &tm) != 0) {
  68                                        puts ("## Bad date format\n");
  69                                        break;
  70                                }
  71                                /* and write to RTC */
  72                                rcode = rtc_set (&tm);
  73                                if(rcode)
  74                                        puts("## Set date failed\n");
  75                        } else {
  76                                puts("## Get date failed\n");
  77                        }
  78                }
  79                /* FALL TROUGH */
  80        case 1:                 /* get date & time */
  81                rcode = rtc_get (&tm);
  82
  83                if (rcode) {
  84                        puts("## Get date failed\n");
  85                        break;
  86                }
  87
  88                printf ("Date: %4d-%02d-%02d (%sday)    Time: %2d:%02d:%02d\n",
  89                        tm.tm_year, tm.tm_mon, tm.tm_mday,
  90                        (tm.tm_wday<0 || tm.tm_wday>6) ?
  91                                "unknown " : RELOC(weekdays[tm.tm_wday]),
  92                        tm.tm_hour, tm.tm_min, tm.tm_sec);
  93
  94                break;
  95        default:
  96                cmd_usage(cmdtp);
  97                rcode = 1;
  98        }
  99
 100        /* switch back to original I2C bus */
 101        I2C_SET_BUS(old_bus);
 102
 103        return rcode;
 104}
 105
 106/*
 107 * simple conversion of two-digit string with error checking
 108 */
 109static int cnvrt2 (char *str, int *valp)
 110{
 111        int val;
 112
 113        if ((*str < '0') || (*str > '9'))
 114                return (-1);
 115
 116        val = *str - '0';
 117
 118        ++str;
 119
 120        if ((*str < '0') || (*str > '9'))
 121                return (-1);
 122
 123        *valp = 10 * val + (*str - '0');
 124
 125        return (0);
 126}
 127
 128/*
 129 * Convert date string: MMDDhhmm[[CC]YY][.ss]
 130 *
 131 * Some basic checking for valid values is done, but this will not catch
 132 * all possible error conditions.
 133 */
 134int mk_date (char *datestr, struct rtc_time *tmp)
 135{
 136        int len, val;
 137        char *ptr;
 138
 139        ptr = strchr (datestr,'.');
 140        len = strlen (datestr);
 141
 142        /* Set seconds */
 143        if (ptr) {
 144                int sec;
 145
 146                *ptr++ = '\0';
 147                if ((len - (ptr - datestr)) != 2)
 148                        return (-1);
 149
 150                len = strlen (datestr);
 151
 152                if (cnvrt2 (ptr, &sec))
 153                        return (-1);
 154
 155                tmp->tm_sec = sec;
 156        } else {
 157                tmp->tm_sec = 0;
 158        }
 159
 160        if (len == 12) {                /* MMDDhhmmCCYY */
 161                int year, century;
 162
 163                if (cnvrt2 (datestr+ 8, &century) ||
 164                    cnvrt2 (datestr+10, &year) ) {
 165                        return (-1);
 166                }
 167                tmp->tm_year = 100 * century + year;
 168        } else if (len == 10) {         /* MMDDhhmmYY   */
 169                int year, century;
 170
 171                century = tmp->tm_year / 100;
 172                if (cnvrt2 (datestr+ 8, &year))
 173                        return (-1);
 174                tmp->tm_year = 100 * century + year;
 175        }
 176
 177        switch (len) {
 178        case 8:                 /* MMDDhhmm     */
 179                /* fall thru */
 180        case 10:                /* MMDDhhmmYY   */
 181                /* fall thru */
 182        case 12:                /* MMDDhhmmCCYY */
 183                if (cnvrt2 (datestr+0, &val) ||
 184                    val > 12) {
 185                        break;
 186                }
 187                tmp->tm_mon  = val;
 188                if (cnvrt2 (datestr+2, &val) ||
 189                    val > ((tmp->tm_mon==2) ? 29 : 31)) {
 190                        break;
 191                }
 192                tmp->tm_mday = val;
 193
 194                if (cnvrt2 (datestr+4, &val) ||
 195                    val > 23) {
 196                        break;
 197                }
 198                tmp->tm_hour = val;
 199
 200                if (cnvrt2 (datestr+6, &val) ||
 201                    val > 59) {
 202                        break;
 203                }
 204                tmp->tm_min  = val;
 205
 206                /* calculate day of week */
 207                GregorianDay (tmp);
 208
 209                return (0);
 210        default:
 211                break;
 212        }
 213
 214        return (-1);
 215}
 216
 217/***************************************************/
 218
 219U_BOOT_CMD(
 220        date,   2,      1,      do_date,
 221        "get/set/reset date & time",
 222        "[MMDDhhmm[[CC]YY][.ss]]\ndate reset\n"
 223        "  - without arguments: print date & time\n"
 224        "  - with numeric argument: set the system date & time\n"
 225        "  - with 'reset' argument: reset the RTC"
 226);
 227