uboot/cmd/sysboot.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2
   3#include <common.h>
   4#include <command.h>
   5#include <env.h>
   6#include <fs.h>
   7#include <pxe_utils.h>
   8
   9/**
  10 * struct sysboot_info - useful information for sysboot helpers
  11 *
  12 * @fstype: Filesystem type (FS_TYPE_...)
  13 * @ifname: Interface name (e.g. "ide", "scsi")
  14 * @dev_part_str is in the format:
  15 *      <dev>.<hw_part>:<part> where <dev> is the device number,
  16 *      <hw_part> is the optional hardware partition number and
  17 *      <part> is the partition number
  18 */
  19struct sysboot_info {
  20        int fstype;
  21        const char *ifname;
  22        const char *dev_part_str;
  23};
  24
  25static int sysboot_read_file(struct pxe_context *ctx, const char *file_path,
  26                             char *file_addr, ulong *sizep)
  27{
  28        struct sysboot_info *info = ctx->userdata;
  29        loff_t len_read;
  30        ulong addr;
  31        int ret;
  32
  33        addr = simple_strtoul(file_addr, NULL, 16);
  34        ret = fs_set_blk_dev(info->ifname, info->dev_part_str, info->fstype);
  35        if (ret)
  36                return ret;
  37        ret = fs_read(file_path, addr, 0, 0, &len_read);
  38        if (ret)
  39                return ret;
  40        *sizep = len_read;
  41
  42        return 0;
  43}
  44
  45/*
  46 * Boots a system using a local disk syslinux/extlinux file
  47 *
  48 * Returns 0 on success, 1 on error.
  49 */
  50static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
  51                      char *const argv[])
  52{
  53        unsigned long pxefile_addr_r;
  54        struct pxe_context ctx;
  55        char *pxefile_addr_str;
  56        struct sysboot_info info;
  57        char *filename;
  58        int prompt = 0;
  59        int ret;
  60
  61        if (argc > 1 && strstr(argv[1], "-p")) {
  62                prompt = 1;
  63                argc--;
  64                argv++;
  65        }
  66
  67        if (argc < 4)
  68                return cmd_usage(cmdtp);
  69
  70        if (argc < 5) {
  71                pxefile_addr_str = from_env("pxefile_addr_r");
  72                if (!pxefile_addr_str)
  73                        return 1;
  74        } else {
  75                pxefile_addr_str = argv[4];
  76        }
  77
  78        if (argc < 6) {
  79                filename = env_get("bootfile");
  80        } else {
  81                filename = argv[5];
  82                env_set("bootfile", filename);
  83        }
  84
  85        if (strstr(argv[3], "ext2")) {
  86                info.fstype = FS_TYPE_EXT;
  87        } else if (strstr(argv[3], "fat")) {
  88                info.fstype = FS_TYPE_FAT;
  89        } else if (strstr(argv[3], "any")) {
  90                info.fstype = FS_TYPE_ANY;
  91        } else {
  92                printf("Invalid filesystem: %s\n", argv[3]);
  93                return 1;
  94        }
  95        info.ifname = argv[1];
  96        info.dev_part_str = argv[2];
  97
  98        if (strict_strtoul(pxefile_addr_str, 16, &pxefile_addr_r) < 0) {
  99                printf("Invalid pxefile address: %s\n", pxefile_addr_str);
 100                return 1;
 101        }
 102
 103        if (pxe_setup_ctx(&ctx, cmdtp, sysboot_read_file, &info, true,
 104                          filename)) {
 105                printf("Out of memory\n");
 106                return CMD_RET_FAILURE;
 107        }
 108
 109        if (get_pxe_file(&ctx, filename, pxefile_addr_r) < 0) {
 110                printf("Error reading config file\n");
 111                pxe_destroy_ctx(&ctx);
 112                return 1;
 113        }
 114
 115        ret = pxe_process(&ctx, pxefile_addr_r, prompt);
 116        pxe_destroy_ctx(&ctx);
 117        if (ret)
 118                return CMD_RET_FAILURE;
 119
 120        return 0;
 121}
 122
 123U_BOOT_CMD(sysboot, 7, 1, do_sysboot,
 124           "command to get and boot from syslinux files",
 125           "[-p] <interface> <dev[:part]> <ext2|fat|any> [addr] [filename]\n"
 126           "    - load and parse syslinux menu file 'filename' from ext2, fat\n"
 127           "      or any filesystem on 'dev' on 'interface' to address 'addr'"
 128);
 129