Blame source/vdo/base/fixedLayout.c

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
}