|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
310c69 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
310c69 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
310c69 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
310c69 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
310c69 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
310c69 |
* GNU General Public License for more details.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
310c69 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
310c69 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
310c69 |
* 02110-1301, USA.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/fixedLayout.c#3 $
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "fixedLayout.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "buffer.h"
|
|
Packit Service |
310c69 |
#include "logger.h"
|
|
Packit Service |
310c69 |
#include "memoryAlloc.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "header.h"
|
|
Packit Service |
310c69 |
#include "statusCodes.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
const BlockCount ALL_FREE_BLOCKS = (uint64_t) -1;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
struct fixedLayout {
|
|
Packit Service |
310c69 |
PhysicalBlockNumber firstFree;
|
|
Packit Service |
310c69 |
PhysicalBlockNumber lastFree;
|
|
Packit Service |
310c69 |
size_t numPartitions;
|
|
Packit Service |
310c69 |
Partition *head;
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
struct partition {
|
|
Packit Service |
310c69 |
PartitionID id; // The id of this partition
|
|
Packit Service |
310c69 |
FixedLayout *layout; // The layout to which this partition belongs
|
|
Packit Service |
310c69 |
PhysicalBlockNumber offset; // The offset into the layout of this partition
|
|
Packit Service |
310c69 |
PhysicalBlockNumber base; // The untranslated number of the first block
|
|
Packit Service |
310c69 |
BlockCount count; // The number of blocks in the partition
|
|
Packit Service |
310c69 |
Partition *next; // A pointer to the next partition in the layout
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct {
|
|
Packit Service |
310c69 |
PhysicalBlockNumber firstFree;
|
|
Packit Service |
310c69 |
PhysicalBlockNumber lastFree;
|
|
Packit Service |
310c69 |
byte partitionCount;
|
|
Packit Service |
310c69 |
} __attribute__((packed)) Layout3_0;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct {
|
|
Packit Service |
310c69 |
PartitionID id;
|
|
Packit Service |
310c69 |
PhysicalBlockNumber offset;
|
|
Packit Service |
310c69 |
PhysicalBlockNumber base;
|
|
Packit Service |
310c69 |
BlockCount count;
|
|
Packit Service |
310c69 |
} __attribute__((packed)) Partition3_0;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
static const Header LAYOUT_HEADER_3_0 = {
|
|
Packit Service |
310c69 |
.id = FIXED_LAYOUT,
|
|
Packit Service |
310c69 |
.version = {
|
|
Packit Service |
310c69 |
.majorVersion = 3,
|
|
Packit Service |
310c69 |
.minorVersion = 0,
|
|
Packit Service |
310c69 |
},
|
|
Packit Service |
310c69 |
.size = sizeof(Layout3_0), // Minimum size (contains no partitions)
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int makeFixedLayout(BlockCount totalBlocks,
|
|
Packit Service |
310c69 |
PhysicalBlockNumber startOffset,
|
|
Packit Service |
310c69 |
FixedLayout **layoutPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
FixedLayout *layout;
|
|
Packit Service |
310c69 |
int result = ALLOCATE(1, FixedLayout, "fixed layout", &layout);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
layout->firstFree = startOffset;
|
|
Packit Service |
310c69 |
layout->lastFree = startOffset + totalBlocks;
|
|
Packit Service |
310c69 |
layout->numPartitions = 0;
|
|
Packit Service |
310c69 |
layout->head = NULL;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*layoutPtr = layout;
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void freeFixedLayout(FixedLayout **layoutPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
FixedLayout *layout = *layoutPtr;
|
|
Packit Service |
310c69 |
if (layout == NULL) {
|
|
Packit Service |
310c69 |
return;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
while (layout->head != NULL) {
|
|
Packit Service |
310c69 |
Partition *part = layout->head;
|
|
Packit Service |
310c69 |
layout->head = part->next;
|
|
Packit Service |
310c69 |
FREE(part);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
FREE(layout);
|
|
Packit Service |
310c69 |
*layoutPtr = NULL;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
BlockCount getTotalFixedLayoutSize(const FixedLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
BlockCount size = getFixedLayoutBlocksAvailable(layout);
|
|
Packit Service |
310c69 |
for (Partition *partition = layout->head; partition != NULL;
|
|
Packit Service |
310c69 |
partition = partition->next) {
|
|
Packit Service |
310c69 |
size += partition->count;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return size;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int getPartition(FixedLayout *layout, PartitionID id, Partition **partitionPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
for (Partition *partition = layout->head; partition != NULL;
|
|
Packit Service |
310c69 |
partition = partition->next) {
|
|
Packit Service |
310c69 |
if (partition->id == id) {
|
|
Packit Service |
310c69 |
if (partitionPtr != NULL) {
|
|
Packit Service |
310c69 |
*partitionPtr = partition;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return VDO_UNKNOWN_PARTITION;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int translateToPBN(const Partition *partition,
|
|
Packit Service |
310c69 |
PhysicalBlockNumber partitionBlockNumber,
|
|
Packit Service |
310c69 |
PhysicalBlockNumber *layerBlockNumber)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (partition == NULL) {
|
|
Packit Service |
310c69 |
*layerBlockNumber = partitionBlockNumber;
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (partitionBlockNumber < partition->base) {
|
|
Packit Service |
310c69 |
return VDO_OUT_OF_RANGE;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
PhysicalBlockNumber offsetFromBase = partitionBlockNumber - partition->base;
|
|
Packit Service |
310c69 |
if (offsetFromBase >= partition->count) {
|
|
Packit Service |
310c69 |
return VDO_OUT_OF_RANGE;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*layerBlockNumber = partition->offset + offsetFromBase;
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int translateFromPBN(const Partition *partition,
|
|
Packit Service |
310c69 |
PhysicalBlockNumber layerBlockNumber,
|
|
Packit Service |
310c69 |
PhysicalBlockNumber *partitionBlockNumberPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (partition == NULL) {
|
|
Packit Service |
310c69 |
*partitionBlockNumberPtr = layerBlockNumber;
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (layerBlockNumber < partition->offset) {
|
|
Packit Service |
310c69 |
return VDO_OUT_OF_RANGE;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
PhysicalBlockNumber partitionBlockNumber
|
|
Packit Service |
310c69 |
= layerBlockNumber - partition->offset;
|
|
Packit Service |
310c69 |
if (partitionBlockNumber >= partition->count) {
|
|
Packit Service |
310c69 |
return VDO_OUT_OF_RANGE;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*partitionBlockNumberPtr = partitionBlockNumber + partition->base;
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
BlockCount getFixedLayoutBlocksAvailable(const FixedLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return layout->lastFree - layout->firstFree;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Allocate a partition. The partition will be attached to the partition
|
|
Packit Service |
310c69 |
* list in the layout.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param layout The layout containing the partition
|
|
Packit Service |
310c69 |
* @param id The id of the partition
|
|
Packit Service |
310c69 |
* @param offset The offset into the layout at which the partition begins
|
|
Packit Service |
310c69 |
* @param base The number of the first block for users of the partition
|
|
Packit Service |
310c69 |
* @param blockCount The number of blocks in the partition
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static int allocatePartition(FixedLayout *layout,
|
|
Packit Service |
310c69 |
byte id,
|
|
Packit Service |
310c69 |
PhysicalBlockNumber offset,
|
|
Packit Service |
310c69 |
PhysicalBlockNumber base,
|
|
Packit Service |
310c69 |
BlockCount blockCount)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
Partition *partition;
|
|
Packit Service |
310c69 |
int result = ALLOCATE(1, Partition, "fixed layout partition", &partition);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
partition->id = id;
|
|
Packit Service |
310c69 |
partition->layout = layout;
|
|
Packit Service |
310c69 |
partition->offset = offset;
|
|
Packit Service |
310c69 |
partition->base = base;
|
|
Packit Service |
310c69 |
partition->count = blockCount;
|
|
Packit Service |
310c69 |
partition->next = layout->head;
|
|
Packit Service |
310c69 |
layout->head = partition;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int makeFixedLayoutPartition(FixedLayout *layout,
|
|
Packit Service |
310c69 |
PartitionID id,
|
|
Packit Service |
310c69 |
BlockCount blockCount,
|
|
Packit Service |
310c69 |
PartitionDirection direction,
|
|
Packit Service |
310c69 |
PhysicalBlockNumber base)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
BlockCount freeBlocks = layout->lastFree - layout->firstFree;
|
|
Packit Service |
310c69 |
if (blockCount == ALL_FREE_BLOCKS) {
|
|
Packit Service |
310c69 |
if (freeBlocks == 0) {
|
|
Packit Service |
310c69 |
return VDO_NO_SPACE;
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
blockCount = freeBlocks;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
} else if (blockCount > freeBlocks) {
|
|
Packit Service |
310c69 |
return VDO_NO_SPACE;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
int result = getPartition(layout, id, NULL);
|
|
Packit Service |
310c69 |
if (result != VDO_UNKNOWN_PARTITION) {
|
|
Packit Service |
310c69 |
return VDO_PARTITION_EXISTS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
PhysicalBlockNumber offset = ((direction == FROM_END)
|
|
Packit Service |
310c69 |
? (layout->lastFree - blockCount)
|
|
Packit Service |
310c69 |
: layout->firstFree);
|
|
Packit Service |
310c69 |
result = allocatePartition(layout, id, offset, base, blockCount);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
layout->numPartitions++;
|
|
Packit Service |
310c69 |
if (direction == FROM_END) {
|
|
Packit Service |
310c69 |
layout->lastFree = layout->lastFree - blockCount;
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
layout->firstFree += blockCount;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
BlockCount getFixedLayoutPartitionSize(const Partition *partition)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return partition->count;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
PhysicalBlockNumber getFixedLayoutPartitionOffset(const Partition *partition)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return partition->offset;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
PhysicalBlockNumber getFixedLayoutPartitionBase(const Partition *partition)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return partition->base;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
static inline size_t getEncodedSize(const FixedLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return sizeof(Layout3_0) + (sizeof(Partition3_0) * layout->numPartitions);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
size_t getFixedLayoutEncodedSize(const FixedLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return ENCODED_HEADER_SIZE + getEncodedSize(layout);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Encode a null-terminated list of fixed layout partitions into a buffer
|
|
Packit Service |
310c69 |
* using partition format 3.0.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param layout The layout containing the list of partitions to encode
|
|
Packit Service |
310c69 |
* @param buffer A buffer positioned at the start of the encoding
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static int encodePartitions_3_0(const FixedLayout *layout, Buffer *buffer)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
for (const Partition *partition = layout->head;
|
|
Packit Service |
310c69 |
partition != NULL;
|
|
Packit Service |
310c69 |
partition = partition->next) {
|
|
Packit Service |
310c69 |
STATIC_ASSERT_SIZEOF(PartitionID, sizeof(byte));
|
|
Packit Service |
310c69 |
int result = putByte(buffer, partition->id);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, partition->offset);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, partition->base);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, partition->count);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Encode the header fields of a fixed layout into a buffer using layout
|
|
Packit Service |
310c69 |
* format 3.0.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param layout The layout to encode
|
|
Packit Service |
310c69 |
* @param buffer A buffer positioned at the start of the encoding
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static int encodeLayout_3_0(const FixedLayout *layout, Buffer *buffer)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = ASSERT(layout->numPartitions <= UINT8_MAX,
|
|
Packit Service |
310c69 |
"fixed layout partition count must fit in a byte");
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, layout->firstFree);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, layout->lastFree);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return putByte(buffer, layout->numPartitions);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int encodeFixedLayout(const FixedLayout *layout, Buffer *buffer)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (!ensureAvailableSpace(buffer, getFixedLayoutEncodedSize(layout))) {
|
|
Packit Service |
310c69 |
return UDS_BUFFER_ERROR;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
Header header = LAYOUT_HEADER_3_0;
|
|
Packit Service |
310c69 |
header.size = getEncodedSize(layout);
|
|
Packit Service |
310c69 |
int result = encodeHeader(&header, buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
size_t initialLength = contentLength(buffer);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = encodeLayout_3_0(layout, buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
size_t encodedSize = contentLength(buffer) - initialLength;
|
|
Packit Service |
310c69 |
result = ASSERT(encodedSize == sizeof(Layout3_0),
|
|
Packit Service |
310c69 |
"encoded size of fixed layout header must match structure");
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = encodePartitions_3_0(layout, buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
encodedSize = contentLength(buffer) - initialLength;
|
|
Packit Service |
310c69 |
return ASSERT(encodedSize == header.size,
|
|
Packit Service |
310c69 |
"encoded size of fixed layout must match header size");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Decode a sequence of fixed layout partitions from a buffer
|
|
Packit Service |
310c69 |
* using partition format 3.0.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param buffer A buffer positioned at the start of the encoding
|
|
Packit Service |
310c69 |
* @param layout The layout in which to allocate the decoded partitions
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static int decodePartitions_3_0(Buffer *buffer, FixedLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
for (size_t i = 0; i < layout->numPartitions; i++) {
|
|
Packit Service |
310c69 |
byte id;
|
|
Packit Service |
310c69 |
int result = getByte(buffer, &id;;
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
uint64_t offset;
|
|
Packit Service |
310c69 |
result = getUInt64LEFromBuffer(buffer, &offset);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
uint64_t base;
|
|
Packit Service |
310c69 |
result = getUInt64LEFromBuffer(buffer, &base);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
uint64_t count;
|
|
Packit Service |
310c69 |
result = getUInt64LEFromBuffer(buffer, &count);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = allocatePartition(layout, id, offset, base, count);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Decode the header fields of a fixed layout from a buffer using layout
|
|
Packit Service |
310c69 |
* format 3.0.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param buffer A buffer positioned at the start of the encoding
|
|
Packit Service |
310c69 |
* @param layout The structure to receive the decoded fields
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static int decodeLayout_3_0(Buffer *buffer, Layout3_0 *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
size_t initialLength = contentLength(buffer);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
PhysicalBlockNumber firstFree;
|
|
Packit Service |
310c69 |
int result = getUInt64LEFromBuffer(buffer, &firstFree);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
PhysicalBlockNumber lastFree;
|
|
Packit Service |
310c69 |
result = getUInt64LEFromBuffer(buffer, &lastFree);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
byte partitionCount;
|
|
Packit Service |
310c69 |
result = getByte(buffer, &partitionCount);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*layout = (Layout3_0) {
|
|
Packit Service |
310c69 |
.firstFree = firstFree,
|
|
Packit Service |
310c69 |
.lastFree = lastFree,
|
|
Packit Service |
310c69 |
.partitionCount = partitionCount,
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
size_t decodedSize = initialLength - contentLength(buffer);
|
|
Packit Service |
310c69 |
return ASSERT(decodedSize == sizeof(Layout3_0),
|
|
Packit Service |
310c69 |
"decoded size of fixed layout header must match structure");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int decodeFixedLayout(Buffer *buffer, FixedLayout **layoutPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
Header header;
|
|
Packit Service |
310c69 |
int result = decodeHeader(buffer, &header);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Layout is variable size, so only do a minimum size check here.
|
|
Packit Service |
310c69 |
result = validateHeader(&LAYOUT_HEADER_3_0, &header, false, __func__);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
Layout3_0 layoutHeader;
|
|
Packit Service |
310c69 |
result = decodeLayout_3_0(buffer, &layoutHeader);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (contentLength(buffer)
|
|
Packit Service |
310c69 |
< (sizeof(Partition3_0) * layoutHeader.partitionCount)) {
|
|
Packit Service |
310c69 |
return VDO_UNSUPPORTED_VERSION;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
FixedLayout *layout;
|
|
Packit Service |
310c69 |
result = ALLOCATE(1, FixedLayout, "fixed layout", &layout);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
layout->firstFree = layoutHeader.firstFree;
|
|
Packit Service |
310c69 |
layout->lastFree = layoutHeader.lastFree;
|
|
Packit Service |
310c69 |
layout->numPartitions = layoutHeader.partitionCount;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = decodePartitions_3_0(buffer, layout);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
freeFixedLayout(&layout);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*layoutPtr = layout;
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|