blob: 94b4623494a153fd94b3ec3e0d09b5cfe46024c9 [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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Paul Menzela46a7122013-02-23 18:37:27 +010017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Uwe Hermann7eb845e2008-11-02 17:01:06 +000018 */
19
20#include "bayou.h"
21#include "self.h"
22
23static int nop_decompress(void *dst, void *src, int len)
24{
25 memcpy(dst, src, len);
26 return len;
27}
28
29#ifdef CONFIG_LZMA
30extern int ulzma(u8 *, u8 *);
31
32static int lzma_decompress(void *dst, void *src, int len)
33{
34 return ulzma((u8 *) src, (u8 *) dst);
35}
36#endif
37
38#ifdef CONFIG_NRV2B
39extern int unrv2b(u8 *, u8 *, unsigned long *);
40
41static int nrv2b_decompress(void *dst, void *src, int len)
42{
43 unsigned long l = (u32) len;
44 return unrv2b(src, dst, &l);
45}
46#endif
47
48static int zeros_decompress(void *dst, void *src, int len)
49{
50 memset(dst, 0, len);
51 return len;
52}
53
54int self_get_params(u8 *fptr, u8 **params)
55{
56 struct self_segment *seg = (struct self_segment *)fptr;
57
58 while (seg->type != SELF_TYPE_ENTRY) {
59 if (seg->type == 0)
60 return -1;
61
62 if (seg->type == SELF_TYPE_PARAMS) {
63 *params = (u8 *) (fptr + seg->offset);
64 return seg->len;
65 }
66
67 seg++;
68 }
69
70 *params = NULL;
71
72 return 0;
73}
74
75int verify_self(u8 *ptr)
76{
77 struct self_segment *seg = (struct self_segment *)ptr;
78
79 switch (seg->type) {
80 case SELF_TYPE_CODE:
81 case SELF_TYPE_DATA:
82 case SELF_TYPE_BSS:
83 case SELF_TYPE_PARAMS:
84 case SELF_TYPE_ENTRY:
85 return 1;
86 }
87
88 return 0;
89}
90
91int self_load_and_run(struct payload *p, int *ret)
92{
93 struct self_segment *seg = (struct self_segment *)p->fptr;
94 int (*dcmp) (void *, void *, int);
95 int dlen;
96
97 switch (p->stat.compression) {
98#ifdef CONFIG_LZMA
99 case ALGO_LZMA:
100 dcmp = lzma_decompress;
101 break;
102#endif
103#ifdef CONFIG_NRV2B
104 case ALGO_NRV2B:
105 dcmp = nrv2b_decompress;
106 break;
107#endif
108 case ALGO_ZEROES:
109 dcmp = zeros_decompress;
110 break;
111 case ALGO_NONE:
112 dcmp = nop_decompress;
113 default:
114 printf("E: Unsupported decompression type\n");
115 return -1;
116 }
117
118 while (1) {
119 u32 laddr = (u32) (seg->load_addr & 0xFFFFFFFF);
120
121 switch (seg->type) {
122 case SELF_TYPE_CODE:
123 case SELF_TYPE_DATA:
124 dlen = dcmp((void *)laddr,
125 (void *)p->fptr + seg->offset, seg->len);
126
127 if (dlen < seg->mem_len) {
128 memset((void *)(laddr + dlen), 0,
129 seg->mem_len - dlen);
130 }
131 break;
132
133 case SELF_TYPE_BSS:
134 memset((void *)laddr, 0, seg->len);
135 break;
136 case SELF_TYPE_ENTRY:
137 *ret = exec(laddr, 0, NULL);
138 return 0;
139 default:
140 break;
141 }
142
143 seg++;
144 }
145
146 return -1;
147}