Files
Linux_Drivers/build/tools/common/emmc_tool/mk_gpt.c
sam.xiang a4f213ceb0 [build] add cvitek build scripts
Change-Id: If63ce4a669e5d4d72b8e3b9253336dd99bf74c30
2023-03-10 20:35:59 +08:00

280 lines
7.4 KiB
C

#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include <getopt.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include "uuid.h"
#include <libxml/parser.h>
#include "crc.h"
#include "mk_gpt.h"
static const char *xml_file = ".";
static const char *update_dev;
static struct legacy_mbr_t mbr;
static struct gpt_header_t pheader;
static struct gpt_entry_t entries[ENTRY_NUM];
static struct gpt_header_t bheader;
static uint32_t current_part;
static uint64_t current_lba;
static void usage(void)
{
printf("Usage:\n");
printf("mk_gpt [options]\n\n"
"options:\n"
" -p, --path xml path\n"
" -d, --dev dev or output file\n"
" -h, --help display this help and exit\n");
exit(EXIT_FAILURE);
}
static void parse_commandline(int argc, char **argv)
{
int c;
static struct option long_options[] = {
{"path", 1, 0, 'p'},
{"dev", 1, 0, 'd'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
while (1) {
c = getopt_long(argc, argv, "p:d:h", long_options, NULL);
if (c == -1)
break;
switch (c) {
case 'p':
xml_file = optarg;
break;
case 'd':
update_dev = optarg;
break;
case 'h':
default:
usage();
}
}
if (update_dev == NULL) {
fprintf(stderr, "sd dev : NULL\n");
usage();
}
}
static void uuid2guid(struct guid_t *guid, uuid_t uuid)
{
guid->time_low = (((uint32_t)uuid[0] & 0xFF) << 24) |
(((uint32_t)uuid[1] & 0xFF) << 16) |
(((uint32_t)uuid[2] & 0xFF) << 8) |
(((uint32_t)uuid[3] & 0xFF) << 0);
guid->time_mid = (((uint16_t)uuid[4] & 0xFF) << 8) |
(((uint16_t)uuid[5] & 0xFF) << 0);
guid->time_hi_and_version = (((uint16_t)uuid[6] & 0xFF) << 8) |
(((uint16_t)uuid[7] & 0xFF) << 0);
guid->clock_seq_hi_and_reserved = (uint8_t)uuid[8];
guid->clock_seq_low = (uint8_t)uuid[9];
memcpy(guid->node, &uuid[10], 6);
}
static void init_gpt(uint64_t total_size)
{
uint64_t sector = total_size / LBA_SIZE;
uuid_t uuid;
memset(&mbr, 0, sizeof(mbr));
memset(&pheader, 0, sizeof(pheader));
memset(&entries, 0, sizeof(entries));
memset(&pheader, 0, sizeof(pheader));
mbr.signature = MBR_SIGNATURE;
mbr.part_record[0].os_type = MBR_OSTYPE_EFI;
mbr.part_record[0].start_sector = 1;
mbr.part_record[0].end_head = 0xFE;
mbr.part_record[0].end_sector = 0xFF;
mbr.part_record[0].end_track = 0xFF;
mbr.part_record[0].starting_lba = 1;
if (sector > 0xFFFFFFFF)
mbr.part_record[0].size_in_lba = 0xFFFFFFFF;
else
mbr.part_record[0].size_in_lba = sector - 1;
pheader.signature = GPT_HEADER_SIGNATURE;
bheader.signature = GPT_HEADER_SIGNATURE;
pheader.revision = GPT_REVISION;
bheader.revision = GPT_REVISION;
pheader.header_size = GPT_HEADER_SIZE;
bheader.header_size = GPT_HEADER_SIZE;
pheader.my_lba = 1;
bheader.my_lba = sector - 1;
pheader.alternate_lba = sector - 1;
bheader.alternate_lba = 1;
pheader.part_entry_lba = 2;
bheader.part_entry_lba = sector - (ENTRY_LBA + 1);
pheader.first_usable_lba = 2 + ENTRY_LBA;
bheader.first_usable_lba = 2 + ENTRY_LBA;
pheader.last_usable_lba = sector - (ENTRY_LBA + 2);
bheader.last_usable_lba = sector - (ENTRY_LBA + 2);
uuid_generate(uuid);
uuid2guid(&pheader.disk_guid, uuid);
uuid2guid(&bheader.disk_guid, uuid);
pheader.number_of_entries = ENTRY_NUM;
bheader.number_of_entries = ENTRY_NUM;
pheader.size_of_entry = ENTRY_SIZE;
bheader.size_of_entry = ENTRY_SIZE;
current_part = 0;
current_lba = 8192;
}
static void write_partition(int fd, xmlNodePtr xml_node)
{
//PARTITION_BASIC_DATA_GUID
const struct guid_t type = { 0xEBD0A0A2, 0xB9E5, 0x4433, 0x87, 0xC0,
{ 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 } };
xmlChar *prop = NULL;
uint64_t size = 0;
int sparse = 0;
int readonly = 0;
uint64_t start = current_lba;
uint64_t end;
uuid_t uuid;
int i;
prop = xmlGetProp(xml_node, BAD_CAST"size_in_kb");
if (prop != NULL) {
size = (uint64_t)atoll((char *)prop) * 1024;
xmlFree(prop);
}
prop = xmlGetProp(xml_node, BAD_CAST"readonly");
if (prop != NULL) {
if (strcmp("true", (char *)prop) == 0)
readonly = 1;
else if (strcmp("false", (char *)prop) == 0)
readonly = 0;
else
printf("readonly attribute error, use default 0\n");
xmlFree(prop);
}
end = start + ((size + LBA_SIZE - 1) / LBA_SIZE) - 1;
memcpy(&entries[current_part].part_type_guid, &type, 16);
uuid_generate(uuid);
uuid2guid(&entries[current_part].unique_part_guid, uuid);
entries[current_part].starting_lba = start;
entries[current_part].ending_lba = end;
if (readonly) {
entries[current_part].attributes = (uint64_t)1 << 60;
}
prop = xmlGetProp(xml_node, BAD_CAST"label");
if (prop != NULL) {
for (i = 0; i < (ENTRY_SIZE - 56) / 2; i++) {
entries[current_part].part_name[i] = (uint16_t)prop[i];
if (entries[current_part].part_name[i] == 0)
break;
}
xmlFree(prop);
}
current_part++;
current_lba = end + 1;
}
static void save_gpt(int fd)
{
uint32_t crc = crc32(0xFFFFFFFF, (uint8_t *)&entries,
ENTRY_NUM * ENTRY_SIZE);
crc ^= 0xFFFFFFFF;
pheader.entry_array_crc32 = crc;
bheader.entry_array_crc32 = crc;
pheader.header_crc32 = 0;
crc = crc32(0xFFFFFFFF, (uint8_t *)&pheader, GPT_HEADER_SIZE);
crc ^= 0xFFFFFFFF;
pheader.header_crc32 = crc;
bheader.header_crc32 = 0;
crc = crc32(0xFFFFFFFF, (uint8_t *)&bheader, GPT_HEADER_SIZE);
crc ^= 0xFFFFFFFF;
bheader.header_crc32 = crc;
lseek64(fd, 0, SEEK_SET);
write(fd, &mbr, sizeof(mbr));
lseek64(fd, pheader.my_lba * LBA_SIZE, SEEK_SET);
write(fd, &pheader, sizeof(pheader));
lseek64(fd, pheader.part_entry_lba * LBA_SIZE, SEEK_SET);
write(fd, &entries, sizeof(entries));
#if 0
lseek64(fd, bheader.my_lba * LBA_SIZE, SEEK_SET);
write(fd, &bheader, sizeof(bheader));
lseek64(fd, bheader.part_entry_lba * LBA_SIZE, SEEK_SET);
write(fd, &entries, sizeof(entries));
#endif
}
int main(int argc, char **argv)
{
int ret = 0;
int fd = -1;
uint64_t size = 0;
xmlDocPtr xml_doc = NULL;
xmlNodePtr xml_node = NULL;
xmlChar *prop = NULL;
char file_name[PATH_MAX];
parse_commandline(argc, argv);
printf("xml_file : %s\n", xml_file);
printf("update_dev : %s\n", update_dev);
fd = open(update_dev, O_CREAT | O_TRUNC | O_RDWR | O_LARGEFILE, 0666);
if (fd < 0) {
fprintf(stderr, "open %s error\n", update_dev);
goto RETURN;
}
snprintf(file_name, PATH_MAX, "%s", xml_file);
xml_doc = xmlReadFile(file_name, "UTF-8", XML_PARSE_RECOVER);
if (xml_doc == NULL) {
fprintf(stderr, "xmlReadFile %s error\n", file_name);
goto RETURN;
}
xml_node = xmlDocGetRootElement(xml_doc);
while (xml_node != NULL) {
if (xml_node->type == XML_ELEMENT_NODE)
if (strcmp("physical_partition",
(char *)xml_node->name) == 0) {
prop = xmlGetProp(xml_node, BAD_CAST"size_in_kb");
if (prop != NULL) {
size = (uint64_t)atoll((char *)prop) * 1024;
printf("[hq] total size:%ld\n", size);
xmlFree(prop);
}
break;
}
xml_node = xml_node->next;
}
if (!xml_node) {
fprintf(stderr, "find physical_partition failed\n");
goto RETURN;
}
init_gpt(size);
if (xml_node == NULL) {
fprintf(stderr, "find physical_partition error\n");
goto RETURN;
}
xml_node = xml_node->xmlChildrenNode;
while (xml_node != NULL) {
if (xml_node->type == XML_ELEMENT_NODE) {
if (strcmp("partition", (char *)xml_node->name) == 0)
write_partition(fd, xml_node);
else
printf("unknown node %s\n", xml_node->name);
}
xml_node = xml_node->next;
}
save_gpt(fd);
RETURN:
if (xml_doc != NULL)
xmlFreeDoc(xml_doc);
if (fd >= 0)
close(fd);
return ret;
}