mirror of
				https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
				synced 2025-10-29 23:28:52 +01:00 
			
		
		
		
	Fixed MTP to work with TWRP
This commit is contained in:
		
						commit
						f6dfaef42e
					
				
					 50820 changed files with 20846062 additions and 0 deletions
				
			
		
							
								
								
									
										116
									
								
								arch/alpha/boot/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								arch/alpha/boot/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,116 @@ | |||
| #
 | ||||
| # arch/alpha/boot/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.
 | ||||
| #
 | ||||
| # Copyright (C) 1994 by Linus Torvalds
 | ||||
| #
 | ||||
| 
 | ||||
| hostprogs-y	:= tools/mkbb tools/objstrip | ||||
| targets		:= vmlinux.gz vmlinux \
 | ||||
| 		   vmlinux.nh tools/lxboot tools/bootlx tools/bootph \
 | ||||
| 		   tools/bootpzh bootloader bootpheader bootpzheader  | ||||
| OBJSTRIP	:= $(obj)/tools/objstrip | ||||
| 
 | ||||
| # SRM bootable image.  Copy to offset 512 of a partition.
 | ||||
| $(obj)/bootimage: $(addprefix $(obj)/tools/,mkbb lxboot bootlx) $(obj)/vmlinux.nh | ||||
| 	( cat $(obj)/tools/lxboot $(obj)/tools/bootlx $(obj)/vmlinux.nh ) > $@  | ||||
| 	$(obj)/tools/mkbb $@ $(obj)/tools/lxboot | ||||
| 	@echo '  Bootimage $@ is ready' | ||||
| 
 | ||||
| # BOOTP bootable image.  Define INITRD during make to append initrd image.
 | ||||
| $(obj)/bootpfile: $(obj)/tools/bootph $(obj)/vmlinux.nh | ||||
| 	cat $(obj)/tools/bootph $(obj)/vmlinux.nh > $@ | ||||
| ifdef INITRD | ||||
| 	cat $(INITRD) >> $@ | ||||
| endif | ||||
| 
 | ||||
| # Compressed kernel BOOTP bootable image.
 | ||||
| # Define INITRD during make to append initrd image.
 | ||||
| $(obj)/bootpzfile: $(obj)/tools/bootpzh $(obj)/vmlinux.nh.gz | ||||
| 	cat $(obj)/tools/bootpzh $(obj)/vmlinux.nh.gz > $@ | ||||
| ifdef INITRD | ||||
| 	cat $(INITRD) >> $@ | ||||
| endif | ||||
| 
 | ||||
| # Compressed kernel image
 | ||||
| $(obj)/vmlinux.gz: $(obj)/vmlinux FORCE | ||||
| 	$(call if_changed,gzip) | ||||
| 	@echo '  Kernel $@ is ready' | ||||
| 
 | ||||
| $(obj)/main.o: $(obj)/ksize.h | ||||
| $(obj)/bootp.o: $(obj)/ksize.h | ||||
| $(obj)/bootpz.o: $(obj)/kzsize.h | ||||
| 
 | ||||
| $(obj)/ksize.h: $(obj)/vmlinux.nh FORCE | ||||
| 	echo "#define KERNEL_SIZE `ls -l $(obj)/vmlinux.nh | awk '{print $$5}'`" > $@T | ||||
| ifdef INITRD | ||||
| 	[ -f $(INITRD) ] || exit 1 | ||||
| 	echo "#define INITRD_IMAGE_SIZE `ls -l $(INITRD) | awk '{print $$5}'`" >> $@T | ||||
| endif | ||||
| 	cmp -s $@T $@ || mv -f $@T $@ | ||||
| 	rm -f $@T | ||||
| 
 | ||||
| $(obj)/kzsize.h: $(obj)/vmlinux.nh.gz FORCE | ||||
| 	echo "#define KERNEL_SIZE `ls -l $(obj)/vmlinux.nh | awk '{print $$5}'`" > $@T | ||||
| 	echo "#define KERNEL_Z_SIZE `ls -l $(obj)/vmlinux.nh.gz | awk '{print $$5}'`" >> $@T | ||||
| ifdef INITRD | ||||
| 	[ -f $(INITRD) ] || exit 1 | ||||
| 	echo "#define INITRD_IMAGE_SIZE `ls -l $(INITRD) | awk '{print $$5}'`" >> $@T | ||||
| endif | ||||
| 	cmp -s $@T $@ || mv -f $@T $@ | ||||
| 	rm -f $@T | ||||
| 
 | ||||
| quiet_cmd_strip = STRIP  $@ | ||||
|       cmd_strip = $(STRIP) -o $@ $< | ||||
| 
 | ||||
| $(obj)/vmlinux: vmlinux FORCE | ||||
| 	$(call if_changed,strip) | ||||
| 
 | ||||
| quiet_cmd_objstrip = OBJSTRIP $@ | ||||
|       cmd_objstrip = $(OBJSTRIP) $(OSFLAGS_$(@F)) $< $@ | ||||
| 
 | ||||
| OSFLAGS_vmlinux.nh	:= -v | ||||
| OSFLAGS_lxboot		:= -p | ||||
| OSFLAGS_bootlx		:= -vb | ||||
| OSFLAGS_bootph		:= -vb | ||||
| OSFLAGS_bootpzh		:= -vb | ||||
| 
 | ||||
| $(obj)/vmlinux.nh: vmlinux $(OBJSTRIP) FORCE | ||||
| 	$(call if_changed,objstrip) | ||||
| 
 | ||||
| $(obj)/vmlinux.nh.gz: $(obj)/vmlinux.nh FORCE | ||||
| 	$(call if_changed,gzip) | ||||
| 
 | ||||
| $(obj)/tools/lxboot: $(obj)/bootloader $(OBJSTRIP) FORCE | ||||
| 	$(call if_changed,objstrip) | ||||
| 
 | ||||
| $(obj)/tools/bootlx: $(obj)/bootloader $(OBJSTRIP) FORCE | ||||
| 	$(call if_changed,objstrip) | ||||
| 
 | ||||
| $(obj)/tools/bootph: $(obj)/bootpheader $(OBJSTRIP) FORCE | ||||
| 	$(call if_changed,objstrip) | ||||
| 
 | ||||
| $(obj)/tools/bootpzh: $(obj)/bootpzheader $(OBJSTRIP) FORCE | ||||
| 	$(call if_changed,objstrip) | ||||
| 
 | ||||
| LDFLAGS_bootloader   := -static -uvsprintf -T  #-N -relax | ||||
| LDFLAGS_bootpheader  := -static -uvsprintf -T  #-N -relax | ||||
| LDFLAGS_bootpzheader := -static -uvsprintf -T  #-N -relax | ||||
| 
 | ||||
| OBJ_bootlx   := $(obj)/head.o $(obj)/main.o | ||||
| OBJ_bootph   := $(obj)/head.o $(obj)/bootp.o | ||||
| OBJ_bootpzh  := $(obj)/head.o $(obj)/bootpz.o $(obj)/misc.o | ||||
| 
 | ||||
| $(obj)/bootloader: $(obj)/bootloader.lds $(OBJ_bootlx) $(LIBS_Y) FORCE | ||||
| 	$(call if_changed,ld) | ||||
| 
 | ||||
| $(obj)/bootpheader: $(obj)/bootloader.lds $(OBJ_bootph) $(LIBS_Y) FORCE | ||||
| 	$(call if_changed,ld) | ||||
| 
 | ||||
| $(obj)/bootpzheader: $(obj)/bootloader.lds $(OBJ_bootpzh) $(LIBS_Y) FORCE | ||||
| 	$(call if_changed,ld) | ||||
| 
 | ||||
| $(obj)/misc.o: lib/inflate.c | ||||
							
								
								
									
										24
									
								
								arch/alpha/boot/bootloader.lds
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								arch/alpha/boot/bootloader.lds
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| OUTPUT_FORMAT("elf64-alpha") | ||||
| ENTRY(__start) | ||||
| printk = srm_printk; | ||||
| SECTIONS | ||||
| { | ||||
|   . = 0x20000000; | ||||
|   .text : { *(.text) } | ||||
|   _etext = .; | ||||
|   PROVIDE (etext = .); | ||||
|   .rodata : { *(.rodata) *(.rodata.*) } | ||||
|   .data : { *(.data) CONSTRUCTORS } | ||||
|   .got : { *(.got) } | ||||
|   .sdata : { *(.sdata) } | ||||
|   _edata = .; | ||||
|   PROVIDE (edata = .); | ||||
|   .sbss : { *(.sbss) *(.scommon) } | ||||
|   .bss : { *(.bss) *(COMMON) } | ||||
|   _end = . ; | ||||
|   PROVIDE (end = .); | ||||
| 
 | ||||
|   .mdebug 0 : { *(.mdebug) } | ||||
|   .note 0 : { *(.note) } | ||||
|   .comment 0 : { *(.comment) } | ||||
| } | ||||
							
								
								
									
										214
									
								
								arch/alpha/boot/bootp.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								arch/alpha/boot/bootp.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,214 @@ | |||
| /*
 | ||||
|  * arch/alpha/boot/bootp.c | ||||
|  * | ||||
|  * Copyright (C) 1997 Jay Estabrook | ||||
|  * | ||||
|  * This file is used for creating a bootp file for the Linux/AXP kernel | ||||
|  * | ||||
|  * based significantly on the arch/alpha/boot/main.c of Linus Torvalds | ||||
|  */ | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/string.h> | ||||
| #include <generated/utsrelease.h> | ||||
| #include <linux/mm.h> | ||||
| 
 | ||||
| #include <asm/console.h> | ||||
| #include <asm/hwrpb.h> | ||||
| #include <asm/pgtable.h> | ||||
| #include <asm/io.h> | ||||
| 
 | ||||
| #include <stdarg.h> | ||||
| 
 | ||||
| #include "ksize.h" | ||||
| 
 | ||||
| extern unsigned long switch_to_osf_pal(unsigned long nr, | ||||
| 	struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa, | ||||
| 	unsigned long *vptb); | ||||
| 
 | ||||
| extern void move_stack(unsigned long new_stack); | ||||
| 
 | ||||
| struct hwrpb_struct *hwrpb = INIT_HWRPB; | ||||
| static struct pcb_struct pcb_va[1]; | ||||
| 
 | ||||
| /*
 | ||||
|  * Find a physical address of a virtual object.. | ||||
|  * | ||||
|  * This is easy using the virtual page table address. | ||||
|  */ | ||||
| 
 | ||||
| static inline void * | ||||
| find_pa(unsigned long *vptb, void *ptr) | ||||
| { | ||||
| 	unsigned long address = (unsigned long) ptr; | ||||
| 	unsigned long result; | ||||
| 
 | ||||
| 	result = vptb[address >> 13]; | ||||
| 	result >>= 32; | ||||
| 	result <<= 13; | ||||
| 	result |= address & 0x1fff; | ||||
| 	return (void *) result; | ||||
| }	 | ||||
| 
 | ||||
| /*
 | ||||
|  * This function moves into OSF/1 pal-code, and has a temporary | ||||
|  * PCB for that. The kernel proper should replace this PCB with | ||||
|  * the real one as soon as possible. | ||||
|  * | ||||
|  * The page table muckery in here depends on the fact that the boot | ||||
|  * code has the L1 page table identity-map itself in the second PTE | ||||
|  * in the L1 page table. Thus the L1-page is virtually addressable | ||||
|  * itself (through three levels) at virtual address 0x200802000. | ||||
|  */ | ||||
| 
 | ||||
| #define VPTB	((unsigned long *) 0x200000000) | ||||
| #define L1	((unsigned long *) 0x200802000) | ||||
| 
 | ||||
| void | ||||
| pal_init(void) | ||||
| { | ||||
| 	unsigned long i, rev; | ||||
| 	struct percpu_struct * percpu; | ||||
| 	struct pcb_struct * pcb_pa; | ||||
| 
 | ||||
| 	/* Create the dummy PCB.  */ | ||||
| 	pcb_va->ksp = 0; | ||||
| 	pcb_va->usp = 0; | ||||
| 	pcb_va->ptbr = L1[1] >> 32; | ||||
| 	pcb_va->asn = 0; | ||||
| 	pcb_va->pcc = 0; | ||||
| 	pcb_va->unique = 0; | ||||
| 	pcb_va->flags = 1; | ||||
| 	pcb_va->res1 = 0; | ||||
| 	pcb_va->res2 = 0; | ||||
| 	pcb_pa = find_pa(VPTB, pcb_va); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * a0 = 2 (OSF) | ||||
| 	 * a1 = return address, but we give the asm the vaddr of the PCB | ||||
| 	 * a2 = physical addr of PCB | ||||
| 	 * a3 = new virtual page table pointer | ||||
| 	 * a4 = KSP (but the asm sets it) | ||||
| 	 */ | ||||
| 	srm_printk("Switching to OSF PAL-code .. "); | ||||
| 
 | ||||
| 	i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB); | ||||
| 	if (i) { | ||||
| 		srm_printk("failed, code %ld\n", i); | ||||
| 		__halt(); | ||||
| 	} | ||||
| 
 | ||||
| 	percpu = (struct percpu_struct *) | ||||
| 		(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB); | ||||
| 	rev = percpu->pal_revision = percpu->palcode_avail[2]; | ||||
| 
 | ||||
| 	srm_printk("Ok (rev %lx)\n", rev); | ||||
| 
 | ||||
| 	tbia(); /* do it directly in case we are SMP */ | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| load(unsigned long dst, unsigned long src, unsigned long count) | ||||
| { | ||||
| 	memcpy((void *)dst, (void *)src, count); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Start the kernel. | ||||
|  */ | ||||
| static inline void | ||||
| runkernel(void) | ||||
| { | ||||
| 	__asm__ __volatile__( | ||||
| 		"bis %0,%0,$27\n\t" | ||||
| 		"jmp ($27)" | ||||
| 		: /* no outputs: it doesn't even return */ | ||||
| 		: "r" (START_ADDR)); | ||||
| } | ||||
| 
 | ||||
| extern char _end; | ||||
| #define KERNEL_ORIGIN \ | ||||
| 	((((unsigned long)&_end) + 511) & ~511) | ||||
| 
 | ||||
| void | ||||
| start_kernel(void) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * Note that this crufty stuff with static and envval | ||||
| 	 * and envbuf is because: | ||||
| 	 * | ||||
| 	 * 1. Frequently, the stack is short, and we don't want to overrun; | ||||
| 	 * 2. Frequently the stack is where we are going to copy the kernel to; | ||||
| 	 * 3. A certain SRM console required the GET_ENV output to stack. | ||||
| 	 *    ??? A comment in the aboot sources indicates that the GET_ENV | ||||
| 	 *    destination must be quadword aligned.  Might this explain the | ||||
| 	 *    behaviour, rather than requiring output to the stack, which | ||||
| 	 *    seems rather far-fetched. | ||||
| 	 */ | ||||
| 	static long nbytes; | ||||
| 	static char envval[256] __attribute__((aligned(8))); | ||||
| 	static unsigned long initrd_start; | ||||
| 
 | ||||
| 	srm_printk("Linux/AXP bootp loader for Linux " UTS_RELEASE "\n"); | ||||
| 	if (INIT_HWRPB->pagesize != 8192) { | ||||
| 		srm_printk("Expected 8kB pages, got %ldkB\n", | ||||
| 		           INIT_HWRPB->pagesize >> 10); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (INIT_HWRPB->vptb != (unsigned long) VPTB) { | ||||
| 		srm_printk("Expected vptb at %p, got %p\n", | ||||
| 			   VPTB, (void *)INIT_HWRPB->vptb); | ||||
| 		return; | ||||
| 	} | ||||
| 	pal_init(); | ||||
| 
 | ||||
| 	/* The initrd must be page-aligned.  See below for the 
 | ||||
| 	   cause of the magic number 5.  */ | ||||
| 	initrd_start = ((START_ADDR + 5*KERNEL_SIZE + PAGE_SIZE) | | ||||
| 			(PAGE_SIZE-1)) + 1; | ||||
| #ifdef INITRD_IMAGE_SIZE | ||||
| 	srm_printk("Initrd positioned at %#lx\n", initrd_start); | ||||
| #endif | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Move the stack to a safe place to ensure it won't be | ||||
| 	 * overwritten by kernel image. | ||||
| 	 */ | ||||
| 	move_stack(initrd_start - PAGE_SIZE); | ||||
| 
 | ||||
| 	nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval)); | ||||
| 	if (nbytes < 0 || nbytes >= sizeof(envval)) { | ||||
| 		nbytes = 0; | ||||
| 	} | ||||
| 	envval[nbytes] = '\0'; | ||||
| 	srm_printk("Loading the kernel...'%s'\n", envval); | ||||
| 
 | ||||
| 	/* NOTE: *no* callbacks or printouts from here on out!!! */ | ||||
| 
 | ||||
| 	/* This is a hack, as some consoles seem to get virtual 20000000 (ie
 | ||||
| 	 * where the SRM console puts the kernel bootp image) memory | ||||
| 	 * overlapping physical memory where the kernel wants to be put, | ||||
| 	 * which causes real problems when attempting to copy the former to | ||||
| 	 * the latter... :-( | ||||
| 	 * | ||||
| 	 * So, we first move the kernel virtual-to-physical way above where | ||||
| 	 * we physically want the kernel to end up, then copy it from there | ||||
| 	 * to its final resting place... ;-} | ||||
| 	 * | ||||
| 	 * Sigh...  */ | ||||
| 
 | ||||
| #ifdef INITRD_IMAGE_SIZE | ||||
| 	load(initrd_start, KERNEL_ORIGIN+KERNEL_SIZE, INITRD_IMAGE_SIZE); | ||||
| #endif | ||||
|         load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE); | ||||
|         load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE); | ||||
| 
 | ||||
| 	memset((char*)ZERO_PGE, 0, PAGE_SIZE); | ||||
| 	strcpy((char*)ZERO_PGE, envval); | ||||
| #ifdef INITRD_IMAGE_SIZE | ||||
| 	((long *)(ZERO_PGE+256))[0] = initrd_start; | ||||
| 	((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE; | ||||
| #endif | ||||
| 
 | ||||
| 	runkernel(); | ||||
| } | ||||
							
								
								
									
										475
									
								
								arch/alpha/boot/bootpz.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										475
									
								
								arch/alpha/boot/bootpz.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,475 @@ | |||
| /*
 | ||||
|  * arch/alpha/boot/bootpz.c | ||||
|  * | ||||
|  * Copyright (C) 1997 Jay Estabrook | ||||
|  * | ||||
|  * This file is used for creating a compressed BOOTP file for the | ||||
|  * Linux/AXP kernel | ||||
|  * | ||||
|  * based significantly on the arch/alpha/boot/main.c of Linus Torvalds | ||||
|  * and the decompression code from MILO. | ||||
|  */ | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/string.h> | ||||
| #include <generated/utsrelease.h> | ||||
| #include <linux/mm.h> | ||||
| 
 | ||||
| #include <asm/console.h> | ||||
| #include <asm/hwrpb.h> | ||||
| #include <asm/pgtable.h> | ||||
| #include <asm/io.h> | ||||
| 
 | ||||
| #include <stdarg.h> | ||||
| 
 | ||||
| #include "kzsize.h" | ||||
| 
 | ||||
| /* FIXME FIXME FIXME */ | ||||
| #define MALLOC_AREA_SIZE 0x200000 /* 2MB for now */ | ||||
| /* FIXME FIXME FIXME */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|   WARNING NOTE | ||||
| 
 | ||||
|   It is very possible that turning on additional messages may cause | ||||
|   kernel image corruption due to stack usage to do the printing. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #undef DEBUG_CHECK_RANGE | ||||
| #undef DEBUG_ADDRESSES | ||||
| #undef DEBUG_LAST_STEPS | ||||
| 
 | ||||
| extern unsigned long switch_to_osf_pal(unsigned long nr, | ||||
| 	struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa, | ||||
| 	unsigned long *vptb); | ||||
| 
 | ||||
| extern int decompress_kernel(void* destination, void *source, | ||||
| 			     size_t ksize, size_t kzsize); | ||||
| 
 | ||||
| extern void move_stack(unsigned long new_stack); | ||||
| 
 | ||||
| struct hwrpb_struct *hwrpb = INIT_HWRPB; | ||||
| static struct pcb_struct pcb_va[1]; | ||||
| 
 | ||||
| /*
 | ||||
|  * Find a physical address of a virtual object.. | ||||
|  * | ||||
|  * This is easy using the virtual page table address. | ||||
|  */ | ||||
| #define VPTB	((unsigned long *) 0x200000000) | ||||
| 
 | ||||
| static inline unsigned long | ||||
| find_pa(unsigned long address) | ||||
| { | ||||
| 	unsigned long result; | ||||
| 
 | ||||
| 	result = VPTB[address >> 13]; | ||||
| 	result >>= 32; | ||||
| 	result <<= 13; | ||||
| 	result |= address & 0x1fff; | ||||
| 	return result; | ||||
| }	 | ||||
| 
 | ||||
| int | ||||
| check_range(unsigned long vstart, unsigned long vend, | ||||
| 	    unsigned long kstart, unsigned long kend) | ||||
| { | ||||
| 	unsigned long vaddr, kaddr; | ||||
| 
 | ||||
| #ifdef DEBUG_CHECK_RANGE | ||||
| 	srm_printk("check_range: V[0x%lx:0x%lx] K[0x%lx:0x%lx]\n", | ||||
| 		   vstart, vend, kstart, kend); | ||||
| #endif | ||||
| 	/* do some range checking for detecting an overlap... */ | ||||
| 	for (vaddr = vstart; vaddr <= vend; vaddr += PAGE_SIZE) | ||||
| 	{ | ||||
| 		kaddr = (find_pa(vaddr) | PAGE_OFFSET); | ||||
| 		if (kaddr >= kstart && kaddr <= kend) | ||||
| 		{ | ||||
| #ifdef DEBUG_CHECK_RANGE | ||||
| 			srm_printk("OVERLAP: vaddr 0x%lx kaddr 0x%lx" | ||||
| 				   " [0x%lx:0x%lx]\n", | ||||
| 				   vaddr, kaddr, kstart, kend); | ||||
| #endif | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This function moves into OSF/1 pal-code, and has a temporary | ||||
|  * PCB for that. The kernel proper should replace this PCB with | ||||
|  * the real one as soon as possible. | ||||
|  * | ||||
|  * The page table muckery in here depends on the fact that the boot | ||||
|  * code has the L1 page table identity-map itself in the second PTE | ||||
|  * in the L1 page table. Thus the L1-page is virtually addressable | ||||
|  * itself (through three levels) at virtual address 0x200802000. | ||||
|  */ | ||||
| 
 | ||||
| #define L1	((unsigned long *) 0x200802000) | ||||
| 
 | ||||
| void | ||||
| pal_init(void) | ||||
| { | ||||
| 	unsigned long i, rev; | ||||
| 	struct percpu_struct * percpu; | ||||
| 	struct pcb_struct * pcb_pa; | ||||
| 
 | ||||
| 	/* Create the dummy PCB.  */ | ||||
| 	pcb_va->ksp = 0; | ||||
| 	pcb_va->usp = 0; | ||||
| 	pcb_va->ptbr = L1[1] >> 32; | ||||
| 	pcb_va->asn = 0; | ||||
| 	pcb_va->pcc = 0; | ||||
| 	pcb_va->unique = 0; | ||||
| 	pcb_va->flags = 1; | ||||
| 	pcb_va->res1 = 0; | ||||
| 	pcb_va->res2 = 0; | ||||
| 	pcb_pa = (struct pcb_struct *)find_pa((unsigned long)pcb_va); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * a0 = 2 (OSF) | ||||
| 	 * a1 = return address, but we give the asm the vaddr of the PCB | ||||
| 	 * a2 = physical addr of PCB | ||||
| 	 * a3 = new virtual page table pointer | ||||
| 	 * a4 = KSP (but the asm sets it) | ||||
| 	 */ | ||||
| 	srm_printk("Switching to OSF PAL-code... "); | ||||
| 
 | ||||
| 	i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB); | ||||
| 	if (i) { | ||||
| 		srm_printk("failed, code %ld\n", i); | ||||
| 		__halt(); | ||||
| 	} | ||||
| 
 | ||||
| 	percpu = (struct percpu_struct *) | ||||
| 		(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB); | ||||
| 	rev = percpu->pal_revision = percpu->palcode_avail[2]; | ||||
| 
 | ||||
| 	srm_printk("OK (rev %lx)\n", rev); | ||||
| 
 | ||||
| 	tbia(); /* do it directly in case we are SMP */ | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Start the kernel. | ||||
|  */ | ||||
| static inline void | ||||
| runkernel(void) | ||||
| { | ||||
| 	__asm__ __volatile__( | ||||
| 		"bis %0,%0,$27\n\t" | ||||
| 		"jmp ($27)" | ||||
| 		: /* no outputs: it doesn't even return */ | ||||
| 		: "r" (START_ADDR)); | ||||
| } | ||||
| 
 | ||||
| /* Must record the SP (it is virtual) on entry, so we can make sure
 | ||||
|    not to overwrite it during movement or decompression. */ | ||||
| unsigned long SP_on_entry; | ||||
| 
 | ||||
| /* Calculate the kernel image address based on the end of the BOOTP
 | ||||
|    bootstrapper (ie this program). | ||||
| */ | ||||
| extern char _end; | ||||
| #define KERNEL_ORIGIN \ | ||||
| 	((((unsigned long)&_end) + 511) & ~511) | ||||
| 
 | ||||
| /* Round address to next higher page boundary. */ | ||||
| #define NEXT_PAGE(a)	(((a) | (PAGE_SIZE - 1)) + 1) | ||||
| 
 | ||||
| #ifdef INITRD_IMAGE_SIZE | ||||
| # define REAL_INITRD_SIZE INITRD_IMAGE_SIZE | ||||
| #else | ||||
| # define REAL_INITRD_SIZE 0 | ||||
| #endif | ||||
| 
 | ||||
| /* Defines from include/asm-alpha/system.h
 | ||||
| 
 | ||||
| 	BOOT_ADDR	Virtual address at which the consoles loads | ||||
| 			the BOOTP image. | ||||
| 
 | ||||
| 	KERNEL_START    KSEG address at which the kernel is built to run, | ||||
| 			which includes some initial data pages before the | ||||
| 			code. | ||||
| 
 | ||||
| 	START_ADDR	KSEG address of the entry point of kernel code. | ||||
| 
 | ||||
| 	ZERO_PGE	KSEG address of page full of zeroes, but  | ||||
| 			upon entry to kerne cvan be expected | ||||
| 			to hold the parameter list and possible | ||||
| 			INTRD information. | ||||
| 
 | ||||
|    These are used in the local defines below. | ||||
| */ | ||||
|    | ||||
| 
 | ||||
| /* Virtual addresses for the BOOTP image. Note that this includes the
 | ||||
|    bootstrapper code as well as the compressed kernel image, and | ||||
|    possibly the INITRD image. | ||||
| 
 | ||||
|    Oh, and do NOT forget the STACK, which appears to be placed virtually | ||||
|    beyond the end of the loaded image. | ||||
| */ | ||||
| #define V_BOOT_IMAGE_START	BOOT_ADDR | ||||
| #define V_BOOT_IMAGE_END	SP_on_entry | ||||
| 
 | ||||
| /* Virtual addresses for just the bootstrapper part of the BOOTP image. */ | ||||
| #define V_BOOTSTRAPPER_START	BOOT_ADDR | ||||
| #define V_BOOTSTRAPPER_END	KERNEL_ORIGIN | ||||
| 
 | ||||
| /* Virtual addresses for just the data part of the BOOTP
 | ||||
|    image. This may also include the INITRD image, but always | ||||
|    includes the STACK. | ||||
| */ | ||||
| #define V_DATA_START		KERNEL_ORIGIN | ||||
| #define V_INITRD_START		(KERNEL_ORIGIN + KERNEL_Z_SIZE) | ||||
| #define V_INTRD_END		(V_INITRD_START + REAL_INITRD_SIZE) | ||||
| #define V_DATA_END	 	V_BOOT_IMAGE_END | ||||
| 
 | ||||
| /* KSEG addresses for the uncompressed kernel.
 | ||||
| 
 | ||||
|    Note that the end address includes workspace for the decompression. | ||||
|    Note also that the DATA_START address is ZERO_PGE, to which we write | ||||
|    just before jumping to the kernel image at START_ADDR. | ||||
|  */ | ||||
| #define K_KERNEL_DATA_START	ZERO_PGE | ||||
| #define K_KERNEL_IMAGE_START	START_ADDR | ||||
| #define K_KERNEL_IMAGE_END	(START_ADDR + KERNEL_SIZE) | ||||
| 
 | ||||
| /* Define to where we may have to decompress the kernel image, before
 | ||||
|    we move it to the final position, in case of overlap. This will be | ||||
|    above the final position of the kernel. | ||||
| 
 | ||||
|    Regardless of overlap, we move the INITRD image to the end of this | ||||
|    copy area, because there needs to be a buffer area after the kernel | ||||
|    for "bootmem" anyway. | ||||
| */ | ||||
| #define K_COPY_IMAGE_START	NEXT_PAGE(K_KERNEL_IMAGE_END) | ||||
| /* Reserve one page below INITRD for the new stack. */ | ||||
| #define K_INITRD_START \ | ||||
|     NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE + PAGE_SIZE) | ||||
| #define K_COPY_IMAGE_END \ | ||||
|     (K_INITRD_START + REAL_INITRD_SIZE + MALLOC_AREA_SIZE) | ||||
| #define K_COPY_IMAGE_SIZE \ | ||||
|     NEXT_PAGE(K_COPY_IMAGE_END - K_COPY_IMAGE_START) | ||||
| 
 | ||||
| void | ||||
| start_kernel(void) | ||||
| { | ||||
| 	int must_move = 0; | ||||
| 
 | ||||
| 	/* Initialize these for the decompression-in-place situation,
 | ||||
| 	   which is the smallest amount of work and most likely to | ||||
| 	   occur when using the normal START_ADDR of the kernel | ||||
| 	   (currently set to 16MB, to clear all console code. | ||||
| 	*/ | ||||
| 	unsigned long uncompressed_image_start = K_KERNEL_IMAGE_START; | ||||
| 	unsigned long uncompressed_image_end = K_KERNEL_IMAGE_END; | ||||
| 
 | ||||
| 	unsigned long initrd_image_start = K_INITRD_START; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Note that this crufty stuff with static and envval | ||||
| 	 * and envbuf is because: | ||||
| 	 * | ||||
| 	 * 1. Frequently, the stack is short, and we don't want to overrun; | ||||
| 	 * 2. Frequently the stack is where we are going to copy the kernel to; | ||||
| 	 * 3. A certain SRM console required the GET_ENV output to stack. | ||||
| 	 *    ??? A comment in the aboot sources indicates that the GET_ENV | ||||
| 	 *    destination must be quadword aligned.  Might this explain the | ||||
| 	 *    behaviour, rather than requiring output to the stack, which | ||||
| 	 *    seems rather far-fetched. | ||||
| 	 */ | ||||
| 	static long nbytes; | ||||
| 	static char envval[256] __attribute__((aligned(8))); | ||||
| 	register unsigned long asm_sp asm("30"); | ||||
| 
 | ||||
| 	SP_on_entry = asm_sp; | ||||
| 
 | ||||
| 	srm_printk("Linux/Alpha BOOTPZ Loader for Linux " UTS_RELEASE "\n"); | ||||
| 
 | ||||
| 	/* Validity check the HWRPB. */ | ||||
| 	if (INIT_HWRPB->pagesize != 8192) { | ||||
| 		srm_printk("Expected 8kB pages, got %ldkB\n", | ||||
| 		           INIT_HWRPB->pagesize >> 10); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (INIT_HWRPB->vptb != (unsigned long) VPTB) { | ||||
| 		srm_printk("Expected vptb at %p, got %p\n", | ||||
| 			   VPTB, (void *)INIT_HWRPB->vptb); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	/* PALcode (re)initialization. */ | ||||
| 	pal_init(); | ||||
| 
 | ||||
| 	/* Get the parameter list from the console environment variable. */ | ||||
| 	nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval)); | ||||
| 	if (nbytes < 0 || nbytes >= sizeof(envval)) { | ||||
| 		nbytes = 0; | ||||
| 	} | ||||
| 	envval[nbytes] = '\0'; | ||||
| 
 | ||||
| #ifdef DEBUG_ADDRESSES | ||||
| 	srm_printk("START_ADDR 0x%lx\n", START_ADDR); | ||||
| 	srm_printk("KERNEL_ORIGIN 0x%lx\n", KERNEL_ORIGIN); | ||||
| 	srm_printk("KERNEL_SIZE 0x%x\n", KERNEL_SIZE); | ||||
| 	srm_printk("KERNEL_Z_SIZE 0x%x\n", KERNEL_Z_SIZE); | ||||
| #endif | ||||
| 
 | ||||
| 	/* Since all the SRM consoles load the BOOTP image at virtual
 | ||||
| 	 * 0x20000000, we have to ensure that the physical memory | ||||
| 	 * pages occupied by that image do NOT overlap the physical | ||||
| 	 * address range where the kernel wants to be run.  This | ||||
| 	 * causes real problems when attempting to cdecompress the | ||||
| 	 * former into the latter... :-( | ||||
| 	 * | ||||
| 	 * So, we may have to decompress/move the kernel/INITRD image | ||||
| 	 * virtual-to-physical someplace else first before moving | ||||
| 	 * kernel /INITRD to their final resting places... ;-} | ||||
| 	 * | ||||
| 	 * Sigh... | ||||
| 	 */ | ||||
| 
 | ||||
| 	/* First, check to see if the range of addresses occupied by
 | ||||
| 	   the bootstrapper part of the BOOTP image include any of the | ||||
| 	   physical pages into which the kernel will be placed for | ||||
| 	   execution. | ||||
| 
 | ||||
| 	   We only need check on the final kernel image range, since we | ||||
| 	   will put the INITRD someplace that we can be sure is not | ||||
| 	   in conflict. | ||||
| 	 */ | ||||
| 	if (check_range(V_BOOTSTRAPPER_START, V_BOOTSTRAPPER_END, | ||||
| 			K_KERNEL_DATA_START, K_KERNEL_IMAGE_END)) | ||||
| 	{ | ||||
| 		srm_printk("FATAL ERROR: overlap of bootstrapper code\n"); | ||||
| 		__halt(); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Next, check to see if the range of addresses occupied by
 | ||||
| 	   the compressed kernel/INITRD/stack portion of the BOOTP | ||||
| 	   image include any of the physical pages into which the | ||||
| 	   decompressed kernel or the INITRD will be placed for | ||||
| 	   execution. | ||||
| 	 */ | ||||
| 	if (check_range(V_DATA_START, V_DATA_END, | ||||
| 			K_KERNEL_IMAGE_START, K_COPY_IMAGE_END)) | ||||
| 	{ | ||||
| #ifdef DEBUG_ADDRESSES | ||||
| 		srm_printk("OVERLAP: cannot decompress in place\n"); | ||||
| #endif | ||||
| 		uncompressed_image_start = K_COPY_IMAGE_START; | ||||
| 		uncompressed_image_end = K_COPY_IMAGE_END; | ||||
| 		must_move = 1; | ||||
| 
 | ||||
| 		/* Finally, check to see if the range of addresses
 | ||||
| 		   occupied by the compressed kernel/INITRD part of | ||||
| 		   the BOOTP image include any of the physical pages | ||||
| 		   into which that part is to be copied for | ||||
| 		   decompression. | ||||
| 		*/ | ||||
| 		while (check_range(V_DATA_START, V_DATA_END, | ||||
| 				   uncompressed_image_start, | ||||
| 				   uncompressed_image_end)) | ||||
| 		{ | ||||
| #if 0 | ||||
| 			uncompressed_image_start += K_COPY_IMAGE_SIZE; | ||||
| 			uncompressed_image_end += K_COPY_IMAGE_SIZE; | ||||
| 			initrd_image_start += K_COPY_IMAGE_SIZE; | ||||
| #else | ||||
| 			/* Keep as close as possible to end of BOOTP image. */ | ||||
| 			uncompressed_image_start += PAGE_SIZE; | ||||
| 			uncompressed_image_end += PAGE_SIZE; | ||||
| 			initrd_image_start += PAGE_SIZE; | ||||
| #endif | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	srm_printk("Starting to load the kernel with args '%s'\n", envval); | ||||
| 
 | ||||
| #ifdef DEBUG_ADDRESSES | ||||
| 	srm_printk("Decompressing the kernel...\n" | ||||
| 		   "...from 0x%lx to 0x%lx size 0x%x\n", | ||||
| 		   V_DATA_START, | ||||
| 		   uncompressed_image_start, | ||||
| 		   KERNEL_SIZE); | ||||
| #endif | ||||
|         decompress_kernel((void *)uncompressed_image_start, | ||||
| 			  (void *)V_DATA_START, | ||||
| 			  KERNEL_SIZE, KERNEL_Z_SIZE); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Now, move things to their final positions, if/as required. | ||||
| 	 */ | ||||
| 
 | ||||
| #ifdef INITRD_IMAGE_SIZE | ||||
| 
 | ||||
| 	/* First, we always move the INITRD image, if present. */ | ||||
| #ifdef DEBUG_ADDRESSES | ||||
| 	srm_printk("Moving the INITRD image...\n" | ||||
| 		   " from 0x%lx to 0x%lx size 0x%x\n", | ||||
| 		   V_INITRD_START, | ||||
| 		   initrd_image_start, | ||||
| 		   INITRD_IMAGE_SIZE); | ||||
| #endif | ||||
| 	memcpy((void *)initrd_image_start, (void *)V_INITRD_START, | ||||
| 	       INITRD_IMAGE_SIZE); | ||||
| 
 | ||||
| #endif /* INITRD_IMAGE_SIZE */ | ||||
| 
 | ||||
| 	/* Next, we may have to move the uncompressed kernel to the
 | ||||
| 	   final destination. | ||||
| 	 */ | ||||
| 	if (must_move) { | ||||
| #ifdef DEBUG_ADDRESSES | ||||
| 		srm_printk("Moving the uncompressed kernel...\n" | ||||
| 			   "...from 0x%lx to 0x%lx size 0x%x\n", | ||||
| 			   uncompressed_image_start, | ||||
| 			   K_KERNEL_IMAGE_START, | ||||
| 			   (unsigned)KERNEL_SIZE); | ||||
| #endif | ||||
| 		/*
 | ||||
| 		 * Move the stack to a safe place to ensure it won't be | ||||
| 		 * overwritten by kernel image. | ||||
| 		 */ | ||||
| 		move_stack(initrd_image_start - PAGE_SIZE); | ||||
| 
 | ||||
| 		memcpy((void *)K_KERNEL_IMAGE_START, | ||||
| 		       (void *)uncompressed_image_start, KERNEL_SIZE); | ||||
| 	} | ||||
| 	 | ||||
| 	/* Clear the zero page, then move the argument list in. */ | ||||
| #ifdef DEBUG_LAST_STEPS | ||||
| 	srm_printk("Preparing ZERO_PGE...\n"); | ||||
| #endif | ||||
| 	memset((char*)ZERO_PGE, 0, PAGE_SIZE); | ||||
| 	strcpy((char*)ZERO_PGE, envval); | ||||
| 
 | ||||
| #ifdef INITRD_IMAGE_SIZE | ||||
| 
 | ||||
| #ifdef DEBUG_LAST_STEPS | ||||
| 	srm_printk("Preparing INITRD info...\n"); | ||||
| #endif | ||||
| 	/* Finally, set the INITRD paramenters for the kernel. */ | ||||
| 	((long *)(ZERO_PGE+256))[0] = initrd_image_start; | ||||
| 	((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE; | ||||
| 
 | ||||
| #endif /* INITRD_IMAGE_SIZE */ | ||||
| 
 | ||||
| #ifdef DEBUG_LAST_STEPS | ||||
| 	srm_printk("Doing 'runkernel()'...\n"); | ||||
| #endif | ||||
| 	runkernel(); | ||||
| } | ||||
| 
 | ||||
|  /* dummy function, should never be called. */ | ||||
| void *__kmalloc(size_t size, gfp_t flags) | ||||
| { | ||||
| 	return (void *)NULL; | ||||
| } | ||||
							
								
								
									
										123
									
								
								arch/alpha/boot/head.S
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								arch/alpha/boot/head.S
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,123 @@ | |||
| /* | ||||
|  * arch/alpha/boot/head.S | ||||
|  * | ||||
|  * initial bootloader stuff.. | ||||
|  */ | ||||
| 
 | ||||
| #include <asm/pal.h> | ||||
| 
 | ||||
| 	.set noreorder
 | ||||
| 	.globl	__start
 | ||||
| 	.ent	__start
 | ||||
| __start: | ||||
| 	br	$29,2f | ||||
| 2:	ldgp	$29,0($29) | ||||
| 	jsr	$26,start_kernel | ||||
| 	call_pal PAL_halt | ||||
| 	.end __start
 | ||||
| 
 | ||||
| 	.align 5
 | ||||
| 	.globl	wrent
 | ||||
| 	.ent	wrent
 | ||||
| wrent: | ||||
| 	.prologue 0
 | ||||
| 	call_pal PAL_wrent | ||||
| 	ret ($26) | ||||
| 	.end wrent
 | ||||
| 
 | ||||
| 	.align 5
 | ||||
| 	.globl	wrkgp
 | ||||
| 	.ent	wrkgp
 | ||||
| wrkgp: | ||||
| 	.prologue 0
 | ||||
| 	call_pal PAL_wrkgp | ||||
| 	ret ($26) | ||||
| 	.end wrkgp
 | ||||
| 
 | ||||
| 	.align 5
 | ||||
| 	.globl	switch_to_osf_pal
 | ||||
| 	.ent	switch_to_osf_pal
 | ||||
| switch_to_osf_pal: | ||||
| 	subq	$30,128,$30 | ||||
| 	.frame	$30,128,$26 | ||||
| 	stq	$26,0($30) | ||||
| 	stq	$1,8($30) | ||||
| 	stq	$2,16($30) | ||||
| 	stq	$3,24($30) | ||||
| 	stq	$4,32($30) | ||||
| 	stq	$5,40($30) | ||||
| 	stq	$6,48($30) | ||||
| 	stq	$7,56($30) | ||||
| 	stq	$8,64($30) | ||||
| 	stq	$9,72($30) | ||||
| 	stq	$10,80($30) | ||||
| 	stq	$11,88($30) | ||||
| 	stq	$12,96($30) | ||||
| 	stq	$13,104($30) | ||||
| 	stq	$14,112($30) | ||||
| 	stq	$15,120($30) | ||||
| 	.prologue 0
 | ||||
| 
 | ||||
| 	stq	$30,0($17)	/* save KSP in PCB */ | ||||
| 
 | ||||
| 	bis	$30,$30,$20	/* a4 = KSP */ | ||||
| 	br	$17,1f | ||||
| 
 | ||||
| 	ldq	$26,0($30) | ||||
| 	ldq	$1,8($30) | ||||
| 	ldq	$2,16($30) | ||||
| 	ldq	$3,24($30) | ||||
| 	ldq	$4,32($30) | ||||
| 	ldq	$5,40($30) | ||||
| 	ldq	$6,48($30) | ||||
| 	ldq	$7,56($30) | ||||
| 	ldq	$8,64($30) | ||||
| 	ldq	$9,72($30) | ||||
| 	ldq	$10,80($30) | ||||
| 	ldq	$11,88($30) | ||||
| 	ldq	$12,96($30) | ||||
| 	ldq	$13,104($30) | ||||
| 	ldq	$14,112($30) | ||||
| 	ldq	$15,120($30) | ||||
| 	addq	$30,128,$30 | ||||
| 	ret ($26) | ||||
| 1:	call_pal PAL_swppal | ||||
| 	.end	switch_to_osf_pal
 | ||||
| 
 | ||||
| 	.align 3
 | ||||
| 	.globl	tbi
 | ||||
| 	.ent	tbi
 | ||||
| tbi: | ||||
| 	.prologue 0
 | ||||
| 	call_pal PAL_tbi | ||||
| 	ret	($26) | ||||
| 	.end tbi
 | ||||
| 
 | ||||
| 	.align 3
 | ||||
| 	.globl	halt
 | ||||
| 	.ent	halt
 | ||||
| halt: | ||||
| 	.prologue 0
 | ||||
| 	call_pal PAL_halt | ||||
| 	.end halt
 | ||||
| 
 | ||||
| /* $16 - new stack page */ | ||||
| 	.align 3
 | ||||
| 	.globl	move_stack
 | ||||
| 	.ent	move_stack
 | ||||
| move_stack: | ||||
| 	.prologue 0
 | ||||
| 	lda	$0, 0x1fff($31) | ||||
| 	and	$0, $30, $1			/* Stack offset */ | ||||
| 	or	$1, $16, $16			/* New stack pointer */ | ||||
| 	mov	$30, $1 | ||||
| 	mov	$16, $2 | ||||
| 1:	ldq	$3, 0($1)			/* Move the stack */ | ||||
| 	addq	$1, 8, $1 | ||||
| 	stq	$3, 0($2) | ||||
| 	and	$0, $1, $4 | ||||
| 	addq	$2, 8, $2 | ||||
| 	bne	$4, 1b | ||||
| 	mov	$16, $30 | ||||
| 	ret	($26) | ||||
| 	.end move_stack
 | ||||
							
								
								
									
										191
									
								
								arch/alpha/boot/main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								arch/alpha/boot/main.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,191 @@ | |||
| /*
 | ||||
|  * arch/alpha/boot/main.c | ||||
|  * | ||||
|  * Copyright (C) 1994, 1995 Linus Torvalds | ||||
|  * | ||||
|  * This file is the bootloader for the Linux/AXP kernel | ||||
|  */ | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/string.h> | ||||
| #include <generated/utsrelease.h> | ||||
| #include <linux/mm.h> | ||||
| 
 | ||||
| #include <asm/console.h> | ||||
| #include <asm/hwrpb.h> | ||||
| #include <asm/pgtable.h> | ||||
| 
 | ||||
| #include <stdarg.h> | ||||
| 
 | ||||
| #include "ksize.h" | ||||
| 
 | ||||
| extern int vsprintf(char *, const char *, va_list); | ||||
| extern unsigned long switch_to_osf_pal(unsigned long nr, | ||||
| 	struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa, | ||||
| 	unsigned long *vptb); | ||||
| struct hwrpb_struct *hwrpb = INIT_HWRPB; | ||||
| static struct pcb_struct pcb_va[1]; | ||||
| 
 | ||||
| /*
 | ||||
|  * Find a physical address of a virtual object.. | ||||
|  * | ||||
|  * This is easy using the virtual page table address. | ||||
|  */ | ||||
| 
 | ||||
| static inline void * | ||||
| find_pa(unsigned long *vptb, void *ptr) | ||||
| { | ||||
| 	unsigned long address = (unsigned long) ptr; | ||||
| 	unsigned long result; | ||||
| 
 | ||||
| 	result = vptb[address >> 13]; | ||||
| 	result >>= 32; | ||||
| 	result <<= 13; | ||||
| 	result |= address & 0x1fff; | ||||
| 	return (void *) result; | ||||
| }	 | ||||
| 
 | ||||
| /*
 | ||||
|  * This function moves into OSF/1 pal-code, and has a temporary | ||||
|  * PCB for that. The kernel proper should replace this PCB with | ||||
|  * the real one as soon as possible. | ||||
|  * | ||||
|  * The page table muckery in here depends on the fact that the boot | ||||
|  * code has the L1 page table identity-map itself in the second PTE | ||||
|  * in the L1 page table. Thus the L1-page is virtually addressable | ||||
|  * itself (through three levels) at virtual address 0x200802000. | ||||
|  */ | ||||
| 
 | ||||
| #define VPTB	((unsigned long *) 0x200000000) | ||||
| #define L1	((unsigned long *) 0x200802000) | ||||
| 
 | ||||
| void | ||||
| pal_init(void) | ||||
| { | ||||
| 	unsigned long i, rev; | ||||
| 	struct percpu_struct * percpu; | ||||
| 	struct pcb_struct * pcb_pa; | ||||
| 
 | ||||
| 	/* Create the dummy PCB.  */ | ||||
| 	pcb_va->ksp = 0; | ||||
| 	pcb_va->usp = 0; | ||||
| 	pcb_va->ptbr = L1[1] >> 32; | ||||
| 	pcb_va->asn = 0; | ||||
| 	pcb_va->pcc = 0; | ||||
| 	pcb_va->unique = 0; | ||||
| 	pcb_va->flags = 1; | ||||
| 	pcb_va->res1 = 0; | ||||
| 	pcb_va->res2 = 0; | ||||
| 	pcb_pa = find_pa(VPTB, pcb_va); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * a0 = 2 (OSF) | ||||
| 	 * a1 = return address, but we give the asm the vaddr of the PCB | ||||
| 	 * a2 = physical addr of PCB | ||||
| 	 * a3 = new virtual page table pointer | ||||
| 	 * a4 = KSP (but the asm sets it) | ||||
| 	 */ | ||||
| 	srm_printk("Switching to OSF PAL-code .. "); | ||||
| 
 | ||||
| 	i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB); | ||||
| 	if (i) { | ||||
| 		srm_printk("failed, code %ld\n", i); | ||||
| 		__halt(); | ||||
| 	} | ||||
| 
 | ||||
| 	percpu = (struct percpu_struct *) | ||||
| 		(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB); | ||||
| 	rev = percpu->pal_revision = percpu->palcode_avail[2]; | ||||
| 
 | ||||
| 	srm_printk("Ok (rev %lx)\n", rev); | ||||
| 
 | ||||
| 	tbia(); /* do it directly in case we are SMP */ | ||||
| } | ||||
| 
 | ||||
| static inline long openboot(void) | ||||
| { | ||||
| 	char bootdev[256]; | ||||
| 	long result; | ||||
| 
 | ||||
| 	result = callback_getenv(ENV_BOOTED_DEV, bootdev, 255); | ||||
| 	if (result < 0) | ||||
| 		return result; | ||||
| 	return callback_open(bootdev, result & 255); | ||||
| } | ||||
| 
 | ||||
| static inline long close(long dev) | ||||
| { | ||||
| 	return callback_close(dev); | ||||
| } | ||||
| 
 | ||||
| static inline long load(long dev, unsigned long addr, unsigned long count) | ||||
| { | ||||
| 	char bootfile[256]; | ||||
| 	extern char _end; | ||||
| 	long result, boot_size = &_end - (char *) BOOT_ADDR; | ||||
| 
 | ||||
| 	result = callback_getenv(ENV_BOOTED_FILE, bootfile, 255); | ||||
| 	if (result < 0) | ||||
| 		return result; | ||||
| 	result &= 255; | ||||
| 	bootfile[result] = '\0'; | ||||
| 	if (result) | ||||
| 		srm_printk("Boot file specification (%s) not implemented\n", | ||||
| 		       bootfile); | ||||
| 	return callback_read(dev, count, (void *)addr, boot_size/512 + 1); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Start the kernel. | ||||
|  */ | ||||
| static void runkernel(void) | ||||
| { | ||||
| 	__asm__ __volatile__( | ||||
| 		"bis %1,%1,$30\n\t" | ||||
| 		"bis %0,%0,$26\n\t" | ||||
| 		"ret ($26)" | ||||
| 		: /* no outputs: it doesn't even return */ | ||||
| 		: "r" (START_ADDR), | ||||
| 		  "r" (PAGE_SIZE + INIT_STACK)); | ||||
| } | ||||
| 
 | ||||
| void start_kernel(void) | ||||
| { | ||||
| 	long i; | ||||
| 	long dev; | ||||
| 	int nbytes; | ||||
| 	char envval[256]; | ||||
| 
 | ||||
| 	srm_printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n"); | ||||
| 	if (INIT_HWRPB->pagesize != 8192) { | ||||
| 		srm_printk("Expected 8kB pages, got %ldkB\n", INIT_HWRPB->pagesize >> 10); | ||||
| 		return; | ||||
| 	} | ||||
| 	pal_init(); | ||||
| 	dev = openboot(); | ||||
| 	if (dev < 0) { | ||||
| 		srm_printk("Unable to open boot device: %016lx\n", dev); | ||||
| 		return; | ||||
| 	} | ||||
| 	dev &= 0xffffffff; | ||||
| 	srm_printk("Loading vmlinux ..."); | ||||
| 	i = load(dev, START_ADDR, KERNEL_SIZE); | ||||
| 	close(dev); | ||||
| 	if (i != KERNEL_SIZE) { | ||||
| 		srm_printk("Failed (%lx)\n", i); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval)); | ||||
| 	if (nbytes < 0) { | ||||
| 		nbytes = 0; | ||||
| 	} | ||||
| 	envval[nbytes] = '\0'; | ||||
| 	strcpy((char*)ZERO_PGE, envval); | ||||
| 
 | ||||
| 	srm_printk(" Ok\nNow booting the kernel\n"); | ||||
| 	runkernel(); | ||||
| 	for (i = 0 ; i < 0x100000000 ; i++) | ||||
| 		/* nothing */; | ||||
| 	__halt(); | ||||
| } | ||||
							
								
								
									
										173
									
								
								arch/alpha/boot/misc.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								arch/alpha/boot/misc.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,173 @@ | |||
| /*
 | ||||
|  * misc.c | ||||
|  *  | ||||
|  * This is a collection of several routines from gzip-1.0.3  | ||||
|  * adapted for Linux. | ||||
|  * | ||||
|  * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 | ||||
|  * | ||||
|  * Modified for ARM Linux by Russell King | ||||
|  * | ||||
|  * Nicolas Pitre <nico@visuaide.com>  1999/04/14 : | ||||
|  *  For this code to run directly from Flash, all constant variables must | ||||
|  *  be marked with 'const' and all other variables initialized at run-time  | ||||
|  *  only.  This way all non constant variables will end up in the bss segment, | ||||
|  *  which should point to addresses in RAM and cleared to 0 on start. | ||||
|  *  This allows for a much quicker boot time. | ||||
|  * | ||||
|  * Modified for Alpha, from the ARM version, by Jay Estabrook 2003. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/slab.h> | ||||
| 
 | ||||
| #include <asm/uaccess.h> | ||||
| 
 | ||||
| #define memzero(s,n)	memset ((s),0,(n)) | ||||
| #define puts		srm_printk | ||||
| extern long srm_printk(const char *, ...) | ||||
|      __attribute__ ((format (printf, 1, 2))); | ||||
| 
 | ||||
| /*
 | ||||
|  * gzip delarations | ||||
|  */ | ||||
| #define OF(args)  args | ||||
| #define STATIC static | ||||
| 
 | ||||
| typedef unsigned char  uch; | ||||
| typedef unsigned short ush; | ||||
| typedef unsigned long  ulg; | ||||
| 
 | ||||
| #define WSIZE 0x8000		/* Window size must be at least 32k, */ | ||||
| 				/* and a power of two */ | ||||
| 
 | ||||
| static uch *inbuf;		/* input buffer */ | ||||
| static uch *window;		/* Sliding window buffer */ | ||||
| 
 | ||||
| static unsigned insize;		/* valid bytes in inbuf */ | ||||
| static unsigned inptr;		/* index of next byte to be processed in inbuf */ | ||||
| static unsigned outcnt;		/* bytes in output buffer */ | ||||
| 
 | ||||
| /* gzip flag byte */ | ||||
| #define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */ | ||||
| #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ | ||||
| #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */ | ||||
| #define ORIG_NAME    0x08 /* bit 3 set: original file name present */ | ||||
| #define COMMENT      0x10 /* bit 4 set: file comment present */ | ||||
| #define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */ | ||||
| #define RESERVED     0xC0 /* bit 6,7:   reserved */ | ||||
| 
 | ||||
| #define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf()) | ||||
| 
 | ||||
| /* Diagnostic functions */ | ||||
| #ifdef DEBUG | ||||
| #  define Assert(cond,msg) {if(!(cond)) error(msg);} | ||||
| #  define Trace(x) fprintf x | ||||
| #  define Tracev(x) {if (verbose) fprintf x ;} | ||||
| #  define Tracevv(x) {if (verbose>1) fprintf x ;} | ||||
| #  define Tracec(c,x) {if (verbose && (c)) fprintf x ;} | ||||
| #  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} | ||||
| #else | ||||
| #  define Assert(cond,msg) | ||||
| #  define Trace(x) | ||||
| #  define Tracev(x) | ||||
| #  define Tracevv(x) | ||||
| #  define Tracec(c,x) | ||||
| #  define Tracecv(c,x) | ||||
| #endif | ||||
| 
 | ||||
| static int  fill_inbuf(void); | ||||
| static void flush_window(void); | ||||
| static void error(char *m); | ||||
| 
 | ||||
| static char *input_data; | ||||
| static int  input_data_size; | ||||
| 
 | ||||
| static uch *output_data; | ||||
| static ulg output_ptr; | ||||
| static ulg bytes_out; | ||||
| 
 | ||||
| static void error(char *m); | ||||
| static void gzip_mark(void **); | ||||
| static void gzip_release(void **); | ||||
| 
 | ||||
| extern int end; | ||||
| static ulg free_mem_ptr; | ||||
| static ulg free_mem_end_ptr; | ||||
| 
 | ||||
| #define HEAP_SIZE 0x3000 | ||||
| 
 | ||||
| #include "../../../lib/inflate.c" | ||||
| 
 | ||||
| /* ===========================================================================
 | ||||
|  * Fill the input buffer. This is called only when the buffer is empty | ||||
|  * and at least one byte is really needed. | ||||
|  */ | ||||
| int fill_inbuf(void) | ||||
| { | ||||
| 	if (insize != 0) | ||||
| 		error("ran out of input data"); | ||||
| 
 | ||||
| 	inbuf = input_data; | ||||
| 	insize = input_data_size; | ||||
| 
 | ||||
| 	inptr = 1; | ||||
| 	return inbuf[0]; | ||||
| } | ||||
| 
 | ||||
| /* ===========================================================================
 | ||||
|  * Write the output window window[0..outcnt-1] and update crc and bytes_out. | ||||
|  * (Used for the decompressed data only.) | ||||
|  */ | ||||
| void flush_window(void) | ||||
| { | ||||
| 	ulg c = crc; | ||||
| 	unsigned n; | ||||
| 	uch *in, *out, ch; | ||||
| 
 | ||||
| 	in = window; | ||||
| 	out = &output_data[output_ptr]; | ||||
| 	for (n = 0; n < outcnt; n++) { | ||||
| 		ch = *out++ = *in++; | ||||
| 		c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); | ||||
| 	} | ||||
| 	crc = c; | ||||
| 	bytes_out += (ulg)outcnt; | ||||
| 	output_ptr += (ulg)outcnt; | ||||
| 	outcnt = 0; | ||||
| /*	puts("."); */ | ||||
| } | ||||
| 
 | ||||
| static void error(char *x) | ||||
| { | ||||
| 	puts("\n\n"); | ||||
| 	puts(x); | ||||
| 	puts("\n\n -- System halted"); | ||||
| 
 | ||||
| 	while(1);	/* Halt */ | ||||
| } | ||||
| 
 | ||||
| unsigned int | ||||
| decompress_kernel(void *output_start, | ||||
| 		  void *input_start, | ||||
| 		  size_t ksize, | ||||
| 		  size_t kzsize) | ||||
| { | ||||
| 	output_data		= (uch *)output_start; | ||||
| 	input_data		= (uch *)input_start; | ||||
| 	input_data_size		= kzsize; /* use compressed size */ | ||||
| 
 | ||||
| 	/* FIXME FIXME FIXME */ | ||||
| 	free_mem_ptr		= (ulg)output_start + ksize; | ||||
| 	free_mem_end_ptr	= (ulg)output_start + ksize + 0x200000; | ||||
| 	/* FIXME FIXME FIXME */ | ||||
| 
 | ||||
| 	/* put in temp area to reduce initial footprint */ | ||||
| 	window = malloc(WSIZE); | ||||
| 
 | ||||
| 	makecrc(); | ||||
| /*	puts("Uncompressing Linux..."); */ | ||||
| 	gunzip(); | ||||
| /*	puts(" done, booting the kernel.\n"); */ | ||||
| 	return output_ptr; | ||||
| } | ||||
							
								
								
									
										152
									
								
								arch/alpha/boot/tools/mkbb.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								arch/alpha/boot/tools/mkbb.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,152 @@ | |||
| /* This utility makes a bootblock suitable for the SRM console/miniloader */ | ||||
| 
 | ||||
| /* Usage:
 | ||||
|  *	mkbb <device> <lxboot> | ||||
|  * | ||||
|  * Where <device> is the name of the device to install the bootblock on, | ||||
|  * and <lxboot> is the name of a bootblock to merge in.  This bootblock | ||||
|  * contains the offset and size of the bootloader.  It must be exactly | ||||
|  * 512 bytes long. | ||||
|  */ | ||||
| 
 | ||||
| #include <fcntl.h> | ||||
| #include <unistd.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| /* Minimal definition of disklabel, so we don't have to include
 | ||||
|  * asm/disklabel.h (confuses make) | ||||
|  */ | ||||
| #ifndef MAXPARTITIONS | ||||
| #define MAXPARTITIONS   8                       /* max. # of partitions */ | ||||
| #endif | ||||
| 
 | ||||
| #ifndef u8 | ||||
| #define u8 unsigned char | ||||
| #endif | ||||
| 
 | ||||
| #ifndef u16 | ||||
| #define u16 unsigned short | ||||
| #endif | ||||
| 
 | ||||
| #ifndef u32 | ||||
| #define u32 unsigned int | ||||
| #endif | ||||
| 
 | ||||
| struct disklabel { | ||||
|     u32	d_magic;				/* must be DISKLABELMAGIC */ | ||||
|     u16	d_type, d_subtype; | ||||
|     u8	d_typename[16]; | ||||
|     u8	d_packname[16]; | ||||
|     u32	d_secsize; | ||||
|     u32	d_nsectors; | ||||
|     u32	d_ntracks; | ||||
|     u32	d_ncylinders; | ||||
|     u32	d_secpercyl; | ||||
|     u32	d_secprtunit; | ||||
|     u16	d_sparespertrack; | ||||
|     u16	d_sparespercyl; | ||||
|     u32	d_acylinders; | ||||
|     u16	d_rpm, d_interleave, d_trackskew, d_cylskew; | ||||
|     u32	d_headswitch, d_trkseek, d_flags; | ||||
|     u32	d_drivedata[5]; | ||||
|     u32	d_spare[5]; | ||||
|     u32	d_magic2;				/* must be DISKLABELMAGIC */ | ||||
|     u16	d_checksum; | ||||
|     u16	d_npartitions; | ||||
|     u32	d_bbsize, d_sbsize; | ||||
|     struct d_partition { | ||||
| 	u32	p_size; | ||||
| 	u32	p_offset; | ||||
| 	u32	p_fsize; | ||||
| 	u8	p_fstype; | ||||
| 	u8	p_frag; | ||||
| 	u16	p_cpg; | ||||
|     } d_partitions[MAXPARTITIONS]; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| typedef union __bootblock { | ||||
|     struct { | ||||
|         char			__pad1[64]; | ||||
|         struct disklabel	__label; | ||||
|     } __u1; | ||||
|     struct { | ||||
| 	unsigned long		__pad2[63]; | ||||
| 	unsigned long		__checksum; | ||||
|     } __u2; | ||||
|     char		bootblock_bytes[512]; | ||||
|     unsigned long	bootblock_quadwords[64]; | ||||
| } bootblock; | ||||
| 
 | ||||
| #define	bootblock_label		__u1.__label | ||||
| #define bootblock_checksum	__u2.__checksum | ||||
| 
 | ||||
| int main(int argc, char ** argv) | ||||
| { | ||||
|     bootblock		bootblock_from_disk; | ||||
|     bootblock		bootloader_image; | ||||
|     int			dev, fd; | ||||
|     int			i; | ||||
|     int			nread; | ||||
| 
 | ||||
|     /* Make sure of the arg count */ | ||||
|     if(argc != 3) { | ||||
| 	fprintf(stderr, "Usage: %s device lxboot\n", argv[0]); | ||||
| 	exit(0); | ||||
|     } | ||||
| 
 | ||||
|     /* First, open the device and make sure it's accessible */ | ||||
|     dev = open(argv[1], O_RDWR); | ||||
|     if(dev < 0) { | ||||
| 	perror(argv[1]); | ||||
| 	exit(0); | ||||
|     } | ||||
| 
 | ||||
|     /* Now open the lxboot and make sure it's reasonable */ | ||||
|     fd = open(argv[2], O_RDONLY); | ||||
|     if(fd < 0) { | ||||
| 	perror(argv[2]); | ||||
| 	close(dev); | ||||
| 	exit(0); | ||||
|     } | ||||
| 
 | ||||
|     /* Read in the lxboot */ | ||||
|     nread = read(fd, &bootloader_image, sizeof(bootblock)); | ||||
|     if(nread != sizeof(bootblock)) { | ||||
| 	perror("lxboot read"); | ||||
| 	fprintf(stderr, "expected %zd, got %d\n", sizeof(bootblock), nread); | ||||
| 	exit(0); | ||||
|     } | ||||
| 
 | ||||
|     /* Read in the bootblock from disk. */ | ||||
|     nread = read(dev, &bootblock_from_disk, sizeof(bootblock)); | ||||
|     if(nread != sizeof(bootblock)) { | ||||
| 	perror("bootblock read"); | ||||
| 	fprintf(stderr, "expected %zd, got %d\n", sizeof(bootblock), nread); | ||||
| 	exit(0); | ||||
|     } | ||||
| 
 | ||||
|     /* Swap the bootblock's disklabel into the bootloader */ | ||||
|     bootloader_image.bootblock_label = bootblock_from_disk.bootblock_label; | ||||
| 
 | ||||
|     /* Calculate the bootblock checksum */ | ||||
|     bootloader_image.bootblock_checksum = 0; | ||||
|     for(i = 0; i < 63; i++) { | ||||
| 	bootloader_image.bootblock_checksum +=  | ||||
| 			bootloader_image.bootblock_quadwords[i]; | ||||
|     } | ||||
| 
 | ||||
|     /* Write the whole thing out! */ | ||||
|     lseek(dev, 0L, SEEK_SET); | ||||
|     if(write(dev, &bootloader_image, sizeof(bootblock)) != sizeof(bootblock)) { | ||||
| 	perror("bootblock write"); | ||||
| 	exit(0); | ||||
|     } | ||||
| 
 | ||||
|     close(fd); | ||||
|     close(dev); | ||||
|     exit(0); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										280
									
								
								arch/alpha/boot/tools/objstrip.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										280
									
								
								arch/alpha/boot/tools/objstrip.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,280 @@ | |||
| /*
 | ||||
|  * arch/alpha/boot/tools/objstrip.c | ||||
|  * | ||||
|  * Strip the object file headers/trailers from an executable (ELF or ECOFF). | ||||
|  * | ||||
|  * Copyright (C) 1996 David Mosberger-Tang. | ||||
|  */ | ||||
| /*
 | ||||
|  * Converts an ECOFF or ELF object file into a bootable file.  The | ||||
|  * object file must be a OMAGIC file (i.e., data and bss follow immediately | ||||
|  * behind the text).  See DEC "Assembly Language Programmer's Guide" | ||||
|  * documentation for details.  The SRM boot process is documented in | ||||
|  * the Alpha AXP Architecture Reference Manual, Second Edition by | ||||
|  * Richard L. Sites and Richard T. Witek. | ||||
|  */ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include <sys/fcntl.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/types.h> | ||||
| 
 | ||||
| #include <linux/a.out.h> | ||||
| #include <linux/coff.h> | ||||
| #include <linux/param.h> | ||||
| #ifdef __ELF__ | ||||
| # include <linux/elf.h> | ||||
| #endif | ||||
| 
 | ||||
| /* bootfile size must be multiple of BLOCK_SIZE: */ | ||||
| #define BLOCK_SIZE	512 | ||||
| 
 | ||||
| const char * prog_name; | ||||
| 
 | ||||
| 
 | ||||
| static void | ||||
| usage (void) | ||||
| { | ||||
|     fprintf(stderr, | ||||
| 	    "usage: %s [-v] -p file primary\n" | ||||
| 	    "       %s [-vb] file [secondary]\n", prog_name, prog_name); | ||||
|     exit(1); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| main (int argc, char *argv[]) | ||||
| { | ||||
|     size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0; | ||||
|     int fd, ofd, i, j, verbose = 0, primary = 0; | ||||
|     char buf[8192], *inname; | ||||
|     struct exec * aout;		/* includes file & aout header */ | ||||
|     long offset; | ||||
| #ifdef __ELF__ | ||||
|     struct elfhdr *elf; | ||||
|     struct elf_phdr *elf_phdr;	/* program header */ | ||||
|     unsigned long long e_entry; | ||||
| #endif | ||||
| 
 | ||||
|     prog_name = argv[0]; | ||||
| 
 | ||||
|     for (i = 1; i < argc && argv[i][0] == '-'; ++i) { | ||||
| 	for (j = 1; argv[i][j]; ++j) { | ||||
| 	    switch (argv[i][j]) { | ||||
| 	      case 'v': | ||||
| 		  verbose = ~verbose; | ||||
| 		  break; | ||||
| 
 | ||||
| 	      case 'b': | ||||
| 		  pad = BLOCK_SIZE; | ||||
| 		  break; | ||||
| 
 | ||||
| 	      case 'p': | ||||
| 		  primary = 1;		/* make primary bootblock */ | ||||
| 		  break; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|     if (i >= argc) { | ||||
| 	usage(); | ||||
|     } | ||||
|     inname = argv[i++]; | ||||
| 
 | ||||
|     fd = open(inname, O_RDONLY); | ||||
|     if (fd == -1) { | ||||
| 	perror("open"); | ||||
| 	exit(1); | ||||
|     } | ||||
| 
 | ||||
|     ofd = 1; | ||||
|     if (i < argc) { | ||||
| 	ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666); | ||||
| 	if (ofd == -1) { | ||||
| 	    perror("open"); | ||||
| 	    exit(1); | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|     if (primary) { | ||||
| 	/* generate bootblock for primary loader */ | ||||
| 	 | ||||
| 	unsigned long bb[64], sum = 0; | ||||
| 	struct stat st; | ||||
| 	off_t size; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (ofd == 1) { | ||||
| 	    usage(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (fstat(fd, &st) == -1) { | ||||
| 	    perror("fstat"); | ||||
| 	    exit(1); | ||||
| 	} | ||||
| 
 | ||||
| 	size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1); | ||||
| 	memset(bb, 0, sizeof(bb)); | ||||
| 	strcpy((char *) bb, "Linux SRM bootblock"); | ||||
| 	bb[60] = size / BLOCK_SIZE;	/* count */ | ||||
| 	bb[61] = 1;			/* starting sector # */ | ||||
| 	bb[62] = 0;			/* flags---must be 0 */ | ||||
| 	for (i = 0; i < 63; ++i) { | ||||
| 	    sum += bb[i]; | ||||
| 	} | ||||
| 	bb[63] = sum; | ||||
| 	if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) { | ||||
| 	    perror("boot-block write"); | ||||
| 	    exit(1); | ||||
| 	} | ||||
| 	printf("%lu\n", size); | ||||
| 	return 0; | ||||
|     } | ||||
| 
 | ||||
|     /* read and inspect exec header: */ | ||||
| 
 | ||||
|     if (read(fd, buf, sizeof(buf)) < 0) { | ||||
| 	perror("read"); | ||||
| 	exit(1); | ||||
|     } | ||||
| 
 | ||||
| #ifdef __ELF__ | ||||
|     elf = (struct elfhdr *) buf; | ||||
| 
 | ||||
|     if (elf->e_ident[0] == 0x7f && strncmp((char *)elf->e_ident + 1, "ELF", 3) == 0) { | ||||
| 	if (elf->e_type != ET_EXEC) { | ||||
| 	    fprintf(stderr, "%s: %s is not an ELF executable\n", | ||||
| 		    prog_name, inname); | ||||
| 	    exit(1); | ||||
| 	} | ||||
| 	if (!elf_check_arch(elf)) { | ||||
| 	    fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n", | ||||
| 		    prog_name, elf->e_machine); | ||||
| 	    exit(1); | ||||
| 	} | ||||
| 	if (elf->e_phnum != 1) { | ||||
| 	    fprintf(stderr, | ||||
| 		    "%s: %d program headers (forgot to link with -N?)\n", | ||||
| 		    prog_name, elf->e_phnum); | ||||
| 	} | ||||
| 
 | ||||
| 	e_entry = elf->e_entry; | ||||
| 
 | ||||
| 	lseek(fd, elf->e_phoff, SEEK_SET); | ||||
| 	if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) { | ||||
| 	    perror("read"); | ||||
| 	    exit(1); | ||||
| 	} | ||||
| 
 | ||||
| 	elf_phdr = (struct elf_phdr *) buf; | ||||
| 	offset	 = elf_phdr->p_offset; | ||||
| 	mem_size = elf_phdr->p_memsz; | ||||
| 	fil_size = elf_phdr->p_filesz; | ||||
| 
 | ||||
| 	/* work around ELF bug: */ | ||||
| 	if (elf_phdr->p_vaddr < e_entry) { | ||||
| 	    unsigned long delta = e_entry - elf_phdr->p_vaddr; | ||||
| 	    offset   += delta; | ||||
| 	    mem_size -= delta; | ||||
| 	    fil_size -= delta; | ||||
| 	    elf_phdr->p_vaddr += delta; | ||||
| 	} | ||||
| 
 | ||||
| 	if (verbose) { | ||||
| 	    fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n", | ||||
| 		    prog_name, (long) elf_phdr->p_vaddr, | ||||
| 		    elf_phdr->p_vaddr + fil_size, offset); | ||||
| 	} | ||||
|     } else | ||||
| #endif | ||||
|     { | ||||
| 	aout = (struct exec *) buf; | ||||
| 
 | ||||
| 	if (!(aout->fh.f_flags & COFF_F_EXEC)) { | ||||
| 	    fprintf(stderr, "%s: %s is not in executable format\n", | ||||
| 		    prog_name, inname); | ||||
| 	    exit(1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (aout->fh.f_opthdr != sizeof(aout->ah)) { | ||||
| 	    fprintf(stderr, "%s: %s has unexpected optional header size\n", | ||||
| 		    prog_name, inname); | ||||
| 	    exit(1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (N_MAGIC(*aout) != OMAGIC) { | ||||
| 	    fprintf(stderr, "%s: %s is not an OMAGIC file\n", | ||||
| 		    prog_name, inname); | ||||
| 	    exit(1); | ||||
| 	} | ||||
| 	offset = N_TXTOFF(*aout); | ||||
| 	fil_size = aout->ah.tsize + aout->ah.dsize; | ||||
| 	mem_size = fil_size + aout->ah.bsize; | ||||
| 
 | ||||
| 	if (verbose) { | ||||
| 	    fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n", | ||||
| 		    prog_name, aout->ah.text_start, | ||||
| 		    aout->ah.text_start + fil_size, offset); | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|     if (lseek(fd, offset, SEEK_SET) != offset) { | ||||
| 	perror("lseek"); | ||||
| 	exit(1); | ||||
|     } | ||||
| 
 | ||||
|     if (verbose) { | ||||
| 	fprintf(stderr, "%s: copying %lu byte from %s\n", | ||||
| 		prog_name, (unsigned long) fil_size, inname); | ||||
|     } | ||||
| 
 | ||||
|     tocopy = fil_size; | ||||
|     while (tocopy > 0) { | ||||
| 	n = tocopy; | ||||
| 	if (n > sizeof(buf)) { | ||||
| 	    n = sizeof(buf); | ||||
| 	} | ||||
| 	tocopy -= n; | ||||
| 	if ((size_t) read(fd, buf, n) != n) { | ||||
| 	    perror("read"); | ||||
| 	    exit(1); | ||||
| 	} | ||||
| 	do { | ||||
| 	    nwritten = write(ofd, buf, n); | ||||
| 	    if ((ssize_t) nwritten == -1) { | ||||
| 		perror("write"); | ||||
| 		exit(1); | ||||
| 	    } | ||||
| 	    n -= nwritten; | ||||
| 	} while (n > 0); | ||||
|     } | ||||
| 
 | ||||
|     if (pad) { | ||||
| 	mem_size = ((mem_size + pad - 1) / pad) * pad; | ||||
|     } | ||||
| 
 | ||||
|     tocopy = mem_size - fil_size; | ||||
|     if (tocopy > 0) { | ||||
| 	fprintf(stderr, | ||||
| 		"%s: zero-filling bss and aligning to %lu with %lu bytes\n", | ||||
| 		prog_name, pad, (unsigned long) tocopy); | ||||
| 
 | ||||
| 	memset(buf, 0x00, sizeof(buf)); | ||||
| 	do { | ||||
| 	    n = tocopy; | ||||
| 	    if (n > sizeof(buf)) { | ||||
| 		n = sizeof(buf); | ||||
| 	    } | ||||
| 	    nwritten = write(ofd, buf, n); | ||||
| 	    if ((ssize_t) nwritten == -1) { | ||||
| 		perror("write"); | ||||
| 		exit(1); | ||||
| 	    } | ||||
| 	    tocopy -= nwritten; | ||||
| 	} while (tocopy > 0); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 awab228
						awab228