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