vloaduc.c revision bdcaa8d0
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/rendition/vloaduc.c,v 1.13tsi Exp $ */ 2/* 3 * includes 4 */ 5 6#ifdef HAVE_CONFIG_H 7#include "config.h" 8#endif 9 10#include "rendition.h" 11#include "v1kregs.h" 12#include "v1krisc.h" 13#include "vloaduc.h" 14#include "vos.h" 15 16#include <sys/types.h> 17#include <sys/stat.h> 18#include <fcntl.h> 19#include <stdio.h> 20#ifdef HAVE_ELF_H 21#include <elf.h> 22#endif 23#ifdef HAVE_ELF_ABI_H 24#include <elf_abi.h> 25#endif 26 27/* 28 * defines 29 */ 30 31#ifdef X_LITTLE_ENDIAN 32 33/* maybe swap word */ 34#define SW32(x) lswapl(x) 35#define SW16(x) lswaps(x) 36#else /* BIG_ENDIAN */ 37#define SW32(x) (x) 38#define SW16(x) (x) 39#endif /* #ifdef LITTLE_ENDIAN */ 40 41 42 43/* 44 * local function prototypes 45 */ 46static void loadSection2board(ScrnInfoPtr pScreenInfo, int fd, 47 Elf32_Shdr *shdr); 48static void loadSegment2board(ScrnInfoPtr pScreenInfo, int fd, 49 Elf32_Phdr *phdr); 50static int seek_and_read_hdr(int fd, void *ptr, long int offset, 51 int size, int cnt); 52static void mmve(ScrnInfoPtr pScreenInfo, vu32 size, vu8 *data, vu32 phys_addr); 53 54 55 56/* 57 * functions 58 */ 59 60/* 61 * int verite_load_ucfile(ScrnInfoPtr pScreenInfo, char *file_name) 62 * 63 * Loads verite elf file microcode file in |name| onto the board. 64 * NOTE: Assumes the ucode loader is already running on the board! 65 * 66 * Returns the program's entry point, on error -1; 67 */ 68int 69verite_load_ucfile(ScrnInfoPtr pScreenInfo, char *file_name) 70{ 71 /* renditionPtr pRendition = RENDITIONPTR(pScreenInfo); */ 72 73 int num; 74 int sz; 75 int fd; 76 Elf32_Phdr *pphdr, *orig_pphdr=NULL; 77 Elf32_Shdr *pshdr, *orig_pshdr=NULL; 78 Elf32_Ehdr ehdr ; 79 80#ifdef DEBUG 81 ErrorF("RENDITION: Loading microcode %s\n", file_name); 82#endif 83 84 /* Stop the RISC if it happends to run */ 85 v1k_stop (pScreenInfo); 86 87 /* open file and read ELF-header */ 88 if (-1 == (fd=open(file_name, O_RDONLY, 0))) { 89 ErrorF("RENDITION: Cannot open microcode %s\n", file_name); 90 return -1; 91 } 92 93 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) { 94 ErrorF("RENDITION: Cannot read microcode header %s\n", file_name); 95 return -1; 96 } 97 if (0 != strncmp((char *)&ehdr.e_ident[1], "ELF", 3)) { 98 ErrorF("RENDITION: Microcode header in %s is corrupt\n", file_name); 99 return -1; 100 } 101 102 /* read in the program header(s) */ 103 sz=SW16(ehdr.e_phentsize); 104 num=SW16(ehdr.e_phnum); 105 if (0!=sz && 0!=num) { 106 orig_pphdr=pphdr=(Elf32_Phdr *)xalloc(sz*num); 107 if (!pphdr) { 108 ErrorF("RENDITION: Cannot allocate global memory (1)\n"); 109 close(fd); 110 return -1; 111 } 112 113 if (seek_and_read_hdr(fd, pphdr, SW32(ehdr.e_phoff), sz, num)) { 114 ErrorF("RENDITION: Error reading microcode (1)\n"); 115 close(fd); 116 return -1; 117 } 118 119 orig_pshdr=pshdr=(Elf32_Shdr *)0; 120 } 121 else { 122 orig_pphdr=pphdr=(Elf32_Phdr *)0; 123 124 /* read in the section header(s) */ 125 sz=SW16(ehdr.e_shentsize); 126 num=SW16(ehdr.e_shnum); 127 if (0!=sz && 0!=num) { 128 orig_pshdr=pshdr=(Elf32_Shdr *)xalloc(sz*num); 129 if (!pshdr) { 130 ErrorF("RENDITION: Cannot allocate global memory (2)\n"); 131 close(fd); 132 return -1; 133 } 134 135 if (seek_and_read_hdr(fd, pshdr, SW32(ehdr.e_shoff), sz, num)) { 136 ErrorF("RENDITION: Error reading microcode (2)\n"); 137 close(fd); 138 return -1; 139 } 140 } 141 else 142 pshdr=(Elf32_Shdr *)0; 143 } 144 145 if (pphdr) { 146 do { 147 if (SW32(pphdr->p_type) == PT_LOAD) 148 loadSegment2board(pScreenInfo, fd, pphdr); 149 pphdr=(Elf32_Phdr *)(((char *)pphdr)+sz); 150 } while (--num); 151 xfree(orig_pphdr); 152 } 153 else { 154 do { 155 if (SW32(pshdr->sh_size) && (SW32(pshdr->sh_flags) & SHF_ALLOC) 156 && ((SW32(pshdr->sh_type)==SHT_PROGBITS) 157 || (SW32(pshdr->sh_type)==SHT_NOBITS))) 158 loadSection2board(pScreenInfo, fd, pshdr); 159 pshdr=(Elf32_Shdr *)(((char *)pshdr)+sz); 160 } while (--num) ; 161 xfree(orig_pshdr); 162 } 163 close(fd); 164 165 return SW32(ehdr.e_entry); 166} 167 168 169 170/* 171 * local functions 172 */ 173 174static void 175loadSection2board(ScrnInfoPtr pScreenInfo, int fd, Elf32_Shdr *shdr) 176{ 177 /* renditionPtr pRendition = RENDITIONPTR(pScreenInfo); */ 178 ErrorF("vlib: loadSection2board not implemented yet!\n"); 179} 180 181 182 183static void 184loadSegment2board(ScrnInfoPtr pScreenInfo, int fd, Elf32_Phdr *phdr) 185{ 186 /* renditionPtr pRendition = RENDITIONPTR(pScreenInfo); */ 187 vu8 *data; 188 vu32 offset=SW32(phdr->p_offset); 189 vu32 size=SW32(phdr->p_filesz); 190 vu32 physAddr=SW32(phdr->p_paddr); 191 192 if (lseek(fd, offset, SEEK_SET) != offset) { 193 ErrorF("RENDITION: Failure in loadSegmentToBoard, offset %lx\n", 194 (unsigned long)offset); 195 return; 196 } 197 198 data=(vu8 *)xalloc(size); 199 if (NULL == data){ 200 ErrorF("RENDITION: GlobalAllocPtr couldn't allocate %lx bytes", 201 (unsigned long)size); 202 return; 203 } 204 205 if (read(fd, data, size) != size){ 206 ErrorF("RENDITION: verite_readfile Failure, couldn't read %lx bytes ", 207 (unsigned long)size); 208 return; 209 } 210 211 mmve(pScreenInfo, size, data, physAddr); 212 213 xfree(data); 214} 215 216 217 218static int 219seek_and_read_hdr(int fd, void *ptr, long int offset, int size, 220 int cnt) 221{ 222 if (lseek(fd, offset, SEEK_SET) != offset) 223 return 1 ; 224 225 if (size*cnt != read(fd, ptr, size*cnt)) 226 return 2 ; 227 228 return 0 ; 229} 230 231 232 233static void 234mmve(ScrnInfoPtr pScreenInfo, vu32 size, vu8 *data, vu32 phys_addr) 235{ 236 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 237 vu8 memend; 238 vu32 *dataout; 239 vu8 *vmb=pRendition->board.vmem_base; 240 241 /* swap bytes 3<>0, 2<>1 */ 242 memend=verite_in8(pRendition->board.io_base+MEMENDIAN); 243 verite_out8(pRendition->board.io_base+MEMENDIAN, MEMENDIAN_END); 244 245 dataout=(vu32 *)data; 246 247 /* If RISC happends to be running, be sure it is stopped */ 248 v1k_stop(pScreenInfo); 249 250 while (size > 0) { 251 verite_write_memory32(vmb, phys_addr, *dataout); 252 phys_addr+=4; 253 dataout++; 254 size-=4; 255 } 256 257 verite_out8(pRendition->board.io_base+MEMENDIAN, memend); 258} 259 260/* 261 * end of file vloaduc.c 262 */ 263