]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Copyright (C) Paul Mackerras 1997. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU General Public License | |
6 | * as published by the Free Software Foundation; either version | |
7 | * 2 of the License, or (at your option) any later version. | |
8 | */ | |
9 | ||
10 | #include "nonstdio.h" | |
11 | #include "of1275.h" | |
12 | #include <linux/string.h> | |
13 | #include <linux/zlib.h> | |
14 | #include <asm/bootinfo.h> | |
15 | #include <asm/page.h> | |
16 | ||
17 | /* Information from the linker */ | |
1da177e4 LT |
18 | |
19 | extern int strcmp(const char *s1, const char *s2); | |
20 | extern char *avail_ram, *avail_high; | |
21 | extern char *end_avail; | |
22 | ||
23 | unsigned int heap_use, heap_max; | |
24 | ||
25 | struct memchunk { | |
26 | unsigned int size; | |
27 | struct memchunk *next; | |
28 | }; | |
29 | ||
30 | static struct memchunk *freechunks; | |
31 | ||
32 | static void *zalloc(unsigned size) | |
33 | { | |
34 | void *p; | |
35 | struct memchunk **mpp, *mp; | |
36 | ||
37 | size = (size + 7) & -8; | |
38 | heap_use += size; | |
39 | if (heap_use > heap_max) | |
40 | heap_max = heap_use; | |
41 | for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { | |
42 | if (mp->size == size) { | |
43 | *mpp = mp->next; | |
44 | return mp; | |
45 | } | |
46 | } | |
47 | p = avail_ram; | |
48 | avail_ram += size; | |
49 | if (avail_ram > avail_high) | |
50 | avail_high = avail_ram; | |
51 | if (avail_ram > end_avail) { | |
52 | printf("oops... out of memory\n\r"); | |
53 | pause(); | |
54 | } | |
55 | return p; | |
56 | } | |
57 | ||
58 | #define HEAD_CRC 2 | |
59 | #define EXTRA_FIELD 4 | |
60 | #define ORIG_NAME 8 | |
61 | #define COMMENT 0x10 | |
62 | #define RESERVED 0xe0 | |
63 | ||
64 | void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) | |
65 | { | |
66 | z_stream s; | |
67 | int r, i, flags; | |
68 | ||
69 | /* skip header */ | |
70 | i = 10; | |
71 | flags = src[3]; | |
72 | if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) { | |
73 | printf("bad gzipped data\n\r"); | |
74 | exit(); | |
75 | } | |
76 | if ((flags & EXTRA_FIELD) != 0) | |
77 | i = 12 + src[10] + (src[11] << 8); | |
78 | if ((flags & ORIG_NAME) != 0) | |
79 | while (src[i++] != 0) | |
80 | ; | |
81 | if ((flags & COMMENT) != 0) | |
82 | while (src[i++] != 0) | |
83 | ; | |
84 | if ((flags & HEAD_CRC) != 0) | |
85 | i += 2; | |
86 | if (i >= *lenp) { | |
87 | printf("gunzip: ran out of data in header\n\r"); | |
88 | exit(); | |
89 | } | |
90 | ||
91 | /* Initialize ourself. */ | |
92 | s.workspace = zalloc(zlib_inflate_workspacesize()); | |
93 | r = zlib_inflateInit2(&s, -MAX_WBITS); | |
94 | if (r != Z_OK) { | |
95 | printf("zlib_inflateInit2 returned %d\n\r", r); | |
96 | exit(); | |
97 | } | |
98 | s.next_in = src + i; | |
99 | s.avail_in = *lenp - i; | |
100 | s.next_out = dst; | |
101 | s.avail_out = dstlen; | |
102 | r = zlib_inflate(&s, Z_FINISH); | |
103 | if (r != Z_OK && r != Z_STREAM_END) { | |
104 | printf("inflate returned %d msg: %s\n\r", r, s.msg); | |
105 | exit(); | |
106 | } | |
107 | *lenp = s.next_out - (unsigned char *) dst; | |
108 | zlib_inflateEnd(&s); | |
109 | } | |
110 | ||
111 | /* Make a bi_rec in OF. We need to be passed a name for BI_BOOTLOADER_ID, | |
112 | * a machine type for BI_MACHTYPE, and the location where the end of the | |
113 | * bootloader is (PROG_START + PROG_SIZE) | |
114 | */ | |
115 | void make_bi_recs(unsigned long addr, char *name, unsigned int mach, | |
116 | unsigned long progend) | |
117 | { | |
1da177e4 LT |
118 | struct bi_record *rec; |
119 | ||
1da177e4 LT |
120 | |
121 | /* leave a 1MB gap then align to the next 1MB boundary */ | |
122 | addr = _ALIGN(addr+ (1<<20) - 1, (1<<20)); | |
123 | /* oldworld machine seem very unhappy about this. -- Tom */ | |
124 | if (addr >= progend) | |
125 | claim(addr, 0x1000, 0); | |
126 | ||
127 | rec = (struct bi_record *)addr; | |
128 | rec->tag = BI_FIRST; | |
129 | rec->size = sizeof(struct bi_record); | |
130 | rec = (struct bi_record *)((unsigned long)rec + rec->size); | |
131 | ||
132 | rec->tag = BI_BOOTLOADER_ID; | |
133 | sprintf( (char *)rec->data, name); | |
134 | rec->size = sizeof(struct bi_record) + strlen(name) + 1; | |
135 | rec = (struct bi_record *)((unsigned long)rec + rec->size); | |
136 | ||
137 | rec->tag = BI_MACHTYPE; | |
138 | rec->data[0] = mach; | |
139 | rec->data[1] = 1; | |
140 | rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); | |
141 | rec = (struct bi_record *)((unsigned long)rec + rec->size); | |
142 | ||
1da177e4 LT |
143 | rec->tag = BI_LAST; |
144 | rec->size = sizeof(struct bi_record); | |
145 | rec = (struct bi_record *)((unsigned long)rec + rec->size); | |
146 | } |