source: ps2launchargs/source/uLaunchELF/hdl_info/apa.c

Last change on this file was 1101, checked in by iritscen, 7 years ago

Added following to ps2launchargs:\n-Source code.\n-DLL needed to run ps2client.\n-Instructions for building uLaunchELF.

  • Property svn:executable set to *
File size: 9.7 KB
Line 
1//--------------------------------------------------------------
2//File name: apa.c
3//--------------------------------------------------------------
4#include <thbase.h>
5#include <sysclib.h>
6#include <cdvdman.h>
7#include <iomanX.h>
8#include <sysmem.h>
9
10#include "ps2_hdd.h"
11#include "hdd.h"
12#include "hdl.h"
13#include "apa.h"
14
15#define AUTO_DELETE_EMPTY
16
17#define _MB * (1024 * 1024) /* really ugly :-) */
18
19typedef struct ps2_partition_run_type
20{
21 unsigned long sector;
22 u_long size_in_mb;
23} ps2_partition_run_t;
24
25//Remove this line, and uncomment the next line, to reactivate 'apa_check'
26//static int apa_check(const apa_partition_table_t *table);
27
28//--------------------------------------------------------------
29u_long apa_partition_checksum(const ps2_partition_header_t *part)
30{
31 const u_long *p = (const u_long*)part;
32 register u_long i;
33 u_long sum = 0;
34 for(i=1; i<256; ++i)
35 sum += get_u32(p + i);
36 return sum;
37}
38//------------------------------
39//endfunc apa_partition_checksum
40//--------------------------------------------------------------
41static apa_partition_table_t* apa_ptable_alloc(void)
42{
43 apa_partition_table_t *table = AllocSysMemory(0, sizeof (apa_partition_table_t), NULL);
44 if(table != NULL)
45 memset(table, 0, sizeof (apa_partition_table_t));
46 return table;
47}
48//------------------------------
49//endfunc apa_ptable_alloc
50//--------------------------------------------------------------
51void apa_ptable_free(apa_partition_table_t *table)
52{
53 if (table != NULL){
54 if (table->chunks_map != NULL)
55 FreeSysMemory(table->chunks_map);
56 if (table->parts != NULL)
57 FreeSysMemory(table->parts);
58 FreeSysMemory(table);
59 }
60}
61//------------------------------
62//endfunc apa_ptable_free
63//--------------------------------------------------------------
64static int apa_part_add (apa_partition_table_t *table, const ps2_partition_header_t *part, int existing, int linked)
65{
66 if (table->part_count == table->part_alloc_){ /* grow buffer */
67 u_long bytes = (table->part_alloc_ + 16) * sizeof (apa_partition_t);
68 apa_partition_t *tmp = AllocSysMemory(0, bytes, NULL);
69 if(tmp != NULL)
70 {
71 memset(tmp, 0, bytes);
72 if (table->parts != NULL) /* copy existing */
73 memcpy(tmp, table->parts, table->part_count * sizeof (apa_partition_t));
74 FreeSysMemory(table->parts);
75 table->parts = tmp;
76 table->part_alloc_ += 16;
77 }
78 else return -2;
79 }
80
81 memcpy(&table->parts[table->part_count].header, part, sizeof (ps2_partition_header_t));
82 table->parts[table->part_count].existing = existing;
83 table->parts[table->part_count].modified = !existing;
84 table->parts[table->part_count].linked = linked;
85 ++table->part_count;
86
87 return 0;
88}
89//------------------------------
90//endfunc apa_part_add
91//--------------------------------------------------------------
92/* //Remove this line and a similar one below to reactivate 'apa_setup_statistics'
93static int apa_setup_statistics(apa_partition_table_t *table)
94{
95 u_long i;
96 char *map;
97
98 table->total_chunks = table->device_size_in_mb / 128;
99 map = AllocSysMemory(0, table->total_chunks * sizeof (char), NULL);
100 if(map != NULL)
101 {
102 for(i=0; i<table->total_chunks; ++i)
103 map [i] = MAP_AVAIL;
104
105 // build occupided/available space map
106 table->allocated_chunks = 0;
107 table->free_chunks = table->total_chunks;
108 for(i=0; i<table->part_count; ++i)
109 {
110 const ps2_partition_header_t *part = &table->parts [i].header;
111 u_long part_no = get_u32(&part->start) / ((128 _MB) / 512);
112 u_long num_parts = get_u32(&part->length) / ((128 _MB) / 512);
113
114 // "alloc" num_parts starting at part_no
115 while (num_parts)
116 {
117 if(map[part_no] == MAP_AVAIL)
118 map[part_no] = get_u32(&part->main) == 0 ? MAP_MAIN : MAP_SUB;
119 else
120 map[part_no] = MAP_COLL; // collision
121 ++part_no;
122 --num_parts;
123 ++table->allocated_chunks;
124 --table->free_chunks;
125 }
126 }
127
128 if(table->chunks_map != NULL)
129 FreeSysMemory(table->chunks_map);
130 table->chunks_map = map;
131
132 return 0;
133 }
134 else return -2;
135}
136*/ //Remove this line and a similar one below to reactivate 'apa_setup_statistics'
137//------------------------------
138//endfunc apa_setup_statistics
139//--------------------------------------------------------------
140int apa_ptable_read_ex ( hio_t *hio, apa_partition_table_t **table)
141{
142 u_long size_in_kb;
143 int result = hio->stat(hio, &size_in_kb);
144 if(result == 0){
145 u_long total_sectors;
146 // limit HDD size to 128GB - 1KB; that is: exclude the last 128MB chunk
147 //if (size_in_kb > 128 * 1024 * 1024 - 1)
148 // size_in_kb = 128 * 1024 * 1024 - 1;
149
150 total_sectors = size_in_kb * 2; /* 1KB = 2 sectors of 512 bytes, each */
151
152 *table = apa_ptable_alloc();
153 if(*table != NULL){
154 u_long sector = 0;
155 do {
156 u_long bytes;
157 ps2_partition_header_t part;
158 result = hio->read(hio, sector, sizeof(part) / 512, &part, &bytes);
159 if(result == 0){
160 if(bytes == sizeof(part) &&
161 get_u32(&part.checksum) == apa_partition_checksum(&part) &&
162 memcmp(part.magic, PS2_PARTITION_MAGIC, 4) == 0)
163 {
164 if(get_u32(&part.start) < total_sectors &&
165 get_u32(&part.start) + get_u32(&part.length) < total_sectors)
166 {
167 if((get_u16(&part.flags)==0x0000) && (get_u16(&part.type) ==0x1337))
168 result = apa_part_add(*table, &part, 1, 1);
169 if(result == 0)
170 sector = get_u32(&part.next);
171 } else { /* partition behind end-of-HDD */
172 result = 7; /* data behind end-of-HDD */
173 break;
174 }
175 } else
176 result = 1;
177 }
178 /* TODO: check whether next partition is not loaded already --
179 * do not deadlock; that is a quick-and-dirty hack */
180 if ((*table)->part_count > 10000)
181 result = 7;
182 } while (result == 0 && sector != 0);
183
184 if (result == 0){
185 (*table)->device_size_in_mb = size_in_kb / 1024;
186 //NB: uncommenting the next lines requires changes elsewhere too
187 //result = apa_setup_statistics (*table);
188 //if (result == 0)
189 //result = apa_check (*table);
190 }
191
192 if (result != 0){
193 result = 20000+(*table)->part_count;
194 apa_ptable_free (*table);
195 }
196 }
197 else result = -2;
198 }
199 return result;
200}
201//------------------------------
202//endfunc apa_ptable_read_ex
203//--------------------------------------------------------------
204/* //Remove this line and a similar one below to reactivate 'apa_check'
205static int apa_check (const apa_partition_table_t *table) {
206
207 u_long i, j, k;
208
209 const u_long total_sectors = table->device_size_in_mb * 1024 * 2;
210
211 for (i=0; i<table->part_count; ++i)
212 {
213 const ps2_partition_header_t *part = &table->parts [i].header;
214 if (get_u32 (&part->checksum) != apa_partition_checksum (part))
215 return 7; // bad checksum
216
217 if (get_u32 (&part->start) < total_sectors &&
218 get_u32 (&part->start) + get_u32 (&part->length) <= total_sectors)
219 ;
220 else
221 {
222 return 7; // data behind end-of-HDD
223 }
224
225 if ((get_u32 (&part->length) % ((128 _MB) / 512)) != 0)
226 return 7; // partition size not multiple to 128MB
227
228 if ((get_u32 (&part->start) % get_u32 (&part->length)) != 0)
229 return 7; // partition start not multiple on partition size
230
231 if (get_u32 (&part->main) == 0 &&
232 get_u16 (&part->flags) == 0 &&
233 get_u32 (&part->start) != 0)
234 { // check sub-partitions
235 u_long count = 0;
236 for (j=0; j<table->part_count; ++j)
237 {
238 const ps2_partition_header_t *part2 = &table->parts [j].header;
239 if (get_u32 (&part2->main) == get_u32 (&part->start))
240 { // sub-partition of current main partition
241 int found;
242 if (get_u16 (&part2->flags) != PS2_PART_FLAG_SUB)
243 return 7;
244
245 found = 0;
246 for (k=0; k<get_u32 (&part->nsub); ++k)
247 if (get_u32 (&part->subs [k].start) == get_u32 (&part2->start))
248 { // in list
249 if (get_u32 (&part->subs [k].length) != get_u32 (&part2->length))
250 return 7;
251 found = 1;
252 break;
253 }
254 if (!found)
255 return 7; // not found in the list
256
257 ++count;
258 }
259 }
260 if (count != get_u32 (&part->nsub))
261 return 7; // wrong number of sub-partitions
262 }
263 }
264
265 // verify double-linked list
266 for (i=0; i<table->part_count; ++i)
267 {
268 apa_partition_t *prev = table->parts + (i > 0 ? i - 1 : table->part_count - 1);
269 apa_partition_t *curr = table->parts + i;
270 apa_partition_t *next = table->parts + (i + 1 < table->part_count ? i + 1 : 0);
271 if (get_u32 (&curr->header.prev) != get_u32 (&prev->header.start) ||
272 get_u32 (&curr->header.next) != get_u32 (&next->header.start))
273 return 7; // bad links
274 }
275
276 return 0;
277}
278*/ //Remove this line and a similar one above to reactivate 'apa_check'
279//------------------------------
280//endfunc apa_check
281//--------------------------------------------------------------
282u_long get_u32 (const void *buffer)
283{
284 const u_char *p = buffer;
285 return ((((u_long) p[3]) << 24) |
286 (((u_long) p[2]) << 16) |
287 (((u_long) p[1]) << 8) |
288 (((u_long) p[0]) << 0));
289}
290//------------------------------
291//endfunc get_u32
292//--------------------------------------------------------------
293void set_u32 (void *buffer, u_long val)
294{
295 u_char *p = buffer;
296 p [3] = (u_char) (val >> 24);
297 p [2] = (u_char) (val >> 16);
298 p [1] = (u_char) (val >> 8);
299 p [0] = (u_char) (val >> 0);
300}
301//------------------------------
302//endfunc set_u32
303//--------------------------------------------------------------
304u_short get_u16 (const void *buffer)
305{
306 const u_char *p = buffer;
307 return ((((u_short) p[1]) << 8) |
308 (((u_short) p[0]) << 0));
309}
310//------------------------------
311//endfunc get_u16
312//--------------------------------------------------------------
313void set_u16 (void *buffer, u_short val)
314{
315 u_char *p = buffer;
316 p [1] = (u_char) (val >> 8);
317 p [0] = (u_char) (val >> 0);
318}
319//------------------------------
320//endfunc set_u16
321//--------------------------------------------------------------
322//End of file: apa.c
323//--------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.