uboot/cmd/tpm_test.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2015 Google, Inc
   4 */
   5
   6#include <common.h>
   7#include <command.h>
   8#include <cpu_func.h>
   9#include <log.h>
  10#include <tpm-v1.h>
  11#include "tpm-user-utils.h"
  12#include <tpm_api.h>
  13
  14/* Prints error and returns on failure */
  15#define TPM_CHECK(tpm_command) do { \
  16        uint32_t result; \
  17        \
  18        result = (tpm_command); \
  19        if (result != TPM_SUCCESS) { \
  20                printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \
  21                        __LINE__, result); \
  22                return result; \
  23        } \
  24} while (0)
  25
  26#define INDEX0                  0xda70
  27#define INDEX1                  0xda71
  28#define INDEX2                  0xda72
  29#define INDEX3                  0xda73
  30#define INDEX_INITIALISED       0xda80
  31#define PHYS_PRESENCE           4
  32#define PRESENCE                8
  33
  34static uint32_t TlclStartupIfNeeded(struct udevice *dev)
  35{
  36        uint32_t result = tpm_startup(dev, TPM_ST_CLEAR);
  37
  38        return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result;
  39}
  40
  41static int test_timer(struct udevice *dev)
  42{
  43        printf("get_timer(0) = %lu\n", get_timer(0));
  44        return 0;
  45}
  46
  47static uint32_t tpm_get_flags(struct udevice *dev, uint8_t *disable,
  48                              uint8_t *deactivated, uint8_t *nvlocked)
  49{
  50        struct tpm_permanent_flags pflags;
  51        uint32_t result;
  52
  53        result = tpm1_get_permanent_flags(dev, &pflags);
  54        if (result)
  55                return result;
  56        if (disable)
  57                *disable = pflags.disable;
  58        if (deactivated)
  59                *deactivated = pflags.deactivated;
  60        if (nvlocked)
  61                *nvlocked = pflags.nv_locked;
  62        debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n",
  63              pflags.disable, pflags.deactivated, pflags.nv_locked);
  64
  65        return 0;
  66}
  67
  68static uint32_t tpm_nv_write_value_lock(struct udevice *dev, uint32_t index)
  69{
  70        debug("TPM: Write lock 0x%x\n", index);
  71
  72        return tpm_nv_write_value(dev, index, NULL, 0);
  73}
  74
  75static int tpm_is_owned(struct udevice *dev)
  76{
  77        uint8_t response[TPM_PUBEK_SIZE];
  78        uint32_t result;
  79
  80        result = tpm_read_pubek(dev, response, sizeof(response));
  81
  82        return result != TPM_SUCCESS;
  83}
  84
  85static int test_early_extend(struct udevice *dev)
  86{
  87        uint8_t value_in[20];
  88        uint8_t value_out[20];
  89
  90        printf("Testing earlyextend ...");
  91        tpm_init(dev);
  92        TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
  93        TPM_CHECK(tpm_continue_self_test(dev));
  94        TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, value_out));
  95        printf("done\n");
  96        return 0;
  97}
  98
  99static int test_early_nvram(struct udevice *dev)
 100{
 101        uint32_t x;
 102
 103        printf("Testing earlynvram ...");
 104        tpm_init(dev);
 105        TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
 106        TPM_CHECK(tpm_continue_self_test(dev));
 107        TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
 108        TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
 109        printf("done\n");
 110        return 0;
 111}
 112
 113static int test_early_nvram2(struct udevice *dev)
 114{
 115        uint32_t x;
 116
 117        printf("Testing earlynvram2 ...");
 118        tpm_init(dev);
 119        TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
 120        TPM_CHECK(tpm_continue_self_test(dev));
 121        TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
 122        TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
 123        printf("done\n");
 124        return 0;
 125}
 126
 127static int test_enable(struct udevice *dev)
 128{
 129        uint8_t disable = 0, deactivated = 0;
 130
 131        printf("Testing enable ...\n");
 132        tpm_init(dev);
 133        TPM_CHECK(TlclStartupIfNeeded(dev));
 134        TPM_CHECK(tpm_self_test_full(dev));
 135        TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
 136        TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
 137        printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
 138        TPM_CHECK(tpm_physical_enable(dev));
 139        TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
 140        TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
 141        printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
 142        if (disable == 1 || deactivated == 1)
 143                printf("\tfailed to enable or activate\n");
 144        printf("\tdone\n");
 145        return 0;
 146}
 147
 148#define reboot() do { \
 149        printf("\trebooting...\n"); \
 150        reset_cpu(); \
 151} while (0)
 152
 153static int test_fast_enable(struct udevice *dev)
 154{
 155        uint8_t disable = 0, deactivated = 0;
 156        int i;
 157
 158        printf("Testing fastenable ...\n");
 159        tpm_init(dev);
 160        TPM_CHECK(TlclStartupIfNeeded(dev));
 161        TPM_CHECK(tpm_self_test_full(dev));
 162        TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
 163        TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
 164        printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
 165        for (i = 0; i < 2; i++) {
 166                TPM_CHECK(tpm_force_clear(dev));
 167                TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
 168                printf("\tdisable is %d, deactivated is %d\n", disable,
 169                       deactivated);
 170                assert(disable == 1 && deactivated == 1);
 171                TPM_CHECK(tpm_physical_enable(dev));
 172                TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
 173                TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
 174                printf("\tdisable is %d, deactivated is %d\n", disable,
 175                       deactivated);
 176                assert(disable == 0 && deactivated == 0);
 177        }
 178        printf("\tdone\n");
 179        return 0;
 180}
 181
 182static int test_global_lock(struct udevice *dev)
 183{
 184        uint32_t zero = 0;
 185        uint32_t result;
 186        uint32_t x;
 187
 188        printf("Testing globallock ...\n");
 189        tpm_init(dev);
 190        TPM_CHECK(TlclStartupIfNeeded(dev));
 191        TPM_CHECK(tpm_self_test_full(dev));
 192        TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
 193        TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
 194        TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero,
 195                                     sizeof(uint32_t)));
 196        TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
 197        TPM_CHECK(tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero,
 198                                     sizeof(uint32_t)));
 199        TPM_CHECK(tpm_set_global_lock(dev));
 200        /* Verifies that write to index0 fails */
 201        x = 1;
 202        result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x));
 203        assert(result == TPM_AREA_LOCKED);
 204        TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
 205        assert(x == 0);
 206        /* Verifies that write to index1 is still possible */
 207        x = 2;
 208        TPM_CHECK(tpm_nv_write_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
 209        TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
 210        assert(x == 2);
 211        /* Turns off PP */
 212        tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
 213        /* Verifies that write to index1 fails */
 214        x = 3;
 215        result = tpm_nv_write_value(dev, INDEX1, (uint8_t *)&x, sizeof(x));
 216        assert(result == TPM_BAD_PRESENCE);
 217        TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
 218        assert(x == 2);
 219        printf("\tdone\n");
 220        return 0;
 221}
 222
 223static int test_lock(struct udevice *dev)
 224{
 225        printf("Testing lock ...\n");
 226        tpm_init(dev);
 227        tpm_startup(dev, TPM_ST_CLEAR);
 228        tpm_self_test_full(dev);
 229        tpm_tsc_physical_presence(dev, PRESENCE);
 230        tpm_nv_write_value_lock(dev, INDEX0);
 231        printf("\tLocked 0x%x\n", INDEX0);
 232        printf("\tdone\n");
 233        return 0;
 234}
 235
 236static void initialise_spaces(struct udevice *dev)
 237{
 238        uint32_t zero = 0;
 239        uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
 240
 241        printf("\tInitialising spaces\n");
 242        tpm1_nv_set_locked(dev);  /* useful only the first time */
 243        tpm1_nv_define_space(dev, INDEX0, perm, 4);
 244        tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero, 4);
 245        tpm1_nv_define_space(dev, INDEX1, perm, 4);
 246        tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero, 4);
 247        tpm1_nv_define_space(dev, INDEX2, perm, 4);
 248        tpm_nv_write_value(dev, INDEX2, (uint8_t *)&zero, 4);
 249        tpm1_nv_define_space(dev, INDEX3, perm, 4);
 250        tpm_nv_write_value(dev, INDEX3, (uint8_t *)&zero, 4);
 251        perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
 252                TPM_NV_PER_PPWRITE;
 253        tpm1_nv_define_space(dev, INDEX_INITIALISED, perm, 1);
 254}
 255
 256static int test_readonly(struct udevice *dev)
 257{
 258        uint8_t c;
 259        uint32_t index_0, index_1, index_2, index_3;
 260        int read0, read1, read2, read3;
 261
 262        printf("Testing readonly ...\n");
 263        tpm_init(dev);
 264        tpm_startup(dev, TPM_ST_CLEAR);
 265        tpm_self_test_full(dev);
 266        tpm_tsc_physical_presence(dev, PRESENCE);
 267        /*
 268         * Checks if initialisation has completed by trying to read-lock a
 269         * space that's created at the end of initialisation
 270         */
 271        if (tpm_nv_read_value(dev, INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
 272                /* The initialisation did not complete */
 273                initialise_spaces(dev);
 274        }
 275
 276        /* Checks if spaces are OK or messed up */
 277        read0 = tpm_nv_read_value(dev, INDEX0, (uint8_t *)&index_0,
 278                                  sizeof(index_0));
 279        read1 = tpm_nv_read_value(dev, INDEX1, (uint8_t *)&index_1,
 280                                  sizeof(index_1));
 281        read2 = tpm_nv_read_value(dev, INDEX2, (uint8_t *)&index_2,
 282                                  sizeof(index_2));
 283        read3 = tpm_nv_read_value(dev, INDEX3, (uint8_t *)&index_3,
 284                                  sizeof(index_3));
 285        if (read0 || read1 || read2 || read3) {
 286                printf("Invalid contents\n");
 287                return 0;
 288        }
 289
 290        /*
 291         * Writes space, and locks it.  Then attempts to write again.
 292         * I really wish I could use the imperative.
 293         */
 294        index_0 += 1;
 295        if (tpm_nv_write_value(dev, INDEX0, (uint8_t *)&index_0,
 296                               sizeof(index_0) !=
 297                TPM_SUCCESS)) {
 298                pr_err("\tcould not write index 0\n");
 299        }
 300        tpm_nv_write_value_lock(dev, INDEX0);
 301        if (tpm_nv_write_value(dev, INDEX0, (uint8_t *)&index_0,
 302                               sizeof(index_0)) ==
 303                        TPM_SUCCESS)
 304                pr_err("\tindex 0 is not locked\n");
 305
 306        printf("\tdone\n");
 307        return 0;
 308}
 309
 310static int test_redefine_unowned(struct udevice *dev)
 311{
 312        uint32_t perm;
 313        uint32_t result;
 314        uint32_t x;
 315
 316        printf("Testing redefine_unowned ...");
 317        tpm_init(dev);
 318        TPM_CHECK(TlclStartupIfNeeded(dev));
 319        TPM_CHECK(tpm_self_test_full(dev));
 320        TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
 321        assert(!tpm_is_owned(dev));
 322
 323        /* Ensures spaces exist. */
 324        TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
 325        TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
 326
 327        /* Redefines spaces a couple of times. */
 328        perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
 329        TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm,
 330                                       2 * sizeof(uint32_t)));
 331        TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)));
 332        perm = TPM_NV_PER_PPWRITE;
 333        TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm,
 334                                       2 * sizeof(uint32_t)));
 335        TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
 336
 337        /* Sets the global lock */
 338        tpm_set_global_lock(dev);
 339
 340        /* Verifies that index0 cannot be redefined */
 341        result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
 342        assert(result == TPM_AREA_LOCKED);
 343
 344        /* Checks that index1 can */
 345        TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm,
 346                                       2 * sizeof(uint32_t)));
 347        TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
 348
 349        /* Turns off PP */
 350        tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
 351
 352        /* Verifies that neither index0 nor index1 can be redefined */
 353        result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
 354        assert(result == TPM_BAD_PRESENCE);
 355        result = tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t));
 356        assert(result == TPM_BAD_PRESENCE);
 357
 358        printf("done\n");
 359        return 0;
 360}
 361
 362#define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK)
 363#define PERMPP TPM_NV_PER_PPWRITE
 364
 365static int test_space_perm(struct udevice *dev)
 366{
 367        uint32_t perm;
 368
 369        printf("Testing spaceperm ...");
 370        tpm_init(dev);
 371        TPM_CHECK(TlclStartupIfNeeded(dev));
 372        TPM_CHECK(tpm_continue_self_test(dev));
 373        TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
 374        TPM_CHECK(tpm_get_permissions(dev, INDEX0, &perm));
 375        assert((perm & PERMPPGL) == PERMPPGL);
 376        TPM_CHECK(tpm_get_permissions(dev, INDEX1, &perm));
 377        assert((perm & PERMPP) == PERMPP);
 378        printf("done\n");
 379        return 0;
 380}
 381
 382static int test_startup(struct udevice *dev)
 383{
 384        uint32_t result;
 385
 386        printf("Testing startup ...\n");
 387
 388        tpm_init(dev);
 389        result = tpm_startup(dev, TPM_ST_CLEAR);
 390        if (result != 0 && result != TPM_INVALID_POSTINIT)
 391                printf("\ttpm startup failed with 0x%x\n", result);
 392        result = tpm_get_flags(dev, NULL, NULL, NULL);
 393        if (result != 0)
 394                printf("\ttpm getflags failed with 0x%x\n", result);
 395        printf("\texecuting SelfTestFull\n");
 396        tpm_self_test_full(dev);
 397        result = tpm_get_flags(dev, NULL, NULL, NULL);
 398        if (result != 0)
 399                printf("\ttpm getflags failed with 0x%x\n", result);
 400        printf("\tdone\n");
 401        return 0;
 402}
 403
 404/*
 405 * Runs [op] and ensures it returns success and doesn't run longer than
 406 * [time_limit] in milliseconds.
 407 */
 408#define TTPM_CHECK(op, time_limit) do { \
 409        ulong start, time; \
 410        uint32_t __result; \
 411        \
 412        start = get_timer(0); \
 413        __result = op; \
 414        if (__result != TPM_SUCCESS) { \
 415                printf("\t" #op ": error 0x%x\n", __result); \
 416                return -1; \
 417        } \
 418        time = get_timer(start); \
 419        printf("\t" #op ": %lu ms\n", time); \
 420        if (time > (ulong)time_limit) { \
 421                printf("\t" #op " exceeded " #time_limit " ms\n"); \
 422        } \
 423} while (0)
 424
 425
 426static int test_timing(struct udevice *dev)
 427{
 428        uint8_t in[20], out[20];
 429        uint32_t x;
 430
 431        printf("Testing timing ...");
 432        tpm_init(dev);
 433        TTPM_CHECK(TlclStartupIfNeeded(dev), 50);
 434        TTPM_CHECK(tpm_continue_self_test(dev), 100);
 435        TTPM_CHECK(tpm_self_test_full(dev), 1000);
 436        TTPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE), 100);
 437        TTPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
 438                   100);
 439        TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
 440                   100);
 441        TTPM_CHECK(tpm_pcr_extend(dev, 0, in, out), 200);
 442        TTPM_CHECK(tpm_set_global_lock(dev), 50);
 443        TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
 444        printf("done\n");
 445        return 0;
 446}
 447
 448#define TPM_MAX_NV_WRITES_NOOWNER 64
 449
 450static int test_write_limit(struct udevice *dev)
 451{
 452        uint32_t result;
 453        int i;
 454
 455        printf("Testing writelimit ...\n");
 456        tpm_init(dev);
 457        TPM_CHECK(TlclStartupIfNeeded(dev));
 458        TPM_CHECK(tpm_self_test_full(dev));
 459        TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
 460        TPM_CHECK(tpm_force_clear(dev));
 461        TPM_CHECK(tpm_physical_enable(dev));
 462        TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
 463
 464        for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
 465                printf("\twriting %d\n", i);
 466                result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i,
 467                                            sizeof(i));
 468                switch (result) {
 469                case TPM_SUCCESS:
 470                        break;
 471                case TPM_MAXNVWRITES:
 472                        assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
 473                default:
 474                        pr_err("\tunexpected error code %d (0x%x)\n",
 475                              result, result);
 476                }
 477        }
 478
 479        /* Reset write count */
 480        TPM_CHECK(tpm_force_clear(dev));
 481        TPM_CHECK(tpm_physical_enable(dev));
 482        TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
 483
 484        /* Try writing again. */
 485        TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i, sizeof(i)));
 486        printf("\tdone\n");
 487        return 0;
 488}
 489
 490#define VOIDTEST(XFUNC) \
 491        int do_test_##XFUNC(struct cmd_tbl *cmd_tbl, int flag, int argc, \
 492        char *const argv[]) \
 493        { \
 494                struct udevice *dev; \
 495                int ret; \
 496\
 497                ret = get_tpm(&dev); \
 498                if (ret) \
 499                        return ret; \
 500                return test_##XFUNC(dev); \
 501        }
 502
 503#define VOIDENT(XNAME) \
 504        U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""),
 505
 506VOIDTEST(early_extend)
 507VOIDTEST(early_nvram)
 508VOIDTEST(early_nvram2)
 509VOIDTEST(enable)
 510VOIDTEST(fast_enable)
 511VOIDTEST(global_lock)
 512VOIDTEST(lock)
 513VOIDTEST(readonly)
 514VOIDTEST(redefine_unowned)
 515VOIDTEST(space_perm)
 516VOIDTEST(startup)
 517VOIDTEST(timing)
 518VOIDTEST(write_limit)
 519VOIDTEST(timer)
 520
 521static struct cmd_tbl cmd_cros_tpm_sub[] = {
 522        VOIDENT(early_extend)
 523        VOIDENT(early_nvram)
 524        VOIDENT(early_nvram2)
 525        VOIDENT(enable)
 526        VOIDENT(fast_enable)
 527        VOIDENT(global_lock)
 528        VOIDENT(lock)
 529        VOIDENT(readonly)
 530        VOIDENT(redefine_unowned)
 531        VOIDENT(space_perm)
 532        VOIDENT(startup)
 533        VOIDENT(timing)
 534        VOIDENT(write_limit)
 535        VOIDENT(timer)
 536};
 537
 538static int do_tpmtest(struct cmd_tbl *cmdtp, int flag, int argc,
 539                      char *const argv[])
 540{
 541        struct cmd_tbl *c;
 542        int i;
 543
 544        printf("argc = %d, argv = ", argc);
 545
 546        for (i = 0; i < argc; i++)
 547                printf(" %s", argv[i]);
 548
 549        printf("\n------\n");
 550
 551        argc--;
 552        argv++;
 553        c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
 554                         ARRAY_SIZE(cmd_cros_tpm_sub));
 555        return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp);
 556}
 557
 558U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests",
 559        "\n\tearly_extend\n"
 560        "\tearly_nvram\n"
 561        "\tearly_nvram2\n"
 562        "\tenable\n"
 563        "\tfast_enable\n"
 564        "\tglobal_lock\n"
 565        "\tlock\n"
 566        "\treadonly\n"
 567        "\tredefine_unowned\n"
 568        "\tspace_perm\n"
 569        "\tstartup\n"
 570        "\ttiming\n"
 571        "\twrite_limit\n");
 572