blob: 73f1b4fbd336c246eb56d6603d81ba26e9847205 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Jason Hobbs06283a62011-08-31 10:37:30 -05002/*
3 * Copyright 2010-2011 Calxeda, Inc.
Bryan Wu1fb7d0e2014-07-31 17:39:59 -07004 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
Jason Hobbs06283a62011-08-31 10:37:30 -05005 */
Wolfgang Denk1a459662013-07-08 09:37:19 +02006
Jason Hobbs06283a62011-08-31 10:37:30 -05007#include <common.h>
8#include <command.h>
Jason Hobbs06283a62011-08-31 10:37:30 -05009
Patrice Chotard2373cba2019-11-25 09:07:37 +010010#include "pxe_utils.h"
Jason Hobbs06283a62011-08-31 10:37:30 -050011
Patrice Chotard2373cba2019-11-25 09:07:37 +010012#ifdef CONFIG_CMD_NET
Rob Herring39f98552012-12-02 21:00:28 -060013const char *pxe_default_paths[] = {
Joe Hershberger58d9ff92013-06-24 17:21:04 -050014#ifdef CONFIG_SYS_SOC
Marek BehĂșn2455efa2019-05-02 15:29:12 +020015#ifdef CONFIG_SYS_BOARD
16 "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC "-" CONFIG_SYS_BOARD,
17#endif
Rob Herring39f98552012-12-02 21:00:28 -060018 "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC,
Joe Hershberger58d9ff92013-06-24 17:21:04 -050019#endif
Rob Herring39f98552012-12-02 21:00:28 -060020 "default-" CONFIG_SYS_ARCH,
21 "default",
22 NULL
23};
24
Steven Falco0e3f3f82013-10-07 09:51:48 -040025static int do_get_tftp(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr)
Rob Herring669df7e2012-05-25 10:47:39 +000026{
27 char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
28
29 tftp_argv[1] = file_addr;
Rob Herring23b71942012-12-02 21:00:21 -060030 tftp_argv[2] = (void *)file_path;
Rob Herring669df7e2012-05-25 10:47:39 +000031
Steven Falco0e3f3f82013-10-07 09:51:48 -040032 if (do_tftpb(cmdtp, 0, 3, tftp_argv))
Rob Herring669df7e2012-05-25 10:47:39 +000033 return -ENOENT;
34
35 return 1;
36}
Stephen Warrenb81fdb02014-02-05 20:49:20 -070037
Jason Hobbs06283a62011-08-31 10:37:30 -050038/*
39 * Looks for a pxe file with a name based on the pxeuuid environment variable.
40 *
41 * Returns 1 on success or < 0 on error.
42 */
Sjoerd Simons4a0bd102015-04-13 22:54:25 +020043static int pxe_uuid_path(cmd_tbl_t *cmdtp, unsigned long pxefile_addr_r)
Jason Hobbs06283a62011-08-31 10:37:30 -050044{
45 char *uuid_str;
46
47 uuid_str = from_env("pxeuuid");
48
49 if (!uuid_str)
50 return -ENOENT;
51
Steven Falco0e3f3f82013-10-07 09:51:48 -040052 return get_pxelinux_path(cmdtp, uuid_str, pxefile_addr_r);
Jason Hobbs06283a62011-08-31 10:37:30 -050053}
54
55/*
56 * Looks for a pxe file with a name based on the 'ethaddr' environment
57 * variable.
58 *
59 * Returns 1 on success or < 0 on error.
60 */
Sjoerd Simons4a0bd102015-04-13 22:54:25 +020061static int pxe_mac_path(cmd_tbl_t *cmdtp, unsigned long pxefile_addr_r)
Jason Hobbs06283a62011-08-31 10:37:30 -050062{
63 char mac_str[21];
64 int err;
65
66 err = format_mac_pxe(mac_str, sizeof(mac_str));
67
68 if (err < 0)
69 return err;
70
Steven Falco0e3f3f82013-10-07 09:51:48 -040071 return get_pxelinux_path(cmdtp, mac_str, pxefile_addr_r);
Jason Hobbs06283a62011-08-31 10:37:30 -050072}
73
74/*
75 * Looks for pxe files with names based on our IP address. See pxelinux
76 * documentation for details on what these file names look like. We match
77 * that exactly.
78 *
79 * Returns 1 on success or < 0 on error.
80 */
Sjoerd Simons4a0bd102015-04-13 22:54:25 +020081static int pxe_ipaddr_paths(cmd_tbl_t *cmdtp, unsigned long pxefile_addr_r)
Jason Hobbs06283a62011-08-31 10:37:30 -050082{
83 char ip_addr[9];
84 int mask_pos, err;
85
Joe Hershberger049a95a2015-04-08 01:41:01 -050086 sprintf(ip_addr, "%08X", ntohl(net_ip.s_addr));
Jason Hobbs06283a62011-08-31 10:37:30 -050087
88 for (mask_pos = 7; mask_pos >= 0; mask_pos--) {
Steven Falco0e3f3f82013-10-07 09:51:48 -040089 err = get_pxelinux_path(cmdtp, ip_addr, pxefile_addr_r);
Jason Hobbs06283a62011-08-31 10:37:30 -050090
91 if (err > 0)
92 return err;
93
94 ip_addr[mask_pos] = '\0';
95 }
96
97 return -ENOENT;
98}
Jason Hobbs06283a62011-08-31 10:37:30 -050099/*
100 * Entry point for the 'pxe get' command.
101 * This Follows pxelinux's rules to download a config file from a tftp server.
102 * The file is stored at the location given by the pxefile_addr_r environment
103 * variable, which must be set.
104 *
105 * UUID comes from pxeuuid env variable, if defined
106 * MAC addr comes from ethaddr env variable, if defined
107 * IP
108 *
109 * see http://syslinux.zytor.com/wiki/index.php/PXELINUX
110 *
111 * Returns 0 on success or 1 on error.
112 */
113static int
114do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
115{
116 char *pxefile_addr_str;
Jason Hobbs834c9382012-03-05 08:12:28 +0000117 unsigned long pxefile_addr_r;
Rob Herring39f98552012-12-02 21:00:28 -0600118 int err, i = 0;
Jason Hobbs06283a62011-08-31 10:37:30 -0500119
Rob Herring669df7e2012-05-25 10:47:39 +0000120 do_getfile = do_get_tftp;
121
Jason Hobbs06283a62011-08-31 10:37:30 -0500122 if (argc != 1)
Simon Glass4c12eeb2011-12-10 08:44:01 +0000123 return CMD_RET_USAGE;
Jason Hobbs06283a62011-08-31 10:37:30 -0500124
Jason Hobbs06283a62011-08-31 10:37:30 -0500125 pxefile_addr_str = from_env("pxefile_addr_r");
126
127 if (!pxefile_addr_str)
128 return 1;
129
130 err = strict_strtoul(pxefile_addr_str, 16,
Patrice Chotard31839dc2019-11-25 09:07:41 +0100131 (unsigned long *)&pxefile_addr_r);
Jason Hobbs06283a62011-08-31 10:37:30 -0500132 if (err < 0)
133 return 1;
134
135 /*
136 * Keep trying paths until we successfully get a file we're looking
137 * for.
138 */
Sjoerd Simons4a0bd102015-04-13 22:54:25 +0200139 if (pxe_uuid_path(cmdtp, pxefile_addr_r) > 0 ||
140 pxe_mac_path(cmdtp, pxefile_addr_r) > 0 ||
141 pxe_ipaddr_paths(cmdtp, pxefile_addr_r) > 0) {
Jason Hobbs06283a62011-08-31 10:37:30 -0500142 printf("Config file found\n");
143
144 return 0;
145 }
146
Rob Herring39f98552012-12-02 21:00:28 -0600147 while (pxe_default_paths[i]) {
Steven Falco0e3f3f82013-10-07 09:51:48 -0400148 if (get_pxelinux_path(cmdtp, pxe_default_paths[i],
Sjoerd Simons4a0bd102015-04-13 22:54:25 +0200149 pxefile_addr_r) > 0) {
Rob Herring39f98552012-12-02 21:00:28 -0600150 printf("Config file found\n");
151 return 0;
152 }
153 i++;
154 }
155
Jason Hobbs06283a62011-08-31 10:37:30 -0500156 printf("Config file not found\n");
157
158 return 1;
159}
Jason Hobbs06283a62011-08-31 10:37:30 -0500160
161/*
162 * Boots a system using a pxe file
163 *
164 * Returns 0 on success, 1 on error.
165 */
166static int
167do_pxe_boot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
168{
169 unsigned long pxefile_addr_r;
170 struct pxe_menu *cfg;
171 char *pxefile_addr_str;
172
Rob Herring669df7e2012-05-25 10:47:39 +0000173 do_getfile = do_get_tftp;
174
Jason Hobbs06283a62011-08-31 10:37:30 -0500175 if (argc == 1) {
176 pxefile_addr_str = from_env("pxefile_addr_r");
177 if (!pxefile_addr_str)
178 return 1;
179
180 } else if (argc == 2) {
181 pxefile_addr_str = argv[1];
182 } else {
Simon Glass4c12eeb2011-12-10 08:44:01 +0000183 return CMD_RET_USAGE;
Jason Hobbs06283a62011-08-31 10:37:30 -0500184 }
185
186 if (strict_strtoul(pxefile_addr_str, 16, &pxefile_addr_r) < 0) {
187 printf("Invalid pxefile address: %s\n", pxefile_addr_str);
188 return 1;
189 }
190
Sjoerd Simons4a0bd102015-04-13 22:54:25 +0200191 cfg = parse_pxefile(cmdtp, pxefile_addr_r);
Jason Hobbs06283a62011-08-31 10:37:30 -0500192
Patrice Chotard31839dc2019-11-25 09:07:41 +0100193 if (!cfg) {
Jason Hobbs06283a62011-08-31 10:37:30 -0500194 printf("Error parsing config file\n");
195 return 1;
196 }
197
Tom Rinid7884e02013-09-24 09:05:08 -0400198 handle_pxe_menu(cmdtp, cfg);
Jason Hobbs06283a62011-08-31 10:37:30 -0500199
200 destroy_pxe_menu(cfg);
201
Joe Hershberger14111572015-04-08 01:41:02 -0500202 copy_filename(net_boot_file_name, "", sizeof(net_boot_file_name));
Stephen Warrended2e202014-07-22 18:06:46 -0600203
Jason Hobbs06283a62011-08-31 10:37:30 -0500204 return 0;
205}
206
207static cmd_tbl_t cmd_pxe_sub[] = {
208 U_BOOT_CMD_MKENT(get, 1, 1, do_pxe_get, "", ""),
209 U_BOOT_CMD_MKENT(boot, 2, 1, do_pxe_boot, "", "")
210};
211
Jeroen Hofstee0e350f82014-06-23 00:22:08 +0200212static int do_pxe(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Jason Hobbs06283a62011-08-31 10:37:30 -0500213{
214 cmd_tbl_t *cp;
215
216 if (argc < 2)
Simon Glass4c12eeb2011-12-10 08:44:01 +0000217 return CMD_RET_USAGE;
Jason Hobbs06283a62011-08-31 10:37:30 -0500218
Rob Herringe5a9a402013-10-18 13:04:42 -0500219 is_pxe = true;
220
Jason Hobbs06283a62011-08-31 10:37:30 -0500221 /* drop initial "pxe" arg */
222 argc--;
223 argv++;
224
225 cp = find_cmd_tbl(argv[0], cmd_pxe_sub, ARRAY_SIZE(cmd_pxe_sub));
226
227 if (cp)
228 return cp->cmd(cmdtp, flag, argc, argv);
229
Simon Glass4c12eeb2011-12-10 08:44:01 +0000230 return CMD_RET_USAGE;
Jason Hobbs06283a62011-08-31 10:37:30 -0500231}
232
Patrice Chotard31839dc2019-11-25 09:07:41 +0100233U_BOOT_CMD(pxe, 3, 1, do_pxe,
234 "commands to get and boot from pxe files",
235 "get - try to retrieve a pxe file using tftp\n"
236 "pxe boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n"
Jason Hobbs06283a62011-08-31 10:37:30 -0500237);
Stephen Warrenb81fdb02014-02-05 20:49:20 -0700238#endif