~vcs-imports/busybox/trunk

« back to all changes in this revision

Viewing changes to util-linux/hwclock.c

  • Committer: Denys Vlasenko
  • Author(s): Andrej Picej
  • Date: 2023-07-12 14:27:49 UTC
  • Revision ID: git-v1:d70256a5c719439cc6fab6a4571c1bb46178e4c7
hwclock: add get/set parameters option

In kernel 5.16 special ioctls were introduced to get/set RTC parameters.
Add option to get/set parameters into busybox version of hwclock.
Implementation is similar to the one already used in linux-utils hwclock
tool.

Example of parameter get use:
$ hwclock -g 2
The RTC parameter 0x2 is set to 0x2.
$ hwclock --param-get bsm
The RTC parameter 0x2 is set to 0x2.

Example of parameter set use:
$ hwclock -p 2=1
The RTC parameter 0x2 will be set to 0x1.
$ hwclock -p bsm=2
The RTC parameter 0x2 will be set to 0x2.

function                                             old     new   delta
hwclock_main                                         298     576    +278
.rodata                                           105231  105400    +169
packed_usage                                       34541   34576     +35
static.hwclock_longopts                               60      84     +24
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 506/0)             Total: 506 bytes

Signed-off-by: Andrej Picej <andrej.picej@norik.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
320
320
                close(rtc);
321
321
}
322
322
 
 
323
static uint64_t resolve_rtc_param_alias(const char *alias)
 
324
{
 
325
        int n;
 
326
 
 
327
        BUILD_BUG_ON(RTC_PARAM_FEATURES != 0
 
328
                || RTC_PARAM_CORRECTION != 1
 
329
                || RTC_PARAM_BACKUP_SWITCH_MODE != 2
 
330
        );
 
331
        n = index_in_strings(
 
332
                "features"   "\0"
 
333
                "correction" "\0"
 
334
                "bsm"        "\0"
 
335
                , alias);
 
336
        if (n >= 0)
 
337
                return n;
 
338
        return xstrtoull(alias, 0);
 
339
}
 
340
 
 
341
static void get_rtc_param(const char **pp_rtcname, const char *rtc_param)
 
342
{
 
343
        int rtc;
 
344
        struct rtc_param param;
 
345
 
 
346
        param.param = resolve_rtc_param_alias(rtc_param);
 
347
 
 
348
        rtc = rtc_xopen(pp_rtcname, O_RDONLY);
 
349
 
 
350
        xioctl(rtc, RTC_PARAM_GET, &param);
 
351
 
 
352
        printf("The RTC parameter 0x%llx is set to 0x%llx.\n",
 
353
                (unsigned long long) param.param, (unsigned long long) param.uvalue);
 
354
 
 
355
        if (ENABLE_FEATURE_CLEAN_UP)
 
356
                close(rtc);
 
357
}
 
358
 
 
359
static void set_rtc_param(const char **pp_rtcname, char *rtc_param)
 
360
{
 
361
        int rtc;
 
362
        struct rtc_param param;
 
363
        char *eq;
 
364
 
 
365
        /* handle param name */
 
366
        eq = strchr(rtc_param, '=');
 
367
        if (!eq)
 
368
                bb_error_msg_and_die("expected <param>=<value>");
 
369
        *eq = '\0';
 
370
        param.param = resolve_rtc_param_alias(rtc_param);
 
371
        *eq = '=';
 
372
 
 
373
        /* handle param value */
 
374
        param.uvalue = xstrtoull(eq + 1, 0);
 
375
 
 
376
        rtc = rtc_xopen(pp_rtcname, O_WRONLY);
 
377
 
 
378
        printf("The RTC parameter 0x%llx will be set to 0x%llx.\n",
 
379
                (unsigned long long) param.param, (unsigned long long) param.uvalue);
 
380
 
 
381
        xioctl(rtc, RTC_PARAM_SET, &param);
 
382
 
 
383
        if (ENABLE_FEATURE_CLEAN_UP)
 
384
                close(rtc);
 
385
}
 
386
 
323
387
// hwclock from util-linux 2.36.1
324
388
// hwclock [function] [option...]
325
389
//Functions:
346
410
 
347
411
//usage:#define hwclock_trivial_usage
348
412
//usage:        IF_LONG_OPTS(
349
 
//usage:       "[-swul] [--systz] [-f DEV]"
 
413
//usage:       "[-swul] [--systz] [--param-get PARAM] [--param-set PARAM=VAL] [-f DEV]"
350
414
//usage:        )
351
415
//usage:        IF_NOT_LONG_OPTS(
352
 
//usage:       "[-swult] [-f DEV]"
 
416
//usage:       "[-swult] [-g PARAM] [-p PARAM=VAL] [-f DEV]"
353
417
//usage:        )
354
418
//usage:#define hwclock_full_usage "\n\n"
355
419
//usage:       "Show or set hardware clock (RTC)\n"
360
424
//usage:        IF_LONG_OPTS(
361
425
//usage:     "\n        --systz Set in-kernel timezone, correct system time"
362
426
//usage:     "\n                if RTC is kept in local time"
 
427
//usage:     "\n        --param-get PARAM       Get RTC parameter"
 
428
//usage:     "\n        --param-set PARAM=VAL   Set RTC parameter"
363
429
//usage:        )
364
430
//usage:     "\n        -f DEV  Use specified device (e.g. /dev/rtc2)"
365
431
//usage:     "\n        -u      Assume RTC is kept in UTC"
375
441
#define HWCLOCK_OPT_SYSTOHC     0x10
376
442
#define HWCLOCK_OPT_SYSTZ       0x20
377
443
#define HWCLOCK_OPT_RTCFILE     0x40
 
444
#define HWCLOCK_OPT_PARAM_GET   0x80
 
445
#define HWCLOCK_OPT_PARAM_SET   0x100
378
446
 
379
447
int hwclock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
380
448
int hwclock_main(int argc UNUSED_PARAM, char **argv)
381
449
{
382
450
        const char *rtcname = NULL;
 
451
        char *param;
383
452
        unsigned opt;
384
453
        int utc;
385
454
#if ENABLE_LONG_OPTS
391
460
                "systohc\0"   No_argument "w"
392
461
                "systz\0"     No_argument "t" /* short opt is non-standard */
393
462
                "rtc\0"       Required_argument "f"
 
463
                "param-get\0" Required_argument "g"  /* short opt is non-standard */
 
464
                "param-set\0" Required_argument "p"  /* short opt is non-standard */
394
465
                ;
395
466
#endif
396
467
        opt = getopt32long(argv,
397
 
                "^""lurswtf:v" /* -v is accepted and ignored */
 
468
                "^""lurswtf:g:p:v" /* -v is accepted and ignored */
398
469
                "\0"
399
 
                "r--wst:w--rst:s--wrt:t--rsw:l--u:u--l",
 
470
                "r--wstgp:w--rstgp:s--wrtgp:t--rswgp:g--rswtp:p--rswtg:l--u:u--l",
400
471
                hwclock_longopts,
401
 
                &rtcname
 
472
                &rtcname,
 
473
                &param,
 
474
                &param
402
475
        );
403
476
 
404
477
        /* If -u or -l wasn't given, check if we are using utc */
413
486
                from_sys_clock(&rtcname, utc);
414
487
        else if (opt & HWCLOCK_OPT_SYSTZ)
415
488
                set_kernel_timezone_and_clock(utc, NULL);
 
489
        else if (opt & HWCLOCK_OPT_PARAM_GET)
 
490
                get_rtc_param(&rtcname, param);
 
491
        else if (opt & HWCLOCK_OPT_PARAM_SET)
 
492
                set_rtc_param(&rtcname, param);
416
493
        else
417
494
                /* default HWCLOCK_OPT_SHOW */
418
495
                show_clock(&rtcname, utc);