From e3912ee3220e6906593b4954b81944468ddb894b Mon Sep 17 00:00:00 2001 From: yoshida_teruhisa Date: Thu, 7 Aug 2008 05:49:41 +0000 Subject: [PATCH] =?UTF-8?q?=E6=AD=A3=E5=BC=8F=E7=89=88FATFS=E3=83=91?= =?UTF-8?q?=E3=83=BC=E3=83=9F=E3=83=83=E3=82=B7=E3=83=A7=E3=83=B3=E3=83=81?= =?UTF-8?q?=E3=82=A7=E3=83=83=E3=82=AF=E3=83=97=E3=83=AD=E3=82=B0=E3=83=A9?= =?UTF-8?q?=E3=83=A0=E3=82=92TestMaker=E3=81=8B=E3=82=89=E7=94=9F=E6=88=90?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=EF=BC=88?= =?UTF-8?q?=E3=82=A2=E3=82=A4=E3=82=B3=E3=83=B3=E4=BB=A5=E5=A4=96=E5=AE=8C?= =?UTF-8?q?=E6=88=90=EF=BC=89=20=E3=80=80=E3=83=BB=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=82=B0=E3=83=A9=E3=83=A0=E3=81=AE=E7=95=AA=E5=8F=B7=E3=81=A8?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C=E3=82=8B=E7=B5=90=E6=9E=9C?= =?UTF-8?q?=E3=81=AF=20docs/=E3=83=87=E3=83=90=E3=83=83=E3=82=B0/=E3=83=91?= =?UTF-8?q?=E3=83=BC=E3=83=9F=E3=83=83=E3=82=B7=E3=83=A7=E3=83=B3=E3=83=81?= =?UTF-8?q?=E3=82=A7=E3=83=83=E3=82=AF=E8=A1=A8.xls=20=E3=81=AB=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C=E3=81=97=E3=81=A6=E3=81=84=E3=81=BE=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@2121 b08762b0-b915-fc4b-9d8c-17b2551a87ff --- .../tests/RomTypeTest/ARM9/src/RomTypeTest.c | 274 ++++++++---------- .../romparam_forFATFSPermissiontest.yaml | Bin 6022 -> 28416 bytes docs/デバッグ/パーミッションチェック表.xls | Bin 0 -> 20992 bytes 3 files changed, 119 insertions(+), 155 deletions(-) create mode 100644 docs/デバッグ/パーミッションチェック表.xls diff --git a/build/tests/RomTypeTest/ARM9/src/RomTypeTest.c b/build/tests/RomTypeTest/ARM9/src/RomTypeTest.c index fd0a2689..0eeedacf 100644 --- a/build/tests/RomTypeTest/ARM9/src/RomTypeTest.c +++ b/build/tests/RomTypeTest/ARM9/src/RomTypeTest.c @@ -43,16 +43,24 @@ #define TEST_NUM 15 +typedef enum AccessPermission { + PERMISSION_NA = 0, + PERMISSION_RO, + PERMISSION_RW, + PERMISSION_ERROR, + PERMISSION_MAX +} +AccessPermission; + // extern data------------------------------------------ // function's prototype declaration--------------------- -static BOOL ROTestCore( char *path, char *testfile ); -static BOOL RWExTestCore( char *path, char *testfile ); -static BOOL SRLTest( void ); -static BOOL ContentTest( void ); +static AccessPermission RWExTestCore( char *path, char *testfile ); +static AccessPermission SRLTest( void ); +static AccessPermission ContentTest( void ); static void FinalizeRWTest( FSFile *file, char* filename ); -static BOOL RWTestCore( char *path, char *testfile ); -static BOOL RWTest( char *path ); +static AccessPermission RWTestCore( char *path, char *testfile ); +static AccessPermission RWTest( char *path ); static void TestFSPermission( void ); // global variable ------------------------------------- @@ -62,32 +70,16 @@ RTCDrawProperty g_rtcDraw = { // static variable ------------------------------------- static BOOL s_quiettest = FALSE; -static char s_testnum = 0; // const data ----------------------------------------- -static const BOOL s_answer_data[][TEST_NUM] = +static AccessPermission s_answer_data[TEST_NUM]; + +static const u16 *s_answer_str[PERMISSION_MAX] = { - { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // 0 - { FALSE, FALSE, FALSE, TRUE, STRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE }, // 1 - { FALSE, FALSE, FALSE, TRUE, STRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE }, // 2 - { TRUE, TRUE, FALSE, TRUE, STRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE }, // 3 - { TRUE, TRUE, FALSE, TRUE, STRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE }, // 4 - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // 5 - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // 6 - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // 7 - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // 8 - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // 9 - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // a - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // b - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // c - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // d - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // e - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // f - { FALSE, FALSE, CTRUE, TRUE, STRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // g - { TRUE, TRUE, CTRUE, TRUE, STRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // h - { TRUE, TRUE, CTRUE, TRUE, STRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // i - { TRUE, TRUE, CTRUE, TRUE, STRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // j - { TRUE, TRUE, CTRUE, TRUE, STRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE } // k + L"NA", + L"RO", + L"RW", + L"~", }; static const u16 *s_test_name[TEST_NUM] = @@ -113,83 +105,31 @@ static const u16 *s_test_name[TEST_NUM] = // eXgvO //====================================================== -static BOOL ROTestCore( char *path, char *testfile ) +static AccessPermission RWExistTestCore( char *path, char *testfile ) { char filename[256]; - char testfilename[256]; int len; char buf[5]; FSFile file[1]; + AccessPermission result = PERMISSION_RW; FS_InitFile( file ); STD_TSNPrintf( filename, 256, "%s/%s", path, testfile ); - STD_TSNPrintf( testfilename, 256, "%s/test.txt", path ); -/* - if ( FS_CreateFile(testfilename, FS_PERMIT_R | FS_PERMIT_W) ) - { - // ReadOnlyȂ̂ŁAt@C쐬炾 - if( !s_quiettest ) OS_TPrintf("%s:File Create succeed. (ReadOnly) \n",testfilename); - FS_DeleteFile( testfilename ); - //return FALSE; - } -*/ - - // t@CI[v - if ( FS_OpenFileEx( file, filename, FS_FILEMODE_RWL ) ) - { - // ReadOnlyȂ̂ŁAWritẽt@CI[v炾 - if( !s_quiettest ) OS_TPrintf("%s:Write mode open succeed. (ReadOnly) \n",filename); - FS_CloseFile( file ); - return FALSE; - } - - // t@CI[v - if ( !FS_OpenFileEx( file, filename, FS_FILEMODE_R ) ) - { - // t@CI[vs - if( !s_quiettest ) OS_TPrintf("%s:open failed.\n",filename); - return FALSE; - } - // t@C[h - len = FS_ReadFile( file, buf, 3 ); - if( len != 3 ) - { - // [hs - if( !s_quiettest ) OS_TPrintf("%s:read failed.\n",filename); - FS_CloseFile( file ); - return FALSE; - } - // t@CN[Y - if( !FS_CloseFile( file ) ) - { - // N[Ys - if( !s_quiettest ) OS_TPrintf("%s:close failed.\n",filename); - return FALSE; - } - - return TRUE; -} - -static BOOL RWExTestCore( char *path, char *testfile ) -{ - char filename[256]; - char testfilename[256]; - int len; - char buf[5]; - FSFile file[1]; - - FS_InitFile( file ); - STD_TSNPrintf( filename, 256, "%s/%s", path, testfile ); - STD_TSNPrintf( testfilename, 256, "%s/test.txt", path ); - - // t@CI[v + // RWL[ht@CI[v if ( !FS_OpenFileEx( file, filename, FS_FILEMODE_RWL ) ) { // RWL[ht@CI[vs if( !s_quiettest ) OS_TPrintf("%s:RWL mode open failed.\n",filename); FS_CloseFile( file ); - return FALSE; + // R[ht@CI[v + if ( !FS_OpenFileEx( file, filename, FS_FILEMODE_R ) ) + { + // R[ht@CI[vs + if( !s_quiettest ) OS_TPrintf("%s:R mode open failed.\n",filename); + return PERMISSION_NA; + } + result = PERMISSION_RO; } // t@C[h @@ -199,41 +139,38 @@ static BOOL RWExTestCore( char *path, char *testfile ) // [hs if( !s_quiettest ) OS_TPrintf("%s:read failed.\n",filename); FS_CloseFile( file ); - return FALSE; + return PERMISSION_ERROR; } + // t@CN[Y if( !FS_CloseFile( file ) ) { // N[Ys if( !s_quiettest ) OS_TPrintf("%s:close failed.\n",filename); - return FALSE; + return PERMISSION_ERROR; } - - return TRUE; + + return result; } -static BOOL SRLTest( void ) +static AccessPermission BannerTest( void ) { - if( s_testnum < 17 ) - { - return ROTestCore( "nand:", "" ); - }else if( 16 < s_testnum && s_testnum < 21) - { - return RWExTestCore( "nand:", "" ); - }else - { - return FALSE; - } + return RWExistTestCore( "nand:", "" ); } -static BOOL ContentTest( void ) +static AccessPermission SRLTest( void ) { - return ROTestCore( "content:", "title.tmd" ); + return RWExistTestCore( "nand:", "" ); } -static BOOL Shared1Test( void ) +static AccessPermission ContentTest( void ) { - return ROTestCore( "shared1:", "TWLCFG0.dat" ); + return RWExistTestCore( "content:", "title.tmd" ); +} + +static AccessPermission Shared1Test( void ) +{ + return RWExistTestCore( "shared1:", "TWLCFG0.dat" ); } static void FinalizeRWTest( FSFile *file, char* filename ) @@ -243,7 +180,7 @@ static void FinalizeRWTest( FSFile *file, char* filename ) } // pX͍ŌɃXbVȂ -static BOOL RWTestCore( char *path, char *testfile ) +static AccessPermission RWTestCore( char *path, char *testfile ) { char filename[256]; int len; @@ -265,7 +202,7 @@ static BOOL RWTestCore( char *path, char *testfile ) // t@CI[vs if( !s_quiettest ) OS_TPrintf("%s:open failed.\n",filename); FS_DeleteFile( filename ); - return FALSE; + return PERMISSION_ERROR; } // t@CCg len = FS_WriteFile( file, "test", 5); @@ -274,7 +211,7 @@ static BOOL RWTestCore( char *path, char *testfile ) // Cgs if( !s_quiettest ) OS_TPrintf("%s:write failed.\n",filename); FinalizeRWTest( file, filename ); - return FALSE; + return PERMISSION_ERROR; } // t@CN[Y if( !FS_CloseFile( file ) ) @@ -282,15 +219,16 @@ static BOOL RWTestCore( char *path, char *testfile ) // N[Ys if( !s_quiettest ) OS_TPrintf("%s:close failed.\n",filename); FinalizeRWTest( file, filename ); - return FALSE; + return PERMISSION_ERROR; } + // t@CI[v if ( !FS_OpenFileEx( file, filename, FS_FILEMODE_R ) ) { // t@CI[vs if( !s_quiettest ) OS_TPrintf("%s:open failed.\n",filename); FS_DeleteFile( filename ); - return FALSE; + return PERMISSION_ERROR; } // t@C[h len = FS_ReadFile( file, buf, len ); @@ -299,7 +237,7 @@ static BOOL RWTestCore( char *path, char *testfile ) // [hs if( !s_quiettest ) OS_TPrintf("%s:read failed.\n",filename); FinalizeRWTest( file, filename ); - return FALSE; + return PERMISSION_ERROR; } // t@CN[Y if( !FS_CloseFile( file ) ) @@ -307,7 +245,7 @@ static BOOL RWTestCore( char *path, char *testfile ) // N[Ys if( !s_quiettest ) OS_TPrintf("%s:close failed.\n",filename); FinalizeRWTest( file, filename ); - return FALSE; + return PERMISSION_ERROR; } // t@Cf[g if( !FS_DeleteFile( filename )) @@ -315,34 +253,51 @@ static BOOL RWTestCore( char *path, char *testfile ) // f[gs if( !s_quiettest ) OS_TPrintf("%s:delete failed.\n",filename); FinalizeRWTest( file, filename ); - return FALSE; + return PERMISSION_ERROR; } }else { // t@C쐬s + FSResult fs_result = FS_GetArchiveResultCode( filename ); if( !s_quiettest ) OS_TPrintf("%s:cleate failed.\n",filename); - return FALSE; + OS_TPrintf( "FS_GetArchiveResultCode(%s) : %d\n", filename, fs_result ); + if( FS_RESULT_ERROR == fs_result ) + { + // dlƂāA}EgĂȂԂ̓p[~bVNAƂĈ + return PERMISSION_NA; + }else if( FS_RESULT_PERMISSION_DENIED == fs_result ) + { + // PERMISSION_DENIEDꍇAROłȂmFKv + if ( !FS_OpenFileEx( file, filename, FS_FILEMODE_R ) ) + { + if( FS_RESULT_PERMISSION_DENIED == FS_GetArchiveResultCode( filename ) ) + { + // ˋ̃t@CR[hœǂݍƂʂDENIEDȂp[~bVNA + return PERMISSION_NA; + } + } + return PERMISSION_ERROR; + } + // ƂERROR + return PERMISSION_ERROR; } - return TRUE; + return PERMISSION_RW; } -static BOOL RWTest( char *path ) +static AccessPermission RWTest( char *path ) { return RWTestCore( path, "test.txt" ); } -static BOOL TMPJumpTest( void ) +static AccessPermission TMPJumpTest( void ) { return RWTestCore( "nand:", "" ); } -u8 tempbuf[ LCFG_TEMP_BUFFER_SIZE * 2 ]; -static TWLSubBannerFile sbf; - static void TestFSPermission( void ) { - BOOL result[TEST_NUM]; + AccessPermission result[TEST_NUM]; BOOL test_ok = TRUE; int l; @@ -359,23 +314,13 @@ static void TestFSPermission( void ) result[10] = RWTest( "nand:/import" ); // nand:/import result[11] = RWTest( "nand:/tmp" ); // nand:/tmp result[12] = SRLTest(); // nand:/ - result[13] = OS_DeleteSubBannerFile(&sbf); // nand:/ + result[13] = BannerTest(); // nand:/ result[14] = TMPJumpTest(); // nand:/ - - OS_TPrintf( "Correct Answer:\n" ); for( l=0; ltitleID_Hi & TITLE_ID_HI_MEDIA_MASK) ? TRUE : FALSE; + BOOL isSecureApp = (rhs->titleID_Hi & TITLE_ID_HI_SECURE_FLAG_MASK) ? TRUE : FALSE; + BOOL isNandAccessOn = (rhs->access_control.nand_access) ? TRUE : FALSE; + BOOL isSDCardAccessOn = (rhs->access_control.sd_card_access) ? TRUE : FALSE; + BOOL isEnablePublicSaveData = ( rhs->public_save_data_size != 0 ) ? TRUE : FALSE; + BOOL isEnablePrivateSaveData = ( rhs->private_save_data_size != 0 ) ? TRUE : FALSE; + + // ANZXݒ𐶐AMȂ́AwŃtANZX + s_answer_data[0] = ( ( isNandApp || isNandAccessOn ) && isSecureApp ) ? PERMISSION_RW : PERMISSION_NA; // nand: iNANDAv or NANDANZXONjand SecureApp + s_answer_data[1] = ( ( isNandApp || isNandAccessOn ) && isSecureApp ) ? PERMISSION_RW : PERMISSION_NA; // nand2: iNANDAv or NANDANZXONjand SecureApp + s_answer_data[2] = ( isNandApp && CTRUE ) ? PERMISSION_RO : PERMISSION_NA; // content: ݖBL̏ꍇNANDAv̂ReadOnly + s_answer_data[3] = ( isNandApp || isNandAccessOn ) ? PERMISSION_RO : PERMISSION_NA; // shared1: iNANDAv or NANDANZXONjReadOnly + s_answer_data[4] = ( ( isNandApp || isNandAccessOn ) && STRUE ) ? PERMISSION_RW : PERMISSION_NA; // shared2: ݖBL̏ꍇ́iNANDAv or NANDANZXONj + s_answer_data[5] = ( isNandApp || isNandAccessOn ) ? PERMISSION_RW : PERMISSION_NA; // photo: NANDAv or NANDANZXON + s_answer_data[6] = ( isNandApp && isEnablePublicSaveData ) ? PERMISSION_RW : PERMISSION_NA; // dataPub: NANDAv and dataPub TCYݒ肠 + s_answer_data[7] = ( isNandApp && isEnablePrivateSaveData ) ? PERMISSION_RW : PERMISSION_NA; // dataPrv: NANDAv and dataPrv TCYݒ肠 + s_answer_data[8] = isSDCardAccessOn ? PERMISSION_RW : PERMISSION_NA; // sdmc: SDANZXiSDJ[hhĂȂƎsj + s_answer_data[9] = ( ( isNandApp || isNandAccessOn ) && isSecureApp ) ? PERMISSION_RW : PERMISSION_NA; // nand:/sys iNANDAv or NANDANZXONjand SecureApp + s_answer_data[10] = ( ( isNandApp || isNandAccessOn ) && isSecureApp ) ? PERMISSION_RW : PERMISSION_NA; // nand:/import iNANDAv or NANDANZXONjand SecureApp + s_answer_data[11] = ( ( isNandApp || isNandAccessOn ) && isSecureApp ) ? PERMISSION_RW : PERMISSION_NA; // nand:/tmp iNANDAv or NANDANZXONjand SecureApp + s_answer_data[12] = isNandApp ? ( isSecureApp ? PERMISSION_RW : PERMISSION_RO ) : PERMISSION_NA; // nand:/ NANDAvReadOnlyiSecurȅꍇ̓tANZXj + s_answer_data[13] = isNandApp ? PERMISSION_RW : PERMISSION_NA; // nand:/ NANDAv + s_answer_data[14] = ( isNandApp || isNandAccessOn ) ? PERMISSION_RW : PERMISSION_NA; // nand:/ NANDAv or NANDANZXON +} + // eXgvȌ void RomTypeTestInit( void ) { @@ -402,24 +375,15 @@ void RomTypeTestInit( void ) PrintfSJIS( 1 * 8, 9 * 8, TXT_COLOR_BLACK, "FATFSPermissionCheck %c", (char)((ROM_Header_Short *)(HW_TWL_ROM_HEADER_BUF))->titleID_Lo[1]); PutStringUTF16( 1 * 8, 11 * 8, TXT_COLOR_BLACK, (const u16 *)L"Start." ); //GetAndDrawRTCData( &g_rtcDraw, TRUE ); - - s_testnum = (char)((ROM_Header_Short *)(HW_TWL_ROM_HEADER_BUF))->titleID_Lo[1]; - if( '0' <= s_testnum && s_testnum <= '9' ) - { - s_testnum -= '0'; - }else if( 'a' <= s_testnum && s_testnum <= 'z' ) - { - s_testnum = (char)( s_testnum - 'a' + 10 ); - }else - { - s_testnum = 0; - } GXS_SetVisiblePlane( GX_PLANEMASK_BG0 ); GX_DispOn(); GXS_DispOn(); - s_quiettest = TRUE; + s_quiettest = FALSE; + + makeAnswerData(); + TestFSPermission(); } diff --git a/build/tests/TestMaker/config/romparam_forFATFSPermissiontest.yaml b/build/tests/TestMaker/config/romparam_forFATFSPermissiontest.yaml index 333c76c12ee774465d5cef475ecf6206ed7bb970..6149b8b7a8a1afd553cd1dbf5bdc3c4cb5a391bb 100644 GIT binary patch literal 28416 zcmeI5PfsL87{<%Q#Dq`a!2@A0dvLLa{}3}K60e*VdS?|=5!5ANaTCAZ+_u>RHm;eYpk`yc#k^>0>w^WXaK z{GZ<1X6MquI{6ZsZFS6P4 zYOViS%n)1d_`O5_=|jKar_kz=f5rbY|K;i%TW=rkG$^zFrvKu&zI6NEdN1p{(9`qo zk?VIJ+kVki_cW@Qz$t#ATnDrjzv$R{jRIIr}&;_&7zl4!!#<1k+Z1a02%AXyfT3j)}5kR?mW%*fItcBPSGrPo_0&PmssvR z?HwV_a!1+%&awMPM@RnnUc$M08^@WQgX`%1O+4Dg5pQS3aL($7tKP!#z31*@ojL3V zVyiey+4*n}v6iL(D5eL;-RZ`w;I+JX<5?Bq9CudZRd8l{`FYN}(s*I-iM`cXSNV>FHL7)|3lM$`C?(KNneG>z{VP2)R8OVf7)N%+pHXxDcGrSH&tm+uNM zZ^z4eeK%03?-)(vJ4Vy^j?px}V>FHL7)|3lM$`C?(bDwYU=qHwD%$nkVClO=e3v(v zz4ybf@A9#i)pmo0+K$mQwqrDn?HEmCJ4Vykj?px>V>FHJ7%ffP4JBbatD;@o4GC;l zbsylJ;Tpyb=9=CqO??b6ZxFLhe7CZg5xkQXTy@_K73w=i)A)|jG`?drjqeyu<2y#v z_>R#uzGJjBeK(wh@2rY;eK#!do#K9#aORI=XIJ??l|_spuVc)43!}+Zj68pWk>{|z zRXqFbcqH1p_nQ8uSj2eq7NWDU>a(=0Hi*sFiSa%cySpIo;^w%x@7do7u~oP?!G530 z-7&+3`jyc%eq}U`Ul~o~S4PwLmC-bQWi*Xn87)n}j^NC3@ps2q747u^yO=DO_(-@Y~(lqR75{9)Z z+BNKGY1m6`*j7)L*RU`CgvV&1hGjI3VHr(hSVq$rmeDkZWi*Xp8BJqYMoZJMV@Vj+ zs%Y1+W2Irc*08O1?vAV2u|gfoXd1^dn#Qq=rg1EzX&lRF8pkr4#<7f+renvGaI96) zu4Bhb$6l~w^CO%#dRfG~#QE{t?y&24p>}07ja?Z{V^>Dg*p<;Vc4ah;T^UVdS4KLik%sO@id<0+ov%t=V@Hac^cbtp2oMFr!g+) zrRv;NW(GRX+(7H4b1$)TTg_RH%)WSJw&K`aESlN(I8WtVwtXt+GM>u0jHhxg zcq->IUaHPbV|Jp7JJ0+?_0qXr>fBaecgMTQcC-|GrOS9K>oT6ox{Rl?F5{`J%Xlj5 zGM>u1jF+l))0iWv;?6Tm(uTmgs(B->?q_MwGltu0&$C?ZwzlmS^Rn4#RM)$Vr!p_& zsm#lGD)Ta)%DjxHGB4w)%*%MGnm3L4nkw!*Gd68@y?IYsujtR%o~+>i-#gXn&eFSf tHnjgc!~VyM9WTXR@iLyuyNsvuF5{`Z%Xlj9GM>u2jHmK0<6W$G{{z}Cievx) delta 396 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 literal 0 HcmV?d00001