17bb84b457d5658da0c850ed13dff3d212af70771Edward Lin/* 27bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 37bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * Copyright (c) Imagination Technologies Limited, UK 47bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * 57bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * Permission is hereby granted, free of charge, to any person obtaining a 67bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * copy of this software and associated documentation files (the 77bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * "Software"), to deal in the Software without restriction, including 87bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * without limitation the rights to use, copy, modify, merge, publish, 97bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * distribute, sub license, and/or sell copies of the Software, and to 107bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * permit persons to whom the Software is furnished to do so, subject to 117bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * the following conditions: 127bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * 137bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * The above copyright notice and this permission notice (including the 147bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * next paragraph) shall be included in all copies or substantial portions 157bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * of the Software. 167bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * 177bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 187bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 197bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 207bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 217bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 227bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 237bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 247bb84b457d5658da0c850ed13dff3d212af70771Edward Lin */ 257bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 267bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 277bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 287bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 297bb84b457d5658da0c850ed13dff3d212af70771Edward Lin/* 307bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * Authors: 317bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * Shengquan Yuan <shengquan.yuan@intel.com> 327bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * Fei Jiang <fei.jiang@intel.com> 337bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * 347bb84b457d5658da0c850ed13dff3d212af70771Edward Lin */ 357bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 367bb84b457d5658da0c850ed13dff3d212af70771Edward Lin#include <stdio.h> 377bb84b457d5658da0c850ed13dff3d212af70771Edward Lin#define TOPAZ_FW_FILE_NAME_ANDROID "/etc/firmware/topaz_fw.bin" 387bb84b457d5658da0c850ed13dff3d212af70771Edward Lin#define MSVDX_FW_FILE_NAME_ANDROID "/etc/firmware/msvdx_fw.bin" 397bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 407bb84b457d5658da0c850ed13dff3d212af70771Edward Lin#define TOPAZ_FW_FILE_NAME_MEEGO "/lib/firmware/topaz_fw.bin" 417bb84b457d5658da0c850ed13dff3d212af70771Edward Lin#define MSVDX_FW_FILE_NAME_MEEGO "/lib/firmware/msvdx_fw.bin" 427bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 437bb84b457d5658da0c850ed13dff3d212af70771Edward Linstruct topaz_fw_info_item_s { 447bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned short ver; 457bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned short codec; 467bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 477bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned int text_size; 487bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned int data_size; 497bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned int data_location; 507bb84b457d5658da0c850ed13dff3d212af70771Edward Lin}; 517bb84b457d5658da0c850ed13dff3d212af70771Edward Lintypedef struct topaz_fw_info_item_s topaz_fw_info_item_t; 527bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 537bb84b457d5658da0c850ed13dff3d212af70771Edward Linenum topaz_fw_codec_e { 547bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_JPEG = 0, 557bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_H264_NO_RC, 567bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_H264_VBR, 577bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_H264_CBR, 587bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_H264_VCM, 597bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_H263_NO_RC, 607bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_H263_VBR, 617bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_H263_CBR, 627bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_MPEG4_NO_RC, 637bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_MPEG4_VBR, 647bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_MPEG4_CBR, 657bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FW_NUM 667bb84b457d5658da0c850ed13dff3d212af70771Edward Lin}; 677bb84b457d5658da0c850ed13dff3d212af70771Edward Lintypedef enum topaz_fw_codec_e topaz_fw_codec_t; 687bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 697bb84b457d5658da0c850ed13dff3d212af70771Edward Linstruct fw_table_s { 707bb84b457d5658da0c850ed13dff3d212af70771Edward Lin topaz_fw_codec_t index; 717bb84b457d5658da0c850ed13dff3d212af70771Edward Lin topaz_fw_info_item_t header; 7256aac329e1b8460829368fcf4352cad7480d9893SUN,Jing // unsigned int *fw_text; 7356aac329e1b8460829368fcf4352cad7480d9893SUN,Jing // unsigned int *fw_data; 747bb84b457d5658da0c850ed13dff3d212af70771Edward Lin}; 757bb84b457d5658da0c850ed13dff3d212af70771Edward Lintypedef struct fw_table_s fw_table_t; 767bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 777bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 787bb84b457d5658da0c850ed13dff3d212af70771Edward Linstruct msvdx_fw { 797bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned int ver; 807bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned int text_size; 817bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned int data_size; 827bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned int data_location; 837bb84b457d5658da0c850ed13dff3d212af70771Edward Lin}; 847bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 857bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 867bb84b457d5658da0c850ed13dff3d212af70771Edward Linstatic char *codec_to_string(int codec) 877bb84b457d5658da0c850ed13dff3d212af70771Edward Lin{ 887bb84b457d5658da0c850ed13dff3d212af70771Edward Lin switch (codec) { 897bb84b457d5658da0c850ed13dff3d212af70771Edward Lin case FW_H264_NO_RC: 907bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "H264_NO_RC"; 917bb84b457d5658da0c850ed13dff3d212af70771Edward Lin case FW_H264_VBR: 927bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "H264_VBR"; 937bb84b457d5658da0c850ed13dff3d212af70771Edward Lin case FW_H264_CBR: 947bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "H264_CBR"; 957bb84b457d5658da0c850ed13dff3d212af70771Edward Lin case FW_H264_VCM: 967bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "H264_VCM"; 977bb84b457d5658da0c850ed13dff3d212af70771Edward Lin case FW_H263_NO_RC: 987bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "H263_NO_RC"; 997bb84b457d5658da0c850ed13dff3d212af70771Edward Lin case FW_H263_VBR: 1007bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "H263_VBR"; 1017bb84b457d5658da0c850ed13dff3d212af70771Edward Lin case FW_H263_CBR: 1027bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "H263_CBR"; 1037bb84b457d5658da0c850ed13dff3d212af70771Edward Lin case FW_MPEG4_NO_RC: 1047bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "MPEG4_NO_RC"; 1057bb84b457d5658da0c850ed13dff3d212af70771Edward Lin case FW_MPEG4_VBR: 1067bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "MPEG4_VBR"; 1077bb84b457d5658da0c850ed13dff3d212af70771Edward Lin case FW_MPEG4_CBR: 1087bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "MPEG4_CBR"; 1097bb84b457d5658da0c850ed13dff3d212af70771Edward Lin default: 1107bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return "Undefined codec"; 1117bb84b457d5658da0c850ed13dff3d212af70771Edward Lin } 1127bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return ""; 1137bb84b457d5658da0c850ed13dff3d212af70771Edward Lin} 1147bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1157bb84b457d5658da0c850ed13dff3d212af70771Edward Linint main() 1167bb84b457d5658da0c850ed13dff3d212af70771Edward Lin{ 1177bb84b457d5658da0c850ed13dff3d212af70771Edward Lin FILE *fp = NULL; 1187bb84b457d5658da0c850ed13dff3d212af70771Edward Lin topaz_fw_codec_t iter = FW_H264_NO_RC; 1197bb84b457d5658da0c850ed13dff3d212af70771Edward Lin // unsigned int read_data; 1207bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned int i, lseek; 1217bb84b457d5658da0c850ed13dff3d212af70771Edward Lin unsigned char system_id = 0; 1227bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fw_table_t topaz_fw_table[FW_NUM + 1]; 1237bb84b457d5658da0c850ed13dff3d212af70771Edward Lin struct msvdx_fw fw; 1247bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1257bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1267bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /* open file 1277bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * RRRdetermine Android or Meego 1287bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * system_id = 0 Android 1297bb84b457d5658da0c850ed13dff3d212af70771Edward Lin * system_id = 1 Meego 1307bb84b457d5658da0c850ed13dff3d212af70771Edward Lin */ 1317bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fp = fopen(TOPAZ_FW_FILE_NAME_ANDROID, "r"); 1327bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1337bb84b457d5658da0c850ed13dff3d212af70771Edward Lin if (NULL == fp) { 1347bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fp = fopen(TOPAZ_FW_FILE_NAME_MEEGO, "r"); 1357bb84b457d5658da0c850ed13dff3d212af70771Edward Lin if (NULL == fp) { 1367bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("\nSystem isn't Android or Meego\n\n"); 1377bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("\nCan't open topaz_fw.bin\n"); 1387bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return -1; 1397bb84b457d5658da0c850ed13dff3d212af70771Edward Lin } 1407bb84b457d5658da0c850ed13dff3d212af70771Edward Lin system_id = 1; 1417bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("\nSystem is Meego\n\n"); 1427bb84b457d5658da0c850ed13dff3d212af70771Edward Lin } else { 1437bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("\nSystem is Android\n\n"); 1447bb84b457d5658da0c850ed13dff3d212af70771Edward Lin } 1457bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1467bb84b457d5658da0c850ed13dff3d212af70771Edward Lin // fseek (fp, 0, SEEK_SET); 1477bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1487bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("topza:Try to read and print topaz_fw_table...\n\n\n\n"); 1497bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1507bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /* read fw table into the topz_fw_table */ 1517bb84b457d5658da0c850ed13dff3d212af70771Edward Lin while (iter < FW_NUM) { 1527bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1537bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /* read header */ 1547bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fread(&(topaz_fw_table[iter].header), sizeof(topaz_fw_table[iter].header), 1, fp); 1557bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1567bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /* print header */ 1577bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("topaz: index : %s\n", codec_to_string(topaz_fw_table[iter].header.codec)); 1587bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("topaz: ver : 0x%04x\n", topaz_fw_table[iter].header.ver); 1597bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("topaz: Codec : %s\n", codec_to_string(topaz_fw_table[iter].header.codec)); 1607bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("topaz: text_size : %d\n", (topaz_fw_table[iter].header.text_size >> 2)); 1617bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("topaz: data_size : %d\n", (topaz_fw_table[iter].header.data_size >> 2)); 1627bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("topaz: data_location : 0x%08x\n\n", topaz_fw_table[iter].header.data_location); 1637bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1647bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fseek(fp, topaz_fw_table[iter].header.text_size + topaz_fw_table[iter].header.data_size, SEEK_CUR); 1657bb84b457d5658da0c850ed13dff3d212af70771Edward Lin#if 0 1667bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /* read and print fw_text */ 1677bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("fw_text = {\n"); 1687bb84b457d5658da0c850ed13dff3d212af70771Edward Lin for (i = 0; i < (topaz_fw_table[iter].header.text_size >> 2); i++) { 1697bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fread(&read_data, 1, 4, fp); 1707bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf(" 0x%08x\n", read_data); 1717bb84b457d5658da0c850ed13dff3d212af70771Edward Lin } 1727bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf(" }\n\n\n\n"); 1737bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1747bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /* read and print fw_data */ 1757bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("fw_data = {\n"); 1767bb84b457d5658da0c850ed13dff3d212af70771Edward Lin for (i = 0; i < (topaz_fw_table[iter].header.data_size >> 2); i++) { 1777bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fread(&read_data, 1, 4, fp); 1787bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf(" 0x%08x\n", read_data); 1797bb84b457d5658da0c850ed13dff3d212af70771Edward Lin } 1807bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf(" }\n\n\n\n"); 1817bb84b457d5658da0c850ed13dff3d212af70771Edward Lin#endif 1827bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1837bb84b457d5658da0c850ed13dff3d212af70771Edward Lin ++iter; 1847bb84b457d5658da0c850ed13dff3d212af70771Edward Lin } 1857bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1867bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /* close topaz_fw.bin file */ 1877bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fclose(fp); 1887bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1897bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("\n\n\n\nmsvdx:Try to read and print msvdx_fw...\n\n\n\n"); 1907bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 1917bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /* open msvdx_fw.bin */ 1927bb84b457d5658da0c850ed13dff3d212af70771Edward Lin if (system_id == 0) { 1937bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fp = fopen(MSVDX_FW_FILE_NAME_ANDROID, "r"); 1947bb84b457d5658da0c850ed13dff3d212af70771Edward Lin } else { 1957bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fp = fopen(MSVDX_FW_FILE_NAME_MEEGO, "r"); 1967bb84b457d5658da0c850ed13dff3d212af70771Edward Lin } 1977bb84b457d5658da0c850ed13dff3d212af70771Edward Lin if (NULL == fp) { 1987bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("Can't open msvdx_fw.bin\n"); 1997bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return -1; 2007bb84b457d5658da0c850ed13dff3d212af70771Edward Lin } 2017bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 2027bb84b457d5658da0c850ed13dff3d212af70771Edward Lin // fseek (fp, 0, SEEK_SET); 2037bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 2047bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /*read and print fw*/ 2057bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fread(&fw, sizeof(fw), 1, fp); 2067bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 2077bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("msvdx slice switch firmware: ver : 0x%04x\n", fw.ver); 2087bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("msvdx slice switch firmware: text_size : %d\n", fw.text_size); 2097bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("msvdx slice switch firmware: data_size : %d\n", fw.data_size); 2107bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("msvdx slice switch firmware: data_location : 0x%08x\n\n", fw.data_location); 2117bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 2127bb84b457d5658da0c850ed13dff3d212af70771Edward Lin lseek = ((sizeof(fw) + (fw.text_size + fw.data_size) * 4 + 0xfff) & ~0xfff); 2137bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fseek(fp, lseek, SEEK_SET); 2147bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 2157bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /*read and print fw*/ 2167bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fread(&fw, sizeof(fw), 1, fp); 2177bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 2187bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("msvdx frame switch firmware: ver : 0x%04x\n", fw.ver); 2197bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("msvdx frame switch firmware: text_size : %d\n", fw.text_size); 2207bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("msvdx frame switch firmware: data_size : %d\n", fw.data_size); 2217bb84b457d5658da0c850ed13dff3d212af70771Edward Lin printf("msvdx frame switch firmware: data_location : 0x%08x\n\n", fw.data_location); 2227bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 2237bb84b457d5658da0c850ed13dff3d212af70771Edward Lin /* close msvdx_fw.bin file */ 2247bb84b457d5658da0c850ed13dff3d212af70771Edward Lin fclose(fp); 2257bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 2267bb84b457d5658da0c850ed13dff3d212af70771Edward Lin return 0; 2277bb84b457d5658da0c850ed13dff3d212af70771Edward Lin} 2287bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 2297bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 2307bb84b457d5658da0c850ed13dff3d212af70771Edward Lin 231