tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / disk / part_uefi.c
1
2 //uefi patition can see http://en.wikipedia.org/wiki/GUID_Partition_Table for more information
3 #include <config.h>
4 #include <common.h>
5 #include "part_efi.h"
6 #include "part_uefi.h"
7 #include "part_cfg.h"
8 #include "diskconfig.h"
9
10
11 //big end and little end will different
12
13 //#define WORDS_BIGENDIAN
14
15 /**
16  *
17  *      swap function
18  *
19 **/
20 #define _GET_BYTE(x, n)         ( ((x) >> (8 * (n))) & 0xff )
21
22 #define _PED_SWAP16(x)          ( (_GET_BYTE(x, 0) << 8)        \
23                                 + (_GET_BYTE(x, 1) << 0) )
24
25 #define _PED_SWAP32(x)          ( (_GET_BYTE(x, 0) << 24)       \
26                                 + (_GET_BYTE(x, 1) << 16)       \
27                                 + (_GET_BYTE(x, 2) << 8)        \
28                                 + (_GET_BYTE(x, 3) << 0) )
29
30 #define _PED_SWAP64(x)          ( (_GET_BYTE(x, 0) << 56)       \
31                                 + (_GET_BYTE(x, 1) << 48)       \
32                                 + (_GET_BYTE(x, 2) << 40)       \
33                                 + (_GET_BYTE(x, 3) << 32)       \
34                                 + (_GET_BYTE(x, 4) << 24)       \
35                                 + (_GET_BYTE(x, 5) << 16)       \
36                                 + (_GET_BYTE(x, 6) << 8)        \
37                                 + (_GET_BYTE(x, 7) << 0) )
38
39 #define PED_SWAP16(x)           ((unsigned short int) _PED_SWAP16( (unsigned short int) (x) ))
40 #define PED_SWAP32(x)           ((unsigned long int) _PED_SWAP32( (unsigned long int) (x) ))
41 #define PED_SWAP64(x)           ((unsigned long long int) _PED_SWAP64( (unsigned long long int) (x) ))
42
43 /**
44  *
45  *      big endian or not
46  *
47 **/
48 #ifdef WORDS_BIGENDIAN
49
50 #define PED_CPU_TO_LE16(x)      PED_SWAP16(x)
51 #define PED_CPU_TO_BE16(x)      (x)
52 #define PED_CPU_TO_LE32(x)      PED_SWAP32(x)
53 #define PED_CPU_TO_BE32(x)      (x)
54 #define PED_CPU_TO_LE64(x)      PED_SWAP64(x)
55 #define PED_CPU_TO_BE64(x)      (x)
56
57 #define PED_LE16_TO_CPU(x)      PED_SWAP16(x)
58 #define PED_BE16_TO_CPU(x)      (x)
59 #define PED_LE32_TO_CPU(x)      PED_SWAP32(x)
60 #define PED_BE32_TO_CPU(x)      (x)
61 #define PED_LE64_TO_CPU(x)      PED_SWAP64(x)
62 #define PED_BE64_TO_CPU(x)      (x)
63
64 #else /* !WORDS_BIGENDIAN */
65
66 #define PED_CPU_TO_LE16(x)      (x)
67 #define PED_CPU_TO_BE16(x)      PED_SWAP16(x)
68 #define PED_CPU_TO_LE32(x)      (x)
69 #define PED_CPU_TO_BE32(x)      PED_SWAP32(x)
70 #define PED_CPU_TO_LE64(x)      (x)
71 #define PED_CPU_TO_BE64(x)      PED_SWAP64(x)
72
73 #define PED_LE16_TO_CPU(x)      (x)
74 #define PED_BE16_TO_CPU(x)      PED_SWAP16(x)
75 #define PED_LE32_TO_CPU(x)      (x)
76 #define PED_BE32_TO_CPU(x)      PED_SWAP32(x)
77 #define PED_LE64_TO_CPU(x)      (x)
78 #define PED_BE64_TO_CPU(x)      PED_SWAP64(x)
79
80 #endif /* !WORDS_BIGENDIAN */
81
82 typedef struct _gpt_entry_block
83 {
84         gpt_entry _gpt_entry[MAX_PARTITION_INFO];
85 } __attribute__ ((packed)) gpt_entry_block;
86
87 gpt_entry_block g_gpt_entry_block = {0};
88
89
90 typedef struct _align_pmbr
91 {
92         unsigned char dummy[2];
93         legacy_mbr pmbr;
94 } __attribute__ ((packed)) align_pmbr;
95
96
97 align_pmbr pmbr __attribute__ ((aligned(4))) = {0};
98 gpt_header gpt_head __attribute__ ((aligned(4))) = {0};
99
100 static unsigned long long int _cur_lba_num = 0; 
101 static unsigned long long int all_used_size = 0;
102
103 /* Convert char[2] in little endian format to the host format integer
104  */
105 static inline unsigned short le16_to_int(unsigned char *le16)
106 {
107         return ((le16[1] << 8) + le16[0]);
108 }
109
110 /* Convert char[4] in little endian format to the host format integer
111  */
112 static inline unsigned long le32_to_int(unsigned char *le32)
113 {
114         return ((le32[3] << 24) + (le32[2] << 16) + (le32[1] << 8) + le32[0]);
115 }
116
117 /* Convert char[8] in little endian format to the host format integer
118  */
119 static inline unsigned long long le64_to_int(unsigned char *le64)
120 {
121         return (((unsigned long long)le64[7] << 56) +
122                 ((unsigned long long)le64[6] << 48) +
123                 ((unsigned long long)le64[5] << 40) +
124                 ((unsigned long long)le64[4] << 32) +
125                 ((unsigned long long)le64[3] << 24) +
126                 ((unsigned long long)le64[2] << 16) +
127                 ((unsigned long long)le64[1] << 8) +
128                 (unsigned long long)le64[0]);
129 }
130 /**
131  *
132  *      CRC32
133  *
134 **/
135 static inline unsigned long uefi_crc32(const void *buf, unsigned long len)
136 {
137         return crc32(0, buf, len);
138 }
139
140
141 /**
142  *
143  *      some internal function for partition
144  *
145 **/
146 int _gen_pmbr_part(struct partition *part)
147 {
148         part->boot_ind = 0x80;
149         part->sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
150         part->sector = 1;
151         part->end_head = 0xFF;
152         part->end_sector = 0xFF;
153         part->end_cyl = 0xFF;
154
155         *(unsigned long int*) part->start_sect = PED_CPU_TO_LE32(1UL);
156
157         //must get device sector number
158         if ( emmc_part_device.total_sector > 0xFFFFFFF)
159         {
160                 *(unsigned long int*) part->nr_sects = PED_CPU_TO_LE32(0xFFFFFFE);
161         }
162         else
163         {
164                 *(unsigned long int*) part->nr_sects = PED_CPU_TO_LE32(emmc_part_device.total_sector);          
165         }
166        return 1;
167 }
168
169 int _gen_pmbr(legacy_mbr *pmbr)
170 {       
171         memset(pmbr->partition_record, 0, sizeof(pmbr->partition_record));
172         
173         *(unsigned short int*)pmbr->signature = PED_CPU_TO_LE16(MSDOS_MBR_SIGNATURE);
174         _gen_pmbr_part(&pmbr->partition_record[0]);
175
176         return 1;
177 }
178
179
180 unsigned int _write_pmbr(legacy_mbr *pmbr)
181 {
182         //write ro disk
183         emmc_part_device._device_io->_write(0,1,(unsigned char *)pmbr);
184        return 1;
185 }
186
187 efi_guid_t _gen_guid(int part_index)
188 {
189         efi_guid_t new_guid = EFI_GUID(0x11111111,0x2222,0x3333,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0+part_index);
190         return new_guid;
191 }
192
193 unsigned int _gen_gpt_entry(int part_index , gpt_entry *g_entry,PARTITION_CFG *p_partition_cfg)
194 {
195         int i = 0;
196
197         //maybe
198         if( PARTITION_RAW == p_partition_cfg[part_index].partition_attr)
199                 g_entry->partition_type_guid = PARTITION_BASIC_DATA_GUID;
200         else if( PARTITION_EXT4 == p_partition_cfg[part_index].partition_attr)
201                 g_entry->partition_type_guid = PARTITION_BASIC_DATA_GUID;
202         else
203                 g_entry->partition_type_guid = PARTITION_BASIC_DATA_GUID;
204         
205         //gen guid
206         g_entry->unique_partition_guid =_gen_guid(part_index+1) ;
207         
208         *(unsigned long long int*)g_entry->starting_lba = _cur_lba_num;
209         
210         //judge if user data partition
211         if( MAX_SIZE_FLAG == p_partition_cfg[part_index].partition_size)
212         {
213                 _cur_lba_num = _cur_lba_num + (emmc_part_device.total_sector-STARTING_LBA_OF_FIRST_PARTITION-MAX_PARTITION_INFO/4-1-all_used_size*2);
214                 _cur_lba_num = (_cur_lba_num/STARTING_LBA_OF_FIRST_PARTITION)*STARTING_LBA_OF_FIRST_PARTITION;
215                 *(unsigned long long int*)g_entry->ending_lba = _cur_lba_num-1;
216         }else
217         {
218                 _cur_lba_num = _cur_lba_num + p_partition_cfg[part_index].partition_size * 2;
219                 *(unsigned long long int*)g_entry->ending_lba = _cur_lba_num - 1;
220         }
221
222         memset (&g_entry->attributes, 0, sizeof (gpt_entry_attributes));
223
224         for (i = 0; i < MAX_UTF_PARTITION_NAME_LEN; i++)
225                         g_entry->partition_name[i] = (efi_char16_t) PED_CPU_TO_LE16 (p_partition_cfg[part_index].partition_name[i]);
226
227         return 1;
228 }
229
230 unsigned int _parser_cfg(unsigned int *total_partition,PARTITION_CFG *p_partition_cfg)
231 {
232         int count = 0;
233         for(count=0;count<MAX_PARTITION_INFO;count++)
234         {
235                 if(0 == p_partition_cfg[count].partition_size)
236                 {
237                         *total_partition = count;
238                         break;
239                 } else
240                 {
241                         if( MAX_SIZE_FLAG !=  p_partition_cfg[count].partition_size)
242                                 all_used_size += p_partition_cfg[count].partition_size;         
243                 }
244         }
245         return 1;
246 }
247
248 unsigned int _gen_gpt(gpt_header *g_header,PARTITION_CFG *p_partition_cfg)
249 {
250         printf("write gpt header \n");
251         int i = 0 ,gpt_partition_number = 0;
252         unsigned long crc = 0;
253         _parser_cfg(&gpt_partition_number,p_partition_cfg);
254         
255         *(unsigned long long int*)g_header->signature = PED_CPU_TO_LE64 (GPT_HEADER_SIGNATURE);
256
257         *(unsigned long int*)g_header->revision = PED_CPU_TO_LE32 (GPT_HEADER_REVISION_V1);
258
259         *(unsigned long int*)g_header->header_size = PED_CPU_TO_LE32(92UL);
260         
261         *(unsigned long int*)g_header->reserved1 = PED_CPU_TO_LE32(0);
262
263         *(unsigned long long int*)g_header->my_lba = PED_CPU_TO_LE64 (1);
264
265         *(unsigned long long int*)g_header->alternate_lba = PED_CPU_TO_LE64 (emmc_part_device.total_sector-1);
266         
267         *(unsigned long long int*)g_header->first_usable_lba = PED_CPU_TO_LE64 (MAX_PARTITION_INFO/4 + 2);
268         
269         *(unsigned long long int*)g_header->last_usable_lba = PED_CPU_TO_LE64 (emmc_part_device.total_sector-2-MAX_PARTITION_INFO/4);
270
271         g_header->disk_guid = _gen_guid(0);
272
273         *(unsigned long long int*)g_header->partition_entry_lba = PED_CPU_TO_LE64 (2);  
274         
275         *(unsigned long int*)g_header->num_partition_entries = PED_CPU_TO_LE32(gpt_partition_number);
276
277         *(unsigned long int*)g_header->sizeof_partition_entry = PED_CPU_TO_LE32(sizeof(gpt_entry));
278         
279         memset(g_header->reserved2,0,GPT_BLOCK_SIZE - 92);      
280
281         //_cur_lba_num = MAX_PARTITION_INFO/4 + 2;
282         _cur_lba_num = STARTING_LBA_OF_FIRST_PARTITION;
283
284         printf("write gpt partition \n");
285         for(i=0;i<gpt_partition_number;i++)
286         {
287                 _gen_gpt_entry(i,&g_gpt_entry_block._gpt_entry[i],p_partition_cfg);
288         }
289
290         //*(unsigned long int*)g_header->partition_entry_array_crc32 = ;
291         crc = uefi_crc32(&g_gpt_entry_block,(le32_to_int(g_header->num_partition_entries)) *(le32_to_int( g_header->sizeof_partition_entry)));
292         *(unsigned long int*)g_header->partition_entry_array_crc32 = PED_CPU_TO_LE32(crc);
293
294         //CRC32 check
295         crc = uefi_crc32(g_header,le32_to_int(g_header->header_size));
296         *(unsigned long int*)g_header->header_crc32 = PED_CPU_TO_LE32(crc);
297
298         return 1;
299 }
300
301 unsigned int _gen_backup_gpt(gpt_header *g_header,PARTITION_CFG *p_partition_cfg)
302 {
303         unsigned long crc = 0;
304         *(unsigned long long int*)g_header->my_lba = PED_CPU_TO_LE64 (emmc_part_device.total_sector-1);
305         *(unsigned long long int*)g_header->alternate_lba = PED_CPU_TO_LE64 (1);
306         *(unsigned long long int*)g_header->partition_entry_lba = PED_CPU_TO_LE64 (emmc_part_device.total_sector-1-MAX_PARTITION_INFO/4);
307         *(unsigned long int*)g_header->header_crc32 = 0;
308         crc = uefi_crc32(g_header,le32_to_int(g_header->header_size));
309         *(unsigned long int*)g_header->header_crc32 = PED_CPU_TO_LE32(crc);
310        return 1;
311 }
312
313 unsigned int _write_gpt(gpt_header *g_header)
314 {
315         //write gpt entry
316         emmc_part_device._device_io->_write(1,1,(unsigned char*)g_header);
317         //write gpt header
318         emmc_part_device._device_io->_write(2,MAX_PARTITION_INFO/4,(unsigned char*)&g_gpt_entry_block);
319
320         printf("write gpt entry success \n");
321         return 1;
322 }
323
324 unsigned int _write_backup_gpt(gpt_header *g_header)
325 {
326         //write gpt entry
327         emmc_part_device._device_io->_write((emmc_part_device.total_sector-1),1,(unsigned char*)g_header);
328         //write gpt header
329         emmc_part_device._device_io->_write((emmc_part_device.total_sector-1-MAX_PARTITION_INFO/4),MAX_PARTITION_INFO/4,(unsigned char*)&g_gpt_entry_block);
330         printf("write gpt entry success \n");
331         return 1;
332 }
333
334 /**
335  *
336  *      UEFI partition interface
337  *
338 **/
339 int ueft_mount()
340 {
341        return 1;
342 }
343
344 int ueft_unmount()
345 {
346         return 1;
347 }
348
349 unsigned int read_uefi_partition_table(PARTITION_TABLE *p_partition_table)
350 {
351         return 1;
352 }
353
354 #ifdef CONFIG_EBR_PARTITION
355 int write_mbr_partition_table(void)
356 {
357         printf("write mbr partition \n");
358         emmc_part_device_init();
359         //write pmbr
360         struct disk_info *device_disk_info;
361         if (!(device_disk_info = load_diskconfig())) {
362                 printf("Errors encountered while loading disk  partation\n");
363                 return 1;
364                 }
365        /* First, partition the drive */
366         if (apply_disk_config(device_disk_info))
367                 printf("write partition list success\n");
368
369         return 1;
370 }
371 #endif
372
373 unsigned int write_uefi_partition_table(PARTITION_CFG *p_partition_cfg)
374 {
375         //mount devices
376         all_used_size = 0;
377         memset(&gpt_head, 0x0, GPT_BLOCK_SIZE);
378         emmc_part_device_init();
379
380         printf("write gpt \n");
381         //write pmbr
382         _gen_pmbr(&pmbr.pmbr);
383         _write_pmbr(&pmbr.pmbr);
384
385         if( NULL == p_partition_cfg )
386         {
387                 return 0;  
388         }
389         //write gpt
390         _gen_gpt(&gpt_head,p_partition_cfg);
391         _write_gpt(&gpt_head);
392
393         //backup
394         _gen_backup_gpt(&gpt_head,p_partition_cfg);
395         _write_backup_gpt(&gpt_head);
396         printf("write gpt success\n");
397         return 1;
398 }
399
400 unsigned int get_uefi_partition_info(int partition_index,PARTITION_INFO *p_partition_info)
401 {
402         return 1;
403 }
404
405 /**
406  *
407  *      UEFI partition test unit
408  *
409 **/
410 unsigned int uefi_unit_test(int test_case)
411 {
412         int ret = 0;
413         switch(test_case)
414         {
415         case 1: //write partition test
416                 break;
417         case 2: //read partition test call part_efi.c function
418                 break;  
419         default:
420                 ;//first write partition than read partition.
421         }
422         return ret;  
423 }