Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:14

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup rtems_bdpart
0007  *
0008  * @brief Manage Partitions of a Disk Device
0009  */
0010 
0011 /*
0012  * Copyright (C) 2009, 2010 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039 
0040 #include <rtems.h>
0041 #include <rtems/bdpart.h>
0042 
0043 rtems_status_code rtems_bdpart_create(
0044   const char *disk_name,
0045   const rtems_bdpart_format *format,
0046   rtems_bdpart_partition *pt,
0047   const unsigned *dist,
0048   size_t count
0049 )
0050 {
0051   rtems_status_code sc = RTEMS_SUCCESSFUL;
0052   bool dos_compatibility = format != NULL
0053     && format->type == RTEMS_BDPART_FORMAT_MBR
0054     && format->mbr.dos_compatibility;
0055   rtems_blkdev_bnum disk_end = 0;
0056   rtems_blkdev_bnum pos = 0;
0057   rtems_blkdev_bnum dist_sum = 0;
0058   rtems_blkdev_bnum record_space =
0059     dos_compatibility ? RTEMS_BDPART_MBR_CYLINDER_SIZE : 1;
0060   rtems_blkdev_bnum overhead = 0;
0061   rtems_blkdev_bnum free_space = 0;
0062   size_t i = 0;
0063 
0064   /* Check if we have something to do */
0065   if (count == 0) {
0066     /* Nothing to do */
0067     return RTEMS_SUCCESSFUL;
0068   }
0069 
0070   /* Check parameter */
0071   if (format == NULL || pt == NULL || dist == NULL) {
0072     return RTEMS_INVALID_ADDRESS;
0073   }
0074 
0075   /* Get disk data */
0076   sc = rtems_bdpart_get_disk_data( disk_name, NULL, NULL, &disk_end);
0077   if (sc != RTEMS_SUCCESSFUL) {
0078     return sc;
0079   }
0080 
0081   /* Get distribution sum and check for overflow */
0082   for (i = 0; i < count; ++i) {
0083     unsigned prev_sum = dist_sum;
0084 
0085     dist_sum += dist [i];
0086 
0087     if (dist_sum < prev_sum) {
0088       return RTEMS_INVALID_NUMBER;
0089     }
0090 
0091     if (dist [i] == 0) {
0092       return RTEMS_INVALID_NUMBER;
0093     }
0094   }
0095 
0096   /* Check format */
0097   if (format->type != RTEMS_BDPART_FORMAT_MBR) {
0098     return RTEMS_NOT_IMPLEMENTED;
0099   }
0100 
0101   /* Align end of disk on cylinder boundary if necessary */
0102   if (dos_compatibility) {
0103     disk_end -= (disk_end % record_space);
0104   }
0105 
0106   /*
0107    * We need at least space for the MBR and the compatibility space for the
0108    * first primary partition.
0109    */
0110   overhead += record_space;
0111 
0112   /*
0113    * In case we need an extended partition and logical partitions we have to
0114    * account for the space of each EBR.
0115    */
0116   if (count > 4) {
0117     overhead += (count - 3) * record_space;
0118   }
0119 
0120   /*
0121    * Account space to align every partition on cylinder boundaries if
0122    * necessary.
0123    */
0124   if (dos_compatibility) {
0125     overhead += (count - 1) * record_space;
0126   }
0127 
0128   /* Check disk space */
0129   if ((overhead + count) > disk_end) {
0130     return RTEMS_IO_ERROR;
0131   }
0132 
0133   /* Begin of first primary partition */
0134   pos = record_space;
0135 
0136   /* Space for partitions */
0137   free_space = disk_end - overhead;
0138 
0139   for (i = 0; i < count; ++i) {
0140     rtems_bdpart_partition *p = pt + i;
0141 
0142     /* Partition size */
0143     rtems_blkdev_bnum s = free_space * dist [i];
0144     if (s < free_space || s < dist [i]) {
0145       /* TODO: Calculate without overflow */
0146       return RTEMS_INVALID_NUMBER;
0147     }
0148     s /= dist_sum;
0149 
0150     /* Ensure that the partition is not empty */
0151     if (s == 0) {
0152       s = 1;
0153     }
0154 
0155     /* Align partition upwards */
0156     s += record_space - (s % record_space);
0157 
0158     /* Reserve space for the EBR if necessary */
0159     if (count > 4 && i > 2) {
0160       pos += record_space;
0161     }
0162 
0163     /* Partition begin and end */
0164     p->begin = pos;
0165     pos += s;
0166     p->end = pos;
0167   }
0168 
0169   /* Expand the last partition to the disk end */
0170   pt [count - 1].end = disk_end;
0171 
0172   return RTEMS_SUCCESSFUL;
0173 }