1 /* 2 * (C) Copyright 2021 rkparm Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <malloc.h> 9 #include <asm/arch/rk_atags.h> 10 11 struct rkram_part { 12 char name[PART_NAME_LEN]; 13 ulong start; 14 ulong size; 15 struct list_head node; 16 }; 17 18 static LIST_HEAD(parts_head); 19 20 static int rkram_part_init(struct blk_desc *dev_desc, 21 struct list_head *parts_head) 22 { 23 struct rkram_part *part; 24 struct tag *t; 25 int i, len; 26 u64 start; 27 u64 size; 28 29 if (!atags_is_available()) { 30 debug("%s: No ATAGS\n", __func__); 31 return -ENODATA; 32 } 33 34 t = atags_get_tag(ATAG_RAM_PARTITION); 35 if (!t) { 36 debug("%s: No ATAGS ramdisk partition\n", __func__); 37 return -ENODATA; 38 } 39 40 INIT_LIST_HEAD(parts_head); 41 42 for (i = 0; i < t->u.ram_part.count; i++) { 43 part = malloc(sizeof(*part)); 44 if (!part) { 45 printf("%s: No memory\n", __func__); 46 break; 47 } 48 49 len = strlen(t->u.ram_part.part[i].name) + 1; 50 memcpy((char *)&part->name, 51 (char *)&t->u.ram_part.part[i].name, len); 52 start = t->u.ram_part.part[i].start; 53 size = t->u.ram_part.part[i].size; 54 55 if (!IS_ALIGNED(start, dev_desc->blksz)) { 56 printf("%s: addr 0x%llx is not %ld align\n", 57 part->name, start, dev_desc->blksz); 58 return -EINVAL; 59 } else if (!IS_ALIGNED(size, dev_desc->blksz)) { 60 printf("%s: size 0x%llx is not %ld align\n", 61 part->name, size, dev_desc->blksz); 62 return -EINVAL; 63 } 64 65 /* bytes to blksz */ 66 part->start = start / dev_desc->blksz; 67 part->size = size / dev_desc->blksz; 68 list_add_tail(&part->node, parts_head); 69 70 debug("%s: name=%s, start=0x%lx, size=0x%lx, blksz=0x%lx\n", 71 __func__, part->name, part->start, 72 part->size, dev_desc->blksz); 73 } 74 75 return 0; 76 } 77 78 static void part_print_rkram_part(struct blk_desc *dev_desc) 79 { 80 struct list_head *node; 81 struct rkram_part *p; 82 int i = 0; 83 84 if (list_empty(&parts_head)) { 85 printf("No Partition Table\n"); 86 return; 87 } 88 89 printf("Part\tStart LBA\tSize\t\tName\n"); 90 list_for_each(node, &parts_head) { 91 p = list_entry(node, struct rkram_part, node); 92 printf("%3d\t0x%08lx\t0x%08lx\t%s\n", (i++ + 1), 93 p->start, p->size, p->name); 94 } 95 } 96 97 static int part_get_info_rkram_part(struct blk_desc *dev_desc, int idx, 98 disk_partition_t *info) 99 { 100 struct rkram_part *p = NULL; 101 struct list_head *node; 102 int part_num = 1; 103 104 if (idx < 1) { 105 printf("Invalid partition no.%d\n", idx); 106 return -EINVAL; 107 } 108 109 if (list_empty(&parts_head)) 110 return -EINVAL; 111 112 list_for_each(node, &parts_head) { 113 p = list_entry(node, struct rkram_part, node); 114 if (idx == part_num) 115 break; 116 part_num++; 117 } 118 119 if (part_num < idx) { 120 debug("%s Invalid partition no.%d\n", __func__, idx); 121 return -EINVAL; 122 } 123 124 info->start = p->start; 125 info->size = p->size; 126 info->blksz = dev_desc->blksz; 127 128 sprintf((char *)info->name, "%s", p->name); 129 strcpy((char *)info->type, "U-Boot"); 130 info->bootable = 0; 131 132 return 0; 133 } 134 135 static int part_test_rkram_part(struct blk_desc *dev_desc) 136 { 137 return rkram_part_init(dev_desc, &parts_head); 138 } 139 140 /* 141 * Add an 'a_a_' prefix so it comes before 'dos' and after 'a_efi' 142 * in the linker list. We need to check this first. 143 */ 144 U_BOOT_PART_TYPE(a_a_rkram_part) = { 145 .name = "RKRAM_PART", 146 .part_type = PART_TYPE_RKRAM, 147 .max_entries = RKRAM_ENTRY_NUMBERS, 148 .get_info = part_get_info_ptr(part_get_info_rkram_part), 149 .print = part_print_ptr(part_print_rkram_part), 150 .test = part_test_rkram_part, 151 }; 152