Home | History | Annotate | Download | only in common
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2008
      4  * Gary Jennejohn, DENX Software Engineering GmbH, garyj (at) 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