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