Files
luban-lite-t3e-pro/bsp/artinchip/drv/spinand/spinand_parts.c
刘可亮 803cac77d5 V1.0.6
2024-09-03 11:16:08 +08:00

267 lines
5.1 KiB
C

/*
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: xuan.wen <xuan.wen@artinchip.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "spinand_parts.h"
static struct nftl_volume *nftl_new_volume(char *s)
{
struct nftl_volume *vol = NULL;
int cnt = 0;
char *p;
vol = malloc(sizeof(struct nftl_volume));
if (!vol)
return NULL;
memset(vol, 0, sizeof(struct nftl_volume));
p = s;
if (*p == '-') {
/* All remain space */
vol->size = 0;
p++;
} else {
vol->size = strtoull(p, &p, 0);
}
if (*p == '@') {
p++;
/* Don't care offset here, just skip it */
strtoull(p, &p, 0);
}
if (*p != '(') {
printf("Volume name should be next of size.\n");
goto err;
}
p++;
cnt = 0;
while (*p != ')') {
if (cnt >= MAX_NAND_NAME)
break;
vol->name[cnt++] = *p++;
}
p++;
vol->vol_type = 1; /* Default is dynamic */
if (*p == 's')
vol->vol_type = 0; /* Static volume */
/* Skip characters until '\0', ',', ';' */
while ((*p != '\0') && (*p != ';') && (*p != ','))
p++;
if (*p == ',') {
p++;
vol->next = nftl_new_volume(p);
}
return vol;
err:
if (vol)
free(vol);
return NULL;
}
static void nftl_free_volume(struct nftl_volume *vol)
{
if (!vol)
return;
nftl_free_volume(vol->next);
free(vol);
}
void free_nftl_list(struct nftl_mtd *nftl)
{
if (!nftl)
return;
free_nftl_list(nftl->next);
nftl_free_volume(nftl->vols);
free(nftl);
}
struct nftl_mtd *build_nftl_list(char *nftlvols)
{
struct nftl_mtd *head, *cur, *nxt;
char *p;
int cnt;
head = NULL;
cur = NULL;
p = nftlvols;
next:
nxt = malloc(sizeof(struct nftl_mtd));
if (!nxt)
goto err;
memset(nxt, 0, sizeof(struct nftl_mtd));
if (cur)
cur->next = nxt;
cur = nxt;
if (!head)
head = cur;
cnt = 0;
while (*p != '\0' && *p != ':') {
if (cnt >= MAX_NAND_NAME)
break;
cur->name[cnt++] = *p++;
}
if (*p != ':') {
printf("nftlvols_nand is invalid\n");
goto err;
}
p++;
cur->vols = nftl_new_volume(p);
if (!cur->vols) {
printf("Build nftl volume list failed.\n");
goto err;
}
/* Check if there is other nftl device */
while (*p != '\0' && *p != ';')
p++;
if (*p == ';') {
p++;
goto next;
}
return head;
err:
if (head)
free_nftl_list(head);
return NULL;
}
uint8_t partition_nftl_is_exist(char *mtd_name, struct nftl_mtd *nftl_list)
{
if (nftl_list == NULL) {
return 0;
}
struct nftl_mtd *current_list;
current_list = nftl_list;
while (current_list) {
if (strcmp(mtd_name, current_list->name) == 0)
return 1;
current_list = current_list->next;
}
return 0;
}
static struct mtd_partition *_part_parse(char *parts, uint32_t start)
{
struct mtd_partition *part;
int cnt = 0;
char *p;
part = malloc(sizeof(struct mtd_partition));
if (!part)
return NULL;
memset(part, 0, sizeof(struct mtd_partition));
part->start = start;
p = parts;
if (*p == '-') {
/* All remain space */
part->size = 0;
p++;
} else {
part->size = strtoul(p, &p, 0);
if ((*p == 'k') || (*p == 'K')) {
part->size *= 1024;
p++;
} else if ((*p == 'm') || (*p == 'M')) {
part->size *= (1024 * 1024);
p++;
} else if ((*p == 'g') || (*p == 'G')) {
part->size *= (1024 * 1024 * 1024);
p++;
}
}
if (*p == '@') {
p++;
/* Don't care offset here, just skip it */
part->start = strtoul(p, &p, 0);
}
if (*p != '(') {
printf("Partition name should be next of size.\n");
printf("%s\n", p);
goto err;
}
p++;
cnt = 0;
while (*p != ')') {
if (cnt >= MAX_MTD_NAME)
break;
part->name[cnt++] = *p++;
}
p++;
/* Skip characters until '\0', ',', ';' */
while ((*p != '\0') && (*p != ';') && (*p != ','))
p++;
if (*p == ',') {
p++;
part->next = _part_parse(p, part->start + part->size);
}
return part;
err:
if (part)
free(part);
return NULL;
}
struct mtd_partition *mtd_parts_parse(char *parts, uint32_t spi_bus)
{
char *p;
p = parts;
if (spi_bus == 2) {
while (*p != '2')
p++;
} else if (spi_bus == 1) {
while (*p != '1')
p++;
}
while ((*p != '\0') && (*p != ':'))
p++;
if (*p != ':') {
printf("mtdparts is invalid: %s\n", parts);
return NULL;
}
p++;
return _part_parse(p, 0);
}
void mtd_parts_free(struct mtd_partition *head)
{
struct mtd_partition *p, *n;
p = head;
n = p;
while (p) {
n = p->next;
free(p);
p = n;
}
}