int apaJournalRestore(s32 device) { // copys apa headers from apal to apa system int i; u32 sector; apa_cache_t *clink; APA_PRINTF(APA_DRV_NAME": checking log...\n"); if(ata_device_sector_io(device, &journalBuf, APA_SECTOR_APAL, sizeof(apa_journal_t)/512, ATA_DIR_READ)){ apaJournalReset(device); return -EIO; } if(journalBuf.magic==APAL_MAGIC) { if(journalBuf.num==0) return 0; clink=apaCacheAlloc(); for(i=0, sector=APA_SECTOR_APAL_HEADERS;i<journalBuf.num;i++, sector+=2) { if(ata_device_sector_io(device, clink->header, sector, 2, ATA_DIR_READ)) break; if(ata_device_sector_io(device, clink->header, journalBuf.sectors[i], 2, ATA_DIR_WRITE)) break; } apaCacheFree(clink); return apaJournalReset(device);// only do if journal.. } memset(&journalBuf, 0, sizeof(apa_journal_t));// safe e journalBuf.magic=APAL_MAGIC; return 0;//-EINVAL; }
static int apaOpen(s32 device, hdd_file_slot_t *fileSlot, apa_params_t *params, int mode) { int rv=0; u32 emptyBlocks[32]; apa_cache_t *clink; apa_cache_t *clink2; u32 sector=0; // walk all looking for any empty blocks & look for partition clink=apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &rv); memset(&emptyBlocks, 0, sizeof(emptyBlocks)); while(clink) { sector=clink->sector; if(!(clink->header->flags & APA_FLAG_SUB)) { if(memcmp(clink->header->id, params->id, APA_IDMAX) == 0) break; // found :) } apaAddEmptyBlock(clink->header, emptyBlocks); clink=apaGetNextHeader(clink, &rv); } if(rv!=0) return rv; rv=-ENOENT; if(clink==NULL && (mode & O_CREAT)) { if((rv=hddCheckPartitionMax(device, params->size))>=0) { if((clink=hddAddPartitionHere(device, params, emptyBlocks, sector, &rv))!=NULL) { sector=clink->header->start; clink2=apaCacheAlloc(); memset(clink2->header, 0, sizeof(apa_header_t)); ata_device_sector_io(device, clink2->header, sector+8 , 2, ATA_DIR_WRITE); ata_device_sector_io(device, clink2->header, sector+0x2000, 2, ATA_DIR_WRITE); apaCacheFree(clink2); } } } if(clink==NULL) return rv; fileSlot->parts[0].start=clink->header->start; fileSlot->parts[0].length=clink->header->length; memcpy(&fileSlot->parts[1], &clink->header->subs, APA_MAXSUB*sizeof(apa_sub_t)); fileSlot->type=clink->header->type; fileSlot->nsub=clink->header->nsub; memcpy(&fileSlot->id, &clink->header->id, APA_IDMAX); apaCacheFree(clink); if(apaPassCmp(clink->header->fpwd, params->fpwd)!=0) { rv = (!(mode & O_WRONLY)) ? apaPassCmp(clink->header->rpwd, params->rpwd) : -EACCES; } else rv = 0; return rv; }
static int fioDataTransfer(iop_file_t *f, void *buf, int size, int mode) { hdd_file_slot_t *fileSlot=(hdd_file_slot_t *)f->privdata; if((size & 0x1FF)) return -EINVAL; size>>=9; // size/512 if(fileSlot->post+size>=0x1FF9)// no over reading size=0x1FF8-fileSlot->post; if(size!=0) { int rv=0; WaitSema(fioSema); if(ata_device_sector_io(f->unit, buf, fileSlot->post+fileSlot->parts[0].start+8, size, mode)) rv=-EIO; SignalSema(fioSema); if(rv==0) { fileSlot->post+=size; return size<<9; } return rv; } return 0; }
void apaSaveError(s32 device, void *buffer, u32 lba, u32 err_lba) { memset(buffer, 0, 512); *(u32 *)buffer = err_lba; ata_device_sector_io(device, buffer, lba, 1, ATA_DIR_WRITE); ata_device_flush_cache(device); }
int apaJournalWrite(apa_cache_t *clink) { clink->header->checksum=journalCheckSum(clink->header); if(ata_device_sector_io(clink->device, clink->header, (journalBuf.num << 1)+APA_SECTOR_APAL_HEADERS, 2, ATA_DIR_WRITE)) return -EIO; journalBuf.sectors[journalBuf.num]=clink->sector; journalBuf.num++; return 0; }
int apaJournalFlush(s32 device) {// this write any thing that in are journal buffer :) if(ata_device_flush_cache(device)) return -EIO; if(ata_device_sector_io(device, &journalBuf, APA_SECTOR_APAL, 1, ATA_DIR_WRITE)) return -EIO; if(ata_device_flush_cache(device)) return -EIO; return 0; }
int apaReadHeader(s32 device, apa_header_t *header, u32 lba) { if (ata_device_sector_io(device, header, lba, 2, ATA_DIR_READ) != 0) return -EIO; if (header->magic != APA_MAGIC) return -EIO; if (apaCheckSum(header) != header->checksum) return -EIO; if (lba == APA_SECTOR_MBR) { if (strncmp(header->mbr.magic, apaMBRMagic, sizeof(header->mbr.magic)) == 0) return 0; APA_PRINTF(APA_DRV_NAME ": error: invalid partition table or version newer than I know.\n"); return -EIO; } return 0; }
int apaGetPartErrorSector(s32 device, u32 lba, u32 *lba_out) { apa_cache_t *clink; int rv = 0; if (!(clink = apaCacheAlloc())) return -ENOMEM; if (ata_device_sector_io(device, clink->header, lba, 1, ATA_DIR_READ)) return -EIO; if (lba_out) *lba_out = *clink->error_lba; if (*clink->error_lba) rv = 1; // error is set ;) apaCacheFree(clink); return rv; }
static int ioctl2Transfer(s32 device, hdd_file_slot_t *fileSlot, hddIoctl2Transfer_t *arg) { if(fileSlot->nsub<arg->sub) return -ENODEV; // main partitions can only be read starting from the 4MB offset. if(arg->sub==0 && (arg->sector < 0x2000)) return -EINVAL; // sub-partitions can only be read starting from after the header. if(arg->sub!=0 && (arg->sector < 2)) return -EINVAL; if(fileSlot->parts[arg->sub].length<arg->sector+arg->size) return -ENXIO; if(ata_device_sector_io(device, arg->buffer, fileSlot->parts[arg->sub].start+arg->sector, arg->size, arg->mode)) return -EIO; return 0; }
int apaGetFormat(s32 device, int *format) { apa_cache_t *clink; int rv = 0; u32 *pDW, i; clink = apaCacheAlloc(); *format = 0; if ((rv = apaReadHeader(device, clink->header, 0)) == 0) { *format = clink->header->mbr.version; if (ata_device_sector_io(device, clink->header, APA_SECTOR_SECTOR_ERROR, 2, ATA_DIR_READ)) rv = -EIO; // return -EIO; if (rv == 0) { pDW = (u32 *)clink->header; for (i = 0; i < 256; i++) { if ((i & 0x7F) && pDW[i] != 0) rv = 1; } } } apaCacheFree(clink); return rv == 0; }
int hddDevctl(iop_file_t *f, const char *devname, int cmd, void *arg, unsigned int arglen, void *bufp, unsigned int buflen) { int rv=0; WaitSema(fioSema); switch(cmd) { // Command set 1 ('H') case HDIOC_DEV9OFF: //Early versions called ata_device_smart_save_attr() here, when their old dev9 versions did not support the pre-shutdown callback. dev9Shutdown(); break; case HDIOC_IDLE: rv=ata_device_idle(f->unit, *(char *)arg); break; case HDIOC_MAXSECTOR: rv=hddDevices[f->unit].partitionMaxSize; break; case HDIOC_TOTALSECTOR: rv=hddDevices[f->unit].totalLBA; break; case HDIOC_FLUSH: if(ata_device_flush_cache(f->unit)) rv=-EIO; break; case HDIOC_SWAPTMP: rv=devctlSwapTemp(f->unit, (char *)arg); break; case HDIOC_SMARTSTAT: rv=ata_device_smart_get_status(f->unit); break; case HDIOC_STATUS: rv=hddDevices[f->unit].status; break; case HDIOC_FORMATVER: rv=hddDevices[f->unit].format; break; case HDIOC_FREESECTOR: rv=apaGetFreeSectors(f->unit, bufp, hddDevices); break; case HDIOC_IDLEIMM: rv=ata_device_idle_immediate(f->unit); break; // Command set 2 ('h') case HDIOC_GETTIME: rv=apaGetTime((apa_ps2time_t *)bufp); break; case HDIOC_SETOSDMBR: rv=devctlSetOsdMBR(f->unit, (hddSetOsdMBR_t *)arg); break; case HDIOC_GETSECTORERROR: rv=apaGetPartErrorSector(f->unit, APA_SECTOR_SECTOR_ERROR, 0); break; case HDIOC_GETERRORPARTNAME: rv=apaGetPartErrorName(f->unit, (char *)bufp); break; case HDIOC_READSECTOR: rv=ata_device_sector_io(f->unit, (void *)bufp, ((hddAtaTransfer_t *)arg)->lba, ((hddAtaTransfer_t *)arg)->size, ATA_DIR_READ); break; case HDIOC_WRITESECTOR: rv=ata_device_sector_io(f->unit, ((hddAtaTransfer_t *)arg)->data, ((hddAtaTransfer_t *)arg)->lba, ((hddAtaTransfer_t *)arg)->size, ATA_DIR_WRITE); break; case HDIOC_SCEIDENTIFY: rv=ata_device_sce_identify_drive(f->unit, (u16 *)bufp); break; default: rv=-EINVAL; break; } SignalSema(fioSema); return rv; }
int hddFormat(iop_file_t *f, const char *dev, const char *blockdev, void *arg, int arglen) { int rv=0; apa_cache_t *clink; u32 i; #ifdef APA_FORMAT_MAKE_PARTITIONS apa_params_t params; u32 emptyBlocks[32]; #endif if(f->unit >= 2) return -ENXIO; // clear all errors on hdd clink=apaCacheAlloc(); memset(clink->header, 0, sizeof(apa_header_t)); if(ata_device_sector_io(f->unit, clink->header, APA_SECTOR_SECTOR_ERROR, 1, ATA_DIR_WRITE)){ apaCacheFree(clink); return -EIO; } if(ata_device_sector_io(f->unit, clink->header, APA_SECTOR_PART_ERROR, 1, ATA_DIR_WRITE)){ apaCacheFree(clink); return -EIO; } // clear apa headers for(i=1024*8;i<hddDevices[f->unit].totalLBA;i+=(1024*256)) { ata_device_sector_io(f->unit, clink->header, i, sizeof(apa_header_t)/512, ATA_DIR_WRITE); } apaCacheFree(clink); if((rv=apaJournalReset(f->unit))!=0) return rv; // set up mbr :) if((clink=apaCacheGetHeader(f->unit, 0, APA_IO_MODE_WRITE, &rv))){ apa_header_t *header=clink->header; memset(header, 0, sizeof(apa_header_t)); header->magic=APA_MAGIC; header->length=(1024*256); // 128MB header->type=APA_TYPE_MBR; strcpy(header->id,"__mbr"); #ifdef APA_FORMAT_LOCK_MBR apaEncryptPassword(header->id, header->fpwd, "sce_mbr"); apaEncryptPassword(header->id, header->rpwd, "sce_mbr"); #endif memcpy(header->mbr.magic, apaMBRMagic, sizeof(header->mbr.magic)); header->mbr.version=APA_MBR_VERSION; header->mbr.nsector=0; apaGetTime(&header->created); apaGetTime(&header->mbr.created); header->checksum=apaCheckSum(header); clink->flags|=APA_CACHE_FLAG_DIRTY; apaCacheFlushDirty(clink); ata_device_flush_cache(f->unit); apaCacheFree(clink); hddDevices[f->unit].status=0; hddDevices[f->unit].format=APA_MBR_VERSION; } #ifdef APA_FORMAT_MAKE_PARTITIONS memset(&emptyBlocks, 0, sizeof(emptyBlocks)); memset(¶ms, 0, sizeof(apa_params_t)); params.size=(1024*256); params.type=APA_TYPE_PFS; // add __net, __system.... for(i=0;formatPartList[i];i++) { memset(params.id, 0, APA_IDMAX); strcpy(params.id, formatPartList[i]); if(!(clink=hddAddPartitionHere(f->unit, ¶ms, emptyBlocks, i ? clink->sector : 0, &rv))) return rv; apaCacheFree(clink); params.size<<=1; if(hddDevices[f->unit].partitionMaxSize < params.size) params.size=hddDevices[f->unit].partitionMaxSize; } #endif return rv; }
int apaWriteHeader(s32 device, apa_header_t *header, u32 lba) { if (ata_device_sector_io(device, header, lba, 2, ATA_DIR_WRITE)) return -EIO; return 0; }