uboot/test/overlay/cmd_ut_overlay.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016 NextThing Co
   3 * Copyright (c) 2016 Free Electrons
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <command.h>
  10#include <errno.h>
  11#include <malloc.h>
  12
  13#include <linux/sizes.h>
  14
  15#include <test/ut.h>
  16#include <test/overlay.h>
  17
  18/* 4k ought to be enough for anybody */
  19#define FDT_COPY_SIZE   (4 * SZ_1K)
  20
  21extern u32 __dtb_test_fdt_base_begin;
  22extern u32 __dtb_test_fdt_overlay_begin;
  23
  24static int fdt_getprop_u32_by_index(void *fdt, const char *path,
  25                                    const char *name, int index,
  26                                    u32 *out)
  27{
  28        const fdt32_t *val;
  29        int node_off;
  30        int len;
  31
  32        node_off = fdt_path_offset(fdt, path);
  33        if (node_off < 0)
  34                return node_off;
  35
  36        val = fdt_getprop(fdt, node_off, name, &len);
  37        if (!val || (len < (sizeof(uint32_t) * (index + 1))))
  38                return -FDT_ERR_NOTFOUND;
  39
  40        *out = fdt32_to_cpu(*(val + index));
  41
  42        return 0;
  43}
  44
  45static int fdt_getprop_u32(void *fdt, const char *path, const char *name,
  46                           u32 *out)
  47{
  48        return fdt_getprop_u32_by_index(fdt, path, name, 0, out);
  49}
  50
  51static int fdt_getprop_str(void *fdt, const char *path, const char *name,
  52                           const char **out)
  53{
  54        int node_off;
  55        int len;
  56
  57        node_off = fdt_path_offset(fdt, path);
  58        if (node_off < 0)
  59                return node_off;
  60
  61        *out = fdt_stringlist_get(fdt, node_off, name, 0, &len);
  62
  63        return len < 0 ? len : 0;
  64}
  65
  66static int fdt_overlay_change_int_property(struct unit_test_state *uts)
  67{
  68        void *fdt = uts->priv;
  69        u32 val = 0;
  70
  71        ut_assertok(fdt_getprop_u32(fdt, "/test-node", "test-int-property",
  72                                    &val));
  73        ut_asserteq(43, val);
  74
  75        return CMD_RET_SUCCESS;
  76}
  77OVERLAY_TEST(fdt_overlay_change_int_property, 0);
  78
  79static int fdt_overlay_change_str_property(struct unit_test_state *uts)
  80{
  81        void *fdt = uts->priv;
  82        const char *val = NULL;
  83
  84        ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property",
  85                                    &val));
  86        ut_asserteq_str("foobar", val);
  87
  88        return CMD_RET_SUCCESS;
  89}
  90OVERLAY_TEST(fdt_overlay_change_str_property, 0);
  91
  92static int fdt_overlay_add_str_property(struct unit_test_state *uts)
  93{
  94        void *fdt = uts->priv;
  95        const char *val = NULL;
  96
  97        ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property-2",
  98                                    &val));
  99        ut_asserteq_str("foobar2", val);
 100
 101        return CMD_RET_SUCCESS;
 102}
 103OVERLAY_TEST(fdt_overlay_add_str_property, 0);
 104
 105static int fdt_overlay_add_node_by_phandle(struct unit_test_state *uts)
 106{
 107        void *fdt = uts->priv;
 108        int off;
 109
 110        off = fdt_path_offset(fdt, "/test-node/new-node");
 111        ut_assert(off >= 0);
 112
 113        ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
 114
 115        return CMD_RET_SUCCESS;
 116}
 117OVERLAY_TEST(fdt_overlay_add_node_by_phandle, 0);
 118
 119static int fdt_overlay_add_node_by_path(struct unit_test_state *uts)
 120{
 121        void *fdt = uts->priv;
 122        int off;
 123
 124        off = fdt_path_offset(fdt, "/new-node");
 125        ut_assert(off >= 0);
 126
 127        ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
 128
 129        return CMD_RET_SUCCESS;
 130}
 131OVERLAY_TEST(fdt_overlay_add_node_by_path, 0);
 132
 133static int fdt_overlay_add_subnode_property(struct unit_test_state *uts)
 134{
 135        void *fdt = uts->priv;
 136        int off;
 137
 138        off = fdt_path_offset(fdt, "/test-node/sub-test-node");
 139        ut_assert(off >= 0);
 140
 141        ut_assertnonnull(fdt_getprop(fdt, off, "sub-test-property", NULL));
 142        ut_assertnonnull(fdt_getprop(fdt, off, "new-sub-test-property", NULL));
 143
 144        return CMD_RET_SUCCESS;
 145}
 146OVERLAY_TEST(fdt_overlay_add_subnode_property, 0);
 147
 148static int fdt_overlay_local_phandle(struct unit_test_state *uts)
 149{
 150        uint32_t local_phandle;
 151        void *fdt = uts->priv;
 152        u32 val = 0;
 153        int off;
 154
 155        off = fdt_path_offset(fdt, "/new-local-node");
 156        ut_assert(off >= 0);
 157
 158        local_phandle = fdt_get_phandle(fdt, off);
 159        ut_assert(local_phandle);
 160
 161        ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle",
 162                                             0, &val));
 163        ut_asserteq(local_phandle, val);
 164
 165        ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle",
 166                                             1, &val));
 167        ut_asserteq(local_phandle, val);
 168
 169        return CMD_RET_SUCCESS;
 170}
 171OVERLAY_TEST(fdt_overlay_local_phandle, 0);
 172
 173static int fdt_overlay_local_phandles(struct unit_test_state *uts)
 174{
 175        uint32_t local_phandle, test_phandle;
 176        void *fdt = uts->priv;
 177        u32 val = 0;
 178        int off;
 179
 180        off = fdt_path_offset(fdt, "/new-local-node");
 181        ut_assert(off >= 0);
 182
 183        local_phandle = fdt_get_phandle(fdt, off);
 184        ut_assert(local_phandle);
 185
 186        off = fdt_path_offset(fdt, "/test-node");
 187        ut_assert(off >= 0);
 188
 189        test_phandle = fdt_get_phandle(fdt, off);
 190        ut_assert(test_phandle);
 191
 192        ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 0,
 193                                             &val));
 194        ut_asserteq(test_phandle, val);
 195
 196        ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 1,
 197                                             &val));
 198        ut_asserteq(local_phandle, val);
 199
 200        return CMD_RET_SUCCESS;
 201}
 202OVERLAY_TEST(fdt_overlay_local_phandles, 0);
 203
 204int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 205{
 206        struct unit_test *tests = ll_entry_start(struct unit_test,
 207                                                 overlay_test);
 208        const int n_ents = ll_entry_count(struct unit_test, overlay_test);
 209        struct unit_test_state *uts;
 210        struct unit_test *test;
 211        void *fdt_base = &__dtb_test_fdt_base_begin;
 212        void *fdt_overlay = &__dtb_test_fdt_overlay_begin;
 213        void *fdt_base_copy, *fdt_overlay_copy;
 214
 215        uts = calloc(1, sizeof(*uts));
 216        if (!uts)
 217                return -ENOMEM;
 218
 219        ut_assertok(fdt_check_header(fdt_base));
 220        ut_assertok(fdt_check_header(fdt_overlay));
 221
 222        fdt_base_copy = malloc(FDT_COPY_SIZE);
 223        if (!fdt_base_copy)
 224                return -ENOMEM;
 225        uts->priv = fdt_base_copy;
 226
 227        fdt_overlay_copy = malloc(FDT_COPY_SIZE);
 228        if (!fdt_overlay_copy)
 229                return -ENOMEM;
 230
 231        /*
 232         * Resize the FDT to 4k so that we have room to operate on
 233         *
 234         * (and relocate it since the memory might be mapped
 235         * read-only)
 236         */
 237        ut_assertok(fdt_open_into(fdt_base, fdt_base_copy, FDT_COPY_SIZE));
 238
 239        /*
 240         * Resize the overlay to 4k so that we have room to operate on
 241         *
 242         * (and relocate it since the memory might be mapped
 243         * read-only)
 244         */
 245        ut_assertok(fdt_open_into(fdt_overlay, fdt_overlay_copy,
 246                                  FDT_COPY_SIZE));
 247
 248        /* Apply the overlay */
 249        ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_copy));
 250
 251        if (argc == 1)
 252                printf("Running %d environment tests\n", n_ents);
 253
 254        for (test = tests; test < tests + n_ents; test++) {
 255                if (argc > 1 && strcmp(argv[1], test->name))
 256                        continue;
 257                printf("Test: %s\n", test->name);
 258
 259                uts->start = mallinfo();
 260
 261                test->func(uts);
 262        }
 263
 264        printf("Failures: %d\n", uts->fail_count);
 265
 266        free(fdt_overlay_copy);
 267        free(fdt_base_copy);
 268        free(uts);
 269
 270        return uts->fail_count ? CMD_RET_FAILURE : 0;
 271}
 272