29#ifdef APA_SUPPORT_BHDD
33const char apaMBRMagic[] =
"Sony Computer Entertainment Inc.";
35void apaSaveError(s32 device,
void *buffer, u32 lba, u32 err_lba)
37 memset(buffer, 0, 512);
38 *(u32 *)buffer = err_lba;
39 blkIoDmaTransfer(device, buffer, lba, 1, BLKIO_DIR_WRITE);
40 blkIoFlushCache(device);
43void apaSetPartErrorSector(s32 device, u32 lba)
46 clink = apaCacheAlloc();
47 apaSaveError(device, clink->header, APA_SECTOR_PART_ERROR, lba);
51int apaGetPartErrorSector(s32 device, u32 lba, u32 *lba_out)
56 if (!(clink = apaCacheAlloc()))
59 if (blkIoDmaTransfer(device, clink->header, lba, 1, BLKIO_DIR_READ))
63 *lba_out = *clink->error_lba;
64 if (*clink->error_lba)
70int apaGetPartErrorName(s32 device,
char *name)
76 if ((rv = apaGetPartErrorSector(device, APA_SECTOR_PART_ERROR, &lba)) <= 0)
78 if (!(clink = apaCacheGetHeader(device, APA_SECTOR_MBR, APA_IO_MODE_READ, &rv)))
82 if (clink->header->type != APA_TYPE_FREE &&
83 !(clink->header->flags & APA_CACHE_FLAG_DIRTY) &&
84 clink->header->start == lba) {
86 strncpy(name, clink->header->id, APA_IDMAX - 1);
87 name[APA_IDMAX - 1] =
'\0';
92 clink = apaGetNextHeader(clink, &rv);
97 apaSetPartErrorSector(device, 0);
102 u32 prev, u32 length,
int *err)
106 if (!(clink = apaCacheGetHeader(device, start, APA_IO_MODE_WRITE, err)))
109 clink->header->magic = APA_MAGIC;
110 clink->header->start = start;
111 clink->header->next = next;
112 clink->header->prev = prev;
113 clink->header->length = length;
114 clink->header->type = params->type;
115 clink->header->flags = params->flags;
116 clink->header->modver = APA_MODVER;
117 memcpy(clink->header->id, params->id, APA_IDMAX);
119 clink->header->main = params->main;
120 clink->header->number = params->number;
122 if (strncmp(clink->header->id,
"_tmp", APA_IDMAX) != 0) {
123 memcpy(clink->header->rpwd, params->rpwd, APA_PASSMAX);
124 memcpy(clink->header->fpwd, params->fpwd, APA_PASSMAX);
127 apaGetTime(&clink->header->created);
128 clink->flags |= APA_CACHE_FLAG_DIRTY;
137 if ((clink_this = apaCacheGetHeader(device, sector, APA_IO_MODE_READ, err)) == 0)
140 while (clink_this->header->length != params->size) {
143 if ((clink_next = apaCacheGetHeader(device, clink_this->header->next, APA_IO_MODE_READ, err)) == NULL) {
144 apaCacheFree(clink_this);
147 clink_this->header->length >>= 1;
148 clink_empty = apaRemovePartition(device, (clink_this->header->start + clink_this->header->length),
149 clink_this->header->next, clink_this->header->start, clink_this->header->length);
150 clink_this->header->next = clink_empty->header->start;
151 clink_this->flags |= APA_CACHE_FLAG_DIRTY;
152 clink_next->header->prev = clink_empty->header->start;
153 clink_next->flags |= APA_CACHE_FLAG_DIRTY;
155 apaCacheFlushAllDirty(device);
156 apaCacheFree(clink_empty);
157 apaCacheFree(clink_next);
159 apaCacheFree(clink_this);
160 clink_this = apaFillHeader(device, params, clink_this->header->start, clink_this->header->next,
161 clink_this->header->prev, params->size, err);
162 apaCacheFlushAllDirty(device);
166apa_cache_t *apaFindPartition(s32 device,
const char *
id,
int *err)
171#ifdef APA_SUPPORT_BHDD
172 if (strcmp(
id,
"__xcontents") == 0 || strcmp(
id,
"__extend") == 0 || strcmp(
id,
"__xdata") == 0)
173 sector = hddDevices[device].totalLBA;
176 clink = apaCacheGetHeader(device, sector, APA_IO_MODE_READ, err);
179 if (memcmp(clink->header->id,
id, APA_IDMAX) == 0)
182 clink = apaGetNextHeader(clink, (
int *)err);
193void apaAddEmptyBlock(
apa_header_t *header, u32 *emptyBlocks)
197 if (header->type == APA_TYPE_FREE) {
198 for (i = 0; i < 32; i++) {
199 if (header->length == (u32)(((u32)1) << i)) {
200 if (emptyBlocks[i] == APA_TYPE_FREE) {
201 emptyBlocks[i] = header->start;
209apa_cache_t *apaRemovePartition(s32 device, u32 start, u32 next, u32 prev,
215 if ((clink = apaCacheGetHeader(device, start, APA_IO_MODE_WRITE, &err)) == NULL)
218 clink->header->magic = APA_MAGIC;
219 clink->header->start = start;
220 clink->header->next = next;
221 clink->header->prev = prev;
222 clink->header->length = length;
223 strcpy(clink->header->id,
"__empty");
224 apaGetTime(&clink->header->created);
225 clink->flags |= APA_CACHE_FLAG_DIRTY;
236 saved_start = clink->header->start;
237 saved_next = clink->header->next;
238 saved_prev = clink->header->prev;
239 saved_length = clink->header->length;
241 clink->header->magic = APA_MAGIC;
242 clink->header->start = saved_start;
243 clink->header->next = saved_next;
244 clink->header->prev = saved_prev;
245 clink->header->length = saved_length;
246 apaGetTime(&clink->header->created);
247 strcpy(clink->header->id,
"__empty");
248 clink->flags |= APA_CACHE_FLAG_DIRTY;
255 u32 device = clink->device;
256 u32 length = clink->header->length;
257 u32 saved_next = clink->header->next;
258 u32 saved_length = clink->header->length;
261 while (header->start) {
262 if (!(clink2 = apaCacheGetHeader(device, header->prev, APA_IO_MODE_READ, err))) {
266 header = clink2->header;
267 tmp = header->length + length;
268 if (header->type != 0) {
269 apaCacheFree(clink2);
272 if ((header->start % tmp) || (tmp & (tmp - 1))) {
273 apaCacheFree(clink2);
280 if (length != saved_length) {
281 if (!(clink2 = apaCacheGetHeader(device, saved_next, APA_IO_MODE_READ, err))) {
285 clink->header->length = length;
286 clink->header->next = clink->header->start + length;
287 clink2->header->prev = clink->header->start;
288 clink2->flags |= APA_CACHE_FLAG_DIRTY;
289 clink->flags |= APA_CACHE_FLAG_DIRTY;
290 apaCacheFlushAllDirty(device);
291 apaCacheFree(clink2);
300 u32 length = header->length;
301 u32 saved_length = header->length;
302 u32 lnext = header->next;
303 u32 device = clink->device;
309 if (!(clink1 = apaCacheGetHeader(device, lnext, APA_IO_MODE_READ, err))) {
313 header = clink1->header;
314 tmp = header->length + length;
315 if (header->type != 0) {
316 apaCacheFree(clink1);
319 if ((clink->header->start % tmp) != 0 || ((tmp - 1) & tmp)) {
320 apaCacheFree(clink1);
324 apaCacheFree(clink1);
325 lnext = header->next;
327 if (length != saved_length) {
330 if (!(clink2 = apaCacheGetHeader(device, lnext, APA_IO_MODE_READ, err))) {
334 clink->header->length = length;
335 clink->header->next = lnext;
337 clink2->header->prev = clink->header->start;
338 clink2->flags |= APA_CACHE_FLAG_DIRTY;
339 apaCacheFlushAllDirty(device);
340 apaCacheFree(clink2);
349 u32 device = clink->device;
350 u32 start = clink->header->start;
357 if (clink->header->next == 0) {
360 if ((clink_mbr = apaCacheGetHeader(device, APA_SECTOR_MBR, APA_IO_MODE_READ, &rv)) == NULL) {
366 if ((clink = apaCacheGetHeader(clink->device, clink->header->prev, APA_IO_MODE_READ, &rv)) == NULL)
368 clink->header->next = 0;
369 clink->flags |= APA_CACHE_FLAG_DIRTY;
370 clink_mbr->header->prev = clink->header->start;
371 clink_mbr->flags |= APA_CACHE_FLAG_DIRTY;
372 apaCacheFlushAllDirty(device);
373 }
while (clink->header->type == 0);
374 apaCacheFree(clink_mbr);
377 u32 length = clink->header->length;
379 for (i = 0; i < 2; i++) {
380 if ((clink = apaDeleteFixPrev(clink, &rv)) == NULL)
382 if ((clink = apaDeleteFixNext(clink, &rv)) == NULL)
385 if (clink->header->start == start && clink->header->length == length) {
387 apaCacheFlushAllDirty(clink->device);
396 u32 *ptr = (u32 *)header;
399 for (sum = 0, i = 1; i < 256; i++)
401#ifdef APA_SUPPORT_GPT
403 for (sum = 0, i = 1; i < 128; i++)
411int apaReadHeader(s32 device,
apa_header_t *header, u32 lba)
413 if (blkIoDmaTransfer(device, header, lba, 2, BLKIO_DIR_READ) != 0)
415 if (header->magic != APA_MAGIC)
417#ifdef APA_SUPPORT_GPT
418 if ((u32)(apaCheckSum(header, 1)) != header->checksum)
419 if (lba == APA_SECTOR_MBR)
420 if ((u32)(apaCheckSum(header, 0)) != header->checksum)
423 if ((u32)(apaCheckSum(header, 1)) != header->checksum)
427 if (lba == APA_SECTOR_MBR) {
428 if (strncmp(header->mbr.magic, apaMBRMagic,
sizeof(header->mbr.magic)) == 0)
430 APA_PRINTF(APA_DRV_NAME
": error: invalid partition table or version newer than I know.\n");
436int apaWriteHeader(s32 device,
apa_header_t *header, u32 lba)
438 if (blkIoDmaTransfer(device, header, lba, 2, BLKIO_DIR_WRITE))
443int apaGetFormat(s32 device,
int *format)
449 clink = apaCacheAlloc();
451 if ((rv = apaReadHeader(device, clink->header, 0)) == 0) {
452 *format = clink->header->mbr.version;
453 if (blkIoDmaTransfer(device, clink->header, APA_SECTOR_SECTOR_ERROR, 2, BLKIO_DIR_READ))
458 pDW = (u32 *)clink->header;
459 for (i = 0; i < 256; i++) {
460 if ((i & 0x7F) && pDW[i] != 0)
469u32 apaGetPartitionMax(u32 totalLBA)
473#ifdef APA_WORKAROUND_LESS_THAN_40GB_CAPACITY
474 if (totalLBA < 0x04ffffff)
475 totalLBA = 0x04ffffff;
479 size = (((u32)1) << 0x1F);
480 for (i = 31; i != 0; i--) {
481 size = ((u32)1) << i;
492 u32 start = clink->header->start;
495 if (!clink->header->next)
498 if (!(clink = apaCacheGetHeader(clink->device, clink->header->next, APA_IO_MODE_READ, err)))
501 if (start != clink->header->prev) {
502 APA_PRINTF(APA_DRV_NAME
": Warning: Invalid partition information. start != prev\n");
503 clink->header->prev = start;
504 clink->flags |= APA_CACHE_FLAG_DIRTY;
505 apaCacheFlushAllDirty(clink->device);