blob: 88e495b17a07398558e7bf0dc3b2f540d4d64398 [file] [log] [blame]
Uwe Hermann7eb845e2008-11-02 17:01:06 +00001/*
2 * This file is part of the bayou project.
3 *
4 * Copyright (C) 2008 Advanced Micro Devices, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Uwe Hermann7eb845e2008-11-02 17:01:06 +000014 */
15
16#include "bayou.h"
17#include "self.h"
18
19static int nop_decompress(void *dst, void *src, int len)
20{
21 memcpy(dst, src, len);
22 return len;
23}
24
25#ifdef CONFIG_LZMA
26extern int ulzma(u8 *, u8 *);
27
28static int lzma_decompress(void *dst, void *src, int len)
29{
30 return ulzma((u8 *) src, (u8 *) dst);
31}
32#endif
33
34#ifdef CONFIG_NRV2B
35extern int unrv2b(u8 *, u8 *, unsigned long *);
36
37static int nrv2b_decompress(void *dst, void *src, int len)
38{
39 unsigned long l = (u32) len;
40 return unrv2b(src, dst, &l);
41}
42#endif
43
44static int zeros_decompress(void *dst, void *src, int len)
45{
46 memset(dst, 0, len);
47 return len;
48}
49
50int self_get_params(u8 *fptr, u8 **params)
51{
52 struct self_segment *seg = (struct self_segment *)fptr;
53
54 while (seg->type != SELF_TYPE_ENTRY) {
55 if (seg->type == 0)
56 return -1;
57
58 if (seg->type == SELF_TYPE_PARAMS) {
59 *params = (u8 *) (fptr + seg->offset);
60 return seg->len;
61 }
62
63 seg++;
64 }
65
66 *params = NULL;
67
68 return 0;
69}
70
71int verify_self(u8 *ptr)
72{
73 struct self_segment *seg = (struct self_segment *)ptr;
74
75 switch (seg->type) {
76 case SELF_TYPE_CODE:
77 case SELF_TYPE_DATA:
78 case SELF_TYPE_BSS:
79 case SELF_TYPE_PARAMS:
80 case SELF_TYPE_ENTRY:
81 return 1;
82 }
83
84 return 0;
85}
86
87int self_load_and_run(struct payload *p, int *ret)
88{
89 struct self_segment *seg = (struct self_segment *)p->fptr;
90 int (*dcmp) (void *, void *, int);
91 int dlen;
92
93 switch (p->stat.compression) {
94#ifdef CONFIG_LZMA
95 case ALGO_LZMA:
96 dcmp = lzma_decompress;
97 break;
98#endif
99#ifdef CONFIG_NRV2B
100 case ALGO_NRV2B:
101 dcmp = nrv2b_decompress;
102 break;
103#endif
104 case ALGO_ZEROES:
105 dcmp = zeros_decompress;
106 break;
107 case ALGO_NONE:
108 dcmp = nop_decompress;
109 default:
110 printf("E: Unsupported decompression type\n");
111 return -1;
112 }
113
114 while (1) {
115 u32 laddr = (u32) (seg->load_addr & 0xFFFFFFFF);
116
117 switch (seg->type) {
118 case SELF_TYPE_CODE:
119 case SELF_TYPE_DATA:
120 dlen = dcmp((void *)laddr,
121 (void *)p->fptr + seg->offset, seg->len);
122
123 if (dlen < seg->mem_len) {
124 memset((void *)(laddr + dlen), 0,
125 seg->mem_len - dlen);
126 }
127 break;
128
129 case SELF_TYPE_BSS:
130 memset((void *)laddr, 0, seg->len);
131 break;
132 case SELF_TYPE_ENTRY:
133 *ret = exec(laddr, 0, NULL);
134 return 0;
135 default:
136 break;
137 }
138
139 seg++;
140 }
141
142 return -1;
143}