1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2008 4 * Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de. 5 */ 6 7 #include <common.h> 8 #include <console.h> 9 #include <serial.h> 10 #include <malloc.h> 11 12 #if CONFIG_IS_ENABLED(CONSOLE_MUX) 13 void iomux_printdevs(const int console) 14 { 15 int i; 16 struct stdio_dev *dev; 17 18 for (i = 0; i < cd_count[console]; i++) { 19 dev = console_devices[console][i]; 20 printf("%s ", dev->name); 21 } 22 printf("\n"); 23 } 24 25 /* This tries to preserve the old list if an error occurs. */ 26 int iomux_doenv(const int console, const char *arg) 27 { 28 char *console_args, *temp, **start; 29 int i, j, k, io_flag, cs_idx, repeat; 30 struct stdio_dev *dev; 31 struct stdio_dev **cons_set; 32 33 console_args = strdup(arg); 34 if (console_args == NULL) 35 return 1; 36 /* 37 * Check whether a comma separated list of devices was 38 * entered and count how many devices were entered. 39 * The array start[] has pointers to the beginning of 40 * each device name (up to MAX_CONSARGS devices). 41 * 42 * Have to do this twice - once to count the number of 43 * commas and then again to populate start. 44 */ 45 i = 0; 46 temp = console_args; 47 for (;;) { 48 temp = strchr(temp, ','); 49 if (temp != NULL) { 50 i++; 51 temp++; 52 continue; 53 } 54 /* There's always one entry more than the number of commas. */ 55 i++; 56 break; 57 } 58 start = (char **)malloc(i * sizeof(char *)); 59 if (start == NULL) { 60 free(console_args); 61 return 1; 62 } 63 i = 0; 64 start[0] = console_args; 65 for (;;) { 66 temp = strchr(start[i++], ','); 67 if (temp == NULL) 68 break; 69 *temp = '\0'; 70 start[i] = temp + 1; 71 } 72 cons_set = (struct stdio_dev **)calloc(i, sizeof(struct stdio_dev *)); 73 if (cons_set == NULL) { 74 free(start); 75 free(console_args); 76 return 1; 77 } 78 79 switch (console) { 80 case stdin: 81 io_flag = DEV_FLAGS_INPUT; 82 break; 83 case stdout: 84 case stderr: 85 io_flag = DEV_FLAGS_OUTPUT; 86 break; 87 default: 88 free(start); 89 free(console_args); 90 free(cons_set); 91 return 1; 92 } 93 94 cs_idx = 0; 95 for (j = 0; j < i; j++) { 96 /* 97 * Check whether the device exists and is valid. 98 * console_assign() also calls search_device(), 99 * but I need the pointer to the device. 100 */ 101 dev = search_device(io_flag, start[j]); 102 if (dev == NULL) 103 continue; 104 /* 105 * Prevent multiple entries for a device. 106 */ 107 repeat = 0; 108 for (k = 0; k < cs_idx; k++) { 109 if (dev == cons_set[k]) { 110 repeat++; 111 break; 112 } 113 } 114 if (repeat) 115 continue; 116 /* 117 * Try assigning the specified device. 118 * This could screw up the console settings for apps. 119 */ 120 if (console_assign(console, start[j]) < 0) 121 continue; 122 cons_set[cs_idx++] = dev; 123 } 124 free(console_args); 125 free(start); 126 /* failed to set any console */ 127 if (cs_idx == 0) { 128 free(cons_set); 129 return 1; 130 } else { 131 /* Works even if console_devices[console] is NULL. */ 132 console_devices[console] = 133 (struct stdio_dev **)realloc(console_devices[console], 134 cs_idx * sizeof(struct stdio_dev *)); 135 if (console_devices[console] == NULL) { 136 free(cons_set); 137 return 1; 138 } 139 memcpy(console_devices[console], cons_set, cs_idx * 140 sizeof(struct stdio_dev *)); 141 142 cd_count[console] = cs_idx; 143 } 144 free(cons_set); 145 return 0; 146 } 147 #endif /* CONSOLE_MUX */ 148