1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 3 #ifndef __PXE_UTILS_H 4 #define __PXE_UTILS_H 5 6 #include <bootflow.h> 7 #include <linux/list.h> 8 9 /* 10 * A note on the pxe file parser. 11 * 12 * We're parsing files that use syslinux grammar, which has a few quirks. 13 * String literals must be recognized based on context - there is no 14 * quoting or escaping support. There's also nothing to explicitly indicate 15 * when a label section completes. We deal with that by ending a label 16 * section whenever we see a line that doesn't include. 17 * 18 * As with the syslinux family, this same file format could be reused in the 19 * future for non pxe purposes. The only action it takes during parsing that 20 * would throw this off is handling of include files. It assumes we're using 21 * pxe, and does a tftp download of a file listed as an include file in the 22 * middle of the parsing operation. That could be handled by refactoring it to 23 * take a 'include file getter' function. 24 */ 25 26 /* 27 * Describes a single label given in a pxe file. 28 * 29 * Create these with the 'label_create' function given below. 30 * 31 * name - the name of the menu as given on the 'menu label' line. 32 * kernel_label - the kernel label, including FIT config if present. 33 * kernel - the path to the kernel file to use for this label. 34 * append - kernel command line to use when booting this label 35 * initrd - path to the initrd to use for this label. 36 * attempted - 0 if we haven't tried to boot this label, 1 if we have. 37 * localboot - 1 if this label specified 'localboot', 0 otherwise. 38 * kaslrseed - 1 if generate kaslrseed from hw_rng 39 * list - lets these form a list, which a pxe_menu struct will hold. 40 */ 41 struct pxe_label { 42 char num[4]; 43 char *name; 44 char *menu; 45 char *kernel_label; 46 char *kernel; 47 char *config; 48 char *append; 49 char *initrd; 50 char *fdt; 51 char *fdtdir; 52 char *fdtoverlays; 53 int ipappend; 54 int attempted; 55 int localboot; 56 int localboot_val; 57 int kaslrseed; 58 struct list_head list; 59 }; 60 61 /* 62 * Describes a pxe menu as given via pxe files. 63 * 64 * title - the name of the menu as given by a 'menu title' line. 65 * default_label - the name of the default label, if any. 66 * fallback_label - the name of the fallback label, if any. 67 * bmp - the bmp file name which is displayed in background 68 * timeout - time in tenths of a second to wait for a user key-press before 69 * booting the default label. 70 * prompt - if 0, don't prompt for a choice unless the timeout period is 71 * interrupted. If 1, always prompt for a choice regardless of 72 * timeout. 73 * labels - a list of labels defined for the menu. 74 */ 75 struct pxe_menu { 76 char *title; 77 char *default_label; 78 char *fallback_label; 79 char *bmp; 80 int timeout; 81 int prompt; 82 struct list_head labels; 83 }; 84 85 struct pxe_context; 86 87 /** 88 * Read a file 89 * 90 * @ctx: PXE context 91 * @file_path: Full path to filename to read 92 * @file_addr: String containing the to which to read the file 93 * @type: File type 94 * @fileszeip: Returns file size 95 */ 96 typedef int (*pxe_getfile_func)(struct pxe_context *ctx, const char *file_path, 97 char *file_addr, enum bootflow_img_t type, 98 ulong *filesizep); 99 100 /** 101 * struct pxe_context - context information for PXE parsing 102 * 103 * @cmdtp: Pointer to command table to use when calling other commands 104 * @getfile: Function called by PXE to read a file 105 * @userdata: Data the caller requires for @getfile 106 * @allow_abs_path: true to allow absolute paths 107 * @bootdir: Directory that files are loaded from ("" if no directory). This is 108 * allocated 109 * @pxe_file_size: Size of the PXE file 110 * @use_ipv6: TRUE : use IPv6 addressing, FALSE : use IPv4 addressing 111 * @use_fallback: TRUE : use "fallback" option as default, FALSE : use 112 * "default" option as default 113 */ 114 struct pxe_context { 115 struct cmd_tbl *cmdtp; 116 /** 117 * getfile() - read a file 118 * 119 * @ctx: PXE context 120 * @file_path: Path to the file 121 * @file_addr: String containing the hex address to put the file in 122 * memory 123 * @filesizep: Returns the file size in bytes 124 * Return 0 if OK, -ve on error 125 */ 126 pxe_getfile_func getfile; 127 128 void *userdata; 129 bool allow_abs_path; 130 char *bootdir; 131 ulong pxe_file_size; 132 bool use_ipv6; 133 bool use_fallback; 134 }; 135 136 /** 137 * destroy_pxe_menu() - Destroy an allocated pxe structure 138 * 139 * Free the memory used by a pxe_menu and its labels 140 * 141 * @cfg: Config to destroy, previous returned from parse_pxefile() 142 */ 143 void destroy_pxe_menu(struct pxe_menu *cfg); 144 145 /** 146 * get_pxe_file() - Read a file 147 * 148 * Retrieve the file at 'file_path' to the locate given by 'file_addr'. If 149 * 'bootfile' was specified in the environment, the path to bootfile will be 150 * prepended to 'file_path' and the resulting path will be used. 151 * 152 * @ctx: PXE context 153 * @file_path: Path to file 154 * @file_addr: Address to place file 155 * Returns 1 on success, or < 0 for error 156 */ 157 int get_pxe_file(struct pxe_context *ctx, const char *file_path, 158 ulong file_addr); 159 160 /** 161 * get_pxelinux_path() - Read a file from the same place as pxelinux.cfg 162 * 163 * Retrieves a file in the 'pxelinux.cfg' folder. Since this uses get_pxe_file() 164 * to do the hard work, the location of the 'pxelinux.cfg' folder is generated 165 * from the bootfile path, as described in get_pxe_file(). 166 * 167 * @ctx: PXE context 168 * @file: Relative path to file 169 * @pxefile_addr_r: Address to load file 170 * Returns 1 on success or < 0 on error. 171 */ 172 int get_pxelinux_path(struct pxe_context *ctx, const char *file, 173 ulong pxefile_addr_r); 174 175 /** 176 * handle_pxe_menu() - Boot the system as prescribed by a pxe_menu. 177 * 178 * Use the menu system to either get the user's choice or the default, based 179 * on config or user input. If there is no default or user's choice, 180 * attempted to boot labels in the order they were given in pxe files. 181 * If the default or user's choice fails to boot, attempt to boot other 182 * labels in the order they were given in pxe files. 183 * 184 * If this function returns, there weren't any labels that successfully 185 * booted, or the user interrupted the menu selection via ctrl+c. 186 * 187 * @ctx: PXE context 188 * @cfg: PXE menu 189 */ 190 void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg); 191 192 /** 193 * parse_pxefile() - Parsing a pxe file 194 * 195 * This is only used for the top-level file. 196 * 197 * @ctx: PXE context (provided by the caller) 198 * Returns NULL if there is an error, otherwise, returns a pointer to a 199 * pxe_menu struct populated with the results of parsing the pxe file (and any 200 * files it includes). The resulting pxe_menu struct can be free()'d by using 201 * the destroy_pxe_menu() function. 202 */ 203 struct pxe_menu *parse_pxefile(struct pxe_context *ctx, ulong menucfg); 204 205 /** 206 * format_mac_pxe() - Convert a MAC address to PXE format 207 * 208 * Convert an ethaddr from the environment to the format used by pxelinux 209 * filenames based on mac addresses. Convert's ':' to '-', and adds "01-" to 210 * the beginning of the ethernet address to indicate a hardware type of 211 * Ethernet. Also converts uppercase hex characters into lowercase, to match 212 * pxelinux's behavior. 213 * 214 * @outbuf: Buffer to hold the output (must hold 22 bytes) 215 * @outbuf_len: Length of buffer 216 * Returns 1 for success, -ENOENT if 'ethaddr' is undefined in the 217 * environment, or some other value < 0 on error. 218 */ 219 int format_mac_pxe(char *outbuf, size_t outbuf_len); 220 221 /** 222 * pxe_setup_ctx() - Setup a new PXE context 223 * 224 * @ctx: Context to set up 225 * @cmdtp: Command table entry which started this action 226 * @getfile: Function to call to read a file 227 * @userdata: Data the caller requires for @getfile - stored in ctx->userdata 228 * @allow_abs_path: true to allow absolute paths 229 * @bootfile: Bootfile whose directory loaded files are relative to, NULL if 230 * none 231 * @use_ipv6: TRUE : use IPv6 addressing 232 * FALSE : use IPv4 addressing 233 * @use_fallback: TRUE : Use "fallback" option instead of "default" should no 234 * other choice be selected 235 * FALSE : Use "default" option should no other choice be 236 * selected 237 * Return: 0 if OK, -ENOMEM if out of memory, -E2BIG if bootfile is larger than 238 * MAX_TFTP_PATH_LEN bytes 239 */ 240 int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp, 241 pxe_getfile_func getfile, void *userdata, 242 bool allow_abs_path, const char *bootfile, bool use_ipv6, 243 bool use_fallback); 244 245 /** 246 * pxe_destroy_ctx() - Destroy a PXE context 247 * 248 * @ctx: Context to destroy 249 */ 250 void pxe_destroy_ctx(struct pxe_context *ctx); 251 252 /** 253 * pxe_process() - Process a PXE file through to boot 254 * 255 * @ctx: PXE context created with pxe_setup_ctx() 256 * @pxefile_addr_r: Address to load file 257 * @prompt: Force a prompt for the user 258 */ 259 int pxe_process(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt); 260 261 /** 262 * pxe_get_file_size() - Read the value of the 'filesize' environment variable 263 * 264 * @sizep: Place to put the value 265 * Return: 0 if OK, -ENOENT if no such variable, -EINVAL if format is invalid 266 */ 267 int pxe_get_file_size(ulong *sizep); 268 269 /** 270 * pxe_get() - Get the PXE file from the server 271 * 272 * This tries various filenames to obtain a PXE file 273 * 274 * @pxefile_addr_r: Address to put file 275 * @bootdirp: Returns the boot filename, or NULL if none. This is the 'bootfile' 276 * option provided by the DHCP server. If none, returns NULL. For example, 277 * "rpi/info", which indicates that all files should be fetched from the 278 * "rpi/" subdirectory 279 * @sizep: Size of the PXE file (not bootfile) 280 * @use_ipv6: TRUE : use IPv6 addressing 281 * FALSE : use IPv4 addressing 282 */ 283 int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep, bool use_ipv6); 284 285 #endif /* __PXE_UTILS_H */ 286