| /* |
| * 2004-2005 (c) MontaVista, Software, Inc. This file is licensed under |
| * the terms of the GNU General Public License version 2. This program |
| * is licensed "as is" without any warranty of any kind, whether express |
| * or implied. |
| */ |
| |
| #include <linux/types.h> |
| #include <linux/string.h> |
| #include <linux/ctype.h> |
| #include <asm/ppcboot.h> |
| #include <asm/ibm4xx.h> |
| |
| extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, |
| unsigned long cksum); |
| |
| /* We need to make sure that this is before the images to ensure |
| * that it's in a mapped location. - Tom */ |
| bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot"))); |
| bd_t *hold_residual = &hold_resid_buf; |
| |
| /* String functions lifted from lib/vsprintf.c and lib/ctype.c */ |
| unsigned char _ctype[] = { |
| _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ |
| _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ |
| _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ |
| _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ |
| _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ |
| _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ |
| _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ |
| _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ |
| _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ |
| _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ |
| _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ |
| _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ |
| _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ |
| _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ |
| _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ |
| _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ |
| 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ |
| 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ |
| _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ |
| _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ |
| _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ |
| _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ |
| _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ |
| _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ |
| |
| /** |
| * simple_strtoull - convert a string to an unsigned long long |
| * @cp: The start of the string |
| * @endp: A pointer to the end of the parsed string will be placed here |
| * @base: The number base to use |
| */ |
| unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) |
| { |
| unsigned long long result = 0,value; |
| |
| if (!base) { |
| base = 10; |
| if (*cp == '0') { |
| base = 8; |
| cp++; |
| if ((toupper(*cp) == 'X') && isxdigit(cp[1])) { |
| cp++; |
| base = 16; |
| } |
| } |
| } else if (base == 16) { |
| if (cp[0] == '0' && toupper(cp[1]) == 'X') |
| cp += 2; |
| } |
| while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) |
| ? toupper(*cp) : *cp)-'A'+10) < base) { |
| result = result*base + value; |
| cp++; |
| } |
| if (endp) |
| *endp = (char *)cp; |
| return result; |
| } |
| |
| void * |
| load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, |
| void *ign1, void *ign2) |
| { |
| unsigned long long mac64; |
| |
| decompress_kernel(load_addr, num_words, cksum); |
| |
| mac64 = simple_strtoull((char *)PIBS_MAC_BASE, 0, 16); |
| memcpy(hold_residual->bi_enetaddr, (char *)&mac64+2, 6); |
| #if defined(CONFIG_440GX) || defined(CONFIG_440EP) |
| mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET), 0, 16); |
| memcpy(hold_residual->bi_enet1addr, (char *)&mac64+2, 6); |
| #endif |
| #ifdef CONFIG_440GX |
| mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*2), 0, 16); |
| memcpy(hold_residual->bi_enet2addr, (char *)&mac64+2, 6); |
| mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*3), 0, 16); |
| memcpy(hold_residual->bi_enet3addr, (char *)&mac64+2, 6); |
| #endif |
| return (void *)hold_residual; |
| } |