1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2012 Boundary Devices Inc. 4 */ 5 #include <common.h> 6 #include <linux/errno.h> 7 #include <asm/io.h> 8 #include <asm/mach-imx/boot_mode.h> 9 #include <malloc.h> 10 #include <command.h> 11 12 static const struct boot_mode *modes[2]; 13 14 static const struct boot_mode *search_modes(char *arg) 15 { 16 int i; 17 18 for (i = 0; i < ARRAY_SIZE(modes); i++) { 19 const struct boot_mode *p = modes[i]; 20 if (p) { 21 while (p->name) { 22 if (!strcmp(p->name, arg)) 23 return p; 24 p++; 25 } 26 } 27 } 28 return NULL; 29 } 30 31 static int create_usage(char *dest) 32 { 33 int i; 34 int size = 0; 35 36 for (i = 0; i < ARRAY_SIZE(modes); i++) { 37 const struct boot_mode *p = modes[i]; 38 if (p) { 39 while (p->name) { 40 int len = strlen(p->name); 41 if (dest) { 42 memcpy(dest, p->name, len); 43 dest += len; 44 *dest++ = '|'; 45 } 46 size += len + 1; 47 p++; 48 } 49 } 50 } 51 if (dest) 52 memcpy(dest - 1, " [noreset]", 11); /* include trailing 0 */ 53 size += 10; 54 return size; 55 } 56 57 static int do_boot_mode(cmd_tbl_t *cmdtp, int flag, int argc, 58 char * const argv[]) 59 { 60 const struct boot_mode *p; 61 int reset_requested = 1; 62 63 if (argc < 2) 64 return CMD_RET_USAGE; 65 p = search_modes(argv[1]); 66 if (!p) 67 return CMD_RET_USAGE; 68 if (argc == 3) { 69 if (strcmp(argv[2], "noreset")) 70 return CMD_RET_USAGE; 71 reset_requested = 0; 72 } 73 74 boot_mode_apply(p->cfg_val); 75 if (reset_requested && p->cfg_val) 76 do_reset(NULL, 0, 0, NULL); 77 return 0; 78 } 79 80 U_BOOT_CMD( 81 bmode, 3, 0, do_boot_mode, 82 NULL, 83 ""); 84 85 void add_board_boot_modes(const struct boot_mode *p) 86 { 87 int size; 88 char *dest; 89 90 cmd_tbl_t *entry = ll_entry_get(cmd_tbl_t, bmode, cmd); 91 92 if (entry->usage) { 93 free(entry->usage); 94 entry->usage = NULL; 95 } 96 97 modes[0] = p; 98 modes[1] = soc_boot_modes; 99 size = create_usage(NULL); 100 dest = malloc(size); 101 if (dest) { 102 create_usage(dest); 103 entry->usage = dest; 104 } 105 } 106