/* ---------------------------------------------------------------------------- * Copyright (c) @CompanyNameMagicTag 2013-2019. All rights reserved. * Description: LiteOS Disk Module Implementation * Create: 2013-01-01 * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * 3. Neither the name of the copyright holder nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior written * permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ #include "disk_pri.h" #include "stdio.h" #include "stdlib.h" #include "unistd.h" #include "sys/mount.h" #include "inode/inode.h" #ifdef CONFIG_DRIVERS_MMC #include "block.h" #endif #ifdef __cplusplus #if __cplusplus extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ los_disk g_sysDisk[SYS_MAX_DISK]; los_part g_sysPart[SYS_MAX_PART]; #define CONFIG_FS_FAT_MAX_SECTOR_PER_BLOCK 2048 #if CONFIG_FS_FAT_SECTOR_PER_BLOCK > CONFIG_FS_FAT_MAX_SECTOR_PER_BLOCK #error CONFIG_FS_FAT_SECTOR_PER_BLOCK should less than 2048! #endif uint32_t g_uwFatSectorsPerBlock = CONFIG_FS_FAT_SECTOR_PER_BLOCK; uint32_t g_uwFatBlockNums = CONFIG_FS_FAT_BLOCK_NUMS; dpal_spinlock g_diskSpinlock; dpal_spinlock g_diskFatBlockSpinlock; uint32_t g_usbMode = 0; #define MEM_ADDR_ALIGN_BYTE 64 #define RWE_RW_RW 0755 typedef void *(*StorageHookFunction)(void *); static uint32_t OsReHookFuncAddDiskRef(StorageHookFunction handler, void *param) __attribute__((weakref("osReHookFuncAdd"))); static uint32_t OsReHookFuncDelDiskRef(StorageHookFunction handler) __attribute__((weakref("osReHookFuncDel"))); #ifdef CONFIG_FS_FAT_CACHE uint32_t GetFatBlockNums(void) { return g_uwFatBlockNums; } void SetFatBlockNums(uint32_t blockNums) { g_uwFatBlockNums = blockNums; } uint32_t GetFatSectorsPerBlock(void) { return g_uwFatSectorsPerBlock; } void SetFatSectorsPerBlock(uint32_t sectorsPerBlock) { if (((sectorsPerBlock % UNSIGNED_INTEGER_BITS) == 0) && (sectorsPerBlock <= CONFIG_FS_FAT_MAX_SECTOR_PER_BLOCK)) { g_uwFatSectorsPerBlock = sectorsPerBlock; } } #endif int32_t los_alloc_diskid_byname(const char *diskName) { int32_t diskId; los_disk *disk = NULL; unsigned long intSave; if (diskName == NULL) { disk_log_err("The paramter disk_name is NULL"); return VFS_ERROR; } if (strnlen(diskName, DISK_NAME + 1) > DISK_NAME) { disk_log_err("diskName is too long!\n"); return VFS_ERROR; } dpal_spin_lock_irqsave(&g_diskSpinlock, &intSave); for (diskId = 0; diskId < SYS_MAX_DISK; diskId++) { disk = get_disk(diskId); if ((disk != NULL) && (disk->disk_status == STAT_UNUSED)) { disk->disk_status = STAT_UNREADY; break; } } dpal_spin_unlock_irqrestore(&g_diskSpinlock, &intSave); if ((disk == NULL) || (diskId == SYS_MAX_DISK)) { disk_log_err("los_alloc_diskid_byname failed %d!\n", diskId); return VFS_ERROR; } if (strncpy_s(disk->disk_name, DISK_NAME + 1, diskName, strlen(diskName)) != EOK) { disk_log_err("The strncpy_s failed.\n"); return VFS_ERROR; } return diskId; } int32_t los_get_diskid_byname(const char *diskName) { int32_t diskId; los_disk *disk = NULL; size_t diskNameLen; if (diskName == NULL) { disk_log_err("The paramter diskName is NULL"); return VFS_ERROR; } diskNameLen = strnlen(diskName, DISK_NAME + 1); if (diskNameLen > DISK_NAME) { disk_log_err("diskName is too long!\n"); return VFS_ERROR; } for (diskId = 0; diskId < SYS_MAX_DISK; diskId++) { disk = get_disk(diskId); if ((disk != NULL) && (disk->disk_status != STAT_INUSED)) { continue; } if ((disk != NULL) && (strcmp(diskName, disk->disk_name) == 0)) { break; } } if ((disk == NULL) || (diskId == SYS_MAX_DISK)) { disk_log_err("los_get_diskid_byname failed!\n"); return VFS_ERROR; } return diskId; } void OsSetUsbStatus(uint32_t diskId) { if (diskId < SYS_MAX_DISK) { g_usbMode |= (1u << diskId) & UINT_MAX; } } void OsClearUsbStatus(uint32_t diskId) { if (diskId < SYS_MAX_DISK) { g_usbMode &= ~((1u << diskId) & UINT_MAX); } } #ifdef CONFIG_FS_FAT_CACHE static uint32_t GetDiskUsbStatus(uint32_t diskId) { return (g_usbMode & (1u << diskId)) ? TRUE : FALSE; } #endif los_disk *get_disk(int32_t id) { if ((id >= 0) && (id < SYS_MAX_DISK)) { return &g_sysDisk[id]; } return NULL; } los_part *get_part(int32_t id) { if ((id >= 0) && (id < SYS_MAX_PART)) { return &g_sysPart[id]; } return NULL; } static uint64_t GetFirstPartStart(const los_part *part) { los_part *firstPart = NULL; los_disk *disk = get_disk((int32_t)part->disk_id); firstPart = (disk == NULL) ? NULL : DPAL_DL_LIST_ENTRY(disk->head.next, los_part, list); return (firstPart == NULL) ? 0 : firstPart->sector_start; } static void DiskPartAddToDisk(los_disk *disk, los_part *part) { DISK_LOCK(disk); part->disk_id = disk->disk_id; part->part_no_disk = disk->part_count; dpal_list_tail_insert(&disk->head, &part->list); disk->part_count++; DISK_UNLOCK(disk); } static void DiskPartDelFromDisk(los_disk *disk, los_part *part) { dpal_list_delete(&part->list); disk->part_count--; } static los_part *DiskPartAllocate(struct inode *dev, uint64_t start, uint64_t count) { uint32_t i; los_part *part = get_part(0); /* traversing from the beginning of the array */ for (i = 0; i < SYS_MAX_PART; i++) { if (part->dev == NULL) { part->part_id = i; part->part_no_mbr = 0; part->dev = dev; part->sector_start = start; part->sector_count = count; part->part_name = NULL; dpal_list_init(&part->list); return part; } part++; } return NULL; } static void DiskPartRelease(los_part *part) { part->dev = NULL; part->part_no_disk = 0; part->part_no_mbr = 0; if (part->part_name != NULL) { dpal_free(part->part_name); part->part_name = NULL; } } /* * name is a combination of disk_name, 'p' and part_count, such as "/dev/mmcblk0p0" * disk_name : DISK_NAME + 1 * 'p' : 1 * part_count: 1 */ #define DEV_NAME_BUFF_SIZE (DISK_NAME + 3) static int32_t DiskAddPart(los_disk *disk, uint64_t sectorStart, uint64_t sectorCount, BOOL IsValidPart) { struct inode_search_s desc; char devName[DEV_NAME_BUFF_SIZE]; struct inode *diskDev = NULL; los_part *part = NULL; if ((disk == NULL) || (disk->disk_status == STAT_UNUSED) || (disk->dev == NULL)) { return VFS_ERROR; } if ((sectorCount > disk->sector_count) || ((disk->sector_count - sectorCount) < sectorStart)) { disk_log_err("DiskAddPart failed: sector start is %llu, sector count is %llu\n", sectorStart, sectorCount); return VFS_ERROR; } diskDev = disk->dev; if (IsValidPart == TRUE) { if (snprintf_s(devName, sizeof(devName), sizeof(devName) - 1, "%s%c%u", disk->disk_name, 'p', disk->part_count) < 0) { return VFS_ERROR; } if (register_blockdriver(devName, diskDev->u.i_bops, RWE_RW_RW, diskDev->i_private)) { disk_log_err("DiskAddPart : register %s fail!\n", devName); return VFS_ERROR; } SETUP_SEARCH(&desc, devName, false); if (inode_find(&desc) < 0) { disk_log_err("DiskAddPart : find %s fail!\n", devName); RELEASE_SEARCH(&desc); return VFS_ERROR; } printf("DiskAddPart : register %s ok!\n", devName); part = DiskPartAllocate(desc.node, sectorStart, sectorCount); inode_release(desc.node); RELEASE_SEARCH(&desc); if (part == NULL) { (void)unregister_blockdriver(devName); return VFS_ERROR; } } else { part = DiskPartAllocate(diskDev, sectorStart, sectorCount); if (part == NULL) { return VFS_ERROR; } } DiskPartAddToDisk(disk, part); if (disk->type == EMMC) { part->type = EMMC; } return (int32_t)part->part_id; } static int32_t DiskDivide(los_disk *disk, struct disk_divide_info *info) { uint32_t i; int32_t ret; disk->type = info->part[0].type; for (i = 0; i < info->part_count; i++) { if (info->sector_count < info->part[i].sector_start) { return VFS_ERROR; } if (info->part[i].sector_count > (info->sector_count - info->part[i].sector_start)) { disk_log_err("Part[%u] sector_start:%llu, sector_count:%llu, exceed emmc sector_count:%llu.\n", i, info->part[i].sector_start, info->part[i].sector_count, (info->sector_count - info->part[i].sector_start)); info->part[i].sector_count = info->sector_count - info->part[i].sector_start; disk_log_err("Part[%u] sector_count change to %llu.\n", i, info->part[i].sector_count); ret = DiskAddPart(disk, info->part[i].sector_start, info->part[i].sector_count, TRUE); if (ret == VFS_ERROR) { return VFS_ERROR; } break; } ret = DiskAddPart(disk, info->part[i].sector_start, info->part[i].sector_count, TRUE); if (ret == VFS_ERROR) { return VFS_ERROR; } } return ENOERR; } static int32_t DiskPartitionMemZalloc(size_t boundary, size_t size, char **gptBuf, char **partitionBuf) { char *buffer1 = NULL; char *buffer2 = NULL; buffer1 = (char *)dpal_memalign(boundary, size); if (buffer1 == NULL) { disk_log_err("%s buffer1 malloc %lu failed! %d\n", __FUNCTION__, size, __LINE__); return -ENOMEM; } buffer2 = (char *)dpal_memalign(boundary, size); if (buffer2 == NULL) { disk_log_err("%s buffer2 malloc %lu failed! %d\n", __FUNCTION__, size, __LINE__); dpal_free(buffer1); return -ENOMEM; } (void)memset_s(buffer1, size, 0, size); (void)memset_s(buffer2, size, 0, size); *gptBuf = buffer1; *partitionBuf = buffer2; return ENOERR; } #ifdef CONFIG_FS_FAT_GPT static char GPTPartitionTypeRecognition(const char *parBuf) { const char *buf = parBuf; const char *fsType = "FAT"; const char *str = "\xEB\x52\x90" "NTFS "; /* NTFS Boot entry point */ if (((LD_DWORD_DISK(&buf[BS_FILSYSTEMTYPE32]) & BS_FS_TYPE_MASK) == BS_FS_TYPE_VALUE) || (strncmp(&buf[BS_FILSYSTYPE], fsType, strlen(fsType)) == 0)) { return BS_FS_TYPE_FAT; } else if (strncmp(&buf[BS_JMPBOOT], str, strlen(str)) == 0) { return BS_FS_TYPE_NTFS; } return ENOERR; } static int32_t GPTInfoGet(struct inode *blkDrv, char *gptBuf) { int32_t ret; ret = blkDrv->u.i_bops->read(blkDrv, (unsigned char *)gptBuf, 1, 1); /* Read the device first sector */ if (ret != 1) { /* Read failed */ disk_log_err("%s %d\n", __FUNCTION__, __LINE__); return -EIO; } if (!VERIFY_GPT(gptBuf)) { disk_log_err("%s %d\n", __FUNCTION__, __LINE__); return VFS_ERROR; } return ENOERR; } static int32_t OsGPTPartitionRecognitionSub(struct disk_divide_info *info, const char *partitionBuf, uint32_t *partitionCount, uint64_t partitionStart, uint64_t partitionEnd) { char partitionType; if (VERIFY_FS(partitionBuf)) { partitionType = GPTPartitionTypeRecognition(partitionBuf); if (partitionType) { if (*partitionCount >= MAX_DIVIDE_PART_PER_DISK) { return VFS_ERROR; } info->part[*partitionCount].type = partitionType; info->part[*partitionCount].sector_start = partitionStart; info->part[*partitionCount].sector_count = (partitionEnd - partitionStart) + 1; (*partitionCount)++; } else { disk_log_err("The partition type is not allowed to use!\n"); } } else { disk_log_err("Do not support the partition type!\n"); } return ENOERR; } static int32_t OsGPTPartitionRecognition(struct inode *blkDrv, struct disk_divide_info *info, const char *gptBuf, char *partitionBuf, uint32_t *partitionCount) { uint32_t j; int32_t ret; uint64_t partitionStart, partitionEnd; for (j = 0; j < PAR_ENTRY_NUM_PER_SECTOR; j++) { if (!VERITY_AVAILABLE_PAR(&gptBuf[j * TABLE_SIZE])) { printf("The partition type is ESP or MSR!\n"); continue; } if (!VERITY_PAR_VALID(&gptBuf[j * TABLE_SIZE])) { return VFS_ERROR; } partitionStart = LD_QWORD_DISK(&gptBuf[(j * TABLE_SIZE) + GPT_PAR_START_OFFSET]); partitionEnd = LD_QWORD_DISK(&gptBuf[(j * TABLE_SIZE) + GPT_PAR_END_OFFSET]); if ((partitionStart >= partitionEnd) || (partitionEnd > info->sector_count)) { disk_log_err("GPT partition %u recognition failed : partitionStart = %llu, partitionEnd = %llu\n", j, partitionStart, partitionEnd); return VFS_ERROR; } (void)memset_s(partitionBuf, info->sector_size, 0, info->sector_size); ret = blkDrv->u.i_bops->read(blkDrv, (unsigned char *)partitionBuf, partitionStart, 1); if (ret != 1) { /* read failed */ disk_log_err("%s %d\n", __FUNCTION__, __LINE__); return -EIO; } ret = OsGPTPartitionRecognitionSub(info, partitionBuf, partitionCount, partitionStart, partitionEnd); if (ret != ENOERR) { return VFS_ERROR; } } return ret; } static int32_t DiskGPTPartitionRecognition(struct inode *blkDrv, struct disk_divide_info *info) { char *gptBuf = NULL; char *partitionBuf = NULL; uint32_t tableNum, i, index; uint32_t partitionCount = 0; int32_t ret; ret = DiskPartitionMemZalloc(MEM_ADDR_ALIGN_BYTE, info->sector_size, &gptBuf, &partitionBuf); if (ret != ENOERR) { return ret; } ret = GPTInfoGet(blkDrv, gptBuf); if (ret < 0) { goto OUT_WITH_MEM; } tableNum = LD_DWORD_DISK(&gptBuf[TABLE_NUM_OFFSET]); if (tableNum > TABLE_MAX_NUM) { tableNum = TABLE_MAX_NUM; } index = (tableNum % PAR_ENTRY_NUM_PER_SECTOR) ? ((tableNum / PAR_ENTRY_NUM_PER_SECTOR) + 1) : (tableNum / PAR_ENTRY_NUM_PER_SECTOR); for (i = 0; i < index; i++) { (void)memset_s(gptBuf, info->sector_size, 0, info->sector_size); ret = blkDrv->u.i_bops->read(blkDrv, (unsigned char *)gptBuf, TABLE_START_SECTOR + i, 1); if (ret != 1) { /* read failed */ disk_log_err("%s %d\n", __FUNCTION__, __LINE__); ret = -EIO; goto OUT_WITH_MEM; } ret = OsGPTPartitionRecognition(blkDrv, info, gptBuf, partitionBuf, &partitionCount); if (ret < 0) { if (ret == VFS_ERROR) { ret = (int32_t)partitionCount; } goto OUT_WITH_MEM; } } ret = (int32_t)partitionCount; OUT_WITH_MEM: dpal_free(gptBuf); dpal_free(partitionBuf); return ret; } #endif static int32_t OsMBRInfoGet(struct inode *blkDrv, char *mbrBuf) { int32_t ret; /* read MBR, start from sector 0, length is 1 sector */ ret = blkDrv->u.i_bops->read(blkDrv, (unsigned char *)mbrBuf, 0, 1); if (ret != 1) { /* read failed */ disk_log_err("driver read return error: %d\n", ret); return -EIO; } /* Check boot record signature. */ if (LD_WORD_DISK(&mbrBuf[BS_SIG55AA]) != BS_SIG55AA_VALUE) { return VFS_ERROR; } return ENOERR; } static int32_t OsEBRInfoGet(struct inode *blkDrv, const struct disk_divide_info *info, char *ebrBuf, const char *mbrBuf) { int32_t ret; if (VERIFY_FS(mbrBuf)) { if (info->sector_count <= LD_DWORD_DISK(&mbrBuf[PAR_OFFSET + PAR_START_OFFSET])) { return VFS_ERROR; } ret = blkDrv->u.i_bops->read(blkDrv, (unsigned char *)ebrBuf, LD_DWORD_DISK(&mbrBuf[PAR_OFFSET + PAR_START_OFFSET]), 1); if ((ret != 1) || (!VERIFY_FS(ebrBuf))) { /* read failed */ disk_log_err("OsEBRInfoGet, verify_fs error, ret = %d\n", ret); return -EIO; } } return ENOERR; } static int32_t OsPrimaryPartitionRecognition(const char *mbrBuf, struct disk_divide_info *info, int32_t *extendedPos, int32_t *mbrCount) { int32_t i; char mbrPartitionType; int32_t extendedFlag = 0; int32_t count = 0; for (i = 0; i < MAX_PRIMARY_PART_PER_DISK; i++) { mbrPartitionType = mbrBuf[PAR_OFFSET + PAR_TYPE_OFFSET + (i * PAR_TABLE_SIZE)]; if (mbrPartitionType) { info->part[i].type = mbrPartitionType; info->part[i].sector_start = LD_DWORD_DISK(&mbrBuf[PAR_OFFSET + PAR_START_OFFSET + (i * PAR_TABLE_SIZE)]); info->part[i].sector_count = LD_DWORD_DISK(&mbrBuf[PAR_OFFSET + PAR_COUNT_OFFSET + (i * PAR_TABLE_SIZE)]); if ((mbrPartitionType == EXTENDED_PAR) || (mbrPartitionType == EXTENDED_8G)) { extendedFlag = 1; *extendedPos = i; continue; } count++; } } *mbrCount = count; return extendedFlag; } static int32_t OsLogicalPartitionRecognition(struct inode *blkDrv, struct disk_divide_info *info, uint32_t extendedAddress, char *ebrBuf, int32_t mbrCount) { int32_t ret; uint32_t extendedOffset = 0; char ebrPartitionType; int32_t ebrCount = 0; do { (void)memset_s(ebrBuf, info->sector_size, 0, info->sector_size); if (((uint64_t)(extendedAddress) + extendedOffset) >= info->sector_count) { disk_log_err("extended partition is out of disk range: extendedAddress = %u, extendedOffset = %u\n", extendedAddress, extendedOffset); break; } ret = blkDrv->u.i_bops->read(blkDrv, (unsigned char *)ebrBuf, extendedAddress + extendedOffset, 1); if (ret != 1) { /* read failed */ disk_log_err("driver read return error: %d, extendedAddress = %u, extendedOffset = %u\n", ret, extendedAddress, extendedOffset); return -EIO; } ebrPartitionType = ebrBuf[PAR_OFFSET + PAR_TYPE_OFFSET]; if (ebrPartitionType && ((mbrCount + ebrCount) < MAX_DIVIDE_PART_PER_DISK)) { info->part[MAX_PRIMARY_PART_PER_DISK + ebrCount].type = ebrPartitionType; info->part[MAX_PRIMARY_PART_PER_DISK + ebrCount].sector_start = extendedAddress + extendedOffset + LD_DWORD_DISK(&ebrBuf[PAR_OFFSET + PAR_START_OFFSET]); info->part[MAX_PRIMARY_PART_PER_DISK + ebrCount].sector_count = LD_DWORD_DISK(&ebrBuf[PAR_OFFSET + PAR_COUNT_OFFSET]); ebrCount++; } extendedOffset = LD_DWORD_DISK(&ebrBuf[PAR_OFFSET + PAR_START_OFFSET + PAR_TABLE_SIZE]); } while ((ebrBuf[PAR_OFFSET + PAR_TYPE_OFFSET + PAR_TABLE_SIZE] != 0) && ((mbrCount + ebrCount) < MAX_DIVIDE_PART_PER_DISK)); return ebrCount; } static int32_t DiskPartitionRecognition(struct inode *blkDrv, struct disk_divide_info *info) { int32_t ret; int32_t extendedFlag; int32_t extendedPos = 0; int32_t mbrCount = 0; uint32_t extendedAddress; char *mbrBuf = NULL; char *ebrBuf = NULL; if ((blkDrv == NULL) || (blkDrv->u.i_bops == NULL) || (blkDrv->u.i_bops->read == NULL)) { return -EINVAL; } ret = DiskPartitionMemZalloc(MEM_ADDR_ALIGN_BYTE, info->sector_size, &mbrBuf, &ebrBuf); if (ret != ENOERR) { return ret; } ret = OsMBRInfoGet(blkDrv, mbrBuf); if (ret < 0) { goto OUT_WITH_MEM; } #ifdef CONFIG_FS_FAT_GPT /* The partition type is GPT */ if (mbrBuf[PARTION_MODE_BTYE] == (char)PARTION_MODE_GPT) { ret = DiskGPTPartitionRecognition(blkDrv, info); goto OUT_WITH_MEM; } #endif ret = OsEBRInfoGet(blkDrv, info, ebrBuf, mbrBuf); if (ret < 0) { ret = 0; /* no mbr */ goto OUT_WITH_MEM; } extendedFlag = OsPrimaryPartitionRecognition(mbrBuf, info, &extendedPos, &mbrCount); if (extendedFlag) { extendedAddress = LD_DWORD_DISK(&mbrBuf[PAR_OFFSET + PAR_START_OFFSET + (extendedPos * PAR_TABLE_SIZE)]); ret = OsLogicalPartitionRecognition(blkDrv, info, extendedAddress, ebrBuf, mbrCount); if (ret <= 0) { goto OUT_WITH_MEM; } } ret += mbrCount; OUT_WITH_MEM: dpal_free(ebrBuf); dpal_free(mbrBuf); return ret; } int32_t DiskPartitionRegister(los_disk *disk) { int32_t count; uint32_t i, partSize; los_part *part = NULL; struct disk_divide_info parInfo; /* Fill disk_divide_info structure to set partition's infomation. */ (void)memset_s(parInfo.part, sizeof(parInfo.part), 0, sizeof(parInfo.part)); partSize = sizeof(parInfo.part) / sizeof(parInfo.part[0]); parInfo.sector_size = disk->sector_size; parInfo.sector_count = disk->sector_count; count = DiskPartitionRecognition(disk->dev, &parInfo); if (count == VFS_ERROR) { part = get_part(DiskAddPart(disk, 0, disk->sector_count, FALSE)); if (part == NULL) { return VFS_ERROR; } part->part_no_mbr = 0; printf("Disk %s doesn't contain a valid partition table.\n", disk->disk_name); return ENOERR; } else if (count < 0) { return VFS_ERROR; } parInfo.part_count = count; if (count == 0) { part = get_part(DiskAddPart(disk, 0, disk->sector_count, TRUE)); if (part == NULL) { return VFS_ERROR; } part->part_no_mbr = 0; printf("No MBR detected.\n"); return ENOERR; } for (i = 0; i < partSize; i++) { /* Read the disk_divide_info structure to get partition's infomation. */ if ((parInfo.part[i].type != 0) && (parInfo.part[i].type != EXTENDED_PAR) && (parInfo.part[i].type != EXTENDED_8G)) { part = get_part(DiskAddPart(disk, parInfo.part[i].sector_start, parInfo.part[i].sector_count, TRUE)); if (part == NULL) { return VFS_ERROR; } part->part_no_mbr = i + 1; part->filesystem_type = parInfo.part[i].type; } } return ENOERR; } int32_t los_disk_read(int32_t drvId, void *buf, uint64_t sector, uint32_t count) { #ifdef CONFIG_FS_FAT_CACHE uint32_t len; #endif int32_t result = VFS_ERROR; los_disk *disk = get_disk(drvId); if ((buf == NULL) || (count == 0)) { /* buff equal to NULL or count equal to 0 */ return result; } if (disk == NULL) { return result; } DISK_LOCK(disk); if (disk->disk_status != STAT_INUSED) { goto ERROR_HANDLE; } if ((count > disk->sector_count) || ((disk->sector_count - count) < sector)) { goto ERROR_HANDLE; } #ifdef CONFIG_FS_FAT_CACHE if (disk->bcache != NULL) { if (((uint64_t)(disk->bcache->sectorSize) * count) > UINT_MAX) { goto ERROR_HANDLE; } len = disk->bcache->sectorSize * count; result = BlockCacheRead(disk->bcache, (unsigned char *)buf, &len, 0, sector); if (result != ENOERR) { disk_log_err("los_disk_read read err = %d, sector = %llu, len = %u\n", result, sector, len); } } else { #endif if ((disk->dev != NULL) && (disk->dev->u.i_bops != NULL) && (disk->dev->u.i_bops->read != NULL)) { result = disk->dev->u.i_bops->read(disk->dev, (unsigned char *)buf, sector, count); if (result == (int32_t)count) { result = ENOERR; } } #ifdef CONFIG_FS_FAT_CACHE } #endif if (result != ENOERR) { goto ERROR_HANDLE; } DISK_UNLOCK(disk); return ENOERR; ERROR_HANDLE: DISK_UNLOCK(disk); return VFS_ERROR; } int32_t los_disk_write(int32_t drvId, const void *buf, uint64_t sector, uint32_t count) { #ifdef CONFIG_FS_FAT_CACHE uint32_t len; #endif int32_t result = VFS_ERROR; los_disk *disk = get_disk(drvId); if (disk == NULL) { return result; } if ((buf == NULL) || (count == 0)) { /* buff equal to NULL or count equal to 0 */ return result; } DISK_LOCK(disk); if (disk->disk_status != STAT_INUSED) { goto ERROR_HANDLE; } if ((count > disk->sector_count) || ((disk->sector_count - count) < sector)) { goto ERROR_HANDLE; } #ifdef CONFIG_FS_FAT_CACHE if (disk->bcache != NULL) { if (((uint64_t)(disk->bcache->sectorSize) * count) > UINT_MAX) { goto ERROR_HANDLE; } len = disk->bcache->sectorSize * count; result = BlockCacheWrite(disk->bcache, (const unsigned char *)buf, &len, 0, sector); if (result != ENOERR) { disk_log_err("los_disk_write write err = %d, sector = %llu, len = %u\n", result, sector, len); } } else { #endif if ((disk->dev != NULL) && (disk->dev->u.i_bops != NULL) && (disk->dev->u.i_bops->write != NULL)) { result = disk->dev->u.i_bops->write(disk->dev, (unsigned char *)buf, sector, count); if (result == (int32_t)count) { result = ENOERR; } } #ifdef CONFIG_FS_FAT_CACHE } #endif if (result != ENOERR) { goto ERROR_HANDLE; } DISK_UNLOCK(disk); return ENOERR; ERROR_HANDLE: DISK_UNLOCK(disk); return VFS_ERROR; } int32_t los_disk_ioctl(int32_t drvId, int32_t cmd, void *buf) { struct geometry info; los_disk *disk = get_disk(drvId); if (disk == NULL) { return VFS_ERROR; } DISK_LOCK(disk); if ((disk->dev == NULL) || (disk->disk_status != STAT_INUSED)) { goto ERROR_HANDLE; } if (cmd == DISK_CTRL_SYNC) { DISK_UNLOCK(disk); return ENOERR; } if (buf == NULL) { goto ERROR_HANDLE; } (void)memset_s(&info, sizeof(info), 0, sizeof(info)); if ((disk->dev->u.i_bops == NULL) || (disk->dev->u.i_bops->geometry == NULL) || (disk->dev->u.i_bops->geometry(disk->dev, &info) != 0)) { goto ERROR_HANDLE; } if (cmd == DISK_GET_SECTOR_COUNT) { *(uint64_t *)buf = info.geo_nsectors; if (info.geo_nsectors == 0) { goto ERROR_HANDLE; } } else if (cmd == DISK_GET_SECTOR_SIZE) { *(size_t *)buf = info.geo_sectorsize; } else if (cmd == DISK_GET_BLOCK_SIZE) { /* Get erase block size in unit of sectors (uint32_t) */ /* Block Num SDHC == 512, SD can be set to 512 or other */ if (info.geo_nsectors == 0) { goto ERROR_HANDLE; } *(size_t *)buf = DISK_MAX_SECTOR_SIZE / info.geo_sectorsize; } else { goto ERROR_HANDLE; } DISK_UNLOCK(disk); return ENOERR; ERROR_HANDLE: DISK_UNLOCK(disk); return VFS_ERROR; } int32_t los_part_read(int32_t pt, void *buf, uint64_t sector, uint32_t count) { const los_part *part = get_part(pt); los_disk *disk = NULL; int32_t ret; if (part == NULL) { return VFS_ERROR; } disk = get_disk((int32_t)part->disk_id); if (disk == NULL) { return VFS_ERROR; } DISK_LOCK(disk); if ((part->dev == NULL) || (disk->disk_status != STAT_INUSED)) { goto ERROR_HANDLE; } if (count > part->sector_count) { disk_log_err("los_part_read failed, invaild count, count = %u\n", count); goto ERROR_HANDLE; } /* Read from absolute sector. */ if (part->type == EMMC) { if ((disk->sector_count - part->sector_start) > sector) { sector += part->sector_start; } else { disk_log_err("los_part_read failed, invaild sector, sector = %llu\n", sector); goto ERROR_HANDLE; } } if ((sector >= GetFirstPartStart(part)) && (((sector + count) > (part->sector_start + part->sector_count)) || (sector < part->sector_start))) { disk_log_err("los_part_read error, sector = %llu, count = %u, part->sector_start = %llu, " "part->sector_count = %llu\n", sector, count, part->sector_start, part->sector_count); goto ERROR_HANDLE; } DISK_UNLOCK(disk); ret = los_disk_read((int32_t)part->disk_id, buf, sector, count); if (ret < 0) { return VFS_ERROR; } return ENOERR; ERROR_HANDLE: DISK_UNLOCK(disk); return VFS_ERROR; } int32_t los_part_write(int32_t pt, const void *buf, uint64_t sector, uint32_t count) { const los_part *part = get_part(pt); los_disk *disk = NULL; int32_t ret; if (part == NULL) { return VFS_ERROR; } disk = get_disk((int32_t)part->disk_id); if (disk == NULL) { return VFS_ERROR; } DISK_LOCK(disk); if ((part->dev == NULL) || (disk->disk_status != STAT_INUSED)) { goto ERROR_HANDLE; } if (count > part->sector_count) { disk_log_err("los_part_write failed, invaild count, count = %u\n", count); goto ERROR_HANDLE; } /* Write to absolute sector. */ if (part->type == EMMC) { if ((disk->sector_count - part->sector_start) > sector) { sector += part->sector_start; } else { disk_log_err("los_part_write failed, invaild sector, sector = %llu\n", sector); goto ERROR_HANDLE; } } if ((sector >= GetFirstPartStart(part)) && (((sector + count) > (part->sector_start + part->sector_count)) || (sector < part->sector_start))) { disk_log_err("los_part_write, sector = %llu, count = %u, part->sector_start = %llu, " "part->sector_count = %llu\n", sector, count, part->sector_start, part->sector_count); goto ERROR_HANDLE; } DISK_UNLOCK(disk); ret = los_disk_write((int32_t)part->disk_id, (const void *)buf, sector, count); if (ret < 0) { goto ERROR_HANDLE; } return ENOERR; ERROR_HANDLE: DISK_UNLOCK(disk); return VFS_ERROR; } #define GET_ERASE_BLOCK_SIZE 0x2 int32_t los_part_ioctl(int32_t pt, int32_t cmd, void *buf) { struct geometry info; los_part *part = get_part(pt); los_disk *disk = NULL; if (part == NULL) { return VFS_ERROR; } disk = get_disk((int32_t)part->disk_id); if (disk == NULL) { return VFS_ERROR; } DISK_LOCK(disk); if ((part->dev == NULL) || (disk->disk_status != STAT_INUSED)) { goto ERROR_HANDLE; } if (cmd == DISK_CTRL_SYNC) { DISK_UNLOCK(disk); return ENOERR; } if (buf == NULL) { goto ERROR_HANDLE; } (void)memset_s(&info, sizeof(info), 0, sizeof(info)); if ((part->dev->u.i_bops == NULL) || (part->dev->u.i_bops->geometry == NULL) || (part->dev->u.i_bops->geometry(part->dev, &info) != 0)) { goto ERROR_HANDLE; } if (cmd == DISK_GET_SECTOR_COUNT) { *(uint64_t *)buf = part->sector_count; if (*(uint64_t *)buf == 0) { goto ERROR_HANDLE; } } else if (cmd == DISK_GET_SECTOR_SIZE) { *(size_t *)buf = info.geo_sectorsize; } else if (cmd == DISK_GET_BLOCK_SIZE) { /* Get erase block size in unit of sectors (uint32_t) */ if ((part->dev->u.i_bops->ioctl == NULL) || (part->dev->u.i_bops->ioctl(part->dev, GET_ERASE_BLOCK_SIZE, (uintptr_t)buf) != 0)) { goto ERROR_HANDLE; } } else { goto ERROR_HANDLE; } DISK_UNLOCK(disk); return ENOERR; ERROR_HANDLE: DISK_UNLOCK(disk); return VFS_ERROR; } #ifdef CONFIG_FS_FAT_CACHE static void DiskCacheThreadInit(uint32_t diskId, OsBcache *bc) { bc->prereadFun = NULL; if (GetDiskUsbStatus(diskId) == FALSE) { #ifdef CONFIG_FS_FAT_CACHE_SYNC_THREAD BcacheSyncThreadInit(bc, diskId); #endif } if (OsReHookFuncAddDiskRef != NULL) { (void)OsReHookFuncAddDiskRef((StorageHookFunction)OsSdSync, (void *)0); (void)OsReHookFuncAddDiskRef((StorageHookFunction)OsSdSync, (void *)1); } } static OsBcache *DiskCacheInit(uint32_t sectorSize, uint64_t nsectors, struct inode *blkDriver) { #define SECTOR_SIZE 512 OsBcache *bc = NULL; uint32_t sectorPerBlock; uint32_t div = sectorSize / SECTOR_SIZE; if (div != 0) { sectorPerBlock = g_uwFatSectorsPerBlock / div; if (sectorPerBlock != 0) { bc = BlockCacheInit(blkDriver, sectorSize, sectorPerBlock, g_uwFatBlockNums, nsectors / sectorPerBlock); } } if (bc == NULL) { disk_log_err("disk_init : disk have not init bcache cache!\n"); return NULL; } return bc; } static void DiskCacheDeinit(los_disk *disk) { uint32_t diskId = disk->disk_id; if (GetDiskUsbStatus(diskId) == FALSE) { #ifdef CONFIG_FS_FAT_CACHE_SYNC_THREAD BcacheSyncThreadDeinit(disk->bcache); #endif } BlockCacheDeinit(disk->bcache); disk->bcache = NULL; if (OsReHookFuncDelDiskRef != NULL) { (void)OsReHookFuncDelDiskRef((StorageHookFunction)OsSdSync); } } #endif static void DiskStructInit(const char *diskName, int32_t diskId, const struct geometry *diskInfo, struct inode *blkDriver, los_disk *disk) { disk->disk_id = diskId; disk->dev = blkDriver; disk->sector_start = 0; disk->sector_size = diskInfo->geo_sectorsize; disk->sector_count = diskInfo->geo_nsectors; if (strncpy_s(disk->disk_name, DISK_NAME + 1, diskName, strlen(diskName)) != EOK) { disk_log_err("DiskStructInit strncpy_s failed.\n"); return; } dpal_list_init(&disk->head); } static int32_t DiskDivideAndPartitionRegister(struct disk_divide_info *info, los_disk *disk) { int32_t ret; if (info != NULL) { ret = DiskDivide(disk, info); if (ret != ENOERR) { disk_log_err("DiskDivide failed, ret = %d\n", ret); return ret; } } else { ret = DiskPartitionRegister(disk); if (ret != ENOERR) { disk_log_err("DiskPartitionRegister failed, ret = %d\n", ret); return ret; } } return ENOERR; } static int32_t DiskDeinit(los_disk *disk) { los_part *part = NULL; char devName[DEV_NAME_BUFF_SIZE]; int32_t ret; if (dpal_list_empty(&disk->head) == FALSE) { part = DPAL_DL_LIST_ENTRY(disk->head.next, los_part, list); while (&part->list != &disk->head) { ret = snprintf_s(devName, sizeof(devName), sizeof(devName) - 1, "%s%c%d", disk->disk_name, 'p', disk->part_count - 1); if (ret < 0) { return -ENAMETOOLONG; } DiskPartDelFromDisk(disk, part); (void)unregister_blockdriver(devName); DiskPartRelease(part); part = DPAL_DL_LIST_ENTRY(disk->head.next, los_part, list); } } DISK_LOCK(disk); #ifdef CONFIG_FS_FAT_CACHE DiskCacheDeinit(disk); #endif disk->dev = NULL; DISK_UNLOCK(disk); (void)unregister_blockdriver(disk->disk_name); disk->disk_status = STAT_UNUSED; disk->disk_name[0] = '\0'; return ENOERR; } void OsDiskInit(void) { int32_t diskId; uint32_t ret; los_disk *disk = NULL; for (diskId = 0; diskId < SYS_MAX_DISK; diskId++) { disk = get_disk(diskId); disk->disk_status = STAT_UNUSED; ret = dpal_mux_create(&disk->disk_mutex); if (ret != DPAL_OK) { disk_log_err("%s %d, mutex created failed, error:%u\n", __FUNCTION__, __LINE__, ret); } } } static void OsDiskInitSub(const char *diskName, int32_t diskId, los_disk *disk, const struct geometry *diskInfo, struct inode *blkDriver) { #ifdef CONFIG_FS_FAT_CACHE OsBcache *bc = DiskCacheInit(diskInfo->geo_sectorsize, diskInfo->geo_nsectors, blkDriver); if (bc != NULL) { DiskCacheThreadInit(diskId, bc); } disk->bcache = bc; #endif DiskStructInit(diskName, diskId, diskInfo, blkDriver, disk); } int32_t los_disk_init(const char *diskName, const struct block_operations *bops, void *priv, int32_t diskId, void *info) { struct inode_search_s desc; struct geometry diskInfo; struct inode *blkDriver = NULL; los_disk *disk = get_disk(diskId); int ret; if ((diskName == NULL) || (disk == NULL) || (disk->disk_status != STAT_UNREADY) || (strnlen(diskName, DISK_NAME + 1) > DISK_NAME)) { return VFS_ERROR; } if (register_blockdriver(diskName, bops, RWE_RW_RW, priv) != 0) { disk_log_err("disk_init : register %s fail!\n", diskName); return VFS_ERROR; } SETUP_SEARCH(&desc, diskName, false); ret = inode_find(&desc); if (ret < 0) { disk_log_err("disk_init : find %s fail!\n", diskName); goto DISK_FIND_ERROR; } blkDriver = desc.node; if ((blkDriver->u.i_bops == NULL) || (blkDriver->u.i_bops->geometry == NULL) || (blkDriver->u.i_bops->geometry(blkDriver, &diskInfo) != 0)) { goto DISK_BLKDRIVER_ERROR; } if (diskInfo.geo_sectorsize < DISK_MAX_SECTOR_SIZE) { goto DISK_BLKDRIVER_ERROR; } printf("disk_init : register %s ok!\n", diskName); OsDiskInitSub(diskName, diskId, disk, &diskInfo, blkDriver); inode_release(blkDriver); if (DiskDivideAndPartitionRegister(info, disk) != ENOERR) { (void)DiskDeinit(disk); return VFS_ERROR; } disk->disk_status = STAT_INUSED; RELEASE_SEARCH(&desc); return ENOERR; DISK_BLKDRIVER_ERROR: disk_log_err("disk_init : register %s ok but get disk info fail!\n", diskName); inode_release(blkDriver); DISK_FIND_ERROR: RELEASE_SEARCH(&desc); (void)unregister_blockdriver(diskName); return VFS_ERROR; } int32_t los_disk_deinit(int32_t diskId) { los_disk *disk = get_disk(diskId); if (disk == NULL) { return -EINVAL; } DISK_LOCK(disk); if (disk->disk_status != STAT_INUSED) { DISK_UNLOCK(disk); return -EINVAL; } disk->disk_status = STAT_UNREADY; DISK_UNLOCK(disk); return DiskDeinit(disk); } int32_t los_disk_sync(int32_t drvId) { int32_t ret = ENOERR; los_disk *disk = get_disk(drvId); if (disk == NULL) { return EINVAL; } DISK_LOCK(disk); if (disk->disk_status != STAT_INUSED) { DISK_UNLOCK(disk); return EINVAL; } #ifdef CONFIG_FS_FAT_CACHE if (disk->bcache != NULL) { ret = BlockCacheSync(disk->bcache); } #endif DISK_UNLOCK(disk); return ret; } int32_t los_disk_set_bcache(int32_t drvId, uint32_t sectorPerBlock, uint32_t blockNum) { #ifdef CONFIG_FS_FAT_CACHE int32_t ret; uint32_t intSave; OsBcache *bc = NULL; los_disk *disk = get_disk(drvId); if ((disk == NULL) || (sectorPerBlock == 0)) { return EINVAL; } if (((sectorPerBlock % UNSIGNED_INTEGER_BITS) != 0) || (sectorPerBlock > CONFIG_FS_FAT_MAX_SECTOR_PER_BLOCK)) { return EINVAL; } DISK_LOCK(disk); if (disk->disk_status != STAT_INUSED) { goto ERROR_HANDLE; } if (disk->bcache != NULL) { ret = BlockCacheSync(disk->bcache); if (ret != ENOERR) { DISK_UNLOCK(disk); return ret; } } dpal_spin_lock_irqsave(&g_diskFatBlockSpinlock, &intSave); DiskCacheDeinit(disk); g_uwFatBlockNums = blockNum; g_uwFatSectorsPerBlock = sectorPerBlock; bc = DiskCacheInit(disk->sector_size, disk->sector_count, disk->dev); if ((bc == NULL) && (blockNum != 0)) { dpal_spin_unlock_irqrestore(&g_diskFatBlockSpinlock, &intSave); DISK_UNLOCK(disk); return ENOMEM; } if (bc != NULL) { DiskCacheThreadInit((uint32_t)drvId, bc); } disk->bcache = bc; dpal_spin_unlock_irqrestore(&g_diskFatBlockSpinlock, &intSave); DISK_UNLOCK(disk); return ENOERR; ERROR_HANDLE: DISK_UNLOCK(disk); return EINVAL; #else return VFS_ERROR; #endif } static los_part *OsPartFind(los_disk *disk, const struct inode *blkDriver) { los_part *part = NULL; DISK_LOCK(disk); if ((disk->disk_status != STAT_INUSED) || (dpal_list_empty(&disk->head) == TRUE)) { goto EXIT; } part = DPAL_DL_LIST_ENTRY(disk->head.next, los_part, list); if (disk->dev == blkDriver) { goto EXIT; } while (&part->list != &disk->head) { if (part->dev == blkDriver) { goto EXIT; } part = DPAL_DL_LIST_ENTRY(part->list.next, los_part, list); } part = NULL; EXIT: DISK_UNLOCK(disk); return part; } los_part *los_part_find(const struct inode *blkDriver) { int32_t i; los_disk *disk = NULL; los_part *part = NULL; if (blkDriver == NULL) { return NULL; } for (i = 0; i < SYS_MAX_DISK; i++) { disk = get_disk(i); if (disk == NULL) { continue; } part = OsPartFind(disk, blkDriver); if (part != NULL) { return part; } } return NULL; } static uint32_t GetDiskNameStart(const char *name) { uint32_t i; uint32_t off = 0; for (i = 0; i < strlen(name); i++) { if (name[i] == '/') { off = i + 1; } } return off; } BOOL IsBlockStatusReady(const struct inode *blkDriver) { los_disk *disk = NULL; int32_t i; uint32_t off; if (blkDriver == NULL) { return FALSE; } for (i = 0; i < SYS_MAX_DISK; i++) { disk = get_disk(i); if ((disk == NULL) || (strlen(disk->disk_name) == 0)) { continue; } off = GetDiskNameStart(disk->disk_name); /* get the diskname removed "/dev/" */ if (strstr(blkDriver->i_name, disk->disk_name + off) == NULL) { continue; } if (OsPartFind(disk, blkDriver) != NULL) { return (disk->disk_status == STAT_INUSED) ? TRUE : FALSE; } else { return FALSE; } } return TRUE; } int32_t los_part_access(const char *dev, mode_t mode) { struct inode_search_s desc; los_part *part = NULL; int ret; (void)mode; SETUP_SEARCH(&desc, dev, false); ret = inode_find(&desc); if (ret < 0) { RELEASE_SEARCH(&desc); return VFS_ERROR; } part = los_part_find(desc.node); inode_release(desc.node); if (part == NULL) { return VFS_ERROR; } RELEASE_SEARCH(&desc); return ENOERR; } int32_t SetDiskPartName(los_part *part, const char *src) { size_t len; los_disk *disk = NULL; if ((part == NULL) || (src == NULL)) { return VFS_ERROR; } len = strlen(src); if ((len == 0) || (len >= DISK_NAME)) { return VFS_ERROR; } disk = get_disk((int32_t)part->disk_id); if (disk == NULL) { return VFS_ERROR; } DISK_LOCK(disk); if (disk->disk_status != STAT_INUSED) { goto ERROR_HANDLE; } part->part_name = (char *)dpal_zalloc(len + 1); if (part->part_name == NULL) { disk_log_err("%s[%d] zalloc failure\n", __FUNCTION__, __LINE__); goto ERROR_HANDLE; } (void)strcpy_s(part->part_name, len + 1, src); DISK_UNLOCK(disk); return ENOERR; ERROR_HANDLE: DISK_UNLOCK(disk); return VFS_ERROR; } int32_t add_mmc_partition(struct disk_divide_info *info, size_t sectorStart, size_t sectorCount) { uint32_t index, i; if (info == NULL) { return VFS_ERROR; } if ((info->part_count >= MAX_DIVIDE_PART_PER_DISK) || (sectorCount == 0)) { return VFS_ERROR; } if ((sectorCount > info->sector_count) || ((info->sector_count - sectorCount) < sectorStart)) { return VFS_ERROR; } index = info->part_count; for (i = 0; i < index; i++) { if (sectorStart < (info->part[i].sector_start + info->part[i].sector_count)) { return VFS_ERROR; } } info->part[index].sector_start = sectorStart; info->part[index].sector_count = sectorCount; info->part[index].type = EMMC; info->part_count++; return ENOERR; } int32_t del_mmc_partition(struct disk_divide_info *info, size_t sectorStart, size_t sectorCount) { if (info == NULL) { return VFS_ERROR; } if ((info->part_count > MAX_DIVIDE_PART_PER_DISK) || (info->part_count == 0) || (sectorCount == 0)) { return VFS_ERROR; } if ((info->sector_count < sectorCount) || ((info->sector_count - sectorCount) < sectorStart)) { return VFS_ERROR; } uint32_t index = info->part_count - 1; if ((info->part[index].sector_start != sectorStart) || (info->part[index].sector_count != sectorCount)) { return VFS_ERROR; } info->part[index].sector_start = 0; info->part[index].sector_count = 0; info->part[index].type = 0; info->part_count--; return ENOERR; } void show_part(const los_part *part) { if ((part == NULL) || (part->dev == NULL)) { disk_log_err("part is NULL\n"); return; } #if defined(CONFIG_SHELL) printf("\npart info :\n"); printf("disk id : %u\n", part->disk_id); printf("part_id in system: %u\n", part->part_id); printf("part no in disk : %u\n", part->part_no_disk); printf("part no in mbr : %u\n", part->part_no_mbr); printf("part filesystem : %02X\n", part->filesystem_type); printf("part dev name : %s\n", part->dev->i_name); printf("part sec start : %llu\n", part->sector_start); printf("part sec count : %llu\n", part->sector_count); #endif } int32_t EraseDiskByID(uint32_t diskId, size_t startSector, uint32_t sectors) { int32_t ret = OK; #ifdef CONFIG_DRIVERS_MMC los_disk *disk = get_disk((int32_t)diskId); if ((disk != NULL) && (disk->dev != NULL)) { ret = (int32_t)mmcsd_erase(disk->dev, startSector, sectors); } #endif return ret; } #ifdef __cplusplus #if __cplusplus } #endif /* __cplusplus */ #endif /* __cplusplus */