예제 #1
0
파일: hdd_fio.c 프로젝트: ps2dev/ps2sdk
static int ioctl2AddSub(hdd_file_slot_t *fileSlot, char *argp)
{
	int			rv;
	u32 		device=fileSlot->f->unit;
	apa_params_t	params;
	u32			emptyBlocks[32];
	apa_cache_t	*clink;
	u32			sector=0;
	u32			length;

	if(!(fileSlot->f->mode & O_WRONLY))
		return -EACCES;

	if(!(fileSlot->nsub < APA_MAXSUB))
		return -EFBIG;

	memset(&params, 0, sizeof(apa_params_t));

	if((rv=fioPartitionSizeLookUp(argp)) < 0)
		return rv;

	params.size=rv;
	params.flags=APA_FLAG_SUB;
	params.type=fileSlot->type;
	params.main=fileSlot->parts[0].start;
	params.number=fileSlot->nsub+1;
	if((rv=hddCheckPartitionMax(device, params.size)) < 0)
		return rv;

	// walk all looking for any empty blocks
	memset(&emptyBlocks, 0, sizeof(emptyBlocks));
	clink=apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &rv);
	while(clink){
		sector=clink->sector;
		apaAddEmptyBlock(clink->header, emptyBlocks);
		clink=apaGetNextHeader(clink, &rv);
	}
	if(rv!=0)
		return rv;

	if(!(clink=hddAddPartitionHere(device, &params, emptyBlocks, sector, &rv)))
		return rv;

	sector=clink->header->start;
	length=clink->header->length;
	apaCacheFree(clink);
	if(!(clink=apaCacheGetHeader(device, fileSlot->parts[0].start, APA_IO_MODE_READ, &rv)))
		return rv;

	clink->header->subs[clink->header->nsub].start=sector;
	clink->header->subs[clink->header->nsub].length=length;
	clink->header->nsub++;
	fileSlot->nsub++;
	fileSlot->parts[fileSlot->nsub].start=sector;
	fileSlot->parts[fileSlot->nsub].length=length;
	clink->flags|=APA_CACHE_FLAG_DIRTY;
	apaCacheFlushAllDirty(device);
	apaCacheFree(clink);
	return rv;
}
예제 #2
0
파일: apa.c 프로젝트: uyjulian/pfsshell
apa_cache_t *apaInsertPartition(s32 device, const apa_params_t *params, u32 sector, int *err)
{ // Adds a new partition using an empty block.
    apa_cache_t *clink_empty;
    apa_cache_t *clink_this;
    apa_cache_t *clink_next;

    if ((clink_this = apaCacheGetHeader(device, sector, APA_IO_MODE_READ, err)) == 0)
        return 0;

    while (clink_this->header->length != params->size) {
        if ((clink_next = apaCacheGetHeader(device, clink_this->header->next, APA_IO_MODE_READ, err)) == NULL) { // Get next partition
            apaCacheFree(clink_this);
            return 0;
        }
        clink_this->header->length >>= 1;
        clink_empty = apaRemovePartition(device, (clink_this->header->start + clink_this->header->length),
                                         clink_this->header->next, clink_this->header->start, clink_this->header->length);
        clink_this->header->next = clink_empty->header->start;
        clink_this->flags |= APA_CACHE_FLAG_DIRTY;
        clink_next->header->prev = clink_empty->header->start;
        clink_next->flags |= APA_CACHE_FLAG_DIRTY;

        apaCacheFlushAllDirty(device);
        apaCacheFree(clink_empty);
        apaCacheFree(clink_next);
    }
    apaCacheFree(clink_this);
    clink_this = apaFillHeader(device, params, clink_this->header->start, clink_this->header->next,
                               clink_this->header->prev, params->size, err);
    apaCacheFlushAllDirty(device);
    return clink_this;
}
예제 #3
0
파일: hdd_fio.c 프로젝트: ps2dev/ps2sdk
static int ioctl2DeleteLastSub(hdd_file_slot_t *fileSlot)
{
	int			rv;
	u32 		device=fileSlot->f->unit;
	apa_cache_t	*mainPart;
	apa_cache_t	*subPart;

	if(!(fileSlot->f->mode & O_WRONLY))
		return -EACCES;

	if(fileSlot->nsub==0)
		return -ENOENT;

	if(!(mainPart=apaCacheGetHeader(device, fileSlot->parts[0].start, APA_IO_MODE_READ, &rv)))
		return rv;

	if((subPart=apaCacheGetHeader(device,
		mainPart->header->subs[mainPart->header->nsub-1].start, APA_IO_MODE_READ, &rv))) {
		fileSlot->nsub--;
		mainPart->header->nsub--;
		mainPart->flags|=APA_CACHE_FLAG_DIRTY;
		apaCacheFlushAllDirty(device);
		rv=apaDelete(subPart);
	}
	apaCacheFree(mainPart);
	return rv;
}
예제 #4
0
파일: hdd_fio.c 프로젝트: ps2dev/ps2sdk
int hddDread(iop_file_t *f, iox_dirent_t *dirent)
{
	int				rv;
	hdd_file_slot_t *fileSlot=f->privdata;
	apa_cache_t 		*clink;

	if(!(f->mode & O_DIROPEN))
		return -ENOTDIR;

	if(fileSlot->parts[0].start==-1)
		return 0;// end :)

	WaitSema(fioSema);
	if((clink=apaCacheGetHeader(f->unit, fileSlot->parts[0].start, APA_IO_MODE_READ, &rv)) &&
		clink->header->length)
	{
		if(clink->header->flags & APA_FLAG_SUB) {
			// if sub get id from main header...
			apa_cache_t *cmain=apaCacheGetHeader(f->unit, clink->header->main, APA_IO_MODE_READ, &rv);
			if(cmain!=NULL){
			/*	This was the SONY original, which didn't do bounds-checking:
				rv=strlen(cmain->header->id);
				strcpy(dirent->name, cmain->header->id); */
				strncpy(dirent->name, cmain->header->id, APA_IDMAX);
				dirent->name[APA_IDMAX] = '\0';
				rv=strlen(dirent->name);

				apaCacheFree(cmain);
			}
		}
		else {
		/*	This was the SONY original, which didn't do bounds-checking:
			rv=strlen(clink->header->id);
			strcpy(dirent->name, clink->header->id); */
			strncpy(dirent->name, clink->header->id, APA_IDMAX);
			dirent->name[APA_IDMAX] = '\0';
			rv=strlen(dirent->name);
		}
		fioGetStatFiller(clink, &dirent->stat);
		if(clink->header->next==0)
			fileSlot->parts[0].start=-1;		// mark end
		else
			fileSlot->parts[0].start=clink->header->next;// set next
		apaCacheFree(clink);
	}
	SignalSema(fioSema);
	return rv;
}
예제 #5
0
파일: apa.c 프로젝트: uyjulian/pfsshell
apa_cache_t *apaFillHeader(s32 device, const apa_params_t *params, u32 start, u32 next,
                           u32 prev, u32 length, int *err)
{ // used for making a new partition
    apa_cache_t *clink;

    if (!(clink = apaCacheGetHeader(device, start, APA_IO_MODE_WRITE, err)))
        return NULL;
    memset(clink->header, 0, sizeof(apa_header_t));
    clink->header->magic = APA_MAGIC;
    clink->header->start = start;
    clink->header->next = next;
    clink->header->prev = prev;
    clink->header->length = length;
    clink->header->type = params->type;
    clink->header->flags = params->flags;
    clink->header->modver = APA_MODVER;
    memcpy(clink->header->id, params->id, APA_IDMAX);
    if (params->flags & APA_FLAG_SUB) {
        clink->header->main = params->main;
        clink->header->number = params->number;
    } else {
        if (strncmp(clink->header->id, "_tmp", APA_IDMAX) != 0) {
            memcpy(clink->header->rpwd, params->rpwd, APA_PASSMAX);
            memcpy(clink->header->fpwd, params->fpwd, APA_PASSMAX);
        }
    }
    apaGetTime(&clink->header->created);
    clink->flags |= APA_CACHE_FLAG_DIRTY;
    return clink;
}
예제 #6
0
파일: apa.c 프로젝트: uyjulian/pfsshell
int apaGetPartErrorName(s32 device, char *name)
{
    u32 lba;
    int rv = 0;
    apa_cache_t *clink;

    if ((rv = apaGetPartErrorSector(device, APA_SECTOR_PART_ERROR, &lba)) <= 0)
        return rv;
    if (!(clink = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &rv)))
        return rv;

    while (clink) {
        if (clink->header->type != APA_TYPE_FREE &&
            !(clink->header->flags & APA_CACHE_FLAG_DIRTY) &&
            clink->header->start == lba) {
            if (name) {
                strncpy(name, clink->header->id, APA_IDMAX - 1);
                name[APA_IDMAX - 1] = '\0';
            }
            apaCacheFree(clink);
            return 1;
        }
        clink = apaGetNextHeader(clink, &rv);
    }

    // clear error if no errors and partitions was not found...
    if (rv == 0)
        apaSetPartErrorSector(device, 0);
    return rv;
}
예제 #7
0
파일: apa.c 프로젝트: uyjulian/pfsshell
int apaDelete(apa_cache_t *clink)
{
    int rv = 0;
    apa_cache_t *clink_mbr;
    u32 device = clink->device;
    u32 start = clink->header->start;
    int i;

    if (!start) {
        apaCacheFree(clink);
        return -EACCES;
    }

    if (clink->header->next == 0) {
        if ((clink_mbr = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &rv)) == NULL) {
            apaCacheFree(clink);
            return rv;
        }
        do {
            apaCacheFree(clink);
            if ((clink = apaCacheGetHeader(clink->device, clink->header->prev, APA_IO_MODE_READ, &rv)) == NULL)
                return 0;
            clink->header->next = 0;
            clink->flags |= APA_CACHE_FLAG_DIRTY;
            clink_mbr->header->prev = clink->header->start;
            clink_mbr->flags |= APA_CACHE_FLAG_DIRTY;
            apaCacheFlushAllDirty(device);
        } while (clink->header->type == 0);
        apaCacheFree(clink_mbr);
    } else {
        u32 length = clink->header->length;

        for (i = 0; i < 2; i++) {
            if ((clink = apaDeleteFixPrev(clink, &rv)) == NULL)
                return 0;
            if ((clink = apaDeleteFixNext(clink, &rv)) == NULL)
                return 0;
        }
        if (clink->header->start == start && clink->header->length == length) {
            apaMakeEmpty(clink);
            apaCacheFlushAllDirty(clink->device);
        }
    }
    apaCacheFree(clink);
    return rv;
}
예제 #8
0
파일: apa.c 프로젝트: uyjulian/pfsshell
apa_cache_t *apaDeleteFixNext(apa_cache_t *clink, int *err)
{
    apa_header_t *header = clink->header;
    u32 length = header->length;
    u32 saved_length = header->length;
    u32 lnext = header->next;
    apa_cache_t *clink1;
    apa_cache_t *clink2;
    u32 device = clink->device;
    u32 tmp;

    while (lnext != 0) {
        if (!(clink1 = apaCacheGetHeader(device, lnext, APA_IO_MODE_READ, err))) {
            apaCacheFree(clink);
            return 0;
        }
        header = clink1->header;
        tmp = header->length + length;
        if (header->type != 0) {
            apaCacheFree(clink1);
            break;
        }
        if ((clink->header->start % tmp) != 0 || ((tmp - 1) & tmp)) {
            apaCacheFree(clink1);
            break;
        }
        length = tmp;
        apaCacheFree(clink1);
        lnext = header->next;
    }
    if (length != saved_length) {
        if (!(clink2 = apaCacheGetHeader(device, lnext, APA_IO_MODE_READ, err))) {
            apaCacheFree(clink);
            return NULL;
        }
        clink->header->length = length;
        clink->header->next = lnext;
        apaMakeEmpty(clink);
        clink2->header->prev = clink->header->start;
        clink2->flags |= APA_CACHE_FLAG_DIRTY;
        apaCacheFlushAllDirty(device);
        apaCacheFree(clink2);
    }
    return clink;
}
예제 #9
0
파일: hdd_fio.c 프로젝트: ps2dev/ps2sdk
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;
}
예제 #10
0
파일: apa.c 프로젝트: uyjulian/pfsshell
apa_cache_t *apaDeleteFixPrev(apa_cache_t *clink, int *err)
{
    apa_cache_t *clink2 = clink;
    apa_header_t *header = clink2->header;
    u32 device = clink->device;
    u32 length = clink->header->length;
    u32 saved_next = clink->header->next;
    u32 saved_length = clink->header->length;
    u32 tmp;

    while (header->start) {
        if (!(clink2 = apaCacheGetHeader(device, header->prev, APA_IO_MODE_READ, err))) {
            apaCacheFree(clink);
            return NULL;
        }
        header = clink2->header;
        tmp = header->length + length;
        if (header->type != 0) {
            apaCacheFree(clink2);
            break;
        }
        if ((header->start % tmp) || (tmp & (tmp - 1))) {
            apaCacheFree(clink2);
            break;
        }
        length = tmp;
        apaCacheFree(clink);
        clink = clink2;
    }
    if (length != saved_length) {
        if (!(clink2 = apaCacheGetHeader(device, saved_next, APA_IO_MODE_READ, err))) {
            apaCacheFree(clink);
            return NULL;
        }
        clink->header->length = length;
        clink->header->next = clink->header->start + length;
        clink2->header->prev = clink->header->start;
        clink2->flags |= APA_CACHE_FLAG_DIRTY;
        clink->flags |= APA_CACHE_FLAG_DIRTY;
        apaCacheFlushAllDirty(device);
        apaCacheFree(clink2);
    }
    return clink;
}
예제 #11
0
파일: hdd_fio.c 프로젝트: ps2dev/ps2sdk
static int devctlSetOsdMBR(s32 device, hddSetOsdMBR_t *mbrInfo)
{
	int rv;
	apa_cache_t *clink;

	if(!(clink=apaCacheGetHeader(device, APA_SECTOR_MBR, APA_IO_MODE_READ, &rv)))
		return rv;

	APA_PRINTF(	APA_DRV_NAME": mbr start: %ld\n"
				APA_DRV_NAME": mbr size : %ld\n", mbrInfo->start, mbrInfo->size);
	clink->header->mbr.osdStart=mbrInfo->start;
	clink->header->mbr.osdSize=mbrInfo->size;
	clink->flags|=APA_CACHE_FLAG_DIRTY;
	apaCacheFlushAllDirty(device);
	apaCacheFree(clink);
	return rv;
}
예제 #12
0
파일: apa.c 프로젝트: uyjulian/pfsshell
apa_cache_t *apaRemovePartition(s32 device, u32 start, u32 next, u32 prev,
                                u32 length)
{
    apa_cache_t *clink;
    int err;

    if ((clink = apaCacheGetHeader(device, start, APA_IO_MODE_WRITE, &err)) == NULL)
        return NULL;
    memset(clink->header, 0, sizeof(apa_header_t));
    clink->header->magic = APA_MAGIC;
    clink->header->start = start;
    clink->header->next = next;
    clink->header->prev = prev;
    clink->header->length = length;
    strcpy(clink->header->id, "__empty");
    apaGetTime(&clink->header->created);
    clink->flags |= APA_CACHE_FLAG_DIRTY;
    return clink;
}
예제 #13
0
파일: apa.c 프로젝트: uyjulian/pfsshell
apa_cache_t *apaGetNextHeader(apa_cache_t *clink, int *err)
{
    u32 start = clink->header->start;

    apaCacheFree(clink);
    if (!clink->header->next)
        return NULL;

    if (!(clink = apaCacheGetHeader(clink->device, clink->header->next, APA_IO_MODE_READ, err)))
        return NULL;

    if (start != clink->header->prev) {
        APA_PRINTF(APA_DRV_NAME ": Warning: Invalid partition information. start != prev\n");
        clink->header->prev = start;
        clink->flags |= APA_CACHE_FLAG_DIRTY;
        apaCacheFlushAllDirty(clink->device);
    }
    return clink;
}
예제 #14
0
파일: hdd_fio.c 프로젝트: ps2dev/ps2sdk
static int apaRemove(s32 device, const char *id, const char *fpwd)
{
	u32			nsub;
	apa_cache_t	*clink;
	apa_cache_t	*clink2;
	int			rv, i;

	for(i=0;i<apaMaxOpen;i++)	// look to see if open
	{
		if(hddFileSlots[i].f!=0) {
			if(memcmp(hddFileSlots[i].id, id, APA_IDMAX)==0)
				return -EBUSY;
		}
	}
	if(id[0]=='_' && id[1]=='_')
		return -EACCES;
	if((clink=apaFindPartition(device, id, &rv))==NULL)
		return rv;
	if(apaPassCmp(clink->header->fpwd, fpwd))
	{
		apaCacheFree(clink);
		return -EACCES;
	}
	// remove all subs frist...
	nsub=clink->header->nsub;
	clink->header->nsub=0;
	clink->flags|=APA_CACHE_FLAG_DIRTY;
	apaCacheFlushAllDirty(device);
	for(i=nsub-1;i!=-1;i--)
	{
		if((clink2=apaCacheGetHeader(device, clink->header->subs[i].start, APA_IO_MODE_READ, &rv))){
			if((rv=apaDelete(clink2))){
				apaCacheFree(clink);
				return rv;
			}
		}
	}
	if(rv==0)
		return apaDelete(clink);

	apaCacheFree(clink);
	return rv;
}
예제 #15
0
파일: apa.c 프로젝트: uyjulian/pfsshell
apa_cache_t *apaFindPartition(s32 device, const char *id, int *err)
{
    apa_cache_t *clink;

    clink = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, err);
    while (clink) {
        if (!(clink->header->flags & APA_FLAG_SUB)) {
            if (memcmp(clink->header->id, id, APA_IDMAX) == 0)
                return clink; // found
        }
        clink = apaGetNextHeader(clink, (int *)err);
    }
    if (*err == 0) {
        *err = -ENOENT;
        return NULL;
        //return (apa_cache_t *)-ENOENT;		// <-- BUG code tests for NULL only
    }
    *err = 0;
    return NULL;
}
예제 #16
0
파일: hdd.c 프로젝트: uyjulian/pfsshell
apa_cache_t *hddAddPartitionHere(s32 device, const apa_params_t *params, u32 *emptyBlocks,
                                 u32 sector, int *err)
{
    apa_cache_t *clink_this;
    apa_cache_t *clink_next;
    apa_cache_t *clink_new;
    apa_header_t *header;
    u32 i;
    u32 tmp, some_size, part_end;
    u32 tempSize;

    // walk empty blocks in case can use one :)
    for (i = 0; i < 32; i++) {
        if ((u32)(1 << i) >= params->size && emptyBlocks[i] != 0)
            return apaInsertPartition(device, params, emptyBlocks[i], err);
    }
    clink_this = apaCacheGetHeader(device, sector, APA_IO_MODE_READ, err);
    header = clink_this->header;
    part_end = header->start + header->length;
    some_size = (part_end % params->size);
    tmp = some_size ? params->size - some_size : 0;

    if (hddDevices[device].totalLBA < (part_end + params->size + tmp)
        //Non-SONY: when dealing with large disks, this check may overflow (therefore, check for overflows!).
        || (part_end < sector)) {
        *err = -ENOSPC;
        apaCacheFree(clink_this);
        return NULL;
    }

    if ((clink_next = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, err)) == NULL) {
        apaCacheFree(clink_this);
        return NULL;
    }

    tempSize = params->size;
    while (part_end % params->size) {
        tempSize = params->size >> 1;
        while (0x3FFFF < tempSize) {
            if (!(part_end % tempSize)) {
                clink_new = apaRemovePartition(device, part_end, 0,
                                               clink_this->header->start, tempSize);
                clink_this->header->next = part_end;
                clink_this->flags |= APA_CACHE_FLAG_DIRTY;
                clink_next->header->prev = clink_new->header->start;
                part_end += tempSize;
                clink_next->flags |= APA_CACHE_FLAG_DIRTY;
                apaCacheFlushAllDirty(device);
                apaCacheFree(clink_this);
                clink_this = clink_new;
                break;
            }
            tempSize >>= 1;
        }
    }
    if ((clink_new = apaFillHeader(device, params, part_end, 0, clink_this->header->start,
                                   params->size, err)) != NULL) {
        clink_this->header->next = part_end;
        clink_this->flags |= APA_CACHE_FLAG_DIRTY;
        clink_next->header->prev = clink_new->header->start;
        clink_next->flags |= APA_CACHE_FLAG_DIRTY;
        apaCacheFlushAllDirty(device);
    }
    apaCacheFree(clink_this);
    apaCacheFree(clink_next);
    return clink_new;
}
예제 #17
0
파일: hdd_fio.c 프로젝트: ps2dev/ps2sdk
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(&params, 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, &params, 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;
}