1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Program and file loading URLs		File: url.c
5    *
6    *  Functions to process URLs for loading software.
7    *
8    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
9    *
10    *********************************************************************
11    *
12    *  Copyright 2000,2001
13    *  Broadcom Corporation. All rights reserved.
14    *
15    *  This software is furnished under license and may be used and
16    *  copied only in accordance with the following terms and
17    *  conditions.  Subject to these conditions, you may download,
18    *  copy, install, use, modify and distribute modified or unmodified
19    *  copies of this software in source and/or binary form.  No title
20    *  or ownership is transferred hereby.
21    *
22    *  1) Any source code used, modified or distributed must reproduce
23    *     and retain this copyright notice and list of conditions as
24    *     they appear in the source file.
25    *
26    *  2) No right is granted to use any trade name, trademark, or
27    *     logo of Broadcom Corporation. Neither the "Broadcom
28    *     Corporation" name nor any trademark or logo of Broadcom
29    *     Corporation may be used to endorse or promote products
30    *     derived from this software without the prior written
31    *     permission of Broadcom Corporation.
32    *
33    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45    *     THE POSSIBILITY OF SUCH DAMAGE.
46    ********************************************************************* */
47
48#include "lib_types.h"
49#include "lib_string.h"
50#include "lib_queue.h"
51#include "lib_malloc.h"
52#include "lib_printf.h"
53
54#include "bsp_config.h"
55#include "cfe_loader.h"
56#include "cfe_autoboot.h"
57#include "cfe_iocb.h"
58#include "cfe_devfuncs.h"
59#include "cfe_fileops.h"
60#include "cfe_error.h"
61
62#include "net_ebuf.h"
63#include "net_ether.h"
64#include "net_api.h"
65
66#include "ui_command.h"
67
68#include "url.h"
69
70static long getaddr(char *str)
71{
72    /*
73     * hold on to your lunch, this is really, really bad!
74     * Make 64-bit addresses expressed as 8-digit numbers
75     * sign extend automagically.  Saves typing, but is very
76     * gross.  Not very portable, either.
77     */
78    int longaddr = 0;
79    long newaddr;
80
81    longaddr = strlen(str);
82    if (memcmp(str,"0x",2) == 0) longaddr -= 2;
83    longaddr = (longaddr > 8) ? 1 : 0;
84
85    if (longaddr) newaddr = (long) xtoq(str);
86    else newaddr = (long) xtoi(str);
87
88    return newaddr;
89}
90
91static int process_oldstyle(char *str,
92			    ui_cmdline_t *cmd,
93			    cfe_loadargs_t *la)
94{
95    char *file;
96    char *devname;
97    char *filesys = NULL;
98    char *loader = la->la_loader;
99    char *x;
100    int info;
101    char *colon;
102
103    colon = strchr(str,':');
104
105    if (!colon) {
106	return CFE_ERR_DEVNOTFOUND;
107	}
108
109    devname = str;	/* will be used to check protocol later */
110    *colon = '\0';
111    file = colon + 1;	/* Ugly, we might put the colon back! */
112
113    /*
114     * Try to determine the load protocol ("filesystem")
115     * first by using the command line, and
116     * if not that try to figure it out automagically
117     */
118
119    if (cmd_sw_isset(cmd,"-fatfs")) filesys = "fat";
120    if (cmd_sw_isset(cmd,"-tftp"))  filesys = "tftp";
121    if (cmd_sw_isset(cmd,"-rawfs")) filesys = "raw";
122#if CFG_TCP && CFG_HTTPFS
123    if (cmd_sw_isset(cmd,"-http"))  filesys = "http";
124#endif
125    if (cmd_sw_value(cmd,"-fs",&x)) filesys = x;
126
127    /*
128     * Automagic configuration
129     */
130
131    /*
132     * Determine the device type from the "host" name.  If we look
133     * up the host name and it appears to be an invalid CFE device
134     * name, then it's probably a TFTP host name.
135     *
136     * This is where we guess based on the device type what
137     * sort of load method we're going to use.
138     */
139
140    info = devname ? cfe_getdevinfo(devname) : -1;
141    if (info >= 0) {
142	switch (info & CFE_DEV_MASK) {
143	    case CFE_DEV_NETWORK:
144		if (!filesys) filesys = "tftp";
145		if (!loader)  loader  = "raw";
146		break;
147	    case CFE_DEV_DISK:
148		if (!filesys) filesys = "raw";
149		if (!loader)  loader  = "raw";
150		break;
151	    case CFE_DEV_FLASH:
152		if (!filesys) filesys = "raw";
153		if (!loader)  loader  = "raw";
154		break;
155	    case CFE_DEV_SERIAL:
156		if (!filesys) filesys = "raw";
157		if (!loader)  loader  = "srec";
158		break;
159	    default:
160		break;
161	    }
162	la->la_device   = devname;
163	la->la_filename = file;
164	}
165    else {
166	/*
167	 * It's probably a network boot.  Default to TFTP
168	 * if not overridden
169	 */
170#if CFG_NETWORK
171	la->la_device = (char *) net_getparam(NET_DEVNAME);
172#else
173	la->la_device = NULL;
174#endif
175	*colon = ':';			/* put the colon back */
176	la->la_filename = devname;
177	if (!filesys) filesys = "tftp";
178	if (!loader)  loader  = "raw";
179	}
180
181    /*
182     * Remember our file system and loader.
183     */
184
185    la->la_filesys = filesys;
186    la->la_loader = loader;
187
188    return 0;
189}
190
191
192#if CFG_URLS
193static int process_url(char *str,
194		       ui_cmdline_t *cmd,
195		       cfe_loadargs_t *la)
196{
197    char *p;
198    char *protocol;
199    int idx,len;
200    int network = 0;
201    const fileio_dispatch_t *fdisp;
202
203    /*
204     * All URLs have the string "://" in them somewhere
205     * If that's not there, try the old syntax.
206     */
207
208    len = strlen(str);
209    p = str;
210
211    for (idx = 0; idx < len-3; idx++) {
212	if (memcmp(p,"://",3) == 0) break;
213	p++;
214	}
215
216    if (idx == (len-3)) {
217	return process_oldstyle(str,cmd,la);
218	}
219
220    /*
221     * Break the string apart into protocol, host, file
222     */
223
224    protocol = str;
225    *p = '\0';
226    p += 3;
227
228    /*
229     * Determine if this is a network loader.  If that is true,
230     * the meaning of the "device" field is different.  Ugh.
231     */
232
233    fdisp = cfe_findfilesys(protocol);
234    if (fdisp && (fdisp->loadflags & FSYS_TYPE_NETWORK)) network = 1;
235
236    /*
237     * Depending on the protocol we parse the file name one of two ways:
238     *
239     *      protocol://hostname/filename
240     *
241     * For network devices:
242     *
243     *      the "device" is the current Ethernet device.
244     *      The filename is the //hostname/filename from the URL.
245     *
246     * For non-network devices:
247     *
248     *      The "device" is the CFE device name from the URL 'hostname' field
249     *      The filename is from the URL filename field.
250     */
251
252    la->la_filesys = protocol;
253
254    if (network) {
255#if CFG_NETWORK
256	la->la_device = (char *) net_getparam(NET_DEVNAME);
257#else
258	la->la_device = NULL;
259#endif
260	la->la_filename = p;
261	}
262    else {
263	la->la_device = p;
264	p = strchr(p,'/');
265	if (p) {
266	    *p++ = '\0';
267	    la->la_filename = p;
268	    }
269	else {
270	    la->la_filename = NULL;
271	    }
272	}
273
274    if (!la->la_loader) la->la_loader = "raw";
275
276    return 0;
277}
278#endif
279
280
281
282int ui_process_url(char *url,ui_cmdline_t *cmd,cfe_loadargs_t *la)
283{
284    int res;
285    char *x;
286
287    /*
288     * Skip leading whitespace
289     */
290
291    while (*url && ((*url == ' ') || (*url == '\t'))) url++;
292
293    /*
294     * Process command-line switches to determine the loader stack
295     */
296
297    la->la_loader = NULL;
298    if (cmd_sw_isset(cmd,"-elf"))  la->la_loader = "elf";
299    if (cmd_sw_isset(cmd,"-srec")) la->la_loader = "srec";
300    if (cmd_sw_isset(cmd,"-raw"))  la->la_loader = "raw";
301    if (cmd_sw_value(cmd,"-loader",&x)) la->la_loader = x;
302
303#if CFG_ZLIB || CFG_LZMA
304    if (cmd_sw_isset(cmd,"-z")) {
305	la->la_flags |= LOADFLG_COMPRESSED;
306	}
307#endif
308
309    /*
310     * Parse the file name into its pieces.
311     */
312
313#if CFG_URLS
314    res = process_url(url,cmd,la);
315    if (res < 0) return res;
316#else
317    res = process_oldstyle(url,cmd,la);
318    if (res < 0) return res;
319#endif
320
321
322    /*
323     * This is used only by "boot" and "load" - to avoid this code
324     * don't include these switches in the command table.
325     */
326
327    if (cmd_sw_value(cmd,"-max",&x)) {
328	la->la_maxsize = atoi(x);
329	}
330
331    if (cmd_sw_value(cmd,"-addr",&x)) {
332	la->la_address = getaddr(x);
333	la->la_flags |= LOADFLG_SPECADDR;
334	}
335
336    if (cmd_sw_isset(cmd,"-noclose")) {
337	la->la_flags |= LOADFLG_NOCLOSE;
338	}
339
340
341    return 0;
342}
343