예제 #1
0
void
LRWMode::EncryptBlock(ThreadContext& context, uint8 *data, size_t length,
	uint64 blockIndex)
{
	uint8 i[8];
	uint8 t[16];
	uint32 b;

	blockIndex = ((blockIndex - fOffset) << 5) + 1;
	*(uint64*)i = B_HOST_TO_BENDIAN_INT64(blockIndex);

	for (b = 0; b < length >> 4; b++) {
		gf128_mul_by_tab64(i, t,
			(galois_field_context*)context.BufferFor(fGaloisField));
		xor128((uint64*)data, (uint64*)t);

		fAlgorithm->Encrypt(context, data, 16);

		xor128((uint64*)data, (uint64*)t);

		data += 16;

		if (i[7] != 0xff)
			i[7]++;
		else {
			*(uint64*)i = B_HOST_TO_BENDIAN_INT64(
				B_BENDIAN_TO_HOST_INT64(*(uint64*)i) + 1);
		}
	}

	memset(t, 0, sizeof (t));
}
예제 #2
0
파일: ahci_port.cpp 프로젝트: DonCN/haiku
void
AHCIPort::ScsiUnmap(scsi_ccb* request, scsi_unmap_parameter_list* unmapBlocks)
{
	// Determine how many ranges we'll need
	// We assume that the SCSI unmap ranges cannot be merged together
	uint32 scsiRangeCount = B_BENDIAN_TO_HOST_INT16(
		unmapBlocks->block_data_length) / sizeof(scsi_unmap_block_descriptor);
	uint32 lbaRangeCount = 0;
	for (uint32 i = 0; i < scsiRangeCount; i++) {
		lbaRangeCount += ((uint32)B_BENDIAN_TO_HOST_INT32(
			unmapBlocks->blocks[i].block_count) + 65534) / 65535;
	}

	uint32 lbaRangesSize = lbaRangeCount * sizeof(uint64);
	uint64* lbaRanges = (uint64*)malloc(lbaRangesSize);
	if (lbaRanges == NULL) {
		TRACE("out of memory when allocating %" B_PRIu32 " unmap ranges\n",
			lbaRangeCount);
		request->subsys_status = SCSI_REQ_ABORTED;
		gSCSI->finished(request, 1);
		return;
	}

	MemoryDeleter deleter(lbaRanges);

	for (uint32 i = 0, scsiIndex = 0; scsiIndex < scsiRangeCount; scsiIndex++) {
		uint64 lba = (uint64)B_BENDIAN_TO_HOST_INT64(
			unmapBlocks->blocks[scsiIndex].lba);
		uint64 blocksLeft = (uint32)B_BENDIAN_TO_HOST_INT32(
			unmapBlocks->blocks[scsiIndex].block_count);
		while (blocksLeft > 0) {
			uint16 blocks = blocksLeft > 65535 ? 65535 : (uint16)blocksLeft;
			lbaRanges[i++] = B_HOST_TO_LENDIAN_INT64(
				((uint64)blocks << 48) | lba);
			lba += blocks;
			blocksLeft -= blocks;
		}
	}

	sata_request sreq;
	sreq.SetATA48Command(ATA_COMMAND_DATA_SET_MANAGEMENT, 0,
		(lbaRangesSize + 511) / 512);
	sreq.SetFeature(1);
	sreq.SetData(lbaRanges, lbaRangesSize);

	ExecuteSataRequest(&sreq);
	sreq.WaitForCompletion();

	if ((sreq.CompletionStatus() & ATA_ERR) != 0) {
		TRACE("trim failed (%" B_PRIu32 " ranges)!\n", lbaRangeCount);
		request->subsys_status = SCSI_REQ_CMP_ERR;
	} else
		request->subsys_status = SCSI_REQ_CMP;

	request->data_resid = 0;
	request->device_status = SCSI_STATUS_GOOD;
	gSCSI->finished(request, 1);
}
예제 #3
0
status_t
BNetBuffer::RemoveUint64(uint64& data)
{
	uint64 be_data;
	status_t result = RemoveData((void*)&be_data, sizeof(uint64));
	if (result != B_OK)
		return result;

	data = B_BENDIAN_TO_HOST_INT64(be_data);

	return B_OK;
}
예제 #4
0
status_t
PackageReaderImpl::Init(int fd, bool keepFD, uint32 flags)
{
	hpkg_header header;
	status_t error = inherited::Init<hpkg_header, B_HPKG_MAGIC, B_HPKG_VERSION,
		B_HPKG_MINOR_VERSION>(fd, keepFD, header, flags);
	if (error != B_OK)
		return error;
	fHeapSize = UncompressedHeapSize();

	// init package attributes section
	error = InitSection(fPackageAttributesSection, fHeapSize,
		B_BENDIAN_TO_HOST_INT32(header.attributes_length),
		kMaxPackageAttributesSize,
		B_BENDIAN_TO_HOST_INT32(header.attributes_strings_length),
		B_BENDIAN_TO_HOST_INT32(header.attributes_strings_count));
	if (error != B_OK)
		return error;

	// init TOC section
	error = InitSection(fTOCSection, fPackageAttributesSection.offset,
		B_BENDIAN_TO_HOST_INT64(header.toc_length), kMaxTOCSize,
		B_BENDIAN_TO_HOST_INT64(header.toc_strings_length),
		B_BENDIAN_TO_HOST_INT64(header.toc_strings_count));
	if (error != B_OK)
		return error;

	// prepare the sections for use
	error = PrepareSection(fTOCSection);
	if (error != B_OK)
		return error;

	error = PrepareSection(fPackageAttributesSection);
	if (error != B_OK)
		return error;

	return B_OK;
}
예제 #5
0
void
AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
{
//	TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);

    if (fIsATAPI) {
        bool isWrite = false;
        switch (request->flags & SCSI_DIR_MASK) {
        case SCSI_DIR_NONE:
            ASSERT(request->data_length == 0);
            break;
        case SCSI_DIR_IN:
            ASSERT(request->data_length > 0);
            break;
        case SCSI_DIR_OUT:
            isWrite = true;
            ASSERT(request->data_length > 0);
            break;
        default:
            panic("CDB has invalid direction mask");
        }

//		TRACE("AHCIPort::ScsiExecuteRequest ATAPI: port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);

        sata_request *sreq = new(std::nothrow) sata_request(request);
        if (sreq == NULL) {
            TRACE("out of memory when allocating atapi request\n");
            request->subsys_status = SCSI_REQ_ABORTED;
            gSCSI->finished(request, 1);
            return;
        }

        sreq->set_atapi_cmd(request->data_length);
//		uint8 *data = (uint8*) sreq->ccb()->cdb;
//		for (int i = 0; i < 16; i += 8) {
//			TRACE("  %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1], data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]);
//		}
        ExecuteSataRequest(sreq, isWrite);
        return;
    }

    if (request->cdb[0] == SCSI_OP_REQUEST_SENSE) {
        panic("ahci: SCSI_OP_REQUEST_SENSE not yet supported\n");
        return;
    }

    if (!fDevicePresent) {
        TRACE("no device present on port %d\n", fIndex);
        request->subsys_status = SCSI_DEV_NOT_THERE;
        gSCSI->finished(request, 1);
        return;
    }

    request->subsys_status = SCSI_REQ_CMP;

    switch (request->cdb[0]) {
    case SCSI_OP_TEST_UNIT_READY:
        ScsiTestUnitReady(request);
        break;
    case SCSI_OP_INQUIRY:
        ScsiInquiry(request);
        break;
    case SCSI_OP_READ_CAPACITY:
        ScsiReadCapacity(request);
        break;
    case SCSI_OP_SERVICE_ACTION_IN:
        if ((request->cdb[1] & 0x1f) == SCSI_SAI_READ_CAPACITY_16)
            ScsiReadCapacity16(request);
        else {
            request->subsys_status = SCSI_REQ_INVALID;
            gSCSI->finished(request, 1);
        }
        break;
    case SCSI_OP_SYNCHRONIZE_CACHE:
        ScsiSynchronizeCache(request);
        break;
    case SCSI_OP_READ_6:
    case SCSI_OP_WRITE_6:
    {
        const scsi_cmd_rw_6 *cmd = (const scsi_cmd_rw_6 *)request->cdb;
        uint32 position = ((uint32)cmd->high_lba << 16)
                          | ((uint32)cmd->mid_lba << 8) | (uint32)cmd->low_lba;
        size_t length = cmd->length != 0 ? cmd->length : 256;
        bool isWrite = request->cdb[0] == SCSI_OP_WRITE_6;
        ScsiReadWrite(request, position, length, isWrite);
        break;
    }
    case SCSI_OP_READ_10:
    case SCSI_OP_WRITE_10:
    {
        const scsi_cmd_rw_10 *cmd = (const scsi_cmd_rw_10 *)request->cdb;
        uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba);
        size_t length = B_BENDIAN_TO_HOST_INT16(cmd->length);
        bool isWrite = request->cdb[0] == SCSI_OP_WRITE_10;
        if (length) {
            ScsiReadWrite(request, position, length, isWrite);
        } else {
            TRACE("AHCIPort::ScsiExecuteRequest error: transfer without "
                  "data!\n");
            request->subsys_status = SCSI_REQ_INVALID;
            gSCSI->finished(request, 1);
        }
        break;
    }
    case SCSI_OP_READ_12:
    case SCSI_OP_WRITE_12:
    {
        const scsi_cmd_rw_12 *cmd = (const scsi_cmd_rw_12 *)request->cdb;
        uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba);
        size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length);
        bool isWrite = request->cdb[0] == SCSI_OP_WRITE_12;
        if (length) {
            ScsiReadWrite(request, position, length, isWrite);
        } else {
            TRACE("AHCIPort::ScsiExecuteRequest error: transfer without "
                  "data!\n");
            request->subsys_status = SCSI_REQ_INVALID;
            gSCSI->finished(request, 1);
        }
        break;
    }
    case SCSI_OP_READ_16:
    case SCSI_OP_WRITE_16:
    {
        const scsi_cmd_rw_16 *cmd = (const scsi_cmd_rw_16 *)request->cdb;
        uint64 position = B_BENDIAN_TO_HOST_INT64(cmd->lba);
        size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length);
        bool isWrite = request->cdb[0] == SCSI_OP_WRITE_16;
        if (length) {
            ScsiReadWrite(request, position, length, isWrite);
        } else {
            TRACE("AHCIPort::ScsiExecuteRequest error: transfer without "
                  "data!\n");
            request->subsys_status = SCSI_REQ_INVALID;
            gSCSI->finished(request, 1);
        }
        break;
    }
    case SCSI_OP_WRITE_SAME_16:
    {
        const scsi_cmd_wsame_16 *cmd = (const scsi_cmd_wsame_16 *)request->cdb;

        // SCSI unmap is used for trim, otherwise we don't support it
        if (!cmd->unmap) {
            TRACE("%s port %d: unsupported request opcode 0x%02x\n",
                  __func__, fIndex, request->cdb[0]);
            request->subsys_status = SCSI_REQ_ABORTED;
            gSCSI->finished(request, 1);
            break;
        }

        if (!fTrim) {
            // Drive doesn't support trim (or atapi)
            // Just say it was successful and quit
            request->subsys_status = SCSI_REQ_CMP;
        } else {
            TRACE("%s unimplemented: TRIM call\n", __func__);
            // TODO: Make Serial ATA (sata_request?) trim call here.
            request->subsys_status = SCSI_REQ_ABORTED;
        }
        gSCSI->finished(request, 1);
        break;
    }
    default:
        TRACE("AHCIPort::ScsiExecuteRequest port %d unsupported request "
              "opcode 0x%02x\n", fIndex, request->cdb[0]);
        request->subsys_status = SCSI_REQ_ABORTED;
        gSCSI->finished(request, 1);
    }
}
예제 #6
0
AtomBase *
GetAtom(BPositionIO *pStream)
{
	uint32 aAtomType;
	uint32 aAtomSize;
	uint64 aRealAtomSize;
	off_t aStreamOffset;
	
	aStreamOffset = pStream->Position();
	
	// Get Size uint32
	pStream->Read(&aAtomSize,4);
	aAtomSize = B_BENDIAN_TO_HOST_INT32(aAtomSize);
	// Get Type uint32
	pStream->Read(&aAtomType,4);
	aAtomType = B_BENDIAN_TO_HOST_INT32(aAtomType);
	// Check for extended size
	if (aAtomSize == 1) {
		// Handle extended size
		pStream->Read(&aRealAtomSize,4);
		aRealAtomSize = B_BENDIAN_TO_HOST_INT64(aRealAtomSize);
	} else if (aAtomSize == 0) {
		// aAtomSize extends to end of file.
		// TODO this is broken
		aRealAtomSize = 0;
	} else {
		aRealAtomSize = aAtomSize;
	}

	if (aAtomType == uint32('moov'))
		return new MOOVAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
	
	if (aAtomType == uint32('mvhd'))
		return new MVHDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('trak'))
		return new TRAKAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('tkhd'))
		return new TKHDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('free'))
		return new FREEAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('skip'))
		return new SKIPAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('wide'))
		return new WIDEAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('mdat'))
		return new MDATAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('mdia'))
		return new MDIAAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('mdhd'))
		return new MDHDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('hdlr'))
		return new HDLRAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('minf'))
		return new MINFAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('vmhd'))
		return new VMHDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('smhd'))
		return new SMHDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('dinf'))
		return new DINFAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('stbl'))
		return new STBLAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('stsd'))
		return new STSDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('tmcd'))
		return new TMCDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('stts'))
		return new STTSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('pnot'))
		return new PNOTAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('stsc'))
		return new STSCAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('stco'))
		return new STCOAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('stss'))
		return new STSSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('ctts'))
		return new CTTSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('stsz'))
		return new STSZAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('stz2'))
		return new STZ2Atom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('ftyp'))
		return new FTYPAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('cmov'))
		return new CMOVAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('dcom'))
		return new DCOMAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('cmvd'))
		return new CMVDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('esds'))
		return new ESDSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('alac'))
		return new ALACAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
	
	if (aAtomType == uint32('wave'))
		return new WAVEAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('dac3'))
		return new DAC3Atom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('dec3'))
		return new DEC3Atom(pStream, aStreamOffset, aAtomType, aRealAtomSize);

	if (aAtomType == uint32('avcC'))
		return new DecoderConfigAtom(pStream, aStreamOffset, aAtomType,
			aRealAtomSize);

	return new AtomBase(pStream, aStreamOffset, aAtomType, aRealAtomSize);
}
예제 #7
0
	uint64 EncryptedSize() const
		{ return B_BENDIAN_TO_HOST_INT64(encrypted_size); }
예제 #8
0
	uint64 EncryptedOffset() const
		{ return B_BENDIAN_TO_HOST_INT64(encrypted_offset); }
예제 #9
0
	uint64 VolumeSize() const
		{ return B_BENDIAN_TO_HOST_INT64(volume_size); }
예제 #10
0
	uint64 HiddenSize() const
		{ return B_BENDIAN_TO_HOST_INT64(hidden_size); }
예제 #11
0
status_t
VolumeCryptContext::_Detect(int fd, off_t offset, off_t size, const uint8* key,
	uint32 keyLength, uint8* buffer, true_crypt_header& header)
{
	ssize_t bytesRead = read_pos(fd, offset, buffer, BLOCK_SIZE);
	if (bytesRead != BLOCK_SIZE)
		return bytesRead < 0 ? errno : B_IO_ERROR;

	// decrypt header first

	uint8* encryptedHeader = buffer + PKCS5_SALT_SIZE;
	uint8* salt = buffer;
	uint8 diskKey[DISK_KEY_SIZE];

	derive_key(key, keyLength, salt, PKCS5_SALT_SIZE, diskKey, DISK_KEY_SIZE);
//dprintf("salt %x, key %x\n", *(int*)salt, *(int*)diskKey);

	status_t status = Init(ALGORITHM_AES, MODE_XTS, diskKey, DISK_KEY_SIZE);
	if (status != B_OK)
		return status;

	memcpy(&header, encryptedHeader, sizeof(true_crypt_header));

	Decrypt((uint8*)&header, sizeof(true_crypt_header));

	if (!valid_true_crypt_header(header)) {
		dump_true_crypt_header(header);

		// Try with legacy encryption mode LRW instead
		status = Init(ALGORITHM_AES, MODE_LRW, diskKey, DISK_KEY_SIZE);
		if (status != B_OK)
			return status;

		memcpy(&header, encryptedHeader, sizeof(true_crypt_header));

		Decrypt((uint8*)&header, sizeof(true_crypt_header));

		if (!valid_true_crypt_header(header)) {
			dump_true_crypt_header(header);
			return B_PERMISSION_DENIED;
		}
	}

	if (header.RequiredProgramVersion() >= 0x700) {
		// TODO: test if the block size is really not 512 bytes
		dprintf("header version not yet supported!\n");
		return B_NOT_SUPPORTED;
	}

	// then init context with the keys from the unencrypted header

	SetKey(header.disk_key, sizeof(header.disk_key));

	if (offset != 0) {
		// this is a hidden drive, take over the size from the header
		fSize = B_BENDIAN_TO_HOST_INT64(header.hidden_size);
		fOffset = offset - fSize;
		fHidden = true;
	} else {
		fOffset = BLOCK_SIZE;
		fSize = size - BLOCK_SIZE;
		fHidden = false;
	}
	if (header.Version() >= 4) {
		fOffset = header.EncryptedOffset();
		fSize = header.EncryptedSize();
	}

	fMode->SetBlockOffset(fOffset / BLOCK_SIZE);
	return B_OK;
}
예제 #12
0
status_t
PackageReader::Init(int fd, bool keepFD)
{
    fFD = fd;
    fOwnsFD = keepFD;

    // stat it
    struct stat st;
    if (fstat(fFD, &st) < 0) {
        fErrorOutput->PrintError("Error: Failed to access package file: %s\n",
                                 strerror(errno));
        return errno;
    }

    // read the header
    hpkg_header header;
    status_t error = _ReadBuffer(0, &header, sizeof(header));
    if (error != B_OK)
        return error;

    // check the header

    // magic
    if (B_BENDIAN_TO_HOST_INT32(header.magic) != B_HPKG_MAGIC) {
        fErrorOutput->PrintError("Error: Invalid package file: Invalid "
                                 "magic\n");
        return B_BAD_DATA;
    }

    // header size
    fHeapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size);
    if ((size_t)fHeapOffset < sizeof(hpkg_header)) {
        fErrorOutput->PrintError("Error: Invalid package file: Invalid header "
                                 "size (%llu)\n", fHeapOffset);
        return B_BAD_DATA;
    }

    // version
    if (B_BENDIAN_TO_HOST_INT16(header.version) != B_HPKG_VERSION) {
        fErrorOutput->PrintError("Error: Invalid/unsupported package file "
                                 "version (%d)\n", B_BENDIAN_TO_HOST_INT16(header.version));
        return B_BAD_DATA;
    }

    // total size
    fTotalSize = B_BENDIAN_TO_HOST_INT64(header.total_size);
    if (fTotalSize != (uint64)st.st_size) {
        fErrorOutput->PrintError("Error: Invalid package file: Total size in "
                                 "header (%llu) doesn't agree with total file size (%lld)\n",
                                 fTotalSize, st.st_size);
        return B_BAD_DATA;
    }

    // package attributes length and compression
    fPackageAttributesCompression
        = B_BENDIAN_TO_HOST_INT32(header.attributes_compression);
    fPackageAttributesCompressedLength
        = B_BENDIAN_TO_HOST_INT32(header.attributes_length_compressed);
    fPackageAttributesUncompressedLength
        = B_BENDIAN_TO_HOST_INT32(header.attributes_length_uncompressed);

    if (const char* errorString = _CheckCompression(
                                      fPackageAttributesCompression, fPackageAttributesCompressedLength,
                                      fPackageAttributesUncompressedLength)) {
        fErrorOutput->PrintError("Error: Invalid package file: package "
                                 "attributes section: %s\n", errorString);
        return B_BAD_DATA;
    }

    // TOC length and compression
    fTOCCompression = B_BENDIAN_TO_HOST_INT32(header.toc_compression);
    fTOCCompressedLength
        = B_BENDIAN_TO_HOST_INT64(header.toc_length_compressed);
    fTOCUncompressedLength
        = B_BENDIAN_TO_HOST_INT64(header.toc_length_uncompressed);

    if (const char* errorString = _CheckCompression(fTOCCompression,
                                  fTOCCompressedLength, fTOCUncompressedLength)) {
        fErrorOutput->PrintError("Error: Invalid package file: TOC section: "
                                 "%s\n", errorString);
        return B_BAD_DATA;
    }

    // TOC subsections
    fTOCAttributeTypesLength
        = B_BENDIAN_TO_HOST_INT64(header.toc_attribute_types_length);
    fTOCAttributeTypesCount
        = B_BENDIAN_TO_HOST_INT64(header.toc_attribute_types_count);
    fTOCStringsLength = B_BENDIAN_TO_HOST_INT64(header.toc_strings_length);
    fTOCStringsCount = B_BENDIAN_TO_HOST_INT64(header.toc_strings_count);

    if (fTOCAttributeTypesLength > fTOCUncompressedLength
            || fTOCStringsLength > fTOCUncompressedLength - fTOCAttributeTypesLength
            || fTOCAttributeTypesCount > fTOCAttributeTypesLength
            || fTOCStringsCount > fTOCStringsLength) {
        fErrorOutput->PrintError("Error: Invalid package file: Invalid TOC "
                                 "subsections description\n");
        return B_BAD_DATA;
    }

    // check whether the sections fit together
    if (fPackageAttributesCompressedLength > fTotalSize
            || fTOCCompressedLength
            > fTotalSize - fPackageAttributesCompressedLength
            || fHeapOffset
            > fTotalSize - fPackageAttributesCompressedLength
            - fTOCCompressedLength) {
        fErrorOutput->PrintError("Error: Invalid package file: The sum of the "
                                 "sections sizes is greater than the package size\n");
        return B_BAD_DATA;
    }

    fPackageAttributesOffset = fTotalSize - fPackageAttributesCompressedLength;
    fTOCSectionOffset = fPackageAttributesOffset - fTOCCompressedLength;
    fHeapSize = fTOCSectionOffset - fHeapOffset;

    // TOC size sanity check
    if (fTOCUncompressedLength > kMaxTOCSize) {
        fErrorOutput->PrintError("Error: Package file TOC section size "
                                 "is %llu bytes. This is beyond the reader's sanity limit\n",
                                 fTOCUncompressedLength);
        return B_UNSUPPORTED;
    }

    // allocate a scratch buffer
    fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize];
    if (fScratchBuffer == NULL) {
        fErrorOutput->PrintError("Error: Out of memory!\n");
        return B_NO_MEMORY;
    }
    fScratchBufferSize = kScratchBufferSize;

    // read in the complete TOC
    fTOCSection = new(std::nothrow) uint8[fTOCUncompressedLength];
    if (fTOCSection == NULL) {
        fErrorOutput->PrintError("Error: Out of memory!\n");
        return B_NO_MEMORY;
    }

    error = _ReadCompressedBuffer(fTOCSectionOffset, fTOCSection,
                                  fTOCCompressedLength, fTOCUncompressedLength, fTOCCompression);
    if (error != B_OK)
        return error;

    // start parsing the TOC
    fCurrentTOCOffset = 0;

    // attribute types
    error = _ParseTOCAttributeTypes();
    if (error != B_OK)
        return error;
    fCurrentTOCOffset += fTOCAttributeTypesLength;

    // strings
    error = _ParseTOCStrings();
    if (error != B_OK)
        return error;
    fCurrentTOCOffset += fTOCStringsLength;

    return B_OK;
}
예제 #13
0
status_t
PackageReader::_ReadAttributeValue(uint8 type, uint8 encoding,
                                   AttributeValue& _value)
{
    switch (type) {
    case B_HPKG_ATTRIBUTE_TYPE_INT:
    case B_HPKG_ATTRIBUTE_TYPE_UINT:
    {
        uint64 intValue;
        status_t error;

        switch (encoding) {
        case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT:
        {
            uint8 value;
            error = _Read(value);
            intValue = value;
            break;
        }
        case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT:
        {
            uint16 value;
            error = _Read(value);
            intValue = B_BENDIAN_TO_HOST_INT16(value);
            break;
        }
        case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT:
        {
            uint32 value;
            error = _Read(value);
            intValue = B_BENDIAN_TO_HOST_INT32(value);
            break;
        }
        case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT:
        {
            uint64 value;
            error = _Read(value);
            intValue = B_BENDIAN_TO_HOST_INT64(value);
            break;
        }
        default:
        {
            fErrorOutput->PrintError("Error: Invalid TOC section: "
                                     "invalid encoding %d for int value type %d\n", encoding,
                                     type);
            return B_BAD_VALUE;
        }
        }

        if (error != B_OK)
            return error;

        if (type == B_HPKG_ATTRIBUTE_TYPE_INT)
            _value.SetTo((int64)intValue);
        else
            _value.SetTo(intValue);

        return B_OK;
    }

    case B_HPKG_ATTRIBUTE_TYPE_STRING:
    {
        if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) {
            uint64 index;
            status_t error = _ReadUnsignedLEB128(index);
            if (error != B_OK)
                return error;

            if (index > fTOCStringsCount) {
                fErrorOutput->PrintError("Error: Invalid TOC section: "
                                         "string reference out of bounds\n");
                return B_BAD_DATA;
            }

            _value.SetTo(fStrings[index]);
        } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) {
            const char* string;
            status_t error = _ReadString(string);
            if (error != B_OK)
                return error;

            _value.SetTo(string);
        } else {
            fErrorOutput->PrintError("Error: Invalid TOC section: invalid "
                                     "string encoding (%u)\n", encoding);
            return B_BAD_DATA;
        }

        return B_OK;
    }

    case B_HPKG_ATTRIBUTE_TYPE_RAW:
    {
        uint64 size;
        status_t error = _ReadUnsignedLEB128(size);
        if (error != B_OK)
            return error;

        if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP) {
            uint64 offset;
            error = _ReadUnsignedLEB128(offset);
            if (error != B_OK)
                return error;

            if (offset > fHeapSize || size > fHeapSize - offset) {
                fErrorOutput->PrintError("Error: Invalid TOC section: "
                                         "invalid data reference\n");
                return B_BAD_DATA;
            }

            _value.SetToData(size, fHeapOffset + offset);
        } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE) {
            if (size > B_HPKG_MAX_INLINE_DATA_SIZE) {
                fErrorOutput->PrintError("Error: Invalid TOC section: "
                                         "inline data too long\n");
                return B_BAD_DATA;
            }

            const void* buffer;
            error = _GetTOCBuffer(size, buffer);
            if (error != B_OK)
                return error;
            _value.SetToData(size, buffer);
        } else {
            fErrorOutput->PrintError("Error: Invalid TOC section: invalid "
                                     "raw encoding (%u)\n", encoding);
            return B_BAD_DATA;
        }

        return B_OK;
    }

    default:
        fErrorOutput->PrintError("Error: Invalid TOC section: invalid "
                                 "value type: %d\n", type);
        return B_BAD_DATA;
    }
}
예제 #14
0
파일: ahci_port.cpp 프로젝트: DonCN/haiku
void
AHCIPort::ScsiExecuteRequest(scsi_ccb* request)
{
//	TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);

	if (fIsATAPI) {
		bool isWrite = false;
		switch (request->flags & SCSI_DIR_MASK) {
			case SCSI_DIR_NONE:
				ASSERT(request->data_length == 0);
				break;
			case SCSI_DIR_IN:
				ASSERT(request->data_length > 0);
				break;
			case SCSI_DIR_OUT:
				isWrite = true;
				ASSERT(request->data_length > 0);
				break;
			default:
				panic("CDB has invalid direction mask");
		}

//		TRACE("AHCIPort::ScsiExecuteRequest ATAPI: port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);

		sata_request* sreq = new(std::nothrow) sata_request(request);
		if (sreq == NULL) {
			TRACE("out of memory when allocating atapi request\n");
			request->subsys_status = SCSI_REQ_ABORTED;
			gSCSI->finished(request, 1);
			return;
		}

		sreq->SetATAPICommand(request->data_length);
//		uint8* data = (uint8*) sreq->ccb()->cdb;
//		for (int i = 0; i < 16; i += 8) {
//			TRACE("  %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1], data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]);
//		}
		ExecuteSataRequest(sreq, isWrite);
		return;
	}

	if (request->cdb[0] == SCSI_OP_REQUEST_SENSE) {
		panic("ahci: SCSI_OP_REQUEST_SENSE not yet supported\n");
		return;
	}

	if (!fDevicePresent) {
		TRACE("no device present on port %d\n", fIndex);
		request->subsys_status = SCSI_DEV_NOT_THERE;
		gSCSI->finished(request, 1);
		return;
	}

	request->subsys_status = SCSI_REQ_CMP;

	switch (request->cdb[0]) {
		case SCSI_OP_TEST_UNIT_READY:
			ScsiTestUnitReady(request);
			break;
		case SCSI_OP_INQUIRY:
			ScsiInquiry(request);
			break;
		case SCSI_OP_READ_CAPACITY:
			ScsiReadCapacity(request);
			break;
		case SCSI_OP_SERVICE_ACTION_IN:
			if ((request->cdb[1] & 0x1f) == SCSI_SAI_READ_CAPACITY_16)
				ScsiReadCapacity16(request);
			else {
				request->subsys_status = SCSI_REQ_INVALID;
				gSCSI->finished(request, 1);
			}
			break;
		case SCSI_OP_SYNCHRONIZE_CACHE:
			ScsiSynchronizeCache(request);
			break;
		case SCSI_OP_READ_6:
		case SCSI_OP_WRITE_6:
		{
			const scsi_cmd_rw_6* cmd = (const scsi_cmd_rw_6*)request->cdb;
			uint32 position = ((uint32)cmd->high_lba << 16)
				| ((uint32)cmd->mid_lba << 8) | (uint32)cmd->low_lba;
			size_t length = cmd->length != 0 ? cmd->length : 256;
			bool isWrite = request->cdb[0] == SCSI_OP_WRITE_6;
			ScsiReadWrite(request, position, length, isWrite);
			break;
		}
		case SCSI_OP_READ_10:
		case SCSI_OP_WRITE_10:
		{
			const scsi_cmd_rw_10* cmd = (const scsi_cmd_rw_10*)request->cdb;
			uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba);
			size_t length = B_BENDIAN_TO_HOST_INT16(cmd->length);
			bool isWrite = request->cdb[0] == SCSI_OP_WRITE_10;
			if (length) {
				ScsiReadWrite(request, position, length, isWrite);
			} else {
				TRACE("AHCIPort::ScsiExecuteRequest error: transfer without "
					"data!\n");
				request->subsys_status = SCSI_REQ_INVALID;
				gSCSI->finished(request, 1);
			}
			break;
		}
		case SCSI_OP_READ_12:
		case SCSI_OP_WRITE_12:
		{
			const scsi_cmd_rw_12* cmd = (const scsi_cmd_rw_12*)request->cdb;
			uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba);
			size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length);
			bool isWrite = request->cdb[0] == SCSI_OP_WRITE_12;
			if (length) {
				ScsiReadWrite(request, position, length, isWrite);
			} else {
				TRACE("AHCIPort::ScsiExecuteRequest error: transfer without "
					"data!\n");
				request->subsys_status = SCSI_REQ_INVALID;
				gSCSI->finished(request, 1);
			}
			break;
		}
		case SCSI_OP_READ_16:
		case SCSI_OP_WRITE_16:
		{
			const scsi_cmd_rw_16* cmd = (const scsi_cmd_rw_16*)request->cdb;
			uint64 position = B_BENDIAN_TO_HOST_INT64(cmd->lba);
			size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length);
			bool isWrite = request->cdb[0] == SCSI_OP_WRITE_16;
			if (length) {
				ScsiReadWrite(request, position, length, isWrite);
			} else {
				TRACE("AHCIPort::ScsiExecuteRequest error: transfer without "
					"data!\n");
				request->subsys_status = SCSI_REQ_INVALID;
				gSCSI->finished(request, 1);
			}
			break;
		}
		case SCSI_OP_UNMAP:
		{
			const scsi_cmd_unmap* cmd = (const scsi_cmd_unmap*)request->cdb;

			if (!fTrimSupported) {
				TRACE("%s port %d: unsupported request opcode 0x%02x\n",
					__func__, fIndex, request->cdb[0]);
				request->subsys_status = SCSI_REQ_ABORTED;
				gSCSI->finished(request, 1);
				break;
			}

			scsi_unmap_parameter_list* unmapBlocks
				= (scsi_unmap_parameter_list*)request->data;
			if (unmapBlocks == NULL
				|| B_BENDIAN_TO_HOST_INT16(cmd->length) != request->data_length
				|| B_BENDIAN_TO_HOST_INT16(unmapBlocks->data_length)
					!= request->data_length - 1) {
				TRACE("%s port %d: invalid unmap parameter data length\n",
					__func__, fIndex);
				request->subsys_status = SCSI_REQ_ABORTED;
				gSCSI->finished(request, 1);
			} else {
				ScsiUnmap(request, unmapBlocks);
			}
			break;
		}
		default:
			TRACE("AHCIPort::ScsiExecuteRequest port %d unsupported request "
				"opcode 0x%02x\n", fIndex, request->cdb[0]);
			request->subsys_status = SCSI_REQ_ABORTED;
			gSCSI->finished(request, 1);
	}
}
예제 #15
0
Layer*
Layer::readLayer(BFile& file, ImageView* imageView, int32 new_id,
                 bool is_little_endian, int32 compression_method)
{
    // This is the new way of reading the layers.
    int32 marker;
    if (file.Read(&marker,sizeof(int32)) != sizeof(int32))
        return NULL;

    if (is_little_endian)
        marker = B_LENDIAN_TO_HOST_INT32(marker);
    else
        marker = B_BENDIAN_TO_HOST_INT32(marker);

    if (marker != PROJECT_FILE_LAYER_START_MARKER)
        return NULL;

    int32 width;
    int32 height;
    layer_type layerType;
    int32 layer_visibility;
    int64 length;
    if (file.Read(&width,sizeof(int32)) != sizeof(int32))
        return NULL;
    if (file.Read(&height,sizeof(int32)) != sizeof(int32))
        return NULL;
    if (file.Read(&layerType,sizeof(int32)) != sizeof(int32))
        return NULL;
    if (file.Read(&layer_visibility,sizeof(int32)) != sizeof(int32))
        return NULL;
    if (file.Read(&length,sizeof(int64)) != sizeof(int64))
        return NULL;

    if (is_little_endian) {
        width = B_LENDIAN_TO_HOST_INT32(width);
        height = B_LENDIAN_TO_HOST_INT32(height);
        layerType = layer_type(B_LENDIAN_TO_HOST_INT32(layerType));
        length = B_LENDIAN_TO_HOST_INT64(length);
    }
    else {
        width = B_BENDIAN_TO_HOST_INT32(width);
        height = B_BENDIAN_TO_HOST_INT32(height);
        layerType = layer_type(B_BENDIAN_TO_HOST_INT32(layerType));
        length = B_BENDIAN_TO_HOST_INT64(length);
    }

    Layer* layer = new Layer(BRect(0, 0, width - 1, height - 1), new_id,
                             imageView, layerType);
    layer->SetVisibility((uint32(layer_visibility) == 0xFFFFFFFF));
    int8* bits = (int8*)layer->Bitmap()->Bits();
    if (file.Read(bits,length) != length) {
        delete layer;
        return NULL;
    }

    // Read the end-marker.
    if (file.Read(&marker,sizeof(int32)) != sizeof(int32)) {
        delete layer;
        return NULL;
    }
    if (is_little_endian)
        marker = B_LENDIAN_TO_HOST_INT32(marker);
    else
        marker = B_BENDIAN_TO_HOST_INT32(marker);

    if (marker != PROJECT_FILE_LAYER_END_MARKER) {
        delete layer;
        return NULL;
    }

    // Here try to read the extra-data block.
    if (file.Read(&marker,sizeof(int32)) == sizeof(int32)) {
        if (is_little_endian)
            marker = B_LENDIAN_TO_HOST_INT32(marker);
        else
            marker = B_BENDIAN_TO_HOST_INT32(marker);

        if (marker == PROJECT_FILE_LAYER_EXTRA_DATA_START_MARKER) {
            // Read the length of this section
            int32 length;
            if (file.Read(&length,sizeof(int32)) != sizeof(int32)) {
                delete layer;
                return NULL;
            }

            if (is_little_endian)
                length = B_LENDIAN_TO_HOST_INT32(length);
            else
                length = B_BENDIAN_TO_HOST_INT32(length);

            // Read the transparency coefficient
            float coeff;
            if (file.Read(&coeff,sizeof(float)) != sizeof(float)) {
                delete layer;
                return NULL;
            }
            if (is_little_endian)
                coeff = B_LENDIAN_TO_HOST_FLOAT(coeff);
            else
                coeff = B_BENDIAN_TO_HOST_FLOAT(coeff);

            layer->SetTransparency(coeff);
            length -= sizeof(float);

            // Skip the extra data that we do not recognize.
            file.Seek(length,SEEK_CUR);

            // Here we should get the end-marker for layer's extra data
            if (file.Read(&marker,sizeof(int32)) != sizeof(int32)) {
                delete layer;
                return NULL;
            }
            if (is_little_endian)
                marker = B_LENDIAN_TO_HOST_INT32(marker);
            else
                marker = B_BENDIAN_TO_HOST_INT32(marker);

            if (marker != PROJECT_FILE_LAYER_EXTRA_DATA_END_MARKER) {
                delete layer;
                return NULL;
            }

        }
        else {
            // Somehow -sizeof(int32) does not seem to work????
            file.Seek(-4,SEEK_CUR);
        }
    }

    // Before returning calculate the layer's miniature image.
    layer->calc_mini_image();

    return layer;
}