clk: sci-clk: add slack to clk-set-rate passed to firmware
[oweals/u-boot.git] / cmd / pxe.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2010-2011 Calxeda, Inc.
4  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
5  */
6
7 #include <common.h>
8 #include <command.h>
9
10 #include "pxe_utils.h"
11
12 #ifdef CONFIG_CMD_NET
13 const char *pxe_default_paths[] = {
14 #ifdef CONFIG_SYS_SOC
15 #ifdef CONFIG_SYS_BOARD
16         "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC "-" CONFIG_SYS_BOARD,
17 #endif
18         "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC,
19 #endif
20         "default-" CONFIG_SYS_ARCH,
21         "default",
22         NULL
23 };
24
25 static int do_get_tftp(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr)
26 {
27         char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
28
29         tftp_argv[1] = file_addr;
30         tftp_argv[2] = (void *)file_path;
31
32         if (do_tftpb(cmdtp, 0, 3, tftp_argv))
33                 return -ENOENT;
34
35         return 1;
36 }
37
38 /*
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  */
43 static int pxe_uuid_path(cmd_tbl_t *cmdtp, unsigned long pxefile_addr_r)
44 {
45         char *uuid_str;
46
47         uuid_str = from_env("pxeuuid");
48
49         if (!uuid_str)
50                 return -ENOENT;
51
52         return get_pxelinux_path(cmdtp, uuid_str, pxefile_addr_r);
53 }
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  */
61 static int pxe_mac_path(cmd_tbl_t *cmdtp, unsigned long pxefile_addr_r)
62 {
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
71         return get_pxelinux_path(cmdtp, mac_str, pxefile_addr_r);
72 }
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  */
81 static int pxe_ipaddr_paths(cmd_tbl_t *cmdtp, unsigned long pxefile_addr_r)
82 {
83         char ip_addr[9];
84         int mask_pos, err;
85
86         sprintf(ip_addr, "%08X", ntohl(net_ip.s_addr));
87
88         for (mask_pos = 7; mask_pos >= 0;  mask_pos--) {
89                 err = get_pxelinux_path(cmdtp, ip_addr, pxefile_addr_r);
90
91                 if (err > 0)
92                         return err;
93
94                 ip_addr[mask_pos] = '\0';
95         }
96
97         return -ENOENT;
98 }
99 /*
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  */
113 static int
114 do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
115 {
116         char *pxefile_addr_str;
117         unsigned long pxefile_addr_r;
118         int err, i = 0;
119
120         do_getfile = do_get_tftp;
121
122         if (argc != 1)
123                 return CMD_RET_USAGE;
124
125         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,
131                              (unsigned long *)&pxefile_addr_r);
132         if (err < 0)
133                 return 1;
134
135         /*
136          * Keep trying paths until we successfully get a file we're looking
137          * for.
138          */
139         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) {
142                 printf("Config file found\n");
143
144                 return 0;
145         }
146
147         while (pxe_default_paths[i]) {
148                 if (get_pxelinux_path(cmdtp, pxe_default_paths[i],
149                                       pxefile_addr_r) > 0) {
150                         printf("Config file found\n");
151                         return 0;
152                 }
153                 i++;
154         }
155
156         printf("Config file not found\n");
157
158         return 1;
159 }
160
161 /*
162  * Boots a system using a pxe file
163  *
164  * Returns 0 on success, 1 on error.
165  */
166 static int
167 do_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
173         do_getfile = do_get_tftp;
174
175         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 {
183                 return CMD_RET_USAGE;
184         }
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
191         cfg = parse_pxefile(cmdtp, pxefile_addr_r);
192
193         if (!cfg) {
194                 printf("Error parsing config file\n");
195                 return 1;
196         }
197
198         handle_pxe_menu(cmdtp, cfg);
199
200         destroy_pxe_menu(cfg);
201
202         copy_filename(net_boot_file_name, "", sizeof(net_boot_file_name));
203
204         return 0;
205 }
206
207 static 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
212 static int do_pxe(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
213 {
214         cmd_tbl_t *cp;
215
216         if (argc < 2)
217                 return CMD_RET_USAGE;
218
219         is_pxe = true;
220
221         /* 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
230         return CMD_RET_USAGE;
231 }
232
233 U_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"
237 );
238 #endif