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)); }
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); }
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; }
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; }
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); } }
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); }
uint64 EncryptedSize() const { return B_BENDIAN_TO_HOST_INT64(encrypted_size); }
uint64 EncryptedOffset() const { return B_BENDIAN_TO_HOST_INT64(encrypted_offset); }
uint64 VolumeSize() const { return B_BENDIAN_TO_HOST_INT64(volume_size); }
uint64 HiddenSize() const { return B_BENDIAN_TO_HOST_INT64(hidden_size); }
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; }
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; }
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; } }
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); } }
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; }