efi_loader: NULL dereference in EFI console

Even if CONFIG_DM_VIDEO=y and stdout="vidconsole", a video device may not
be available. Check the return values of the relevant functions.

If no video output device is available, assume that the serial console is
in use.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
Heinrich Schuchardt 2021-03-16 12:56:57 +01:00
parent e3310c21a4
commit a95f4c8859
1 changed files with 38 additions and 13 deletions

View File

@ -254,7 +254,7 @@ static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols)
}
/**
* query_console_serial() - query console size
* query_console_serial() - query serial console size
*
* When using a serial console or the net console we can only devise the
* terminal size by querying the terminal using ECMA-48 control sequences.
@ -299,6 +299,37 @@ out:
return ret;
}
/**
* query_vidconsole() - query video console size
*
*
* @rows: pointer to return number of rows
* @cols: pointer to return number of columns
* Returns: 0 on success
*/
static int __maybe_unused query_vidconsole(int *rows, int *cols)
{
const char *stdout_name = env_get("stdout");
struct stdio_dev *stdout_dev;
struct udevice *dev;
struct vidconsole_priv *priv;
if (!stdout_name || strncmp(stdout_name, "vidconsole", 10))
return -ENODEV;
stdout_dev = stdio_get_by_name("vidconsole");
if (!stdout_dev)
return -ENODEV;
dev = stdout_dev->priv;
if (!dev)
return -ENODEV;
priv = dev_get_uclass_priv(dev);
if (!priv)
return -ENODEV;
*rows = priv->rows;
*cols = priv->cols;
return 0;
}
/**
* query_console_size() - update the mode table.
*
@ -308,21 +339,15 @@ out:
*/
static void query_console_size(void)
{
const char *stdout_name = env_get("stdout");
int rows = 25, cols = 80;
int ret = -ENODEV;
if (stdout_name && !strncmp(stdout_name, "vidconsole", 10) &&
IS_ENABLED(CONFIG_DM_VIDEO)) {
struct stdio_dev *stdout_dev =
stdio_get_by_name("vidconsole");
struct udevice *dev = stdout_dev->priv;
struct vidconsole_priv *priv =
dev_get_uclass_priv(dev);
rows = priv->rows;
cols = priv->cols;
} else if (query_console_serial(&rows, &cols)) {
if IS_ENABLED(CONFIG_DM_VIDEO)
ret = query_vidconsole(&rows, &cols);
if (ret)
ret = query_console_serial(&rows, &cols);
if (ret)
return;
}
/* Test if we can have Mode 1 */
if (cols >= 80 && rows >= 50) {