Quentin Schulz | 1e1a92b | 2024-01-17 18:59:10 +0100 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* |
| 3 | * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH |
| 4 | */ |
| 5 | |
| 6 | #include <dm.h> |
| 7 | #include <env.h> |
| 8 | #include <env_internal.h> |
| 9 | #include <dm/uclass-internal.h> |
| 10 | |
| 11 | /* |
| 12 | * Swap mmc0 and mmc1 in boot_targets if booted from SD-Card. |
| 13 | * |
| 14 | * If bootsource is uSD-card we can assume that we want to use the |
| 15 | * SD-Card instead of the eMMC as first boot_target for distroboot. |
| 16 | * We only want to swap the defaults and not any custom environment a |
| 17 | * user has set. We exit early if a changed boot_targets environment |
| 18 | * is detected. |
| 19 | */ |
| 20 | int setup_boottargets(void) |
| 21 | { |
| 22 | const char *boot_device = |
| 23 | ofnode_read_chosen_string("u-boot,spl-boot-device"); |
| 24 | char *env_default, *env; |
| 25 | |
| 26 | if (!boot_device) { |
| 27 | debug("%s: /chosen/u-boot,spl-boot-device not set\n", |
| 28 | __func__); |
| 29 | return -1; |
| 30 | } |
| 31 | debug("%s: booted from %s\n", __func__, boot_device); |
| 32 | |
| 33 | env_default = env_get_default("boot_targets"); |
| 34 | env = env_get("boot_targets"); |
| 35 | if (!env) { |
| 36 | debug("%s: boot_targets does not exist\n", __func__); |
| 37 | return -1; |
| 38 | } |
| 39 | debug("%s: boot_targets current: %s - default: %s\n", |
| 40 | __func__, env, env_default); |
| 41 | |
| 42 | if (strcmp(env_default, env) != 0) { |
| 43 | debug("%s: boot_targets not default, don't change it\n", |
| 44 | __func__); |
| 45 | return 0; |
| 46 | } |
| 47 | |
| 48 | /* |
| 49 | * Make the default boot medium between SD Card and eMMC, the one that |
| 50 | * was used to load U-Boot proper. If SPI-NOR flash was used, keep |
| 51 | * original default order. |
| 52 | */ |
| 53 | struct udevice *devp; |
| 54 | |
| 55 | if (uclass_find_device_by_ofnode(UCLASS_MMC, ofnode_path(boot_device), &devp)) { |
| 56 | debug("%s: not reordering boot_targets, bootdev %s != MMC\n", |
| 57 | __func__, boot_device); |
| 58 | return 0; |
| 59 | } |
| 60 | |
| 61 | char *mmc0, *mmc1; |
| 62 | |
| 63 | mmc0 = strstr(env, "mmc0"); |
| 64 | mmc1 = strstr(env, "mmc1"); |
| 65 | |
| 66 | if (!mmc0 || !mmc1) { |
| 67 | debug("%s: only one mmc boot_target found\n", __func__); |
| 68 | return -1; |
| 69 | } |
| 70 | |
| 71 | /* |
| 72 | * If mmc0 comes first in the boot order and U-Boot proper was |
| 73 | * loaded from mmc1, swap mmc0 and mmc1 in the list. |
| 74 | * If mmc1 comes first in the boot order and U-Boot proper was |
| 75 | * loaded from mmc0, swap mmc0 and mmc1 in the list. |
| 76 | */ |
| 77 | if ((mmc0 < mmc1 && devp->seq_ == 1) || |
| 78 | (mmc0 > mmc1 && devp->seq_ == 0)) { |
| 79 | mmc0[3] = '1'; |
| 80 | mmc1[3] = '0'; |
| 81 | debug("%s: set boot_targets to: %s\n", __func__, env); |
| 82 | env_set("boot_targets", env); |
| 83 | } |
| 84 | |
| 85 | return 0; |
| 86 | } |
| 87 | |
| 88 | int mmc_get_env_dev(void) |
| 89 | { |
| 90 | const char *boot_device = |
| 91 | ofnode_read_chosen_string("u-boot,spl-boot-device"); |
| 92 | struct udevice *devp; |
| 93 | |
| 94 | if (!boot_device) { |
| 95 | debug("%s: /chosen/u-boot,spl-boot-device not set\n", |
| 96 | __func__); |
| 97 | #ifdef CONFIG_SYS_MMC_ENV_DEV |
| 98 | return CONFIG_SYS_MMC_ENV_DEV; |
| 99 | #else |
| 100 | return 0; |
| 101 | #endif |
| 102 | } |
| 103 | |
| 104 | debug("%s: booted from %s\n", __func__, boot_device); |
| 105 | |
| 106 | if (uclass_find_device_by_ofnode(UCLASS_MMC, ofnode_path(boot_device), &devp)) |
| 107 | #ifdef CONFIG_SYS_MMC_ENV_DEV |
| 108 | return CONFIG_SYS_MMC_ENV_DEV; |
| 109 | #else |
| 110 | return 0; |
| 111 | #endif |
| 112 | |
| 113 | debug("%s: get MMC ENV from mmc%d\n", __func__, devp->seq_); |
| 114 | |
| 115 | return devp->seq_; |
| 116 | } |
| 117 | |
| 118 | enum env_location arch_env_get_location(enum env_operation op, int prio) |
| 119 | { |
| 120 | const char *boot_device = |
| 121 | ofnode_read_chosen_string("u-boot,spl-boot-device"); |
| 122 | struct udevice *devp; |
| 123 | |
| 124 | if (prio > 0) |
| 125 | return ENVL_UNKNOWN; |
| 126 | |
| 127 | if (!boot_device) { |
| 128 | debug("%s: /chosen/u-boot,spl-boot-device not set\n", |
| 129 | __func__); |
| 130 | return ENVL_NOWHERE; |
| 131 | } |
| 132 | |
| 133 | debug("%s: booted from %s\n", __func__, boot_device); |
| 134 | |
| 135 | if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH) && |
| 136 | !uclass_find_device_by_ofnode(UCLASS_SPI_FLASH, ofnode_path(boot_device), &devp)) |
| 137 | return ENVL_SPI_FLASH; |
| 138 | |
| 139 | if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC) && |
| 140 | !uclass_find_device_by_ofnode(UCLASS_MMC, ofnode_path(boot_device), &devp)) |
| 141 | return ENVL_MMC; |
| 142 | |
| 143 | printf("%s: No environment available: booted from %s but U-Boot config does not allow loading environment from it.", |
| 144 | __func__, boot_device); |
| 145 | |
| 146 | return ENVL_NOWHERE; |
| 147 | } |