Beispiel #1
0
rtems_status_code rtems_bdpart_register(
  const char *disk_name,
  const rtems_bdpart_partition *pt,
  size_t count
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_status_code esc = RTEMS_SUCCESSFUL;
  rtems_blkdev_bnum disk_end = 0;
  char *logical_disk_name = NULL;
  char *logical_disk_marker = NULL;
  size_t i = 0;
  int fd = -1;
  rtems_disk_device *dd = NULL;

  /* Get disk data */
  sc = rtems_bdpart_get_disk_data( disk_name, &fd, &dd, &disk_end);
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  /* Create logical disk name */
  logical_disk_name = create_logical_disk_name(
    disk_name,
    &logical_disk_marker
  );
  if (logical_disk_name == NULL) {
    esc = sc;
    goto cleanup;
  }

  /* Create a logical disk for each partition */
  for (i = 0; i < count; ++i) {
    const rtems_bdpart_partition *p = pt + i;

    /* Set partition number for logical disk name */
    sc = update_logical_disk_name( logical_disk_marker, i);
    if (sc != RTEMS_SUCCESSFUL) {
      esc = sc;
      goto cleanup;
    }

    /* Create logical disk */
    sc = rtems_blkdev_create_partition(
      logical_disk_name,
      disk_name,
      p->begin,
      p->end - p->begin
    );
    if (sc != RTEMS_SUCCESSFUL) {
      esc = sc;
      goto cleanup;
    }
  }

cleanup:

  free( logical_disk_name);
  close( fd);

  return esc;
}
Beispiel #2
0
  const char *disk_name,
  const rtems_bdpart_partition *pt __attribute__((unused)),
  size_t count
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_status_code esc = RTEMS_SUCCESSFUL;
  rtems_blkdev_bnum disk_end = 0;
  char *logical_disk_name = NULL;
  char *logical_disk_marker = NULL;
  size_t i = 0;
  int fd = -1;
  rtems_disk_device *dd = NULL;

  /* Get disk data */
  sc = rtems_bdpart_get_disk_data( disk_name, &fd, &dd, &disk_end);
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  /* Create logical disk name */
  logical_disk_name = create_logical_disk_name(
    disk_name,
    &logical_disk_marker
  );
  if (logical_disk_name == NULL) {
    esc = sc;
    goto cleanup;
  }

  /* Delete the logical disk for each partition */
Beispiel #3
0
rtems_status_code rtems_bdpart_write(
  const char *disk_name,
  const rtems_bdpart_format *format,
  const rtems_bdpart_partition *pt,
  size_t count
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_status_code esc = RTEMS_SUCCESSFUL;
  bool dos_compatibility = format != NULL
    && format->type == RTEMS_BDPART_FORMAT_MBR
    && format->mbr.dos_compatibility;
  rtems_bdbuf_buffer *block = NULL;
  rtems_blkdev_bnum disk_end = 0;
  rtems_blkdev_bnum record_space =
    dos_compatibility ? RTEMS_BDPART_MBR_CYLINDER_SIZE : 1;
  size_t ppc = 0; /* Primary partition count */
  size_t i = 0;
  uint8_t *data = NULL;
  int fd = -1;
  rtems_disk_device *dd = NULL;

  /* Check if we have something to do */
  if (count == 0) {
    /* Nothing to do */
    return RTEMS_SUCCESSFUL;
  }

  /* Check parameter */
  if (format == NULL || pt == NULL) {
    return RTEMS_INVALID_ADDRESS;
  }

  /* Get disk data */
  sc = rtems_bdpart_get_disk_data( disk_name, &fd, &dd, &disk_end);
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  /* Align end of disk on cylinder boundary if necessary */
  if (dos_compatibility) {
    disk_end -= (disk_end % record_space);
  }

  /* Check that we have a consistent partition table */
  for (i = 0; i < count; ++i) {
    const rtems_bdpart_partition *p = pt + i;

    /* Check that begin and end are proper within the disk */
    if (p->begin >= disk_end || p->end > disk_end) {
      esc = RTEMS_INVALID_NUMBER;
      goto cleanup;
    }

    /* Check that begin and end are valid */
    if (p->begin >= p->end) {
      esc = RTEMS_INVALID_NUMBER;
      goto cleanup;
    }

    /* Check that partitions do not overlap */
    if (i > 0 && pt [i - 1].end > p->begin) {
      esc = RTEMS_INVALID_NUMBER;
      goto cleanup;
    }
  }

  /* Check format */
  if (format->type != RTEMS_BDPART_FORMAT_MBR) {
    esc = RTEMS_NOT_IMPLEMENTED;
    goto cleanup;
  }

  /*
   * Set primary partition count.  If we have more than four partitions we need
   * an extended partition which will contain the partitions of number four and
   * above as logical partitions.  If we have four or less partitions we can
   * use the primary partition table.
   */
  ppc = count <= 4 ? count : 3;

  /*
   * Check that the first primary partition starts at head one and sector one
   * under the virtual one head and 63 sectors geometry if necessary.
   */
  if (dos_compatibility && pt [0].begin != RTEMS_BDPART_MBR_CYLINDER_SIZE) {
    esc = RTEMS_INVALID_NUMBER;
    goto cleanup;
  }

  /*
   * Check that we have enough space for the EBRs.  The partitions with number
   * four and above are logical partitions if we have more than four partitions
   * in total.  The logical partitions are contained in the extended partition.
   * Each logical partition is described via one EBR preceding the partition.
   * The space for the EBR and maybe some space which is needed for DOS
   * compatibility resides between the partitions.  So there have to be gaps of
   * the appropriate size between the partitions.
   */
  for (i = ppc; i < count; ++i) {
    if ((pt [i].begin - pt [i - 1].end) < record_space) {
      esc = RTEMS_INVALID_NUMBER;
      goto cleanup;
    }
  }

  /* Check that we can convert the parition descriptions to the MBR format */
  for (i = 0; i < count; ++i) {
    uint8_t type = 0;

    const rtems_bdpart_partition *p = pt + i;

    /* Check type */
    if (!rtems_bdpart_to_mbr_partition_type( p->type, &type)) {
      esc =  RTEMS_INVALID_ID;
      goto cleanup;
    }

    /* Check flags */
    if (p->flags > 0xffU) {
      esc = RTEMS_INVALID_ID;
      goto cleanup;
    }

    /* Check ID */
    /* TODO */
  }

  /* New MBR */
  sc = rtems_bdpart_new_record( dd, 0, &block);
  if (sc != RTEMS_SUCCESSFUL) {
    esc = sc;
    goto cleanup;
  }

  /* Write disk ID */
  rtems_uint32_to_little_endian(
    format->mbr.disk_id,
    block->buffer + RTEMS_BDPART_MBR_OFFSET_DISK_ID
  );

  /* Write primary partition table */
  data = block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0;
  for (i = 0; i < ppc; ++i) {
    const rtems_bdpart_partition *p = pt + i;

    /* Write partition entry */
    rtems_bdpart_write_mbr_partition(
      data,
      p->begin,
      p->end - p->begin,
      rtems_bdpart_mbr_partition_type( p->type),
      (uint8_t) p->flags
    );

    data += RTEMS_BDPART_MBR_TABLE_ENTRY_SIZE;
  }

  /* Write extended partition with logical partitions if necessary */
  if (ppc != count) {
    rtems_blkdev_bnum ebr = 0; /* Extended boot record block index */

    /* Begin of extended partition */
    rtems_blkdev_bnum ep_begin = pt [ppc].begin - record_space;

    /* Write extended partition */
    rtems_bdpart_write_mbr_partition(
      data,
      ep_begin,
      disk_end - ep_begin,
      RTEMS_BDPART_MBR_EXTENDED,
      0
    );

    /* Write logical partitions */
    for (i = ppc; i < count; ++i) {
      const rtems_bdpart_partition *p = pt + i;

      /* Write second partition entry */
      if (i > ppc) {
        rtems_blkdev_bnum begin = p->begin - record_space;

        rtems_bdpart_write_mbr_partition(
          block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_1,
          begin - ep_begin,
          disk_end - begin,
          RTEMS_BDPART_MBR_EXTENDED,
          0
        );
      }

      /* New EBR */
      ebr = p->begin - record_space;
      sc = rtems_bdpart_new_record( dd, ebr, &block);
      if (sc != RTEMS_SUCCESSFUL) {
        esc = sc;
        goto cleanup;
      }

      /* Write first partition entry */
      rtems_bdpart_write_mbr_partition(
        block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0,
        record_space,
        p->end - p->begin,
        rtems_bdpart_mbr_partition_type( p->type),
        (uint8_t) p->flags
      );
    }
  }

cleanup:

  if (fd >= 0) {
    close( fd);
  }

  if (block != NULL) {
    rtems_bdbuf_sync( block);
  }

  return esc;
}
rtems_status_code rtems_bdpart_register(
  const char *disk_name,
  const rtems_bdpart_partition *pt,
  size_t count
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_status_code esc = RTEMS_SUCCESSFUL;
  rtems_device_major_number major = 0;
  rtems_device_minor_number minor = 0;
  rtems_blkdev_bnum disk_end = 0;
  dev_t disk = 0;
  dev_t logical_disk = 0;
  char *logical_disk_name = NULL;
  char *logical_disk_marker = NULL;
  size_t disk_name_size = strlen( disk_name);
  size_t i = 0;
  int fd = -1;
  const rtems_disk_device *dd = NULL;

  /* Get disk data */
  sc = rtems_bdpart_get_disk_data( disk_name, &fd, &dd, &disk_end);
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }
  disk = rtems_disk_get_device_identifier( dd);
  close( fd);

  /* Get the disk device identifier */
  rtems_filesystem_split_dev_t( disk, major, minor);

  /* Create logical disk name */
  logical_disk_name = malloc( disk_name_size + RTEMS_BDPART_NUMBER_SIZE);
  if (logical_disk_name == NULL) {
    return RTEMS_NO_MEMORY;
  }
  strncpy( logical_disk_name, disk_name, disk_name_size);
  logical_disk_marker = logical_disk_name + disk_name_size;

  /* Create a logical disk for each partition */
  for (i = 0; i < count; ++i) {
    const rtems_bdpart_partition *p = pt + i;
    int rv = 0;

    /* New minor number */
    ++minor;

    /* Create a new device identifier */
    logical_disk = rtems_filesystem_make_dev_t( major, minor);

    /* Set partition number for logical disk name */
    rv = snprintf( logical_disk_marker, RTEMS_BDPART_NUMBER_SIZE, "%zu", i + 1);
    if (rv >= RTEMS_BDPART_NUMBER_SIZE) {
      esc = RTEMS_INVALID_NAME;
      goto cleanup;
    }

    /* Create logical disk */
    sc = rtems_disk_create_log(
      logical_disk,
      disk,
      p->begin,
      p->end - p->begin,
      logical_disk_name
    );
    if (sc != RTEMS_SUCCESSFUL) {
      esc = sc;
      goto cleanup;
    }
  }

cleanup:

  free( logical_disk_name);

  return esc;
}
Beispiel #5
0
rtems_status_code rtems_bdpart_read(
  const char *disk_name,
  rtems_bdpart_format *format,
  rtems_bdpart_partition *pt,
  size_t *count
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_status_code esc = RTEMS_SUCCESSFUL;
  rtems_bdbuf_buffer *block = NULL;
  rtems_bdpart_partition *p = pt - 1;
  const rtems_bdpart_partition *p_end = pt + (count != NULL ? *count : 0);
  rtems_blkdev_bnum ep_begin = 0; /* Extended partition begin */
  rtems_blkdev_bnum ebr = 0; /* Extended boot record block index */
  rtems_blkdev_bnum disk_end = 0;
  size_t i = 0;
  const uint8_t *data = NULL;
  int fd = -1;
  rtems_disk_device *dd = NULL;

  /* Check parameter */
  if (format == NULL || pt == NULL || count == NULL) {
    return RTEMS_INVALID_ADDRESS;
  }

  /* Set count to a save value */
  *count = 0;

  /* Get disk data */
  sc = rtems_bdpart_get_disk_data( disk_name, &fd, &dd, &disk_end);
  if (sc != RTEMS_SUCCESSFUL) {
    return sc;
  }

  /* Read MBR */
  sc = rtems_bdpart_read_record( dd, 0, &block);
  if (sc != RTEMS_SUCCESSFUL) {
    esc = sc;
    goto cleanup;
  }

  /* Read the first partition entry */
  data = block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0;
  sc = rtems_bdpart_read_mbr_partition( data, &p, p_end, &ep_begin);
  if (sc != RTEMS_SUCCESSFUL) {
    esc = sc;
    goto cleanup;
  }

  /* Determine if we have a MBR or GPT format */
  if (rtems_bdpart_mbr_partition_type( p->type) == RTEMS_BDPART_MBR_GPT) {
    esc = RTEMS_NOT_IMPLEMENTED;
    goto cleanup;
  }

  /* Set format */
  format->type = RTEMS_BDPART_FORMAT_MBR;
  format->mbr.disk_id = rtems_uint32_from_little_endian(
    block->buffer + RTEMS_BDPART_MBR_OFFSET_DISK_ID
  );
  format->mbr.dos_compatibility = true;

  /* Iterate through the rest of the primary partition table */
  for (i = 1; i < 4; ++i) {
    data += RTEMS_BDPART_MBR_TABLE_ENTRY_SIZE;

    sc = rtems_bdpart_read_mbr_partition( data, &p, p_end, &ep_begin);
    if (sc != RTEMS_SUCCESSFUL) {
      esc = sc;
      goto cleanup;
    }
  }

  /* Iterate through the logical partitions within the extended partition */
  ebr = ep_begin;
  while (ebr != 0) {
    rtems_blkdev_bnum tmp = 0;

    /* Read EBR */
    sc = rtems_bdpart_read_record( dd, ebr, &block);
    if (sc != RTEMS_SUCCESSFUL) {
      esc = sc;
      goto cleanup;
    }

    /* Read first partition entry */
    sc = rtems_bdpart_read_mbr_partition(
      block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0,
      &p,
      p_end,
      NULL
    );
    if (sc != RTEMS_SUCCESSFUL) {
      esc = sc;
      goto cleanup;
    }

    /* Adjust partition begin */
    tmp = p->begin + ebr;
    if (tmp > p->begin) {
      p->begin = tmp;
    } else {
      esc = RTEMS_IO_ERROR;
      goto cleanup;
    }

    /* Adjust partition end */
    tmp = p->end + ebr;
    if (tmp > p->end) {
      p->end = tmp;
    } else {
      esc = RTEMS_IO_ERROR;
      goto cleanup;
    }

    /* Read second partition entry for next EBR block */
    ebr = rtems_bdpart_next_ebr(
      block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_1
    );
    if (ebr != 0) {
      /* Adjust partition EBR block index */
      tmp = ebr + ep_begin;
      if (tmp > ebr) {
        ebr = tmp;
      } else {
        esc = RTEMS_IO_ERROR;
        goto cleanup;
      }
    }
  }

  /* Return partition count */
  *count = (size_t) (p - pt + 1);

cleanup:

  if (fd >= 0) {
    close( fd);
  }

  if (block != NULL) {
    rtems_bdbuf_release( block);
  }

  return esc;
}