Update of /cvsroot/linux-vax/kernel-2.4/arch/ppc/boot/common In directory usw-pr-cvs1:/tmp/cvs-serv25860/ppc/boot/common Added Files: Makefile crt0.S misc-common.c misc-simple.c no_initrd.c ns16550.c ofcommon.c string.S Log Message: synch 2.4.15 commit 43 --- NEW FILE --- # # arch/ppc/boot/common/Makefile # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. # # Tom Rini January 2001 # .c.s: $(CC) $(CFLAGS) -S -o $*.s $< .s.o: $(AS) -o $*.o $< .c.o: $(CC) $(CFLAGS) -c -o $*.o $< .S.s: $(CPP) $(AFLAGS) -traditional -o $*.o $< .S.o: $(CC) $(AFLAGS) -traditional -c -o $*.o $< OBJCOPY_ARGS = -O elf32-powerpc coffcrt0.o: $(CC) $(AFLAGS) -DXCOFF -traditional -c -o coffcrt0.o crt0.S include $(TOPDIR)/Rules.make --- NEW FILE --- /* * BK Id: SCCS/s.crt0.S 1.12 08/09/01 17:09:10 paulus */ /* Copyright (c) 1997 Paul Mackerras <pa...@cs...> * Initial Power Macintosh COFF version. * Copyright (c) 1999 Grant Erickson <gr...@lc...> * Modifications for IBM PowerPC 400-class processor evaluation * boards. * * Module name: crt0.S * * Description: * Boot loader execution entry point. Clears out .bss section as per * ANSI C requirements. Invalidates and flushes the caches over the * range covered by the boot loader's .text section. Sets up a stack * below the .text section entry point. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <linux/config.h> #include "../../kernel/ppc_asm.tmpl" .text .globl _start _start: #ifdef XCOFF .long __start,0,0 .globl __start __start: #endif ## Flush and invalidate the caches for the range in memory covering ## the .text section of the boot loader lis r9,_start@h # r9 = &_start lis r8,_etext@ha # addi r8,r8,_etext@l # r8 = &_etext 3: dcbf r0,r9 # Flush the data cache icbi r0,r9 # Invalidate the instruction cache addi r9,r9,0x10 # Increment by one cache line cmplw cr0,r9,r8 # Are we at the end yet? blt 3b # No, keep flushing and invalidating sync # sync ; isync after flushing the icache isync ## Clear out the BSS as per ANSI C requirements lis r7,_end@ha addi r7,r7,_end@l # r7 = &_end lis r8,__bss_start@ha # addi r8,r8,__bss_start@l # r8 = &_bss_start ## Determine how large an area, in number of words, to clear subf r7,r8,r7 # r7 = &_end - &_bss_start + 1 addi r7,r7,3 # r7 += 3 srwi. r7,r7,2 # r7 = size in words. beq 2f # If the size is zero, do not bother addi r8,r8,-4 # r8 -= 4 mtctr r7 # SPRN_CTR = number of words to clear li r0,0 # r0 = 0 1: stwu r0,4(r8) # Clear out a word bdnz 1b # If we are not done yet, keep clearing 2: #ifdef CONFIG_4xx ## Set up the stack lis r9,_start@h # r9 = &_start (text section entry) addi r9,r9,_start@l subi r1,r9,64 # Start the stack 64 bytes below _start clrrwi r1,r1,4 # Make sure it is aligned on 16 bytes. li r0,0 stwu r0,-16(r1) mtlr r9 #endif b start # All done, start the real work. --- NEW FILE --- /* * arch/ppc/boot/common/misc-common.c * * Misc. bootloader code (almost) all platforms can use * * Author: Johnnie Peters <jp...@mv...> * Editor: Tom Rini <tr...@mv...> * * Derived from arch/ppc/boot/prep/misc.c * * Copyright 2000-2001 MontaVista Software Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdarg.h> /* for va_ bits */ #include <linux/config.h> #include "zlib.h" #include "nonstdio.h" /* If we're on a ALL_PPC, assume we have a keyboard controller * Also note, if we're not ALL_PPC, we assume you are a serial * console - Tom */ #if defined(CONFIG_ALL_PPC) && defined(CONFIG_VGA_CONSOLE) extern void cursor(int x, int y); extern void scroll(void); extern char *vidmem; extern int lines, cols; extern int orig_x, orig_y; extern int keyb_present; extern int CRT_tstc(void); extern int CRT_getc(void); #else int cursor(int x, int y) {return 0;} void scroll(void) {} char vidmem[1]; #define lines 0 #define cols 0 int orig_x = 0; int orig_y = 0; #define keyb_present 0 int CRT_tstc(void) {return 0;} int CRT_getc(void) {return 0;} #endif extern char *avail_ram; extern char *end_avail; extern char _end[]; void puts(const char *); void putc(const char c); void puthex(unsigned long val); void _bcopy(char *src, char *dst, int len); void gunzip(void *, int, unsigned char *, int *); static int _cvt(unsigned long val, char *buf, long radix, char *digits); void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap); unsigned char *ISA_io = NULL; #if defined(CONFIG_SERIAL_CONSOLE) extern unsigned long com_port; extern int serial_tstc(unsigned long com_port); extern unsigned char serial_getc(unsigned long com_port); extern void serial_putc(unsigned long com_port, unsigned char c); #endif void pause(void) { puts("pause\n"); } void exit(void) { puts("exit\n"); while(1); } int tstc(void) { #if defined(CONFIG_SERIAL_CONSOLE) if(keyb_present) return (CRT_tstc() || serial_tstc(com_port)); else return (serial_tstc(com_port)); #else return CRT_tstc(); #endif } int getc(void) { while (1) { #if defined(CONFIG_SERIAL_CONSOLE) if (serial_tstc(com_port)) return (serial_getc(com_port)); #endif /* CONFIG_SERIAL_CONSOLE */ if (keyb_present) if(CRT_tstc()) return (CRT_getc()); } } void putc(const char c) { int x,y; #if defined(CONFIG_SERIAL_CONSOLE) serial_putc(com_port, c); if ( c == '\n' ) serial_putc(com_port, '\r'); #endif /* CONFIG_SERIAL_CONSOLE */ x = orig_x; y = orig_y; if ( c == '\n' ) { x = 0; if ( ++y >= lines ) { scroll(); y--; } } else if (c == '\r') { x = 0; } else if (c == '\b') { if (x > 0) { x--; } } else { vidmem [ ( x + cols * y ) * 2 ] = c; if ( ++x >= cols ) { x = 0; if ( ++y >= lines ) { scroll(); y--; } } } cursor(x, y); orig_x = x; orig_y = y; } void puts(const char *s) { int x,y; char c; x = orig_x; y = orig_y; while ( ( c = *s++ ) != '\0' ) { #if defined(CONFIG_SERIAL_CONSOLE) serial_putc(com_port, c); if ( c == '\n' ) serial_putc(com_port, '\r'); #endif /* CONFIG_SERIAL_CONSOLE */ if ( c == '\n' ) { x = 0; if ( ++y >= lines ) { scroll(); y--; } } else if (c == '\b') { if (x > 0) { x--; } } else { vidmem [ ( x + cols * y ) * 2 ] = c; if ( ++x >= cols ) { x = 0; if ( ++y >= lines ) { scroll(); y--; } } } } cursor(x, y); orig_x = x; orig_y = y; } void error(char *x) { puts("\n\n"); puts(x); puts("\n\n -- System halted"); while(1); /* Halt */ } void *zalloc(void *x, unsigned items, unsigned size) { void *p = avail_ram; size *= items; size = (size + 7) & -8; avail_ram += size; if (avail_ram > end_avail) { puts("oops... out of memory\n"); pause(); } return p; } void zfree(void *x, void *addr, unsigned nb) { } #define HEAD_CRC 2 #define EXTRA_FIELD 4 #define ORIG_NAME 8 #define COMMENT 0x10 #define RESERVED 0xe0 #define DEFLATED 8 void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) { z_stream s; int r, i, flags; /* skip header */ i = 10; flags = src[3]; if (src[2] != DEFLATED || (flags & RESERVED) != 0) { puts("bad gzipped data\n"); exit(); } if ((flags & EXTRA_FIELD) != 0) i = 12 + src[10] + (src[11] << 8); if ((flags & ORIG_NAME) != 0) while (src[i++] != 0) ; if ((flags & COMMENT) != 0) while (src[i++] != 0) ; if ((flags & HEAD_CRC) != 0) i += 2; if (i >= *lenp) { puts("gunzip: ran out of data in header\n"); exit(); } s.zalloc = zalloc; s.zfree = zfree; r = inflateInit2(&s, -MAX_WBITS); if (r != Z_OK) { puts("inflateInit2 returned "); puthex(r); puts("\n"); exit(); } s.next_in = src + i; s.avail_in = *lenp - i; s.next_out = dst; s.avail_out = dstlen; r = inflate(&s, Z_FINISH); if (r != Z_OK && r != Z_STREAM_END) { puts("inflate returned "); puthex(r); puts("\n"); exit(); } *lenp = s.next_out - (unsigned char *) dst; inflateEnd(&s); } void puthex(unsigned long val) { unsigned char buf[10]; int i; for (i = 7; i >= 0; i--) { buf[i] = "0123456789ABCDEF"[val & 0x0F]; val >>= 4; } buf[8] = '\0'; puts(buf); } #define FALSE 0 #define TRUE 1 void _printk(char const *fmt, ...) { va_list ap; va_start(ap, fmt); _vprintk(putc, fmt, ap); va_end(ap); return; } #define is_digit(c) ((c >= '0') && (c <= '9')) void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap) { char c, sign, *cp = 0; int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right; char buf[32]; long val; while ((c = *fmt0++)) { if (c == '%') { c = *fmt0++; left_prec = right_prec = pad_on_right = 0; if (c == '-') { c = *fmt0++; pad_on_right++; } if (c == '0') { zero_fill = TRUE; c = *fmt0++; } else { zero_fill = FALSE; } while (is_digit(c)) { left_prec = (left_prec * 10) + (c - '0'); c = *fmt0++; } if (c == '.') { c = *fmt0++; zero_fill++; while (is_digit(c)) { right_prec = (right_prec * 10) + (c - '0'); c = *fmt0++; } } else { right_prec = left_prec; } sign = '\0'; switch (c) { case 'd': case 'x': case 'X': val = va_arg(ap, long); switch (c) { case 'd': if (val < 0) { sign = '-'; val = -val; } length = _cvt(val, buf, 10, "0123456789"); break; case 'x': length = _cvt(val, buf, 16, "0123456789abcdef"); break; case 'X': length = _cvt(val, buf, 16, "0123456789ABCDEF"); break; } cp = buf; break; case 's': cp = va_arg(ap, char *); length = strlen(cp); break; case 'c': c = va_arg(ap, long /*char*/); (*putc)(c); continue; default: (*putc)('?'); } pad = left_prec - length; if (sign != '\0') { pad--; } if (zero_fill) { c = '0'; if (sign != '\0') { (*putc)(sign); sign = '\0'; } } else { c = ' '; } if (!pad_on_right) { while (pad-- > 0) { (*putc)(c); } } if (sign != '\0') { (*putc)(sign); } while (length-- > 0) { (*putc)(c = *cp++); if (c == '\n') { (*putc)('\r'); } } if (pad_on_right) { while (pad-- > 0) { (*putc)(c); } } } else { (*putc)(c); if (c == '\n') { (*putc)('\r'); } } } } int _cvt(unsigned long val, char *buf, long radix, char *digits) { char temp[80]; char *cp = temp; int length = 0; if (val == 0) { /* Special case */ *cp++ = '0'; } else while (val) { *cp++ = digits[val % radix]; val /= radix; } while (cp != temp) { *buf++ = *--cp; length++; } *buf = '\0'; return (length); } void _dump_buf_with_offset(unsigned char *p, int s, unsigned char *base) { int i, c; if ((unsigned int)s > (unsigned int)p) { s = (unsigned int)s - (unsigned int)p; } while (s > 0) { if (base) { _printk("%06X: ", (int)p - (int)base); } else { _printk("%06X: ", p); } for (i = 0; i < 16; i++) { if (i < s) { _printk("%02X", p[i] & 0xFF); } else { _printk(" "); } if ((i % 2) == 1) _printk(" "); if ((i % 8) == 7) _printk(" "); } _printk(" |"); for (i = 0; i < 16; i++) { if (i < s) { c = p[i] & 0xFF; if ((c < 0x20) || (c >= 0x7F)) c = '.'; } else { c = ' '; } _printk("%c", c); } _printk("|\n"); s -= 16; p += 16; } } void _dump_buf(unsigned char *p, int s) { _printk("\n"); _dump_buf_with_offset(p, s, 0); } /* Very simple inb/outb routines. We declare ISA_io to be 0 above, and * then modify it on platforms which need to. We do it like this * because on some platforms we give inb/outb an exact location, and * on others it's an offset from a given location. -- Tom */ void outb(int port, unsigned char val) { /* Ensure I/O operations complete */ __asm__ volatile("eieio"); ISA_io[port] = val; } unsigned char inb(int port) { /* Ensure I/O operations complete */ __asm__ volatile("eieio"); return (ISA_io[port]); } /* * Local variables: * c-indent-level: 8 * c-basic-offset: 8 * tab-width: 8 * End: */ --- NEW FILE --- /* * arch/ppc/common/misc-simple.c * * Misc. bootloader code for many machines. This assumes you have are using * a 6xx/7xx/74xx CPU in your machine. This assumes the chunk of memory * below 8MB is free. Finally, it assumes you have a NS16550-style uart for * your serial console. If a machine meets these requirements, it can quite * likely use this code during boot. * * Author: Matt Porter <mp...@mv...> * Derived from arch/ppc/boot/prep/misc.c * * Copyright 2001 MontaVista Software Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ #include <linux/types.h> #include <linux/elf.h> #include <linux/config.h> #include <asm/page.h> #include <asm/processor.h> #include <asm/mmu.h> #include "nonstdio.h" #include "zlib.h" unsigned long com_port; char *avail_ram; char *end_avail; extern char _end[]; #ifdef CONFIG_CMDLINE #define CMDLINE CONFIG_CMDLINE #else #define CMDLINE "" #endif char cmd_preset[] = CMDLINE; char cmd_buf[256]; char *cmd_line = cmd_buf; unsigned long initrd_start = 0, initrd_end = 0; char *zimage_start; int zimage_size; extern void gunzip(void *, int, unsigned char *, int *); extern unsigned long serial_init(int chan); void decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) { int timer = 0; extern unsigned long start; char *cp, ch; com_port = serial_init(0); /* assume the chunk below 8M is free */ end_avail = (char *)0x00800000; /* * Reveal where we were loaded at and where we * were relocated to. */ puts("loaded at: "); puthex(load_addr); puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); if ( (unsigned long)load_addr != (unsigned long)&start ) { puts("relocated to: "); puthex((unsigned long)&start); puts(" "); puthex((unsigned long)((unsigned long)&start + (4*num_words))); puts("\n"); } /* we have to subtract 0x10000 here to correct for objdump including the size of the elf header which we strip -- Cort */ zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET); zimage_size = ZIMAGE_SIZE; if ( INITRD_OFFSET ) initrd_start = load_addr - 0x10000 + INITRD_OFFSET; else initrd_start = 0; initrd_end = INITRD_SIZE + initrd_start; /* * Find a place to stick the zimage and initrd and * relocate them if we have to. -- Cort */ avail_ram = (char *)PAGE_ALIGN((unsigned long)_end); puts("zimage at: "); puthex((unsigned long)zimage_start); puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n"); if ( (unsigned long)zimage_start <= 0x00800000 ) { memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size ); zimage_start = (char *)avail_ram; puts("relocated to: "); puthex((unsigned long)zimage_start); puts(" "); puthex((unsigned long)zimage_size+(unsigned long)zimage_start); puts("\n"); /* relocate initrd */ if ( initrd_start ) { puts("initrd at: "); puthex(initrd_start); puts(" "); puthex(initrd_end); puts("\n"); avail_ram = (char *)PAGE_ALIGN( (unsigned long)zimage_size+(unsigned long)zimage_start); memcpy ((void *)avail_ram, (void *)initrd_start, INITRD_SIZE ); initrd_start = (unsigned long)avail_ram; initrd_end = initrd_start + INITRD_SIZE; puts("relocated to: "); puthex(initrd_start); puts(" "); puthex(initrd_end); puts("\n"); } } else if ( initrd_start ) { puts("initrd at: "); puthex(initrd_start); puts(" "); puthex(initrd_end); puts("\n"); } avail_ram = (char *)0x00400000; end_avail = (char *)0x00800000; puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); puthex((unsigned long)end_avail); puts("\n"); /* Display standard Linux/PPC boot prompt for kernel args */ puts("\nLinux/PPC load: "); cp = cmd_line; memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); while ( *cp ) putc(*cp++); while (timer++ < 5*1000) { if (tstc()) { while ((ch = getc()) != '\n' && ch != '\r') { /* Test for backspace/delete */ if (ch == '\b' || ch == '\177') { if (cp != cmd_line) { cp--; puts("\b \b"); } /* Test for ^x/^u (and wipe the line) */ } else if (ch == '\030' || ch == '\025') { while (cp != cmd_line) { cp--; puts("\b \b"); } } else { *cp++ = ch; putc(ch); } } break; /* Exit 'timer' loop */ } udelay(1000); /* 1 msec */ } *cp = 0; puts("\n"); /* mappings on early boot can only handle 16M */ if ( (int)(cmd_line[0]) > (16<<20)) puts("cmd_line located > 16M\n"); if ( initrd_start > (16<<20)) puts("initrd_start located > 16M\n"); puts("Uncompressing Linux..."); gunzip(0, 0x400000, zimage_start, &zimage_size); puts("done.\n"); puts("Now booting the kernel\n"); } --- NEW FILE --- /* * BK Id: SCCS/s.no_initrd.c 1.7 05/18/01 15:17:23 cort */ char initrd_data[1]; int initrd_len = 0; --- NEW FILE --- /* * BK Id: SCCS/s.ns16550.c 1.9 07/30/01 17:19:40 trini */ /* * COM1 NS16550 support */ #include <linux/config.h> #include <linux/serialP.h> #include <linux/serial_reg.h> #include <asm/serial.h> extern void outb(int port, unsigned char val); extern unsigned char inb(int port); extern unsigned long ISA_io; static struct serial_state rs_table[RS_TABLE_SIZE] = { SERIAL_PORT_DFNS /* Defined in <asm/serial.h> */ }; static int shift; unsigned long serial_init(int chan) { unsigned long com_port; /* We need to find out which type io we're expecting. If it's * 'SERIAL_IO_PORT', we get an offset from the isa_io_base. * If it's 'SERIAL_IO_MEM', we can the exact location. -- Tom */ switch (rs_table[chan].io_type) { case SERIAL_IO_PORT: com_port = rs_table[chan].port; break; case SERIAL_IO_MEM: com_port = (unsigned long)rs_table[chan].iomem_base; break; default: /* We can't deal with it. */ return -1; } /* How far apart the registers are. */ shift = rs_table[chan].iomem_reg_shift; /* See if port is present */ outb(com_port + (UART_LCR << shift), 0x00); outb(com_port + (UART_IER << shift), 0x00); /* Access baud rate */ outb(com_port + (UART_LCR << shift), 0x80); #ifdef CONFIG_SERIAL_CONSOLE_NONSTD /* Input clock. */ outb(com_port + (UART_DLL << shift), (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD)); outb(com_port + (UART_DLM << shift), (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD) >> 8); #endif /* 8 data, 1 stop, no parity */ outb(com_port + (UART_LCR << shift), 0x03); /* RTS/DTR */ outb(com_port + (UART_MCR << shift), 0x03); /* Clear & enable FIFOs */ outb(com_port + (UART_FCR << shift), 0x07); return (com_port); } void serial_putc(unsigned long com_port, unsigned char c) { while ((inb(com_port + (UART_LSR << shift)) & UART_LSR_THRE) == 0) ; outb(com_port, c); } unsigned char serial_getc(unsigned long com_port) { while ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) == 0) ; return inb(com_port); } int serial_tstc(unsigned long com_port) { return ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0); } --- NEW FILE --- /* * BK Id: SCCS/s.ofcommon.c 1.1 07/27/01 20:24:18 trini * * Copyright (C) Paul Mackerras 1997. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include "zlib.h" #include "nonstdio.h" #include <asm/bootinfo.h> #include <asm/page.h> extern int strcmp(const char *s1, const char *s2); extern char *avail_ram, *avail_high; extern char *end_avail; extern void claim(unsigned int virt, unsigned int size, unsigned int align); extern void pause(void); unsigned int heap_use, heap_max; struct memchunk { unsigned int size; struct memchunk *next; }; static struct memchunk *freechunks; static void *zalloc(void *x, unsigned items, unsigned size) { void *p; struct memchunk **mpp, *mp; size *= items; size = (size + 7) & -8; heap_use += size; if (heap_use > heap_max) heap_max = heap_use; for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { if (mp->size == size) { *mpp = mp->next; return mp; } } p = avail_ram; avail_ram += size; if (avail_ram > avail_high) avail_high = avail_ram; if (avail_ram > end_avail) { printf("oops... out of memory\n\r"); pause(); } return p; } static void zfree(void *x, void *addr, unsigned nb) { struct memchunk *mp = addr; nb = (nb + 7) & -8; heap_use -= nb; if (avail_ram == addr + nb) { avail_ram = addr; return; } mp->size = nb; mp->next = freechunks; freechunks = mp; } #define HEAD_CRC 2 #define EXTRA_FIELD 4 #define ORIG_NAME 8 #define COMMENT 0x10 #define RESERVED 0xe0 #define DEFLATED 8 void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) { z_stream s; int r, i, flags; /* skip header */ i = 10; flags = src[3]; if (src[2] != DEFLATED || (flags & RESERVED) != 0) { printf("bad gzipped data\n\r"); exit(); } if ((flags & EXTRA_FIELD) != 0) i = 12 + src[10] + (src[11] << 8); if ((flags & ORIG_NAME) != 0) while (src[i++] != 0) ; if ((flags & COMMENT) != 0) while (src[i++] != 0) ; if ((flags & HEAD_CRC) != 0) i += 2; if (i >= *lenp) { printf("gunzip: ran out of data in header\n\r"); exit(); } s.zalloc = zalloc; s.zfree = zfree; r = inflateInit2(&s, -MAX_WBITS); if (r != Z_OK) { printf("inflateInit2 returned %d\n\r", r); exit(); } s.next_in = src + i; s.avail_in = *lenp - i; s.next_out = dst; s.avail_out = dstlen; r = inflate(&s, Z_FINISH); if (r != Z_OK && r != Z_STREAM_END) { printf("inflate returned %d msg: %s\n\r", r, s.msg); exit(); } *lenp = s.next_out - (unsigned char *) dst; inflateEnd(&s); } /* Make a bi_rec in OF. We need to be passed a name for BI_BOOTLOADER_ID, * a machine type for BI_MACHTYPE, and the location where the end of the * bootloader is (PROG_START + PROG_SIZE) */ void make_bi_recs(unsigned long addr, char *name, unsigned int mach, unsigned long progend) { struct bi_record *rec; /* leave a 1MB gap then align to the next 1MB boundary */ addr = _ALIGN(addr+ (1<<20) - 1, (1<<20)); /* oldworld machine seem very unhappy about this. -- Tom */ if (addr >= progend) claim(addr, 0x1000, 0); rec = (struct bi_record *)addr; rec->tag = BI_FIRST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_BOOTLOADER_ID; sprintf( (char *)rec->data, name); rec->size = sizeof(struct bi_record) + strlen(name) + 1; rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_MACHTYPE; rec->data[0] = mach; rec->data[1] = 1; rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); #ifdef SYSMAP_OFFSET rec->tag = BI_SYSMAP; rec->data[0] = SYSMAP_OFFSET; rec->data[1] = SYSMAP_SIZE; rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); #endif /* SYSMAP_OFFSET */ rec->tag = BI_LAST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); } --- NEW FILE --- /* * BK Id: SCCS/s.string.S 1.8 05/18/01 06:20:29 patch */ /* * String handling functions for PowerPC. * * Copyright (C) 1996 Paul Mackerras. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #define r0 0 #define r3 3 #define r4 4 #define r5 5 #define r6 6 #define r7 7 #define r8 8 .globl strlen strlen: addi r4,r3,-1 1: lbzu r0,1(r4) cmpwi 0,r0,0 bne 1b subf r3,r3,r4 blr .globl memset memset: rlwimi r4,r4,8,16,23 rlwimi r4,r4,16,0,15 addi r6,r3,-4 cmplwi 0,r5,4 blt 7f stwu r4,4(r6) beqlr andi. r0,r6,3 add r5,r0,r5 subf r6,r0,r6 rlwinm r0,r5,32-2,2,31 mtctr r0 bdz 6f 1: stwu r4,4(r6) bdnz 1b 6: andi. r5,r5,3 7: cmpwi 0,r5,0 beqlr mtctr r5 addi r6,r6,3 8: stbu r4,1(r6) bdnz 8b blr .globl memmove memmove: cmplw 0,r3,r4 bgt backwards_memcpy /* fall through */ .globl memcpy memcpy: rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ addi r6,r3,-4 addi r4,r4,-4 beq 2f /* if less than 8 bytes to do */ andi. r0,r6,3 /* get dest word aligned */ mtctr r7 bne 5f 1: lwz r7,4(r4) lwzu r8,8(r4) stw r7,4(r6) stwu r8,8(r6) bdnz 1b andi. r5,r5,7 2: cmplwi 0,r5,4 blt 3f lwzu r0,4(r4) addi r5,r5,-4 stwu r0,4(r6) 3: cmpwi 0,r5,0 beqlr mtctr r5 addi r4,r4,3 addi r6,r6,3 4: lbzu r0,1(r4) stbu r0,1(r6) bdnz 4b blr 5: subfic r0,r0,4 mtctr r0 6: lbz r7,4(r4) addi r4,r4,1 stb r7,4(r6) addi r6,r6,1 bdnz 6b subf r5,r0,r5 rlwinm. r7,r5,32-3,3,31 beq 2b mtctr r7 b 1b .globl backwards_memcpy backwards_memcpy: rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ add r6,r3,r5 add r4,r4,r5 beq 2f andi. r0,r6,3 mtctr r7 bne 5f 1: lwz r7,-4(r4) lwzu r8,-8(r4) stw r7,-4(r6) stwu r8,-8(r6) bdnz 1b andi. r5,r5,7 2: cmplwi 0,r5,4 blt 3f lwzu r0,-4(r4) subi r5,r5,4 stwu r0,-4(r6) 3: cmpwi 0,r5,0 beqlr mtctr r5 4: lbzu r0,-1(r4) stbu r0,-1(r6) bdnz 4b blr 5: mtctr r0 6: lbzu r7,-1(r4) stbu r7,-1(r6) bdnz 6b subf r5,r0,r5 rlwinm. r7,r5,32-3,3,31 beq 2b mtctr r7 b 1b .globl memcmp memcmp: cmpwi 0,r5,0 blelr mtctr r5 addi r6,r3,-1 addi r4,r4,-1 1: lbzu r3,1(r6) lbzu r0,1(r4) subf. r3,r0,r3 bdnzt 2,1b blr |