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