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