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