From 0ca1d3e0ee2aa2af09a545eaa70dda50b66b64b3 Mon Sep 17 00:00:00 2001 From: rmc Date: Sat, 16 Dec 2023 15:41:34 -0500 Subject: [PATCH] Add unedited TwlIPL commit #99. --- .DS_Store | Bin 0 -> 6148 bytes Makefile | 31 + add-ins/TwlSystem/NitroSystem_patch.zip | Bin 0 -> 7335 bytes add-ins/TwlSystem/使用方法.txt | 25 + build/.DS_Store | Bin 0 -> 8196 bytes build/Makefile | 37 + build/buildtools/commondefs | 30 + build/buildtools/commondefs.firm | 260 +++ build/buildtools/commondefs.sysmenu | 97 + build/buildtools/modulerules | 34 + build/buildtools/modulerules.firm | 92 + build/buildtools/modulerules.sysmenu | 30 + build/libraries/.DS_Store | Bin 0 -> 6148 bytes build/libraries/Makefile | 44 + build/libraries/aes/ARM7/Makefile | 60 + build/libraries/aes/ARM7/aes_init.c | 72 + build/libraries/aes/ARM7/aes_util.c | 46 + build/libraries/aes/Makefile | 31 + build/libraries/fatfs/ARM7/Makefile | 65 + build/libraries/fatfs/ARM7/src/fatfs_firm.c | 506 +++++ build/libraries/fatfs/ARM7/src/fatfs_loader.c | 491 +++++ build/libraries/fatfs/Makefile | 31 + build/libraries/gcd/ARM7/Makefile | 60 + build/libraries/gcd/ARM9/Makefile | 65 + build/libraries/gcd/Makefile | 34 + build/libraries/gcd/common/blowfish.c | 149 ++ build/libraries/gcd/common/ds_blowfish.c | 186 ++ .../libraries/gcd/common/ds_blowfish_table.c | 286 +++ build/libraries/gcd/common/gcd.c | 1215 ++++++++++++ build/libraries/gcd/common/gcd_init.c | 1696 +++++++++++++++++ .../gcd/common/gcdfirm_blowfish_table.c | 288 +++ build/libraries/init/ARM7/Makefile | 58 + build/libraries/init/ARM7/crt0_firm.c | 447 +++++ build/libraries/init/ARM9/Makefile | 54 + build/libraries/init/ARM9/crt0_firm.c | 817 ++++++++ build/libraries/init/Makefile | 32 + build/libraries/mi/ARM9/Makefile | 60 + build/libraries/mi/ARM9/mi_init_mainMemory.c | 160 ++ build/libraries/mi/ARM9/mi_loader.c | 509 +++++ build/libraries/mi/Makefile | 31 + build/libraries/mi/common/mi_exDma.c | 286 +++ build/libraries/os/ARM7/Makefile | 62 + build/libraries/os/ARM9/Makefile | 60 + build/libraries/os/ARM9/os_cache_tag.c | 269 +++ build/libraries/os/Makefile | 32 + build/libraries/os/common/os_boot.c | 219 +++ build/libraries/os/common/os_init_firm.c | 148 ++ build/libraries/pm/ARM7/Makefile | 62 + build/libraries/pm/ARM7/pm_init.c | 88 + build/libraries/pm/ARM7/pm_pmic_ex.c | 72 + build/libraries/pm/Makefile | 31 + build/libraries/pxi/ARM7/Makefile | 61 + build/libraries/pxi/ARM9/Makefile | 58 + build/libraries/pxi/Makefile | 32 + build/libraries/pxi/common/pxi_misc.c | 352 ++++ build/libraries_sysmenu/.DS_Store | Bin 0 -> 6148 bytes build/libraries_sysmenu/Makefile | 32 + build/libraries_sysmenu/acsign/ARM9/Makefile | 57 + .../acsign/ARM9/include/acmemory.h | 36 + .../acsign/ARM9/include/bn.h | 1136 +++++++++++ .../acsign/ARM9/include/bn_lcl.h | 356 ++++ .../acsign/ARM9/include/bn_thx.h | 317 +++ .../acsign/ARM9/include/md5.h | 73 + .../acsign/ARM9/include/r_error.h | 226 +++ .../acsign/ARM9/include/r_stdiag.h | 98 + .../acsign/ARM9/include/r_types.h | 257 +++ .../acsign/ARM9/include/sha.h | 105 + .../acsign/ARM9/include/sha1.h | 90 + .../acsign/ARM9/include/sha_locl.h | 290 +++ .../acsign/ARM9/src/acmemory.c | 306 +++ .../acsign/ARM9/src/acsign.c | 453 +++++ .../acsign/ARM9/src/acsign_util.c | 111 ++ .../acsign/ARM9/src/bn_add.c | 320 ++++ .../acsign/ARM9/src/bn_asm.c | 525 +++++ .../acsign/ARM9/src/bn_comba.c | 450 +++++ .../acsign/ARM9/src/bn_div.c | 381 ++++ .../acsign/ARM9/src/bn_ex_str.c | 453 +++++ .../acsign/ARM9/src/bn_exp.c | 172 ++ .../acsign/ARM9/src/bn_fm_w.c | 79 + .../acsign/ARM9/src/bn_gcd.c | 245 +++ .../acsign/ARM9/src/bn_lib.c | 1095 +++++++++++ .../acsign/ARM9/src/bn_lsh.c | 128 ++ .../acsign/ARM9/src/bn_m_exp.c | 299 +++ .../libraries_sysmenu/acsign/ARM9/src/bn_me.c | 267 +++ .../acsign/ARM9/src/bn_mont.c | 247 +++ .../acsign/ARM9/src/bn_ms_w.c | 137 ++ .../acsign/ARM9/src/bn_mul.c | 795 ++++++++ .../acsign/ARM9/src/bn_r_exp.c | 150 ++ .../acsign/ARM9/src/bn_rec.c | 249 +++ .../acsign/ARM9/src/bn_recp.c | 218 +++ .../acsign/ARM9/src/bn_rsh.c | 139 ++ .../acsign/ARM9/src/bn_sqr.c | 289 +++ .../acsign/ARM9/src/bn_wdiv.c | 116 ++ .../acsign/ARM9/src/bn_word.c | 238 +++ .../libraries_sysmenu/acsign/ARM9/src/main.c | 320 ++++ build/libraries_sysmenu/acsign/ARM9/src/md5.c | 412 ++++ .../libraries_sysmenu/acsign/ARM9/src/sha1.c | 470 +++++ .../acsign/ARM9/src/sha1dgst.c | 786 ++++++++ build/libraries_sysmenu/acsign/Makefile | 31 + .../libraries_sysmenu/mb_loader/ARM7/Makefile | 53 + .../libraries_sysmenu/mb_loader/ARM9/Makefile | 52 + build/libraries_sysmenu/mb_loader/Makefile | 30 + .../mb_loader/common/src/mb_loader.c | 312 +++ build/libraries_sysmenu/sysmenu/ARM9/MakeCrt0 | 46 + build/libraries_sysmenu/sysmenu/ARM9/Makefile | 53 + .../sysmenu/ARM9/include/sysmenu_card.h | 248 +++ .../sysmenu/ARM9/include/sysmenu_define.h | 50 + .../libraries_sysmenu/sysmenu/ARM9/src/cmn.c | 250 +++ .../libraries_sysmenu/sysmenu/ARM9/src/crt1.c | 559 ++++++ .../sysmenu/ARM9/src/gameBoot.c | 247 +++ .../sysmenu/ARM9/src/ninLogoFunc.c | 168 ++ .../sysmenu/ARM9/src/nitroSettingsEx.c | 505 +++++ .../sysmenu/ARM9/src/sysmenu_card.c | 253 +++ .../sysmenu/ARM9/src/sysmenu_lib.c | 743 ++++++++ .../sysmenu/ARM9/src/sysmenu_util.c | 172 ++ build/libraries_sysmenu/sysmenu/Makefile | 33 + build/nand_formatter/.DS_Store | Bin 0 -> 6148 bytes build/nand_formatter/ARM7/Makefile | 53 + .../ARM7/formatter_sub.lcf.template | 897 +++++++++ build/nand_formatter/ARM7/formatter_sub.lsf | 79 + .../ARM7/formatter_sub.response.template | 40 + build/nand_formatter/ARM7/src/dummy.EXTWRAM.c | 27 + build/nand_formatter/ARM7/src/dummy.FLXMAIN.c | 27 + build/nand_formatter/ARM7/src/dummy.FLXWRAM.c | 27 + build/nand_formatter/ARM7/src/dummy.LTDMAIN.c | 27 + build/nand_formatter/ARM7/src/dummy.LTDWRAM.c | 27 + build/nand_formatter/ARM7/src/main.c | 393 ++++ build/nand_formatter/ARM9/Makefile | 42 + build/nand_formatter/ARM9/src/main.c | 89 + build/nand_formatter/Makefile | 34 + build/nandfirm/.DS_Store | Bin 0 -> 6148 bytes build/nandfirm/Makefile | 35 + build/nandfirm/menu-launcher/ARM7/Makefile | 51 + build/nandfirm/menu-launcher/ARM7/main.c | 182 ++ build/nandfirm/menu-launcher/ARM9/Makefile | 50 + build/nandfirm/menu-launcher/ARM9/main.c | 134 ++ build/nandfirm/menu-launcher/Makefile | 59 + build/nandfirm/menu-launcher/nandfirm.nandsf | 24 + .../nandfirm/menu-launcher/wram_regs/Makefile | 48 + .../menu-launcher/wram_regs/wram_regs.c | 91 + build/nandfirm/nandfirm-print/Makefile | 50 + .../nandfirm-print/nandfirm-BB.nandsf | 24 + build/nandfirm/sdmc-launcher/ARM7/Makefile | 51 + build/nandfirm/sdmc-launcher/ARM7/main.c | 222 +++ build/nandfirm/sdmc-launcher/ARM9/Makefile | 50 + build/nandfirm/sdmc-launcher/ARM9/main.c | 173 ++ build/nandfirm/sdmc-launcher/Makefile | 59 + build/nandfirm/sdmc-launcher/nandfirm.nandsf | 24 + .../nandfirm/sdmc-launcher/wram_regs/Makefile | 48 + .../sdmc-launcher/wram_regs/wram_regs.c | 91 + build/norfirm/.DS_Store | Bin 0 -> 6148 bytes build/norfirm/Makefile | 34 + build/norfirm/norfirm-empty/Makefile | 48 + build/norfirm/norfirm-empty/norfirm-BB.norsf | 8 + build/norfirm/norfirm-print/ARM7/Makefile | 50 + build/norfirm/norfirm-print/ARM7/main.c | 31 + build/norfirm/norfirm-print/ARM9/Makefile | 49 + build/norfirm/norfirm-print/ARM9/main.c | 31 + build/norfirm/norfirm-print/Makefile | 60 + build/norfirm/norfirm-print/norfirm-BB.norsf | 25 + .../norfirm/norfirm-print/wram_regs/Makefile | 48 + .../norfirm-print/wram_regs/wram_regs.c | 91 + build/systemMenu_RED/.DS_Store | Bin 0 -> 6148 bytes .../DS_DownloadPlay/ARM9/ARM9-TS.lsf | 70 + .../DS_DownloadPlay/ARM9/Makefile | 52 + .../DS_DownloadPlay/ARM9/main.rsf | 146 ++ .../ARM9/src/DS_DownloadPlay.c | 1618 ++++++++++++++++ .../ARM9/src/DS_DownloadPlay.h | 37 + build/systemMenu_RED/DS_DownloadPlay/Makefile | 30 + .../DS_DownloadPlay/banner/Makefile | 52 + .../DS_DownloadPlay/banner/banner_v3.bsf | Bin 0 -> 828 bytes .../DS_DownloadPlay/banner/icon/gameIcon.bmp | Bin 0 -> 630 bytes .../systemMenu_RED/Launcher/ARM9/ARM9-TS.lsf | 54 + build/systemMenu_RED/Launcher/ARM9/Makefile | 54 + build/systemMenu_RED/Launcher/ARM9/main.rsf | 147 ++ .../Launcher/ARM9/src/Logo/logoData.c | 204 ++ .../Launcher/ARM9/src/Logo/logoDemo.c | 131 ++ .../Launcher/ARM9/src/Logo/logoDemo.h | 35 + .../Launcher/ARM9/src/launcher.c | 388 ++++ .../Launcher/ARM9/src/launcher.h | 41 + build/systemMenu_RED/Launcher/ARM9/src/main.c | 434 +++++ build/systemMenu_RED/Launcher/ARM9/src/misc.c | 588 ++++++ build/systemMenu_RED/Launcher/ARM9/src/misc.h | 153 ++ build/systemMenu_RED/Launcher/Makefile | 30 + .../MachineSettings/ARM9/Makefile | 54 + .../MachineSettings/ARM9/main.rsf | 146 ++ .../MachineSettings/ARM9/src/MachineSetting.c | 295 +++ .../MachineSettings/ARM9/src/MachineSetting.h | 77 + .../MachineSettings/ARM9/src/calibrationTP.c | 524 +++++ .../MachineSettings/ARM9/src/main.c | 117 ++ .../MachineSettings/ARM9/src/misc.c | 601 ++++++ .../MachineSettings/ARM9/src/misc.h | 168 ++ .../MachineSettings/ARM9/src/selectLanguage.c | 148 ++ .../MachineSettings/ARM9/src/setOwnerInfo.c | 1077 +++++++++++ .../MachineSettings/ARM9/src/setRTC.c | 557 ++++++ build/systemMenu_RED/MachineSettings/Makefile | 30 + .../MachineSettings/banner/Makefile | 52 + .../MachineSettings/banner/banner_v3.bsf | Bin 0 -> 768 bytes .../MachineSettings/banner/icon/gameIcon.bmp | Bin 0 -> 630 bytes build/systemMenu_RED/Makefile | 31 + build/systemMenu_RED/PictoChat/ARM9/Makefile | 53 + build/systemMenu_RED/PictoChat/ARM9/main.rsf | 146 ++ .../PictoChat/ARM9/src/PictoChat.c | 83 + .../PictoChat/ARM9/src/PictoChat.h | 37 + .../systemMenu_RED/PictoChat/ARM9/src/main.c | 107 ++ build/systemMenu_RED/PictoChat/Makefile | 30 + .../systemMenu_RED/PictoChat/banner/Makefile | 52 + .../PictoChat/banner/banner_v3.bsf | Bin 0 -> 762 bytes .../PictoChat/banner/icon/gameIcon.bmp | Bin 0 -> 630 bytes build/systemMenu_RED/data/CardBanner.bnr | Bin 0 -> 2624 bytes build/systemMenu_RED/data/DownloadBanner.bnr | Bin 0 -> 2624 bytes build/systemMenu_RED/data/EmptyBanner.bnr | Bin 0 -> 2624 bytes build/systemMenu_RED/data/NTR_IPL_font_l.NFTR | Bin 0 -> 181128 bytes build/systemMenu_RED/data/NTR_IPL_font_m.NFTR | Bin 0 -> 107180 bytes build/systemMenu_RED/data/NTR_IPL_font_s.NFTR | Bin 0 -> 79924 bytes build/systemMenu_RED/data/PictoChatBanner.bnr | Bin 0 -> 2624 bytes build/systemMenu_RED/data/SettingBanner.bnr | Bin 0 -> 2624 bytes build/tools/.DS_Store | Bin 0 -> 6148 bytes build/tools/Makefile | 35 + build/tools/acsign/Makefile | 61 + build/tools/acsign/acsign.c | 334 ++++ build/tools/acsign/acsign_gcd.c | 74 + build/tools/acsign/acsign_nand.c | 75 + build/tools/acsign/acsign_nor.c | 75 + build/tools/acsign/aes.h | 139 ++ build/tools/acsign/aes2.c | 133 ++ build/tools/acsign/aes2.h | 21 + build/tools/acsign/aes_e.c | 115 ++ build/tools/acsign/aes_e.h | 284 +++ build/tools/acsign/aes_e_ecb.c | 48 + build/tools/acsign/aes_sbox.h | 59 + build/tools/acsign/aes_skey.c | 143 ++ build/tools/acsign/bn_add.c | 304 +++ build/tools/acsign/bn_asm.c | 509 +++++ build/tools/acsign/bn_comba.c | 434 +++++ build/tools/acsign/bn_div.c | 365 ++++ build/tools/acsign/bn_ex_str.c | 437 +++++ build/tools/acsign/bn_exp.c | 156 ++ build/tools/acsign/bn_fm_w.c | 63 + build/tools/acsign/bn_gcd.c | 229 +++ build/tools/acsign/bn_lib.c | 1079 +++++++++++ build/tools/acsign/bn_lsh.c | 112 ++ build/tools/acsign/bn_m_exp.c | 283 +++ build/tools/acsign/bn_me.c | 251 +++ build/tools/acsign/bn_mont.c | 231 +++ build/tools/acsign/bn_ms_w.c | 121 ++ build/tools/acsign/bn_mul.c | 779 ++++++++ build/tools/acsign/bn_r_exp.c | 134 ++ build/tools/acsign/bn_rec.c | 232 +++ build/tools/acsign/bn_recp.c | 202 ++ build/tools/acsign/bn_rsh.c | 123 ++ build/tools/acsign/bn_sqr.c | 273 +++ build/tools/acsign/bn_wdiv.c | 100 + build/tools/acsign/bn_word.c | 222 +++ build/tools/acsign/include/acsign.h | 49 + build/tools/acsign/include/acsign_gcd.h | 30 + build/tools/acsign/include/acsign_nand.h | 30 + build/tools/acsign/include/acsign_nor.h | 30 + build/tools/acsign/include/bn.h | 1120 +++++++++++ build/tools/acsign/include/bn_lcl.h | 324 ++++ build/tools/acsign/include/bn_thx.h | 301 +++ build/tools/acsign/include/r_error.h | 210 ++ build/tools/acsign/include/r_stdiag.h | 82 + build/tools/acsign/include/r_types.h | 241 +++ build/tools/acsign/include/sha.h | 89 + build/tools/acsign/include/sha1.h | 73 + build/tools/acsign/include/sha_locl.h | 274 +++ build/tools/acsign/sha1.c | 453 +++++ build/tools/acsign/sha1dgst.c | 770 ++++++++ build/tools/makegcdfirm/Makefile | 151 ++ build/tools/makegcdfirm/compress.c | 293 +++ build/tools/makegcdfirm/compress.h | 38 + build/tools/makegcdfirm/defval.c | 315 +++ build/tools/makegcdfirm/defval.h | 38 + build/tools/makegcdfirm/elf.h | 431 +++++ build/tools/makegcdfirm/format_nlist.h | 54 + build/tools/makegcdfirm/format_rom.h | 59 + build/tools/makegcdfirm/format_sign.h | 32 + .../gcdfirm_header_twlj.template.sbin | Bin 0 -> 16384 bytes build/tools/makegcdfirm/makegcdfirm.c | 106 ++ build/tools/makegcdfirm/makegcdfirm.h | 24 + build/tools/makegcdfirm/misc.c | 628 ++++++ build/tools/makegcdfirm/misc.h | 124 ++ build/tools/makegcdfirm/out_gcdfirm.c | 994 ++++++++++ build/tools/makegcdfirm/path.c | 931 +++++++++ build/tools/makegcdfirm/path.h | 93 + build/tools/makegcdfirm/test/Makefile | 56 + .../makegcdfirm/test/nandfirm_print.nand | Bin 0 -> 50688 bytes .../tools/makegcdfirm/test/norfirm_print.nor | Bin 0 -> 30896 bytes build/tools/makegcdfirm/test/rsa_private.der | Bin 0 -> 607 bytes build/tools/makegcdfirm/test/test.gcdsf | 22 + .../makegcdfirm/test/twl_gcdfirm7_print.axf | Bin 0 -> 175676 bytes .../makegcdfirm/test/twl_gcdfirm7_print.sbin | Bin 0 -> 12772 bytes .../makegcdfirm/test/twl_gcdfirm9_print.axf | Bin 0 -> 288636 bytes .../makegcdfirm/test/twl_gcdfirm9_print.sbin | Bin 0 -> 33184 bytes .../tools/makegcdfirm/test/wram_rbin/Makefile | 48 + .../makegcdfirm/test/wram_rbin/wram_regs.c | 89 + build/tools/makegcdfirm/wram_regs.c | 96 + build/tools/makenandfirm/Makefile | 151 ++ build/tools/makenandfirm/compress.c | 293 +++ build/tools/makenandfirm/compress.h | 38 + build/tools/makenandfirm/defval.c | 315 +++ build/tools/makenandfirm/defval.h | 38 + build/tools/makenandfirm/elf.h | 431 +++++ build/tools/makenandfirm/format_nlist.h | 54 + build/tools/makenandfirm/format_rom.h | 51 + build/tools/makenandfirm/format_sign.h | 32 + build/tools/makenandfirm/makenandfirm.c | 106 ++ build/tools/makenandfirm/makenandfirm.h | 24 + build/tools/makenandfirm/misc.c | 628 ++++++ build/tools/makenandfirm/misc.h | 124 ++ build/tools/makenandfirm/out_nandfirm.c | 979 ++++++++++ build/tools/makenandfirm/path.c | 931 +++++++++ build/tools/makenandfirm/path.h | 93 + build/tools/makenandfirm/test/Makefile | 56 + build/tools/makenandfirm/test/rsa_private.der | Bin 0 -> 607 bytes build/tools/makenandfirm/test/test.nandsf | 28 + .../makenandfirm/test/twl_nandfirm7_print.axf | Bin 0 -> 175676 bytes .../test/twl_nandfirm7_print.sbin | Bin 0 -> 12772 bytes .../makenandfirm/test/twl_nandfirm9_print.axf | Bin 0 -> 288636 bytes .../test/twl_nandfirm9_print.sbin | Bin 0 -> 33184 bytes .../makenandfirm/test/wram_rbin/Makefile | 48 + .../makenandfirm/test/wram_rbin/wram_regs.c | 89 + build/tools/makenandfirm/wram_regs.c | 96 + build/tools/makenorfirm/Makefile | 151 ++ build/tools/makenorfirm/compress.c | 293 +++ build/tools/makenorfirm/compress.h | 38 + build/tools/makenorfirm/defval.c | 315 +++ build/tools/makenorfirm/defval.h | 38 + build/tools/makenorfirm/elf.h | 431 +++++ build/tools/makenorfirm/format_nlist.h | 54 + build/tools/makenorfirm/format_rom.h | 51 + build/tools/makenorfirm/format_sign.h | 32 + build/tools/makenorfirm/makenorfirm.c | 106 ++ build/tools/makenorfirm/makenorfirm.h | 24 + build/tools/makenorfirm/misc.c | 628 ++++++ build/tools/makenorfirm/misc.h | 128 ++ build/tools/makenorfirm/out_norfirm.c | 984 ++++++++++ build/tools/makenorfirm/path.c | 931 +++++++++ build/tools/makenorfirm/path.h | 93 + build/tools/makenorfirm/test/Makefile | 58 + build/tools/makenorfirm/test/rsa_private.der | Bin 0 -> 608 bytes build/tools/makenorfirm/test/test.norsf | 30 + .../makenorfirm/test/twl_norfirm7_print.axf | Bin 0 -> 175676 bytes .../makenorfirm/test/twl_norfirm7_print.sbin | Bin 0 -> 12772 bytes .../makenorfirm/test/twl_norfirm9_print.axf | Bin 0 -> 288636 bytes .../makenorfirm/test/twl_norfirm9_print.sbin | Bin 0 -> 33184 bytes .../tools/makenorfirm/test/wram_rbin/Makefile | 48 + .../makenorfirm/test/wram_rbin/wram_regs.c | 89 + build/tools/makenorfirm/wram_regs.c | 96 + doc/NORフラッシュマップ.xls | Bin 0 -> 19968 bytes doc/SystemMenu_REDリリース.txt | 55 + doc/TWL-NANDファーム二重化.vsd | Bin 0 -> 79872 bytes doc/TWL_SystemMenuメモリマップ.vsd | Bin 0 -> 198144 bytes doc/TWL_staticModule.xls | Bin 0 -> 54272 bytes doc/TWLフォルダツリー&NUP.vsd | Bin 0 -> 844800 bytes doc/rom_header_format.xls | Bin 0 -> 89088 bytes include/.DS_Store | Bin 0 -> 6148 bytes include/firm.h | 35 + include/firm/.DS_Store | Bin 0 -> 8196 bytes include/firm/acsign.h | 33 + include/firm/aes.h | 28 + include/firm/aes/ARM7/aes_ids.h | 42 + include/firm/aes/ARM7/aes_init.h | 35 + include/firm/aes/ARM7/aes_util.h | 35 + include/firm/fatfs.h | 28 + include/firm/fatfs/ARM7/fatfs_firm.h | 79 + include/firm/fatfs/ARM7/fatfs_loader.h | 89 + include/firm/format/firm_common.h | 67 + include/firm/format/format_rom.h | 532 ++++++ include/firm/format/format_rom_certificate.h | 50 + include/firm/format/from_brom.h | 100 + include/firm/format/gcdfirm.h | 114 ++ include/firm/format/nandfirm.h | 131 ++ include/firm/format/norfirm.h | 108 ++ include/firm/format/sign.h | 95 + include/firm/format/wram_regs.h | 85 + include/firm/gcd.h | 26 + include/firm/gcd/blowfish.h | 42 + include/firm/gcd/gcd.h | 779 ++++++++ include/firm/gcd/gcd_misc.h | 516 +++++ include/firm/hw/ARM7/mmap_firm.h | 55 + include/firm/hw/ARM9/mmap_firm.h | 54 + include/firm/hw/common/mmap_firm.h | 37 + include/firm/memorymap.h | 30 + include/firm/mi.h | 30 + include/firm/mi/ARM9/mi_loader.h | 67 + include/firm/mi/exDma.h | 203 ++ include/firm/mi/mainMemory.h | 111 ++ include/firm/misc.h | 33 + include/firm/nvram.h | 43 + include/firm/os.h | 36 + include/firm/os/ARM9/os_cache_tag.h | 151 ++ include/firm/os/common/boot.h | 86 + include/firm/os/common/init.h | 43 + include/firm/os/common/system.h | 53 + include/firm/os/common/tick_brom.h | 51 + include/firm/pm.h | 27 + include/firm/pm/ARM7/pm_init.h | 64 + include/firm/pm/ARM7/pm_pmic_ex.h | 73 + include/firm/pxi.h | 28 + include/firm/pxi/common/misc.h | 217 +++ include/firm/pxi/common/regname_ex.h | 42 + .../firm/specfiles/ARM7-BB-FIRM.lcf.template | 507 +++++ include/firm/specfiles/ARM7-BB-FIRM.lsf | 28 + .../specfiles/ARM7-BB-GCDFIRM.lcf.template | 507 +++++ include/firm/specfiles/ARM7-BB-GCDFIRM.lsf | 28 + .../firm/specfiles/ARM7-TS-FIRM.lcf.template | 929 +++++++++ include/firm/specfiles/ARM7-TS-FIRM.lsf | 31 + .../specfiles/ARM7-TS-GCDFIRM.lcf.template | 507 +++++ include/firm/specfiles/ARM7-TS-GCDFIRM.lsf | 28 + .../specfiles/ARM7-TS-PARTNER.lcf.template | 899 +++++++++ .../firm/specfiles/ARM9-BB-FIRM.lcf.template | 602 ++++++ include/firm/specfiles/ARM9-BB-FIRM.lsf | 42 + .../specfiles/ARM9-BB-GCDFIRM.lcf.template | 602 ++++++ include/firm/specfiles/ARM9-BB-GCDFIRM.lsf | 42 + .../firm/specfiles/ARM9-TS-FIRM.lcf.template | 1033 ++++++++++ include/firm/specfiles/ARM9-TS-FIRM.lsf | 56 + .../specfiles/ARM9-TS-GCDFIRM.lcf.template | 602 ++++++ include/firm/specfiles/ARM9-TS-GCDFIRM.lsf | 42 + .../specfiles/ARM9-TS-PARTNER.lcf.template | 983 ++++++++++ include/firm/specfiles/ROM-TS.rsf | 148 ++ include/sysmenu.h | 33 + include/sysmenu/.DS_Store | Bin 0 -> 6148 bytes include/sysmenu/acsign.h | 35 + include/sysmenu/acsign/ARM9/acsign.h | 59 + include/sysmenu/acsign/ARM9/acsign_util.h | 37 + include/sysmenu/banner.h | 111 ++ include/sysmenu/machineSettings.h | 32 + .../machineSettings/common/nitroSettings.h | 483 +++++ include/sysmenu/mb_loader.h | 32 + include/sysmenu/mb_loader/common/mb_loader.h | 86 + include/sysmenu/memorymap.h | 34 + include/sysmenu/mmap.h | 57 + include/sysmenu/rom_header.h | 175 ++ include/sysmenu/sysmenu_lib.h | 35 + include/sysmenu/sysmenu_lib/ARM9/cmn.h | 54 + .../sysmenu/sysmenu_lib/ARM9/sysmenu_api.h | 117 ++ include/sysmenu/sysmenu_work.h | 202 ++ keys/dummy/rsa/private_gcd.der | Bin 0 -> 609 bytes keys/dummy/rsa/private_nand.der | Bin 0 -> 607 bytes keys/dummy/rsa/private_nor.der | Bin 0 -> 607 bytes keys/dummy/rsa/pubkey_gcd.der | Bin 0 -> 162 bytes keys/dummy/rsa/pubkey_nand.der | Bin 0 -> 162 bytes keys/dummy/rsa/pubkey_nor.der | Bin 0 -> 162 bytes readme.txt | 13 + setup | 8 + tools/.DS_Store | Bin 0 -> 6148 bytes tools/bin/TXLib.dll | Bin 0 -> 90112 bytes tools/bin/makebanner.exe | Bin 0 -> 51303 bytes tools/bin/ntexconv.exe | Bin 0 -> 98304 bytes tools/openssl/openssl.exe | Bin 0 -> 286720 bytes 452 files changed, 79054 insertions(+) create mode 100644 .DS_Store create mode 100644 Makefile create mode 100644 add-ins/TwlSystem/NitroSystem_patch.zip create mode 100644 add-ins/TwlSystem/使用方法.txt create mode 100644 build/.DS_Store create mode 100644 build/Makefile create mode 100644 build/buildtools/commondefs create mode 100644 build/buildtools/commondefs.firm create mode 100644 build/buildtools/commondefs.sysmenu create mode 100644 build/buildtools/modulerules create mode 100644 build/buildtools/modulerules.firm create mode 100644 build/buildtools/modulerules.sysmenu create mode 100644 build/libraries/.DS_Store create mode 100644 build/libraries/Makefile create mode 100644 build/libraries/aes/ARM7/Makefile create mode 100644 build/libraries/aes/ARM7/aes_init.c create mode 100644 build/libraries/aes/ARM7/aes_util.c create mode 100644 build/libraries/aes/Makefile create mode 100644 build/libraries/fatfs/ARM7/Makefile create mode 100644 build/libraries/fatfs/ARM7/src/fatfs_firm.c create mode 100644 build/libraries/fatfs/ARM7/src/fatfs_loader.c create mode 100644 build/libraries/fatfs/Makefile create mode 100644 build/libraries/gcd/ARM7/Makefile create mode 100644 build/libraries/gcd/ARM9/Makefile create mode 100644 build/libraries/gcd/Makefile create mode 100644 build/libraries/gcd/common/blowfish.c create mode 100644 build/libraries/gcd/common/ds_blowfish.c create mode 100644 build/libraries/gcd/common/ds_blowfish_table.c create mode 100644 build/libraries/gcd/common/gcd.c create mode 100644 build/libraries/gcd/common/gcd_init.c create mode 100644 build/libraries/gcd/common/gcdfirm_blowfish_table.c create mode 100644 build/libraries/init/ARM7/Makefile create mode 100644 build/libraries/init/ARM7/crt0_firm.c create mode 100644 build/libraries/init/ARM9/Makefile create mode 100644 build/libraries/init/ARM9/crt0_firm.c create mode 100644 build/libraries/init/Makefile create mode 100644 build/libraries/mi/ARM9/Makefile create mode 100644 build/libraries/mi/ARM9/mi_init_mainMemory.c create mode 100644 build/libraries/mi/ARM9/mi_loader.c create mode 100644 build/libraries/mi/Makefile create mode 100644 build/libraries/mi/common/mi_exDma.c create mode 100644 build/libraries/os/ARM7/Makefile create mode 100644 build/libraries/os/ARM9/Makefile create mode 100644 build/libraries/os/ARM9/os_cache_tag.c create mode 100644 build/libraries/os/Makefile create mode 100644 build/libraries/os/common/os_boot.c create mode 100644 build/libraries/os/common/os_init_firm.c create mode 100644 build/libraries/pm/ARM7/Makefile create mode 100644 build/libraries/pm/ARM7/pm_init.c create mode 100644 build/libraries/pm/ARM7/pm_pmic_ex.c create mode 100644 build/libraries/pm/Makefile create mode 100644 build/libraries/pxi/ARM7/Makefile create mode 100644 build/libraries/pxi/ARM9/Makefile create mode 100644 build/libraries/pxi/Makefile create mode 100644 build/libraries/pxi/common/pxi_misc.c create mode 100644 build/libraries_sysmenu/.DS_Store create mode 100644 build/libraries_sysmenu/Makefile create mode 100644 build/libraries_sysmenu/acsign/ARM9/Makefile create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/acmemory.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/bn.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/bn_lcl.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/bn_thx.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/md5.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/r_error.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/r_stdiag.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/r_types.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/sha.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/sha1.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/include/sha_locl.h create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/acmemory.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/acsign.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/acsign_util.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_add.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_asm.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_comba.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_div.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_ex_str.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_exp.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_fm_w.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_gcd.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_lib.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_lsh.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_m_exp.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_me.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_mont.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_ms_w.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_mul.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_r_exp.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_rec.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_recp.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_rsh.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_sqr.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_wdiv.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/bn_word.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/main.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/md5.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/sha1.c create mode 100644 build/libraries_sysmenu/acsign/ARM9/src/sha1dgst.c create mode 100644 build/libraries_sysmenu/acsign/Makefile create mode 100644 build/libraries_sysmenu/mb_loader/ARM7/Makefile create mode 100644 build/libraries_sysmenu/mb_loader/ARM9/Makefile create mode 100644 build/libraries_sysmenu/mb_loader/Makefile create mode 100644 build/libraries_sysmenu/mb_loader/common/src/mb_loader.c create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/MakeCrt0 create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/Makefile create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/include/sysmenu_card.h create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/include/sysmenu_define.h create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/src/cmn.c create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/src/crt1.c create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/src/gameBoot.c create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/src/ninLogoFunc.c create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/src/nitroSettingsEx.c create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_card.c create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_lib.c create mode 100644 build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_util.c create mode 100644 build/libraries_sysmenu/sysmenu/Makefile create mode 100644 build/nand_formatter/.DS_Store create mode 100644 build/nand_formatter/ARM7/Makefile create mode 100644 build/nand_formatter/ARM7/formatter_sub.lcf.template create mode 100644 build/nand_formatter/ARM7/formatter_sub.lsf create mode 100644 build/nand_formatter/ARM7/formatter_sub.response.template create mode 100644 build/nand_formatter/ARM7/src/dummy.EXTWRAM.c create mode 100644 build/nand_formatter/ARM7/src/dummy.FLXMAIN.c create mode 100644 build/nand_formatter/ARM7/src/dummy.FLXWRAM.c create mode 100644 build/nand_formatter/ARM7/src/dummy.LTDMAIN.c create mode 100644 build/nand_formatter/ARM7/src/dummy.LTDWRAM.c create mode 100644 build/nand_formatter/ARM7/src/main.c create mode 100644 build/nand_formatter/ARM9/Makefile create mode 100644 build/nand_formatter/ARM9/src/main.c create mode 100644 build/nand_formatter/Makefile create mode 100644 build/nandfirm/.DS_Store create mode 100644 build/nandfirm/Makefile create mode 100644 build/nandfirm/menu-launcher/ARM7/Makefile create mode 100644 build/nandfirm/menu-launcher/ARM7/main.c create mode 100644 build/nandfirm/menu-launcher/ARM9/Makefile create mode 100644 build/nandfirm/menu-launcher/ARM9/main.c create mode 100644 build/nandfirm/menu-launcher/Makefile create mode 100644 build/nandfirm/menu-launcher/nandfirm.nandsf create mode 100644 build/nandfirm/menu-launcher/wram_regs/Makefile create mode 100644 build/nandfirm/menu-launcher/wram_regs/wram_regs.c create mode 100644 build/nandfirm/nandfirm-print/Makefile create mode 100644 build/nandfirm/nandfirm-print/nandfirm-BB.nandsf create mode 100644 build/nandfirm/sdmc-launcher/ARM7/Makefile create mode 100644 build/nandfirm/sdmc-launcher/ARM7/main.c create mode 100644 build/nandfirm/sdmc-launcher/ARM9/Makefile create mode 100644 build/nandfirm/sdmc-launcher/ARM9/main.c create mode 100644 build/nandfirm/sdmc-launcher/Makefile create mode 100644 build/nandfirm/sdmc-launcher/nandfirm.nandsf create mode 100644 build/nandfirm/sdmc-launcher/wram_regs/Makefile create mode 100644 build/nandfirm/sdmc-launcher/wram_regs/wram_regs.c create mode 100644 build/norfirm/.DS_Store create mode 100644 build/norfirm/Makefile create mode 100644 build/norfirm/norfirm-empty/Makefile create mode 100644 build/norfirm/norfirm-empty/norfirm-BB.norsf create mode 100644 build/norfirm/norfirm-print/ARM7/Makefile create mode 100644 build/norfirm/norfirm-print/ARM7/main.c create mode 100644 build/norfirm/norfirm-print/ARM9/Makefile create mode 100644 build/norfirm/norfirm-print/ARM9/main.c create mode 100644 build/norfirm/norfirm-print/Makefile create mode 100644 build/norfirm/norfirm-print/norfirm-BB.norsf create mode 100644 build/norfirm/norfirm-print/wram_regs/Makefile create mode 100644 build/norfirm/norfirm-print/wram_regs/wram_regs.c create mode 100644 build/systemMenu_RED/.DS_Store create mode 100644 build/systemMenu_RED/DS_DownloadPlay/ARM9/ARM9-TS.lsf create mode 100644 build/systemMenu_RED/DS_DownloadPlay/ARM9/Makefile create mode 100644 build/systemMenu_RED/DS_DownloadPlay/ARM9/main.rsf create mode 100644 build/systemMenu_RED/DS_DownloadPlay/ARM9/src/DS_DownloadPlay.c create mode 100644 build/systemMenu_RED/DS_DownloadPlay/ARM9/src/DS_DownloadPlay.h create mode 100644 build/systemMenu_RED/DS_DownloadPlay/Makefile create mode 100644 build/systemMenu_RED/DS_DownloadPlay/banner/Makefile create mode 100644 build/systemMenu_RED/DS_DownloadPlay/banner/banner_v3.bsf create mode 100644 build/systemMenu_RED/DS_DownloadPlay/banner/icon/gameIcon.bmp create mode 100644 build/systemMenu_RED/Launcher/ARM9/ARM9-TS.lsf create mode 100644 build/systemMenu_RED/Launcher/ARM9/Makefile create mode 100644 build/systemMenu_RED/Launcher/ARM9/main.rsf create mode 100644 build/systemMenu_RED/Launcher/ARM9/src/Logo/logoData.c create mode 100644 build/systemMenu_RED/Launcher/ARM9/src/Logo/logoDemo.c create mode 100644 build/systemMenu_RED/Launcher/ARM9/src/Logo/logoDemo.h create mode 100644 build/systemMenu_RED/Launcher/ARM9/src/launcher.c create mode 100644 build/systemMenu_RED/Launcher/ARM9/src/launcher.h create mode 100644 build/systemMenu_RED/Launcher/ARM9/src/main.c create mode 100644 build/systemMenu_RED/Launcher/ARM9/src/misc.c create mode 100644 build/systemMenu_RED/Launcher/ARM9/src/misc.h create mode 100644 build/systemMenu_RED/Launcher/Makefile create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/Makefile create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/main.rsf create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/src/MachineSetting.c create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/src/MachineSetting.h create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/src/calibrationTP.c create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/src/main.c create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/src/misc.c create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/src/misc.h create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/src/selectLanguage.c create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/src/setOwnerInfo.c create mode 100644 build/systemMenu_RED/MachineSettings/ARM9/src/setRTC.c create mode 100644 build/systemMenu_RED/MachineSettings/Makefile create mode 100644 build/systemMenu_RED/MachineSettings/banner/Makefile create mode 100644 build/systemMenu_RED/MachineSettings/banner/banner_v3.bsf create mode 100644 build/systemMenu_RED/MachineSettings/banner/icon/gameIcon.bmp create mode 100644 build/systemMenu_RED/Makefile create mode 100644 build/systemMenu_RED/PictoChat/ARM9/Makefile create mode 100644 build/systemMenu_RED/PictoChat/ARM9/main.rsf create mode 100644 build/systemMenu_RED/PictoChat/ARM9/src/PictoChat.c create mode 100644 build/systemMenu_RED/PictoChat/ARM9/src/PictoChat.h create mode 100644 build/systemMenu_RED/PictoChat/ARM9/src/main.c create mode 100644 build/systemMenu_RED/PictoChat/Makefile create mode 100644 build/systemMenu_RED/PictoChat/banner/Makefile create mode 100644 build/systemMenu_RED/PictoChat/banner/banner_v3.bsf create mode 100644 build/systemMenu_RED/PictoChat/banner/icon/gameIcon.bmp create mode 100644 build/systemMenu_RED/data/CardBanner.bnr create mode 100644 build/systemMenu_RED/data/DownloadBanner.bnr create mode 100644 build/systemMenu_RED/data/EmptyBanner.bnr create mode 100644 build/systemMenu_RED/data/NTR_IPL_font_l.NFTR create mode 100644 build/systemMenu_RED/data/NTR_IPL_font_m.NFTR create mode 100644 build/systemMenu_RED/data/NTR_IPL_font_s.NFTR create mode 100644 build/systemMenu_RED/data/PictoChatBanner.bnr create mode 100644 build/systemMenu_RED/data/SettingBanner.bnr create mode 100644 build/tools/.DS_Store create mode 100644 build/tools/Makefile create mode 100644 build/tools/acsign/Makefile create mode 100644 build/tools/acsign/acsign.c create mode 100644 build/tools/acsign/acsign_gcd.c create mode 100644 build/tools/acsign/acsign_nand.c create mode 100644 build/tools/acsign/acsign_nor.c create mode 100644 build/tools/acsign/aes.h create mode 100644 build/tools/acsign/aes2.c create mode 100644 build/tools/acsign/aes2.h create mode 100644 build/tools/acsign/aes_e.c create mode 100644 build/tools/acsign/aes_e.h create mode 100644 build/tools/acsign/aes_e_ecb.c create mode 100644 build/tools/acsign/aes_sbox.h create mode 100644 build/tools/acsign/aes_skey.c create mode 100644 build/tools/acsign/bn_add.c create mode 100644 build/tools/acsign/bn_asm.c create mode 100644 build/tools/acsign/bn_comba.c create mode 100644 build/tools/acsign/bn_div.c create mode 100644 build/tools/acsign/bn_ex_str.c create mode 100644 build/tools/acsign/bn_exp.c create mode 100644 build/tools/acsign/bn_fm_w.c create mode 100644 build/tools/acsign/bn_gcd.c create mode 100644 build/tools/acsign/bn_lib.c create mode 100644 build/tools/acsign/bn_lsh.c create mode 100644 build/tools/acsign/bn_m_exp.c create mode 100644 build/tools/acsign/bn_me.c create mode 100644 build/tools/acsign/bn_mont.c create mode 100644 build/tools/acsign/bn_ms_w.c create mode 100644 build/tools/acsign/bn_mul.c create mode 100644 build/tools/acsign/bn_r_exp.c create mode 100644 build/tools/acsign/bn_rec.c create mode 100644 build/tools/acsign/bn_recp.c create mode 100644 build/tools/acsign/bn_rsh.c create mode 100644 build/tools/acsign/bn_sqr.c create mode 100644 build/tools/acsign/bn_wdiv.c create mode 100644 build/tools/acsign/bn_word.c create mode 100644 build/tools/acsign/include/acsign.h create mode 100644 build/tools/acsign/include/acsign_gcd.h create mode 100644 build/tools/acsign/include/acsign_nand.h create mode 100644 build/tools/acsign/include/acsign_nor.h create mode 100644 build/tools/acsign/include/bn.h create mode 100644 build/tools/acsign/include/bn_lcl.h create mode 100644 build/tools/acsign/include/bn_thx.h create mode 100644 build/tools/acsign/include/r_error.h create mode 100644 build/tools/acsign/include/r_stdiag.h create mode 100644 build/tools/acsign/include/r_types.h create mode 100644 build/tools/acsign/include/sha.h create mode 100644 build/tools/acsign/include/sha1.h create mode 100644 build/tools/acsign/include/sha_locl.h create mode 100644 build/tools/acsign/sha1.c create mode 100644 build/tools/acsign/sha1dgst.c create mode 100644 build/tools/makegcdfirm/Makefile create mode 100644 build/tools/makegcdfirm/compress.c create mode 100644 build/tools/makegcdfirm/compress.h create mode 100644 build/tools/makegcdfirm/defval.c create mode 100644 build/tools/makegcdfirm/defval.h create mode 100644 build/tools/makegcdfirm/elf.h create mode 100644 build/tools/makegcdfirm/format_nlist.h create mode 100644 build/tools/makegcdfirm/format_rom.h create mode 100644 build/tools/makegcdfirm/format_sign.h create mode 100644 build/tools/makegcdfirm/gcdfirm_header_twlj.template.sbin create mode 100644 build/tools/makegcdfirm/makegcdfirm.c create mode 100644 build/tools/makegcdfirm/makegcdfirm.h create mode 100644 build/tools/makegcdfirm/misc.c create mode 100644 build/tools/makegcdfirm/misc.h create mode 100644 build/tools/makegcdfirm/out_gcdfirm.c create mode 100644 build/tools/makegcdfirm/path.c create mode 100644 build/tools/makegcdfirm/path.h create mode 100644 build/tools/makegcdfirm/test/Makefile create mode 100644 build/tools/makegcdfirm/test/nandfirm_print.nand create mode 100644 build/tools/makegcdfirm/test/norfirm_print.nor create mode 100644 build/tools/makegcdfirm/test/rsa_private.der create mode 100644 build/tools/makegcdfirm/test/test.gcdsf create mode 100644 build/tools/makegcdfirm/test/twl_gcdfirm7_print.axf create mode 100644 build/tools/makegcdfirm/test/twl_gcdfirm7_print.sbin create mode 100644 build/tools/makegcdfirm/test/twl_gcdfirm9_print.axf create mode 100644 build/tools/makegcdfirm/test/twl_gcdfirm9_print.sbin create mode 100644 build/tools/makegcdfirm/test/wram_rbin/Makefile create mode 100644 build/tools/makegcdfirm/test/wram_rbin/wram_regs.c create mode 100644 build/tools/makegcdfirm/wram_regs.c create mode 100644 build/tools/makenandfirm/Makefile create mode 100644 build/tools/makenandfirm/compress.c create mode 100644 build/tools/makenandfirm/compress.h create mode 100644 build/tools/makenandfirm/defval.c create mode 100644 build/tools/makenandfirm/defval.h create mode 100644 build/tools/makenandfirm/elf.h create mode 100644 build/tools/makenandfirm/format_nlist.h create mode 100644 build/tools/makenandfirm/format_rom.h create mode 100644 build/tools/makenandfirm/format_sign.h create mode 100644 build/tools/makenandfirm/makenandfirm.c create mode 100644 build/tools/makenandfirm/makenandfirm.h create mode 100644 build/tools/makenandfirm/misc.c create mode 100644 build/tools/makenandfirm/misc.h create mode 100644 build/tools/makenandfirm/out_nandfirm.c create mode 100644 build/tools/makenandfirm/path.c create mode 100644 build/tools/makenandfirm/path.h create mode 100644 build/tools/makenandfirm/test/Makefile create mode 100644 build/tools/makenandfirm/test/rsa_private.der create mode 100644 build/tools/makenandfirm/test/test.nandsf create mode 100644 build/tools/makenandfirm/test/twl_nandfirm7_print.axf create mode 100644 build/tools/makenandfirm/test/twl_nandfirm7_print.sbin create mode 100644 build/tools/makenandfirm/test/twl_nandfirm9_print.axf create mode 100644 build/tools/makenandfirm/test/twl_nandfirm9_print.sbin create mode 100644 build/tools/makenandfirm/test/wram_rbin/Makefile create mode 100644 build/tools/makenandfirm/test/wram_rbin/wram_regs.c create mode 100644 build/tools/makenandfirm/wram_regs.c create mode 100644 build/tools/makenorfirm/Makefile create mode 100644 build/tools/makenorfirm/compress.c create mode 100644 build/tools/makenorfirm/compress.h create mode 100644 build/tools/makenorfirm/defval.c create mode 100644 build/tools/makenorfirm/defval.h create mode 100644 build/tools/makenorfirm/elf.h create mode 100644 build/tools/makenorfirm/format_nlist.h create mode 100644 build/tools/makenorfirm/format_rom.h create mode 100644 build/tools/makenorfirm/format_sign.h create mode 100644 build/tools/makenorfirm/makenorfirm.c create mode 100644 build/tools/makenorfirm/makenorfirm.h create mode 100644 build/tools/makenorfirm/misc.c create mode 100644 build/tools/makenorfirm/misc.h create mode 100644 build/tools/makenorfirm/out_norfirm.c create mode 100644 build/tools/makenorfirm/path.c create mode 100644 build/tools/makenorfirm/path.h create mode 100644 build/tools/makenorfirm/test/Makefile create mode 100644 build/tools/makenorfirm/test/rsa_private.der create mode 100644 build/tools/makenorfirm/test/test.norsf create mode 100644 build/tools/makenorfirm/test/twl_norfirm7_print.axf create mode 100644 build/tools/makenorfirm/test/twl_norfirm7_print.sbin create mode 100644 build/tools/makenorfirm/test/twl_norfirm9_print.axf create mode 100644 build/tools/makenorfirm/test/twl_norfirm9_print.sbin create mode 100644 build/tools/makenorfirm/test/wram_rbin/Makefile create mode 100644 build/tools/makenorfirm/test/wram_rbin/wram_regs.c create mode 100644 build/tools/makenorfirm/wram_regs.c create mode 100644 doc/NORフラッシュマップ.xls create mode 100644 doc/SystemMenu_REDリリース.txt create mode 100644 doc/TWL-NANDファーム二重化.vsd create mode 100644 doc/TWL_SystemMenuメモリマップ.vsd create mode 100644 doc/TWL_staticModule.xls create mode 100644 doc/TWLフォルダツリー&NUP.vsd create mode 100644 doc/rom_header_format.xls create mode 100644 include/.DS_Store create mode 100644 include/firm.h create mode 100644 include/firm/.DS_Store create mode 100644 include/firm/acsign.h create mode 100644 include/firm/aes.h create mode 100644 include/firm/aes/ARM7/aes_ids.h create mode 100644 include/firm/aes/ARM7/aes_init.h create mode 100644 include/firm/aes/ARM7/aes_util.h create mode 100644 include/firm/fatfs.h create mode 100644 include/firm/fatfs/ARM7/fatfs_firm.h create mode 100644 include/firm/fatfs/ARM7/fatfs_loader.h create mode 100644 include/firm/format/firm_common.h create mode 100644 include/firm/format/format_rom.h create mode 100644 include/firm/format/format_rom_certificate.h create mode 100644 include/firm/format/from_brom.h create mode 100644 include/firm/format/gcdfirm.h create mode 100644 include/firm/format/nandfirm.h create mode 100644 include/firm/format/norfirm.h create mode 100644 include/firm/format/sign.h create mode 100644 include/firm/format/wram_regs.h create mode 100644 include/firm/gcd.h create mode 100644 include/firm/gcd/blowfish.h create mode 100644 include/firm/gcd/gcd.h create mode 100644 include/firm/gcd/gcd_misc.h create mode 100644 include/firm/hw/ARM7/mmap_firm.h create mode 100644 include/firm/hw/ARM9/mmap_firm.h create mode 100644 include/firm/hw/common/mmap_firm.h create mode 100644 include/firm/memorymap.h create mode 100644 include/firm/mi.h create mode 100644 include/firm/mi/ARM9/mi_loader.h create mode 100644 include/firm/mi/exDma.h create mode 100644 include/firm/mi/mainMemory.h create mode 100644 include/firm/misc.h create mode 100644 include/firm/nvram.h create mode 100644 include/firm/os.h create mode 100644 include/firm/os/ARM9/os_cache_tag.h create mode 100644 include/firm/os/common/boot.h create mode 100644 include/firm/os/common/init.h create mode 100644 include/firm/os/common/system.h create mode 100644 include/firm/os/common/tick_brom.h create mode 100644 include/firm/pm.h create mode 100644 include/firm/pm/ARM7/pm_init.h create mode 100644 include/firm/pm/ARM7/pm_pmic_ex.h create mode 100644 include/firm/pxi.h create mode 100644 include/firm/pxi/common/misc.h create mode 100644 include/firm/pxi/common/regname_ex.h create mode 100644 include/firm/specfiles/ARM7-BB-FIRM.lcf.template create mode 100644 include/firm/specfiles/ARM7-BB-FIRM.lsf create mode 100644 include/firm/specfiles/ARM7-BB-GCDFIRM.lcf.template create mode 100644 include/firm/specfiles/ARM7-BB-GCDFIRM.lsf create mode 100644 include/firm/specfiles/ARM7-TS-FIRM.lcf.template create mode 100644 include/firm/specfiles/ARM7-TS-FIRM.lsf create mode 100644 include/firm/specfiles/ARM7-TS-GCDFIRM.lcf.template create mode 100644 include/firm/specfiles/ARM7-TS-GCDFIRM.lsf create mode 100644 include/firm/specfiles/ARM7-TS-PARTNER.lcf.template create mode 100644 include/firm/specfiles/ARM9-BB-FIRM.lcf.template create mode 100644 include/firm/specfiles/ARM9-BB-FIRM.lsf create mode 100644 include/firm/specfiles/ARM9-BB-GCDFIRM.lcf.template create mode 100644 include/firm/specfiles/ARM9-BB-GCDFIRM.lsf create mode 100644 include/firm/specfiles/ARM9-TS-FIRM.lcf.template create mode 100644 include/firm/specfiles/ARM9-TS-FIRM.lsf create mode 100644 include/firm/specfiles/ARM9-TS-GCDFIRM.lcf.template create mode 100644 include/firm/specfiles/ARM9-TS-GCDFIRM.lsf create mode 100644 include/firm/specfiles/ARM9-TS-PARTNER.lcf.template create mode 100644 include/firm/specfiles/ROM-TS.rsf create mode 100644 include/sysmenu.h create mode 100644 include/sysmenu/.DS_Store create mode 100644 include/sysmenu/acsign.h create mode 100644 include/sysmenu/acsign/ARM9/acsign.h create mode 100644 include/sysmenu/acsign/ARM9/acsign_util.h create mode 100644 include/sysmenu/banner.h create mode 100644 include/sysmenu/machineSettings.h create mode 100644 include/sysmenu/machineSettings/common/nitroSettings.h create mode 100644 include/sysmenu/mb_loader.h create mode 100644 include/sysmenu/mb_loader/common/mb_loader.h create mode 100644 include/sysmenu/memorymap.h create mode 100644 include/sysmenu/mmap.h create mode 100644 include/sysmenu/rom_header.h create mode 100644 include/sysmenu/sysmenu_lib.h create mode 100644 include/sysmenu/sysmenu_lib/ARM9/cmn.h create mode 100644 include/sysmenu/sysmenu_lib/ARM9/sysmenu_api.h create mode 100644 include/sysmenu/sysmenu_work.h create mode 100644 keys/dummy/rsa/private_gcd.der create mode 100644 keys/dummy/rsa/private_nand.der create mode 100644 keys/dummy/rsa/private_nor.der create mode 100644 keys/dummy/rsa/pubkey_gcd.der create mode 100644 keys/dummy/rsa/pubkey_nand.der create mode 100644 keys/dummy/rsa/pubkey_nor.der create mode 100644 readme.txt create mode 100644 setup create mode 100644 tools/.DS_Store create mode 100644 tools/bin/TXLib.dll create mode 100644 tools/bin/makebanner.exe create mode 100644 tools/bin/ntexconv.exe create mode 100644 tools/openssl/openssl.exe diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..3cd779d9ef353b84bdc90a8f812c8b0675df1ad6 GIT binary patch literal 6148 zcmeHLu}%U(5S^7HoY;`i*ch*{HIc&3;v|^Z^8?5oQ3H4+N?~_jWAr18zhdKm_-1#& zTaHbvjL{jg`;MKNeR~gXhlPktf0_4)Iz$wsF-C24Ta5kOYPKUI`#@voxTQO~pI!Hc zSy7AD0aZX1_-zXCv)iI8%JDj;%JVy4xTPLu^@w>f7>sAd7#`jjoONVyrKxdBtzzDCmR2lX7e?xD@mM3fACD_yU*;mJTrj(;os>2JKXVA64KJ DL72B7 literal 0 HcmV?d00001 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..be8c706 --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - build +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = build + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/add-ins/TwlSystem/NitroSystem_patch.zip b/add-ins/TwlSystem/NitroSystem_patch.zip new file mode 100644 index 0000000000000000000000000000000000000000..4eb1525b7fa8d96cf8399b89ce54b290c577cf51 GIT binary patch literal 7335 zcma)B1ymeMn;jemhrylT3^uq!2niM}1a~JeOaj3rxCMd)ch}$=GZ z_rKlE|FUoQZTG3F?sMw9UDZ`}>#O^zE2E$S0e@U+5z4~ z3d&>dV&`DVqyFFZOTzwIpXP7t|I6w%4CdhcFH_KcB}_p6{ig=-?{uBf0Dyix0D$$M zOf6tgD9q8)%G$Y2dlW_`50WasyQ3qvlfex5V=; z{5S0fZ3k(>wckwqDm>oGpqSst9-FqGjtX%ihd^puHNsNa6F0oAN>G#o`T6e?mp z+e?_1HuadCZ^oHzy^vpq{7b7nkleJ~j&?(AmKhJ4s$Q3-h{VBXBgSKT{Ml>)h3yrm zsJS2w<0ny$FbW~`s)yi>WExx5vb|&jMS@_Qv0i__YKl;Fq_@q(c+Pz9_}8Gjx?}t_ zs^QpQ2m$fB8-u$SV#y>I%z#cFVAzAWrqvg(c_Q`O>hI(+ z{&evp_)M720^WbZ35J&7^Goh0%st6xV4X zhD2^!4%}sE*pAl}x^|qAiN;G&434(f}HcsQIK2he>aRoR1v}npU3-$&5m8{=hwo5r;yr zNAfdYGo&y$-si5-3*TFi&i8Qn_IUr`rUQ;RS(_7|8_{T)-!ZUsN2|9TZR8POA7dIm zU`Mm7ab7m41epv^16Mi+I_-NGIL{2N1Oo-09JEr%*Mi21eTnm5KM0P9W~ZL8N<*#6 zs46jBENyAa7kvwXGC$X>VVnnXq=`i_Hdt7{-SZ%2@IhukaT**uGD%}hPDJ|_aOqqN zC?N)Lm~vv{NPZyO#_JyLze#VrS?(J5UJq1 z_q^z7!zz1T7*5LB%fVz!?ZHn~o)OjucEJ&hrx&vcm&0`-jSzQ-3^S^<$i@o5WpNEU z$0l>c3|wu~=56TO2LEeXqm&NsbV)gb zjVdgzeQyt!`qljUofvmGb%>bV^b9wV;AMEh-s=d%xy>ajNOl-I}X zrgnIb;Li2cBEvaN+U46y%vmCbyiSy)q+`RF8ec;Z7%72=GW+v(h+Μi#m(W#Vwc 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 a@7neY2km|o0RXJ~d*ohT>!$eQ?LPp)_wL;Q literal 0 HcmV?d00001 diff --git a/add-ins/TwlSystem/使用方法.txt b/add-ins/TwlSystem/使用方法.txt new file mode 100644 index 0000000..2572dc4 --- /dev/null +++ b/add-ins/TwlSystem/使用方法.txt @@ -0,0 +1,25 @@ +--------------- +̃pb`͎bIȂ NitroSystem +TWL-SDK Ńrh/gpł悤ɂ̂łB +Yt zip t@CWJ NitroSystem ɏ㏑ĂB + + +ETWLSYSTEM_ROOT ‹ϐ NITROSYSTEM_ROOT ‹ϐ +@lݒ肷Kv܂B +ENitroSystem ̓rhȂKv܂B +Esnd, mcs Cu͎gpł܂B +Edemo ͂̂܂܂ł̓rhł܂B +@TWL-SDK ł nef tef ֕ύXꂽ +@TARGET_NEF ݒ肳Ă͍̂폜Kv܂B +---- + + +demõrhʂ@ + +LLIBRARY_DIRS = $(G2D_DEMOLIB)/lib/$(NITRO_BUILDTYPE) + +LLIBRARY_DIRS = $(G2D_DEMOLIB)/$(LIBDIR) + + +TARGET_NEF = main.nef@폜B + diff --git a/build/.DS_Store b/build/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5acca63d74a4f9b72ae6ca2831006d45772dc4a4 GIT binary patch literal 8196 zcmeHMy-piJ5S}F_{7ES3C=b#gD(Ij)tRq!Y5FP;Rm>)|%4jEj~-8-bnBZM@0gOm{^ z5igJ?>3Iac*FDrFG@Mjwtc;?7C{R@(!PGppX+T|6?N0sPJKos)T;ylQrTHa>%Zn^) z_lh>w`4PPO_w)O99NVdlJv(vZYZ`N4*ag=cpiZN9%*S^oNq_s!TCZZ>s&ygXEi5ZI@~JdUu7kcH3v`a=lg z^2PdapI5HsavX;X@R|WHRyD|KmyhWFL%5tyZyz+QphkNjj`H}>Zv?}=FngEpZ%!Z0 z4#vIzL_3sun$1uBeGKn%1$L<4*ccHl$NG4AEZlJ()1y;KkM+ANe*T=*2uBYw($dMo zL3r_34*-%T3QVK|uMDdtuK#!9=l>JQT}X)nqQKKApc>g;*2J}JZC$x4*V+mC0XjFv umBwlp47wbL)#W(s!yktDo&d@|skNoCm_d8?gMd+0BkzBG2V{7O3fu$aL02mP literal 0 HcmV?d00001 diff --git a/build/Makefile b/build/Makefile new file mode 100644 index 0000000..a3f0a1e --- /dev/null +++ b/build/Makefile @@ -0,0 +1,37 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - build +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + tools \ + libraries \ + nandfirm \ + nand_formatter \ + libraries_sysmenu\ + systemmenu_RED + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/buildtools/commondefs b/build/buildtools/commondefs new file mode 100644 index 0000000..d091bed --- /dev/null +++ b/build/buildtools/commondefs @@ -0,0 +1,30 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - commondefs - common definitions for build system +# File: commondefs +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +ifndef TWL_IPL_COMMONDEFS_ +TWL_IPL_COMMONDEFS_ = TRUE + + +ifeq ($(TARGET_FIRM),SYSTEMMENU) +include $(TWLIPL_ROOT)/build/buildtools/commondefs.sysmenu +else +include $(TWLIPL_ROOT)/build/buildtools/commondefs.firm +endif + +#---------------------------------------------------------------------------- +endif # TWL_IPL_COMMONDEFS_ +#----- End of commondefs ----- diff --git a/build/buildtools/commondefs.firm b/build/buildtools/commondefs.firm new file mode 100644 index 0000000..d8a8d2b --- /dev/null +++ b/build/buildtools/commondefs.firm @@ -0,0 +1,260 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - commondefs - common definitions for build system +# File: commondefs +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +ifndef TWLFIRM_COMMONDEFS_ +TWLFIRM_COMMONDEFS_ = TRUE + +NITRO_NO_STD_PCHDR = TRUE # vRpCwb_}~ + +ifndef TWL_KEYSDIR +DUMMY_KEYS_SUFFIX = .dummykey +endif +TWL_KEYSDIR ?= $(FIRM_ROOT)/keys/dummy + + +ifneq ($(filter FIRM GCDFIRM,$(FIRM_TARGET)),) +TARGET_BIN ?= $(subst .,$(DUMMY_KEYS_SUFFIX).,$(TARGET_FIRM_BIN)) +endif + +EMPTY ?= +SPACE ?= $(EMPTY) $(EMPTY) + +# +# CodeGen Target +# +# FIRM_PLATFORM = [BB/EVA/TS] +# FIRM_MEMSIZE = [16M/32M] +# FIRM_CODEGEN = [ARM/THUMB] +# FIRM_PROC = [ARM9/ARM7] +# +# FIRM_TARGET = [FIRM/GCDFIRM/APP] +# + +FIRM_PLATFORM ?= TS +FIRM_MEMSIZE ?= 16M +FIRM_CODEGEN ?= ARM +FIRM_PROC ?= ARM9 +FIRM_TARGET ?= APP + +# replace TwlSDK +TWL_PLATFORM = $(FIRM_PLATFORM) +TWL_MEMSIZE = $(FIRM_MEMSIZE) +TWL_CODEGEN = $(FIRM_CODEGEN) +TWL_PROC = $(FIRM_PROC) + +# replace NitroSDK +ifndef CODEGEN_PROC +CODEGEN_PROC := $(FIRM_PROC) +endif + +ifeq ($(FIRM_CODEGEN),ALL) +FIRM_CODEGEN_ALL ?= TRUE +override FIRM_CODEGEN = ARM +endif + +ifeq ($(FIRM_CODEGEN),ARM) +FIRM_CODEGEN_ARCH = +else # ($(FIRM_CODEGEN),THUMB) +FIRM_CODEGEN_ARCH = .thumb +endif + +# +# SDK build type +# +# one of [FIRM_DEBUG/FIRM_RELEASE/FIRM_FINALROM] +# + +ifdef FIRM_DEBUG +FIRM_BUILD_TYPE ?= DEBUG +FIRM_BUILD_DIR ?= Debug + +else +ifdef FIRM_FINALROM +FIRM_BUILD_TYPE ?= FINALROM +FIRM_BUILD_DIR ?= Rom + +else # FIRM_RELEASE (default) +FIRM_BUILD_TYPE ?= RELEASE +FIRM_BUILD_DIR ?= Release + +endif +endif + +# replace TwlSDK +TWL_BUILD_TYPE ?= $(FIRM_BUILD_TYPE) +TWL_BUILD_DIR ?= $(FIRM_BUILD_DIR) + + + +#---------------------------------------------------------------------------- +# TWL-FIRM path settings +# + +FIRM_ROOT := $(subst $(SPACE),\ ,$(subst \,/,$(TWLIPL_ROOT))) +FIRM_BUILDTOOLSDIR := $(FIRM_ROOT)/build/buildtools +FIRM_BUILDSETUPDIR := $(FIRM_ROOT)/build/buildsetup +FIRM_INCDIR := $(FIRM_ROOT)/include +FIRM_TOOLSDIR := $(FIRM_ROOT)/tools +FIRM_COMPONENTSDIR := $(FIRM_ROOT)/components +FIRM_ADDINS ?= $(FIRM_ROOT)/add-ins + +FIRM_TWLSDK_ROOT ?=$(shell cygpath -w $(TWLSDK_ROOT)) +FIRM_NITROSDK_ROOT ?=$(shell cygpath -w $(NITROSDK_ROOT)) + +FIRM_BUILDARCH ?= $(CODEGEN_PROC)-$(FIRM_PLATFORM)$(FIRM_CODEGEN_ARCH) +FIRM_BUILDARCH_ARM9 := ARM9-$(FIRM_PLATFORM)$(FIRM_CODEGEN_ARCH) +FIRM_BUILDARCH_ARM7 := ARM7-$(FIRM_PLATFORM)$(FIRM_CODEGEN_ARCH) + +FIRM_BUILDTYPE ?= $(FIRM_BUILDARCH)/$(FIRM_BUILD_DIR) +FIRM_BUILDTYPE_ARM9 := $(FIRM_BUILDARCH_ARM9)/$(FIRM_BUILD_DIR) +FIRM_BUILDTYPE_ARM7 := $(FIRM_BUILDARCH_ARM7)/$(FIRM_BUILD_DIR) + +FIRM_LIBARCH := $(CODEGEN_PROC)-$(FIRM_PLATFORM) +FIRM_LIBTYPE := $(FIRM_LIBARCH)/$(FIRM_BUILD_DIR) +FIRM_LIBDIR := $(FIRM_ROOT)/lib/$(FIRM_LIBTYPE) +FIRM_LIBSYSCALLDIR := $(FIRM_ROOT)/lib/$(FIRM_LIBARCH)/etc +FIRM_LIBSUFFIX := .firm$(FIRM_CODEGEN_ARCH) + + +FIRM_SPECDIR := $(FIRM_INCDIR)/firm/specfiles +FIRM_LSFARCH := $(FIRM_LIBARCH) +ifneq ($(FIRM_TARGET),APP) +FIRM_LSFARCH := $(addsuffix -$(FIRM_TARGET),$(FIRM_LSFARCH)) +endif # FIRM_TARGET!=APP +FIRM_LCFARCH := $(FIRM_LSFARCH) +DEFAULT_FIRM_LCFILE := $(FIRM_SPECDIR)/$(FIRM_LCFARCH).lcf +DEFAULT_FIRM_LCFILE_TEMPLATE := $(FIRM_SPECDIR)/$(FIRM_LCFARCH)$(LCF_SUFFIX_).lcf.template +DEFAULT_FIRM_LCFILE_SPEC := $(FIRM_SPECDIR)/$(FIRM_LSFARCH).lsf +DEFAULT_FIRM_ROM_SPEC := $(FIRM_SPECDIR)/ROM-$(FIRM_PLATFORM).rsf + +# replace TwlSDK +TWL_BUILDARCH ?= $(FIRM_BUILDARCH) + + +### Compiler & Linker settings + +# replace NitroSDK +ifneq ($(FIRM_TARGET),APP) +LCFILE_TEMPLATE ?= $(DEFAULT_FIRM_LCFILE_TEMPLATE) +LCFILE_SPEC ?= $(DEFAULT_FIRM_LCFILE_SPEC) +ROM_SPEC ?= $(DEFAULT_FIRM_ROM_SPEC) +endif # FIRM_TARGET!=APP + +LDEPENDS_LCF += $(FIRM_BUILDTOOLSDIR)/commondefs +LDEPENDS_RES += $(FIRM_BUILDTOOLSDIR)/commondefs + + +### SDK Library settings + +ifeq ($(CODEGEN_PROC),ARM9) + +FIRM_LIBS_BASE ?= \ + libos \ + libmi \ + libpxi \ +# libgcd \ +# libacsign \ + +FIRM_TWL_LIBS_BASE ?= \ + +else # ($(CODEGEN_PROC),ARM7) + +FIRM_LIBS_BASE ?= \ + libos_sp \ + libfatfs_sp \ + libpxi_sp \ + libaes_sp \ + libpm_sp \ +# libnvram_sp \ +# libgcd_sp \ +# libacsign_sp \ +# libfirmsd_sp \ + +FIRM_TWL_LIBS_BASE ?= \ + +endif + +FIRM_LIBS ?= $(addsuffix $(FIRM_LIBSUFFIX).a,$(FIRM_LIBS_BASE)) +FIRM_LIBS += $(addsuffix $(TWL_LIBSUFFIX).a,$(FIRM_TWL_LIBS_BASE)) + +#---------------------------------------------------------------------------- +### TWL-commondefs +# +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- +# MY BUILD TOOLS +# +MAKENORFIRM := $(FIRM_TOOLSDIR)/bin/makenorfirm.exe +MAKENANDFIRM := $(FIRM_TOOLSDIR)/bin/makenandfirm.exe +MAKEGCDFIRM := $(FIRM_TOOLSDIR)/bin/makegcdfirm.exe +OPENSSL := $(FIRM_TOOLSDIR)/openssl/openssl.exe + +MAKEFIRM_RSA_PRVKEY ?= $(FIRM_TOOLSDIR)/openssl/rsa_private.der +MAKEFIRM_RSA_PUBKEY ?= $(FIRM_TOOLSDIR)/openssl/rsa_public.der + +MAKEFIRM_FLAGS ?= + +ifneq ($(filter FIRM GCDFIRM,$(FIRM_TARGET)),) +FIRM_STRIP_AXF := TRUE +endif + +#---------------------------------------------------------------------------- + +### Global Library resettings + +GINCLUDES := $(FIRM_INCDIR) $(GINCLUDES) +GLIBRARY_DIRS := $(FIRM_LIBDIR) $(GLIBRARY_DIRS) +GLIBRARIES := $(FIRM_LIBS) $(GLIBRARIES) + + +#---------------------------------------------------------------------------- +# TWLFIRM_INSTALL_ROOT +# + +ifdef TWLFIRM_INSTALL_ROOT +TWLFIRM_INSTALL_ROOT_ := $(TWLFIRM_INSTALL_ROOT) +else +TWLFIRM_INSTALL_ROOT_ := $(TWLIPL_ROOT) +endif + +FIRM_INSTALL_ROOT := $(subst $(SPACE),\ ,$(subst \,/,$(TWLFIRM_INSTALL_ROOT_))) +FIRM_INSTALL_INCDIR := $(FIRM_INSTALL_ROOT)/include +FIRM_INSTALL_TOOLSDIR := $(FIRM_INSTALL_ROOT)/tools +FIRM_INSTALL_LIBDIR := $(FIRM_INSTALL_ROOT)/lib/$(FIRM_LIBTYPE) +FIRM_INSTALL_PROMDIR := $(FIRM_INSTALL_TOOLSDIR)/prom +FIRM_INSTALL_COMPONENTSDIR := $(FIRM_INSTALL_ROOT)/components +FIRM_INSTALL_ADDINS := $(FIRM_INSTALL_ROOT)/add-ins + + +#---------------------------------------------------------------------------- +# Compiler flags +# +MACRO_FLAGS += -DFIRM_TARGET_$(FIRM_TARGET) + + +#---------------------------------------------------------------------------- +# Makelcf change for build firmware +# +ifneq ($(filter FIRM GCDFIRM,$(FIRM_TARGET)),) +MAKELCF := $(TWLSDK_ROOT)/tools/bin/makelcf.exe +endif + +#---------------------------------------------------------------------------- +endif # TWLFIRM_COMMONDEFS_ +#----- End of commondefs ----- diff --git a/build/buildtools/commondefs.sysmenu b/build/buildtools/commondefs.sysmenu new file mode 100644 index 0000000..64dd0dc --- /dev/null +++ b/build/buildtools/commondefs.sysmenu @@ -0,0 +1,97 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - commondefs - common definitions for build system +# File: commondefs +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +ifndef TWL_SYSMENU_COMMONDEFS_ +TWL_SYSMENU_COMMONDEFS_ = TRUE + +NITRO_NO_STD_PCHDR = TRUE # vRpCwb_}~ + +EMPTY ?= +SPACE ?= $(EMPTY) $(EMPTY) + +#---------------------------------------------------------------------------- +# TWL-SYSTEM-MENU path settings +# + +SYSMENU_ROOT := $(subst $(SPACE),\ ,$(subst \,/,$(TWLIPL_ROOT))) +SYSMENU_BUILDTOOLSDIR := $(SYSMENU_ROOT)/build/buildtools +SYSMENU_INCDIR := $(SYSMENU_ROOT)/include \ + $(TWLSDK_ROOT)/build/libraries/spi/arm9/include \ + $(TWLSDK_ROOT)/build/libraries/mb/common/include +SYSMENU_TOOLSDIR := $(SYSMENU_ROOT)/tools +SYSMENU_COMPONENTSDIR := $(SYSMENU_ROOT)/components + +LDEPENDS_LCF += $(SYSMENU_BUILDTOOLSDIR)/commondefs.sysmenu +LDEPENDS_RES += $(SYSMENU_BUILDTOOLSDIR)/commondefs.sysmenu + + +#---------------------------------------------------------------------------- +### TWL-commondefs +# +#include $(TWLSDK_ROOT)/build/buildtools/commondefs +include $(NITROSYSTEM_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- +### SYSTEM_MENU Library settings + +SYSMENU_LIBDIR := $(SYSMENU_ROOT)/lib/$(TWL_LIBTYPE) + +ifeq ($(CODEGEN_PROC),ARM9) + +SYSMENU_LIBS ?= \ + libsysmenu$(TWL_LIBSUFFIX).a \ + libmbloader$(TWL_LIBSUFFIX).a \ + libacsign$(TWL_LIBSUFFIX).a + +else # ($(CODEGEN_PROC),ARM7) + +SYSMENU_LIBS ?= \ + libmbloader_sp$(TWL_LIBSUFFIX).a + +endif + + +#---------------------------------------------------------------------------- +# MY BUILD TOOLS +# +OPENSSL := $(SYSMENU_TOOLSDIR)/openssl/openssl.exe + +MAKESYSMENU_RSA_PRVKEY ?= $(SYSMENU_TOOLSDIR)/openssl/rsa_private.der +MAKESYSMENU_RSA_PUBKEY ?= $(SYSMENU_TOOLSDIR)/openssl/rsa_public.der + +#---------------------------------------------------------------------------- + +### Global Library resettings + +GINCLUDES := $(SYSMENU_INCDIR) $(GINCLUDES) +GLIBRARY_DIRS := $(SYSMENU_LIBDIR) $(GLIBRARY_DIRS) +GLIBRARIES := $(SYSMENU_LIBS) $(GLIBRARIES) + + +#---------------------------------------------------------------------------- +# TWLSYSMENU_INSTALL_ROOT +# +SYSMENU_INSTALL_ROOT := $(SYSMENU_ROOT) +SYSMENU_INSTALL_INCDIR := $(SYSMENU_INSTALL_ROOT)/include +SYSMENU_INSTALL_TOOLSDIR := $(SYSMENU_INSTALL_ROOT)/tools +SYSMENU_INSTALL_LIBDIR := $(SYSMENU_INSTALL_ROOT)/lib/$(TWL_LIBTYPE) +SYSMENU_INSTALL_COMPONENTSDIR := $(SYSMENU_INSTALL_ROOT)/components + +#---------------------------------------------------------------------------- +endif # TWL_SYSMENU_COMMONDEFS_ +#----- End of commondefs ----- diff --git a/build/buildtools/modulerules b/build/buildtools/modulerules new file mode 100644 index 0000000..e6a5189 --- /dev/null +++ b/build/buildtools/modulerules @@ -0,0 +1,34 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - modulerules - common rules for build system +# File: modulerules +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +ifndef TWL_IPL_MODULERULES_ + +#---------------------------------------------------------------------------- +### TWL-modulerules +# + +ifeq ($(TARGET_FIRM),SYSTEMMENU) +include $(TWLIPL_ROOT)/build/buildtools/modulerules.sysmenu +else +include $(TWLIPL_ROOT)/build/buildtools/modulerules.firm +endif + + +#---------------------------------------------------------------------------- +TWL_IPL_MODULERULES_ = TRUE +endif # TWL_IPL_MODULERULES_ +#----- End of modulerules ----- diff --git a/build/buildtools/modulerules.firm b/build/buildtools/modulerules.firm new file mode 100644 index 0000000..4ea316f --- /dev/null +++ b/build/buildtools/modulerules.firm @@ -0,0 +1,92 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - modulerules - common rules for build system +# File: modulerules +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +ifndef TWLFIRM_MODULERULES_ + + +ifneq ($(MAKEFIRM_ARM9),) +MAKEROM_ARM9 = $(MAKEFIRM_ARM9) +endif +ifneq ($(MAKEFIRM_ARM7),) +MAKEROM_ARM7 = $(MAKEFIRM_ARM7) +endif + +#---------------------------------------------------------------------------- +### TWL-modulerules +# +include $(TWLSDK_ROOT)/build/buildtools/modulerules + +#---------------------------------------------------------------------------- + +# +# MAKENORFIRM / MAKENANDFIRM / MAKEGCDFIRM +# + +MAKEFIRM_ARM9 ?= $(MAKEROM_ARM9) +MAKEFIRM_ARM7 ?= $(MAKEROM_ARM7) + +MAKEFIRM_DEFS += -DFIRM_ROOT='$(FIRM_ROOT)' \ + -DMAKEFIRM_ARM9='$(basename $(MAKEFIRM_ARM9))' \ + -DMAKEFIRM_ARM7='$(basename $(MAKEFIRM_ARM7))' \ + -DMAKEFIRM_RSA_PRVKEY='$(MAKEFIRM_RSA_PRVKEY)' \ + +SDEPENDS_BIN += $(MAKEFIRM_RSA_PRVKEY) + + +.PHONY: firmtop firmlib + +firmtop: + @$(MAKE) -C $(TWLIPL_ROOT)/build + +firmlib: + @$(MAKE) -C $(TWLIPL_ROOT)/build/libraries + +# .nor +$(BINDIR)/%.nor: $(SDEPENDS_BIN) $(FIRM_SPEC) $(LDEPENDS_BIN) $(EDEPENDS_BIN) $(MAKEFILE) $(MAKENORFIRM) + $(MAKENORFIRM) $(MAKEFIRM_FLAGS) $(MAKEFIRM_DEFS) $(FIRM_SPEC) $@ + +# .nand +$(BINDIR)/%.nand: $(SDEPENDS_BIN) $(FIRM_SPEC) $(LDEPENDS_BIN) $(EDEPENDS_BIN) $(MAKEFILE) $(MAKENANDFIRM) + $(MAKENANDFIRM) $(MAKEFIRM_FLAGS) $(MAKEFIRM_DEFS) $(FIRM_SPEC) $@ + +# .gcd +$(BINDIR)/%.gcd: $(SDEPENDS_BIN) $(FIRM_SPEC) $(LDEPENDS_BIN) $(EDEPENDS_BIN) $(MAKEFILE) $(MAKEGCDFIRM) + $(MAKEGCDFIRM) $(MAKEFIRM_FLAGS) $(MAKEFIRM_DEFS) $(FIRM_SPEC) $@ + +# .rbin +$(BINDIR)/$(TARGET_BIN_BASENAME).rbin: $(OBJS) + objcopy -I elf32-little -O binary $< $@ + +# .axf +#$(BINDIR)/$(TARGET_BIN_BASENAME).axf: $(OBJS) $(LCFILE) $(MAKEFILE) $(LDEPENDS_NEF) $(EDEPENDS_NEF) $(ALIBRARIES) $(LDRES_FILE) $(CW_LIBCXX) +#ifeq ($(NITRO_CCTYPE),RVCT) +# $(LD) $(LDFLAGS) $(LIBRARY_DIRS) -o $@ $(GLIBRARIES) $(OBJS) +#else +# $(LD) $(LDFLAGS) $(LIBRARY_DIRS) @$(LDRES_FILE) $(LCFILE) -o $@ +#ifeq ($(TWL_PLATFORM),TS) +# cp $(BINDIR)/$(TARGET_BIN_BASENAME).axf $(BINDIR)/$(TARGET_BIN_BASENAME).tef +#else # ($(TWL_PLATFORM),BB) +#ifdef FIRM_STRIP_AXF +# $(OBJCOPY) $@ $(BINDIR)/$(TARGET_BIN_BASENAME).sbin +#endif +#endif +#endif + +#---------------------------------------------------------------------------- +TWLFIRM_MODULERULES_ = TRUE +endif # TWLFIRM_MODULERULES_ +#----- End of modulerules ----- diff --git a/build/buildtools/modulerules.sysmenu b/build/buildtools/modulerules.sysmenu new file mode 100644 index 0000000..ff50b1e --- /dev/null +++ b/build/buildtools/modulerules.sysmenu @@ -0,0 +1,30 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - modulerules - common rules for build system +# File: modulerules +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +ifndef TWL_SYSMENU_MODULERULES_ + +#---------------------------------------------------------------------------- +### TWL-modulerules +# +#include $(TWLSDK_ROOT)/build/buildtools/modulerules +include $(NITROSYSTEM_ROOT)/build/buildtools/modulerules + + +#---------------------------------------------------------------------------- +TWL_SYSMENU_MODULERULES_ = TRUE +endif # TWL_SYSMENU_MODULERULES_ +#----- End of modulerules ----- diff --git a/build/libraries/.DS_Store b/build/libraries/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..191272fe03eac5e77545ed990575df2c142c10b9 GIT binary patch literal 6148 zcmeHK!Ab)$5S_Fu6ulI@^q5bu;0LT_1<&^2wYJq-=(+_f6uc~W^Go#RSrGgQe?ai; zFZd=I+fCbeRFN4--gaJQU-Pz`G(==N*TXhZlZYB_QnTW2`MKpyC^lE#om(Z9l z(Pn`nz1~#0h~}a;qPpM%U98548s#(&HE)l;@)12(6VY;9phGWSr&xWG$0tq)`KXTL zHa@)?feUp?uQR1QoR6J59ps}rj*IAk3w2V~sne9^tIqAeEt!ax)J5DAHq`5}-fxBf zl~9A&f)YSk0 literal 0 HcmV?d00001 diff --git a/build/libraries/Makefile b/build/libraries/Makefile new file mode 100644 index 0000000..43e0847 --- /dev/null +++ b/build/libraries/Makefile @@ -0,0 +1,44 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + os \ + gcd \ + mi \ + init \ + pxi \ + fatfs \ + aes \ + pm \ +# syscall \ +# nvram \ +# acsign \ +# acsign_ecc \ +# devices \ + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/aes/ARM7/Makefile b/build/libraries/aes/ARM7/Makefile new file mode 100644 index 0000000..a19bb1d --- /dev/null +++ b/build/libraries/aes/ARM7/Makefile @@ -0,0 +1,60 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries - aes +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = +SUBMAKES = + + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= TRUE + +# Codegen for sub processer +FIRM_PROC = ARM7 + +SRCDIR = . + +SRCS = \ + aes_init.c \ + aes_util.c \ + +TARGET_LIB = libaes_sp$(FIRM_LIBSUFFIX).a + +#---------------------------------------------------------------------------- + +# DEBUGŃrh̏ꍇARELEASEłŃrh +# DEBUGł̃Cu𑕂܂B + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/libraries/aes/ARM7/aes_init.c b/build/libraries/aes/ARM7/aes_init.c new file mode 100644 index 0000000..9f37d4c --- /dev/null +++ b/build/libraries/aes/ARM7/aes_init.c @@ -0,0 +1,72 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - aes + File: aes_init.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +/*---------------------------------------------------------------------------* + Name: AESi_InitGameKeys + + Description: set IDs depending on the application. + you SHOULD NOT touch any ID registers after this call. + + Arguments: u8[4] game code + + Returns: None + *---------------------------------------------------------------------------*/ +void AESi_InitGameKeys( u8 game_code[4] ) +{ + while (reg_AES_AES_CNT & REG_AES_AES_CNT_E_MASK) + { + } + + reg_AES_AES_ID_B2 = AES_IDS_ID0_C(game_code); + reg_AES_AES_ID_B3 = AES_IDS_ID0_D(game_code); + + reg_AES_AES_ID_C0 = AES_IDS_ID1_A(game_code); + reg_AES_AES_ID_C1 = AES_IDS_ID1_B(game_code); + + // set dummy without seed[3] + reg_AES_AES_SEED_A0 = 1; + reg_AES_AES_SEED_A1 = 2; + reg_AES_AES_SEED_A2 = 3; + reg_AES_AES_SEED_B0 = 4; + reg_AES_AES_SEED_B1 = 5; + reg_AES_AES_SEED_B2 = 6; + reg_AES_AES_SEED_C0 = 7; + reg_AES_AES_SEED_C1 = 8; + reg_AES_AES_SEED_C2 = 9; + reg_AES_AES_SEED_D0 = 10; + reg_AES_AES_SEED_D1 = 11; + reg_AES_AES_SEED_D2 = 12; + + reg_AES_AES_KEY_A0 = 1; + reg_AES_AES_KEY_A1 = 2; + reg_AES_AES_KEY_A2 = 3; + reg_AES_AES_KEY_A3 = 3; + reg_AES_AES_KEY_B0 = 4; + reg_AES_AES_KEY_B1 = 5; + reg_AES_AES_KEY_B2 = 6; + reg_AES_AES_KEY_B3 = 6; + reg_AES_AES_KEY_C0 = 7; + reg_AES_AES_KEY_C1 = 8; + reg_AES_AES_KEY_C2 = 9; + reg_AES_AES_KEY_C3 = 9; + reg_AES_AES_KEY_D0 = 10; + reg_AES_AES_KEY_D1 = 11; + reg_AES_AES_KEY_D2 = 12; + reg_AES_AES_KEY_D3 = 12; +} diff --git a/build/libraries/aes/ARM7/aes_util.c b/build/libraries/aes/ARM7/aes_util.c new file mode 100644 index 0000000..47e8298 --- /dev/null +++ b/build/libraries/aes/ARM7/aes_util.c @@ -0,0 +1,46 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - aes + File: aes_util.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +/*---------------------------------------------------------------------------* + Name: AESi_AddCounter + + Description: calculate updated counter + + Arguments: pCounter pointer to the counter at offset 0 + nums offset in blocks (AES_BLOCK_SIZE) + + Returns: None + *---------------------------------------------------------------------------*/ +void AESi_AddCounter(AESCounter* pCounter, u32 nums) +{ + u32 data = 0; + int i; + for (i = 0; i < 16; i++) + { + data += pCounter->bytes[i] + (nums & 0xFF); + pCounter->bytes[i] = (u8)(data & 0xFF); + data >>= 8; + nums >>= 8; + if ( !data && !nums ) + { + break; + } + } +} + diff --git a/build/libraries/aes/Makefile b/build/libraries/aes/Makefile new file mode 100644 index 0000000..6f81501 --- /dev/null +++ b/build/libraries/aes/Makefile @@ -0,0 +1,31 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - libraries - aes +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM7 + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/fatfs/ARM7/Makefile b/build/libraries/fatfs/ARM7/Makefile new file mode 100644 index 0000000..16ea02f --- /dev/null +++ b/build/libraries/fatfs/ARM7/Makefile @@ -0,0 +1,65 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries - fatfs +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = +SUBMAKES = + + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= TRUE + +# Codegen for sub processer +FIRM_PROC = ARM7 + +INCDIR = \ + $(TWLSDK_ROOT)/build/libraries/fatfs/ARM7.TWL/include \ + $(TWLSDK_ROOT)/build/libraries/fatfs/ARM7.TWL/include/twl/fatfs/ARM7 + +SRCDIR = src + +SRCS = \ + fatfs_loader.c \ + fatfs_firm.c \ + + +TARGET_LIB = libfatfs_sp$(FIRM_LIBSUFFIX).a + +#---------------------------------------------------------------------------- + +# DEBUGŃrh̏ꍇARELEASEłŃrh +# DEBUGł̃Cu𑕂܂B + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/libraries/fatfs/ARM7/src/fatfs_firm.c b/build/libraries/fatfs/ARM7/src/fatfs_firm.c new file mode 100644 index 0000000..11fcbd1 --- /dev/null +++ b/build/libraries/fatfs/ARM7/src/fatfs_firm.c @@ -0,0 +1,506 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - fatfs + File: fatfs_firm.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +#include +#include +#include +#include +#include +#include + +extern u32 NAND_FAT_PARTITION_COUNT; + +#define DMA_PIPE 2 +#define DMA_RECV 3 + +/* + pSD֐ +*/ +extern volatile SDMC_ERR_CODE SDCARD_ErrStatus; +extern s16 SDCARD_SDHCFlag; /* SDHCJ[htO */ +extern SDPortContext* SDNandContext; /* NANDp[^ */ + +/*---------------------------------------------------------------------------* + Name: WaitFifoFull + + Description: waiting to fill the SD FIFO + + SDJ[h̓ǂݍ݃f[^FIFOǂݍ߂ԂɂȂ܂ + Xg[܂B + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static inline void WaitFifoFull( void ) +{ + while( (*SDIF_CNT & SDIF_CNT_FULL) == 0 ) + { + if ( SDCARD_ErrStatus != SDMC_NORMAL ) // an error was occurred + { + break; + } + } +} + +/*---------------------------------------------------------------------------* + Name: StartToRead + + Description: start to read from SD I/F + + SDJ[h̓ǂݍ݂̊Jns܂B + + Arguments: block begining sector to transfer + count number of setctors to transfer + + Returns: None + *---------------------------------------------------------------------------*/ +static void StartToRead(u32 block, u32 count) +{ + *SDIF_FSC = count; + *SDIF_FDS = SECTOR_SIZE; + *SDIF_CNT = (*SDIF_CNT & ~(SDIF_CNT_FEIE | SDIF_CNT_FFIE)) | SDIF_CNT_FCLR | SDIF_CNT_USEFIFO; + CC_EXT_MODE = CC_EXT_MODE_DMA; + + SDCARD_ErrStatus = SDMC_NORMAL; + SD_EnableClock(); + SD_EnableSeccnt(count); + if ( SDCARD_SDHCFlag ) + { + SD_MultiReadBlock( block ); + } + else + { + SD_MultiReadBlock( block * SECTOR_SIZE ); + } +} + +/*---------------------------------------------------------------------------* + Name: StopToRead + + Description: stop to read from SD I/F + + SDJ[h̓ǂݍ݂̊s܂B + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static void StopToRead( void ) +{ + if( !SD_CheckFPGAReg( SD_STOP,SD_STOP_SEC_ENABLE ) ){ + SD_StopTransmission(); /* J[h]IFPGAɒʒmiCMD12sj */ + } + SD_TransEndFPGA(); /* ]I(荞݃}XN֎~ɖ߂) */ + SD_DisableClock(); /* NbN~ */ + + *SDIF_CNT = (*SDIF_CNT & ~SDIF_CNT_USEFIFO) | SDIF_CNT_FCLR; /* FIFOgptOOFF */ + CC_EXT_MODE = CC_EXT_MODE_PIO; /* PIO[h(DMA[hOFF) */ +} + +/* + FATFS-SDMC̊ԂAESgݍ + ꕔ̐ݒ́AFATFSI񂵂Đݒ肷邱ƂɂȂB +*/ + +#define AES_GET_CNT_BITS(regValue, name) \ + ((regValue) & (REG_AES_AES_CNT_##name##_MASK)) + +static BOOL useAES = FALSE; +static AESCounter aesCounter; + +/*---------------------------------------------------------------------------* + Name: FATFS_EnableAES + + Description: enable AES data path + + ɓǂݍރf[^AESÍĂ邱ƂAO + IO֐ɒʒm邽߂APIłB + + APIĂяoɓǂݍރf[^AES̏lw + Ă΁AȌ̃V[PVȌĂяoł̏l͎ + vZ܂B + _ANZXsꍇ́ÂтɂAPIĂяo + Kv܂B + + Arguments: counter initial counter value + + Returns: None + *---------------------------------------------------------------------------*/ +void FATFS_EnableAES( const AESCounter* pCounter ) +{ + useAES = TRUE; + aesCounter = *pCounter; +} + +/*---------------------------------------------------------------------------* + Name: FATFS_DisableAES + + Description: bypass AES + + ɓǂݍރf[^AESÍĂȂƂAO + IO֐ɒʒm邽߂APIłB + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void FATFS_DisableAES( void ) +{ + useAES = FALSE; +} + +/*---------------------------------------------------------------------------* + Name: ReadNormal + + Description: normal read + + ʂNAND/SDJ[hǂݍ݂܂B + + 荞݋֎~Ԃōɓ삷dlɂȂĂ܂B + + Arguments: block: source sector number in NAND + dest: dest address (4 bytes alignment) + count: sectors to transfer + + Returns: 0 if success + *---------------------------------------------------------------------------*/ +static u16 ReadNormal(u32 block, void *dest, u16 count) +{ + MINDmaConfig config = + { + MI_NDMA_NO_INTERVAL, + MI_NDMA_INTERVAL_PS_1, + MI_NDMA_BWORD_128, + SECTOR_SIZE/4 + }; +// OS_TPrintf("ReadNormal(0x%X, 0x%08X, 0x%X) is calling.\n", block, dest, count); + MI_NDmaRecvExAsync_Dev( DMA_PIPE, SDIF_FI, dest, (u32)(count * SECTOR_SIZE), NULL, NULL, &config, MI_NDMA_TIMING_SD_1 ); + StartToRead( block, count ); + MI_WaitNDma( DMA_PIPE ); + StopToRead(); + + return SDCARD_ErrStatus; +} + +/*---------------------------------------------------------------------------* + Name: ReadAES + + Description: AES read + + AESȂNAND/SDJ[hǂݍ݂܂B + AEŠ̐ݒ͂炩ߍsĂKv܂B + AES̏l̐ݒ́AFATFS_EnableAES̈vZ܂B + + 荞݋֎~Ԃōɓ삷dlɂȂĂ܂B + + Arguments: block: source sector number in NAND + dest: dest address (4 bytes alignment) + count: sectors to transfer + + Returns: 0 if success + *---------------------------------------------------------------------------*/ +#define PIPE_SIZE 64 +static u16 ReadAES(u32 block, void *dest, u16 count) +{ + u32 offset = 0; // in bytes + +// OS_TPrintf("ReadAES(0x%X, 0x%08X, 0x%X) is calling.\n", block, dest, count); + MI_NDmaPipeAsync_SetUp( DMA_PIPE, (void*)SDIF_FI, (void*)REG_AES_IFIFO_ADDR, PIPE_SIZE, NULL, NULL ); + +/* + AES̃ZbgAbvoDMAݒ +*/ + AESi_Reset(); + AESi_Reset(); + AESi_DmaRecv( DMA_RECV, dest, (u32)(count * SECTOR_SIZE), NULL, NULL ); + AESi_SetCounter( &aesCounter ); + AESi_Run( AES_MODE_CTR, 0, (u32)(count * SECTOR_SIZE / AES_BLOCK_SIZE), NULL, NULL ); + + // update for next read + AESi_AddCounter( &aesCounter, (u32)(count * SECTOR_SIZE / AES_BLOCK_SIZE) ); + + StartToRead( block, count ); + if ( SDCARD_ErrStatus != SDMC_NORMAL ) + { + goto err; + } + + while ( count * SECTOR_SIZE > offset ) + { + while ( AES_GET_CNT_BITS( reg_AES_AES_CNT, IFIFO_CNT ) ) + { + } + if ( (offset & (SECTOR_SIZE-1)) == 0 ) + { + WaitFifoFull(); + if ( SDCARD_ErrStatus != SDMC_NORMAL ) + { + goto err; + } + } + MI_NDmaRestart( DMA_PIPE ); + offset += PIPE_SIZE; + } + MI_WaitNDma( DMA_PIPE ); + StopToRead(); + MI_WaitNDma( DMA_RECV ); + return SDCARD_ErrStatus; + +err: + MI_StopNDma( DMA_RECV ); + MI_StopNDma( DMA_PIPE ); + StopToRead(); + AESi_Reset(); + return SDCARD_ErrStatus; +} + +/*---------------------------------------------------------------------------* + Name: nandRtfsIoFirm + + Description: ʑw̃ZN^[h^Cgv󂯂 + + Readɑ΂Ă̂݁AƎ̊֐gphCoIO֐łB + AES̗L̔͒fЉɖ؂łB + (Ԃɘ_̈̓ǂݍ݂܂”\邩) + + Arguments: driveno : hCuԍ + block : JnubNԍ + buffer : + count : ubN + reading : [hvTRUE + + Returns: TRUE/FALSE + *---------------------------------------------------------------------------*/ +static BOOL nandRtfsIoFirm( int driveno, u32 block, void* buffer, u16 count, BOOL reading ) +{ + u16 result; +#pragma unused( driveno) + + sdmcSelect( (u16)SDMC_PORT_NAND); + + if( reading ) + { + result = useAES ? + ReadAES( block, buffer, count ) : + ReadNormal( block, buffer, count ); + } + else + { + SdmcResultInfo SdResult; + result = sdmcWriteFifo( buffer, count, block, NULL, &SdResult ); + } + + return result ? FALSE : TRUE; +} + +/*---------------------------------------------------------------------------* + Name: sdmcRtfsIoFirm + + Description: ʑw̃ZN^[h^Cgv󂯂 + + Readɑ΂Ă̂݁AƎ̊֐gphCoIO֐łB + + Arguments: driveno : hCuԍ + block : JnubNԍ + buffer : + count : ubN + reading : [hvTRUE + + Returns: TRUE/FALSE + *---------------------------------------------------------------------------*/ +static BOOL sdmcRtfsIoFirm( int driveno, u32 block, void* buffer, u16 count, BOOL reading ) +{ + u16 result; +#pragma unused( driveno) + + sdmcSelect( (u16)SDMC_PORT_CARD ); + + if( reading ) + { + result = useAES ? + ReadAES( block, buffer, count ) : + ReadNormal( block, buffer, count ); + } + else + { + SdmcResultInfo SdResult; + result = sdmcWriteFifo( buffer, count, block, NULL, &SdResult ); + } + + return result ? FALSE : TRUE; +} + +/*---------------------------------------------------------------------------* + Name: nandRtfsAttachFirm + + Description: sdmchCohCuɊ蓖Ă + + ƎIO֐gp悤ɏ܂B + + Arguments: driveno : hCuԍ + + Returns: + *---------------------------------------------------------------------------*/ +#define nandRtfsCtrl FATFSi_nandRtfsCtrl +extern int nandRtfsCtrl( int driveno, int opcode, void* pargs); +static BOOL nandRtfsAttachFirm( int driveno, int partition_no) +{ + BOOLEAN result; + DDRIVE pdr; + + pdr.dev_table_drive_io = nandRtfsIoFirm; + pdr.dev_table_perform_device_ioctl = nandRtfsCtrl; + pdr.register_file_address = (dword) 0; /* Not used */ + pdr.interrupt_number = 0; /* Not used */ + pdr.drive_flags = (DRIVE_FLAGS_VALID | DRIVE_FLAGS_PARTITIONED);//DRIVE_FLAGS_FAILSAFE; + pdr.partition_number = partition_no; /* Not used */ + pdr.pcmcia_slot_number = 0; /* Not used */ + pdr.controller_number = 0; + pdr.logical_unit_number = 0; + + switch( partition_no ) + { + case 0: + result = rtfs_attach( driveno, &pdr, "SD1p0" ); //\̂FSCuɃRs[ + break; + case 1: + result = rtfs_attach( driveno, &pdr, "SD1p1" ); //\̂FSCuɃRs[ + break; + case 2: + result = rtfs_attach( driveno, &pdr, "SD1p2" ); //\̂FSCuɃRs[ + break; + case 3: + result = rtfs_attach( driveno, &pdr, "SD1p3" ); //\̂FSCuɃRs[ + break; + default: + result = FALSE; + break; + } + + return result; +} + +/*---------------------------------------------------------------------------* + Name: sdmcRtfsAttachFirm + + Description: sdmchCohCuɊ蓖Ă + + ƎIO֐gp悤ɏ܂B + + Arguments: driveno : hCuԍ + + Returns: + *---------------------------------------------------------------------------*/ +#define sdmcRtfsCtrl FATFSi_sdmcRtfsCtrl +extern int sdmcRtfsCtrl( int driveno, int opcode, void* pargs); +static BOOL sdmcRtfsAttachFirm( int driveno) +{ + BOOLEAN result; + DDRIVE pdr; + + pdr.dev_table_drive_io = sdmcRtfsIoFirm; + pdr.dev_table_perform_device_ioctl = sdmcRtfsCtrl; + pdr.register_file_address = (dword) 0; /* Not used */ + pdr.interrupt_number = 0; /* Not used */ + pdr.drive_flags = 0;//DRIVE_FLAGS_FAILSAFE; + pdr.partition_number = 0; /* Not used */ + pdr.pcmcia_slot_number = 0; /* Not used */ + pdr.controller_number = 0; + pdr.logical_unit_number = 0; + + result = rtfs_attach( driveno, &pdr, "SD0" ); //\̂FSCuɃRs[ + + return result; +} + +/*---------------------------------------------------------------------------* + Name: FATFS_InitFIRM + + Description: init file system + + FATFS܂B + WFATFS_Init̎gpȂȗĂ邾łB + ȑONANDReLXgcĂȂAԂ𒘂 + Zkł܂B + FATFSp̃q[v(OS_ARENA_MAIN_SUBPRIV̊֘Aƃq[v) + 炩ߊmۂĂĂB + + Arguments: nandContext context of nand driver's previous life + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL FATFS_InitFIRM( void* nandContext ) +{ + /* RTFSCu */ + if( !FATFSi_rtfs_init() ) + { + return FALSE; + } + + /* NANDp[^̐ݒ */ + SDNandContext = (SDPortContext*)nandContext; + + /* SDhCo */ + if ( FATFSi_sdmcInit( SDMC_NOUSE_DMA ) != SDMC_NORMAL ) + { + return FALSE; + } + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: FATFS_MountDriveFIRM + + Description: mount specified partition + + w肵foCX̎w肵p[eBVw肵hCu + }Eg܂BNAND܂SDJ[ĥݑΉĂ܂B + APIŃ}EgꍇAƎIO֐gp悤ɂȂ܂B + + Arguments: driveno drive number "A:" is 0 + media media type + partition_no pertition number + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL FATFS_MountDriveFIRM( int driveno, FATFSMediaType media, int partition_no ) +{ + if ( media == FATFS_MEDIA_TYPE_NAND ) + { + // CAUTION!: ֐2ĂяoRɂ‚ėvmFB + if ( !nandRtfsAttachFirm( driveno, partition_no ) || nandRtfsAttachFirm( driveno, partition_no ) ) + { + return FALSE; + } + } + else + { + if ( partition_no ) // support only 0 + { + return FALSE; + } + // CAUTION!: ֐2ĂяoRɂ‚ėvmFB + if ( !sdmcRtfsAttachFirm( driveno ) || sdmcRtfsAttachFirm( driveno ) ) + { + return FALSE; + } + } + return TRUE; +} diff --git a/build/libraries/fatfs/ARM7/src/fatfs_loader.c b/build/libraries/fatfs/ARM7/src/fatfs_loader.c new file mode 100644 index 0000000..03ee058 --- /dev/null +++ b/build/libraries/fatfs/ARM7/src/fatfs_loader.c @@ -0,0 +1,491 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - fatfs + File: fatfs_loader.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +#include +#include +#include +#include + +/* + PROFILE_ENABLE `Ƃx̃ptH[}X`FbNł܂B + p邽߂ɂ́Amain.cǂɁAu32 profile[256]; u32 pf_cnt; + `Kv܂B +*/ +//#define PROFILE_ENABLE + +#define MODULE_ALIGNMENT 0x10 // 16oCgPʂœǂݍ +//#define MODULE_ALIGNMENT 0x200 // 512oCgPʂœǂݍ +#define RoundUpModuleSize(value) (((value) + MODULE_ALIGNMENT - 1) & -MODULE_ALIGNMENT) + +#ifdef SDK_FINALROM // FINALROMŖ +#undef PROFILE_ENABLE +#endif + +#ifdef PROFILE_ENABLE +#define PROFILE_PXI_SEND 0x10000000 +#define PROFILE_PXI_RECV 0x20000000 +extern u32 profile[]; +extern u32 pf_cnt; +#endif + + +#define PXI_FIFO_TAG_DATA PXI_FIFO_TAG_USER_0 + +static ROM_Header* const rh= (ROM_Header*)HW_TWL_ROM_HEADER_BUF; +static int menu_fd = -1; + +/*---------------------------------------------------------------------------* + Name: FATFS_OpenRecentMenu + + Description: open recent menu file + VXej[̃t@C肵AI[vAt@CID + menu_fdɃZbg܂B + ŏIIɂ́AŒ̃^Cg^f[^ǂݍ݁AeTicket̏ + āAVXej[̃t@C肷邱ƂɂȂ\B + + Arguments: driveno drive number ('A' is 0) + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL FATFS_OpenRecentMenu( int driveno ) +{ + char *menufile = (char*)L"A:\\ipl\\menu.srl"; + if (driveno < 0 || driveno >= 26) + { + return FALSE; + } + menufile[0] += (char)driveno; + menu_fd = po_open((u8*)menufile, PO_BINARY, 0); + if (menu_fd < 0) + { + return FALSE; + } + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: FATFS_OpenSpecifiedSrl + + Description: open specified menu file + + Cӂ̃t@CI[vAt@CIDmenu_fdɃZbg܂B + + Arguments: menufile target filename + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL FATFS_OpenSpecifiedSrl( const char* menufile ) +{ + menu_fd = po_open((u8*)menufile, PO_BINARY, 0); + if (menu_fd < 0) + { + return FALSE; + } + return TRUE; +} + +#define HEADER_SIZE 0x1000 +#define AUTH_SIZE ROM_HEADER_SIGN_TARGET_SIZE + +/*---------------------------------------------------------------------------* + Name: FATFS_LoadBuffer + + Description: load data and pass to ARM9 via WRAM[B] + + LoadBufferJjYŁAFAT̃t@C̓eARM9ɓ]܂B + + [LoadBufferJjY] + WRAM[B]𗘗pāAARM7,ARM9Ԃ̃f[^]s܂B + WRAM[B]̊eXbgoPc[œn܂B + 1Xbg̃f[^܂͑Sf[^i[łƂAARM9 + FIRM_PXI_ID_LOAD_PIRIOD𑗐M܂B + f[^cꍇ͎̃Xbg̏Ɉڂ܂B + 2ڈȍ~̌Ăяoł́AOŌ̃Xbg̑gp܂B + gpXbgARM9Ɋ蓖ĂĂƂ́AARM7 + Ȃ܂ŃXg[܂B + + [gp] + WRAM[B]bNAԂƂARM7ɓ|ĂƁB + + [ӓ_] + offsetsizeARM9ɒʒm܂Bʂ̌oHœĂB + SRLt@Cǂݍޏꍇ́A݂ROMwb_QƂłΏ\łB + (ROMwb_͌mĂ͂) + + ⑫: + ł́A郉CuARM7/ARM9ŕ킹邱Ƃ + OɂĂ邪AėpIɂɂ(ƗCuȂ)A + MŃXbg𔼕‚ƂAꂼɎMPXIR[obN + XbhpӂAMAPIf[^WRAMɊi[A + destsizeʒmƂ`OKł͂ȂH + (ŊԎԂ) + + Arguments: offset offset of the file to load (512 bytes alignment) + size size to load + + Returns: None + *---------------------------------------------------------------------------*/ +static BOOL FATFS_LoadBuffer(u32 offset, u32 size) +{ + u8* base = (u8*)HW_FIRM_LOAD_BUFFER_BASE; + static int count = 0; + + // seek first +// OS_TPrintf("po_lseek(offset=%X);\n", offset); + if (po_lseek(menu_fd, (s32)offset, PSEEK_SET) < 0) + { + return FALSE; + } +#ifdef PROFILE_ENABLE + // x2: after Seek + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + // loading loop + while (size > 0) + { + u8* dest = base + count * HW_FIRM_LOAD_BUFFER_UNIT_SIZE; // target buffer address + u32 unit = size < HW_FIRM_LOAD_BUFFER_UNIT_SIZE ? size : HW_FIRM_LOAD_BUFFER_UNIT_SIZE; // size + while (MI_GetWramBankMaster_B(count) != MI_WRAM_ARM7) // waiting to be master + { + } +#ifdef PROFILE_ENABLE + // x3...: after to wait ARM9 + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif +// OS_TPrintf("po_read(dest=%X, unit=%X);\n", dest, unit); + if (po_read(menu_fd, (u8*)dest, (int)unit) < 0) // reading + { + return FALSE; + } +#ifdef PROFILE_ENABLE + // x4...: before PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); + profile[pf_cnt++] = (u32)PROFILE_PXI_SEND | FIRM_PXI_ID_LOAD_PIRIOD; // checkpoint +#endif + PXI_NotifyID( FIRM_PXI_ID_LOAD_PIRIOD ); + count = (count + 1) % HW_FIRM_LOAD_BUFFER_UNIT_NUMS; + size -= unit; + } + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: FATFS_LoadHeader + + Description: load header + + SRLROMwb_ǂݍ݁AARM9ɓn܂B + MOɁAARM9 FIRM_PXI_ID_LOAD_HEADER 𑗐M܂B + MAARM9 FIRM_PXI_ID_AUTH_HEADER M܂B + ̎_ŁAC̏̈ʒuROMwb_i[ꂽ + z肵܂B + Ȃ΁Aseedf[^16oCgM܂B + 󂯎seedSeedAKeyCɐݒ肳܂B + makerom.TWL܂IPL̎dlɈˑ܂B + + Arguments: None + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +BOOL FATFS_LoadHeader( void ) +{ + // open the file in FATFS_InitFIRM() + if (menu_fd < 0) + { + return FALSE; + } + +#ifdef PROFILE_ENABLE + // 10: before PXI + pf_cnt = 0x10; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); + profile[pf_cnt++] = (u32)PROFILE_PXI_SEND | FIRM_PXI_ID_LOAD_HEADER; // checkpoint +#endif + // load header without AES + PXI_NotifyID( FIRM_PXI_ID_LOAD_HEADER ); + FATFS_DisableAES(); + if (!FATFS_LoadBuffer(0, AUTH_SIZE) || +#ifdef PROFILE_ENABLE + // 12: after to load half + ((profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick())), FALSE) || +#endif + !FATFS_LoadBuffer(AUTH_SIZE, HEADER_SIZE - AUTH_SIZE) || +#ifdef PROFILE_ENABLE + // 1x: after to load remain + ((profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick())), FALSE) || +#endif + PXI_RecvID() != FIRM_PXI_ID_AUTH_HEADER ) + { + return FALSE; + } +#ifdef PROFILE_ENABLE + // 1x: after PXI + profile[pf_cnt++] = (u32)PROFILE_PXI_RECV | FIRM_PXI_ID_AUTH_HEADER; // checkpoint + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + // set id depends on game_code and seed to use (or all?) + { + AESKeySeed seed; + AESi_InitGameKeys((u8*)rh->s.game_code); + PXI_RecvDataByFifo( PXI_FIFO_TAG_DATA, &seed, AES_BLOCK_SIZE ); + AESi_WaitKey(); + AESi_SetKeySeedA(&seed); // APP + //AESi_WaitKey(); + //AESi_SetKeySeedB(&seed); // APP & HARD + //AESi_WaitKey(); + //AESi_SetKeySeedC(&seed); // + //AESi_WaitKey(); + //AESi_SetKeySeedD(&seed); // HARD + AESi_WaitKey(); + AESi_SetKeyC(&seed); // Direct + } + + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: FATFSi_GetCounter + + Description: get counter + + offsetɑΉAES̃JE^lvZ܂B + makerom.TWL̃R[hɈˑ܂B + + Arguments: offset offset from head of ROM_Header + + Returns: counter + *---------------------------------------------------------------------------*/ +static AESCounter* FATFSi_GetCounter( u32 offset ) +{ + static AESCounter counter; + + MI_CpuCopy8( rh->s.main_static_digest, &counter, 16 ); + AESi_AddCounter( &counter, offset - rh->s.aes_target_rom_offset ); + return &counter; +} + +/*---------------------------------------------------------------------------* + Name: FATFSi_SetupAES + + Description: setup whiere to use AES + + AESÍꂽf[^ǂݍނ߂̃ZbgAbvs܂B + fatfs_sdmc.c̃hCogpĂ邱ƂƂȂ܂B + (TwlSDKWōsꍇ́A̎dlɍ킹ďCKvI) + + APIĂяoOɁAC̏̈ʒuROMwb_ + i[ĂKv܂B + + ̑IsĂ܂A̐ݒ͕ʂ̏ꏊōsĂ + Kv܂B + + ]͈͂AES̈܂ꍇ́AE܂ł̃TCY ( + ȃTCY) Ԃ܂B + makerom.TWL܂IPL̎gpɈˑ܂B + + Arguments: offset offset of region from head of ROM_Header + size size of region + + Returns: size to transfer once + *---------------------------------------------------------------------------*/ +static u32 FATFSi_SetupAES( u32 offset, u32 size ) +{ + u32 aes_offset = rh->s.aes_target_rom_offset; + u32 aes_end = aes_offset + RoundUpModuleSize(rh->s.aes_target_size); + u32 end = offset + RoundUpModuleSize(size); + if ( rh->s.enable_aes ) + { + if ( offset >= aes_offset && offset < aes_end ) + { + if ( end > aes_end ) + { + size = aes_end - offset; + } + AESi_WaitKey(); + if (rh->s.developer_encrypt) + { + AESi_LoadKey( AES_KEY_SLOT_C ); + } + else + { + AESi_LoadKey( AES_KEY_SLOT_A ); + } + FATFS_EnableAES( FATFSi_GetCounter( offset ) ); + } + else + { + if ( offset < aes_offset && offset + size > aes_offset ) + { + size = aes_offset - offset; + } + FATFS_DisableAES(); + } + } + else + { + FATFS_DisableAES(); + } + return size; +} + +/*---------------------------------------------------------------------------* + Name: FATFSi_LoadModule + + Description: transfer module to ARM9 via WRAM[B] + + FATFSi_LoadBuffeȑAPIłB + + AESE܂Ƃ2ɕ邾łB + + Arguments: offset offset from head of ROM_Header + size size to load + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +static /*inline*/ BOOL FATFSi_LoadModule(u32 offset, u32 size) +{ + size = RoundUpModuleSize( size ); // ACg + while ( size > 0 ) + { + u32 unit = FATFSi_SetupAES( offset, size ); // x̓]TCY + if ( !FATFS_LoadBuffer( offset, unit ) ) + { + return FALSE; + } + offset += unit; + size -= unit; + } + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: FATFS_LoadStatic + + Description: load static binary + + ARM9/ARM7StaticLTD Staticǂݍ݂܂B + MOɁAARM9FIRM_PXI_ID_LOAD_*_STATIC𑗐M܂B + ḾAARM9FIRM_PXI_ID_AUTH_*_STATICM܂B + TCY0̏ꍇ́Ãp[gPXIʐMs܂B + + APIĂяoOɁAC̏̈ʒuROMwb_ + i[ĂKv܂B + + ARM9ƈقȂAfoCXˑ̃ACgCsĂ܂B + (TCŶ) + + Arguments: None + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +BOOL FATFS_LoadStatic( void ) +{ +#ifdef PROFILE_ENABLE + // 30: LoadStatic + pf_cnt = 0x30; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); + profile[pf_cnt++] = (u32)PROFILE_PXI_SEND | FIRM_PXI_ID_LOAD_STATIC; // checkpoint +#endif + PXI_NotifyID( FIRM_PXI_ID_LOAD_STATIC ); + + // load ARM9 static region without AES + if ( rh->s.main_size > 0 ) + { +#ifdef PROFILE_ENABLE + // 31: before PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + if ( !FATFSi_LoadModule( rh->s.main_rom_offset, rh->s.main_size ) ) + { + return FALSE; + } + } + // load ARM7 static region without AES + if ( rh->s.sub_size > 0 ) + { +#ifdef PROFILE_ENABLE + // 50: before PXI + pf_cnt = 0x50; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + if ( !FATFSi_LoadModule( rh->s.sub_rom_offset, rh->s.sub_size ) ) + { + return FALSE; + } + } + // load ARM9 extended static region with AES + if ( rh->s.main_ltd_size > 0 ) + { +#ifdef PROFILE_ENABLE + // 70: before PXI + pf_cnt = 0x70; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + if ( !FATFSi_LoadModule( rh->s.main_ltd_rom_offset, rh->s.main_ltd_size ) ) + { + return FALSE; + } + } + // load ARM7 extended static region with AES + if ( rh->s.sub_ltd_size > 0 ) + { +#ifdef PROFILE_ENABLE + // 90: before PXI + pf_cnt = 0x90; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + if ( !FATFSi_LoadModule( rh->s.sub_ltd_rom_offset, rh->s.sub_ltd_size ) ) + { + return FALSE; + } + } + + // waiting result + if ( PXI_RecvID() != FIRM_PXI_ID_AUTH_STATIC ) + { + return FALSE; + } +#ifdef PROFILE_ENABLE + // 9x: after PXI + profile[pf_cnt++] = (u32)PROFILE_PXI_RECV | FIRM_PXI_ID_AUTH_STATIC; // checkpoint + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: FATFS_Boot + + Description: boot + + ROMwb_̏ɁAOSi_BootĂяołB + + APIĂяoOɁAC̏̈ʒuROMwb_ + i[ĂKv܂B + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void FATFS_Boot( void ) +{ + OSi_Boot( rh->s.sub_entry_address, (MIHeader_WramRegs*)rh->s.main_wram_config_data ); +} diff --git a/build/libraries/fatfs/Makefile b/build/libraries/fatfs/Makefile new file mode 100644 index 0000000..a6aec45 --- /dev/null +++ b/build/libraries/fatfs/Makefile @@ -0,0 +1,31 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - libraries - fatfs +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM7 + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/gcd/ARM7/Makefile b/build/libraries/gcd/ARM7/Makefile new file mode 100644 index 0000000..29f06b7 --- /dev/null +++ b/build/libraries/gcd/ARM7/Makefile @@ -0,0 +1,60 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= True + +FIRM_PROC = ARM7 + +SRCDIR = . ../common +SRCS = \ + gcd.c \ + gcd_init.c \ + blowfish.c \ + ds_blowfish.c \ + ds_blowfish_table.c \ + gcdfirm_blowfish_table.c \ + +TARGET_LIB = libgcd_sp$(FIRM_LIBSUFFIX).a +INCDIR = ../include + +#---------------------------------------------------------------------------- + +# DEBUGŃrh̏ꍇARELEASEłŃrh +# DEBUGł̃Cu𑕂܂B + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/libraries/gcd/ARM9/Makefile b/build/libraries/gcd/ARM9/Makefile new file mode 100644 index 0000000..52cee61 --- /dev/null +++ b/build/libraries/gcd/ARM9/Makefile @@ -0,0 +1,65 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= True + + + +SRCDIR = . ../common +SRCS = \ + gcd.c \ + gcd_init.c \ + blowfish.c \ + ds_blowfish.c \ + ds_blowfish_table.c \ + gcdfirm_blowfish_table.c \ + +TARGET_LIB = libgcd$(FIRM_LIBSUFFIX).a +INCDIR = ../include + +#---------------------------------------------------------------------------- + +# DEBUGŃrh̏ꍇARELEASEłŃrh +# DEBUGł̃Cu𑕂܂B + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +LDEPENDS_OBJ := $(MAKEFIRM_RSA_PUBKEY) \ + +gcd_acsign.c : $(LDEPENDS_OBJ) + touch gcd_acsign.c + +#===== End of Makefile ===== diff --git a/build/libraries/gcd/Makefile b/build/libraries/gcd/Makefile new file mode 100644 index 0000000..cd64988 --- /dev/null +++ b/build/libraries/gcd/Makefile @@ -0,0 +1,34 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries - init +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Log: $ +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM9 + +#ifdef TWL_WITH_ARM7 +SUBDIRS += ARM7 +#endif + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/gcd/common/blowfish.c b/build/libraries/gcd/common/blowfish.c new file mode 100644 index 0000000..60f8fb2 --- /dev/null +++ b/build/libraries/gcd/common/blowfish.c @@ -0,0 +1,149 @@ +/*---------------------------------------------------------------------------* + Project: TwlBrom - libraries - GCD + File: blowfish.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include + +#define MAXKEYBYTES 56 /* 448 bits */ +#define N 16 + + +static u32 F(const BLOWFISH_CTX *ctx, u32 x); + +void InitBlowfish(BLOWFISH_CTX *ctx, const unsigned char *key, int keyLen) +{ + int i, j, k; + u32 data, datal, datar; + + j = 0; + for (i = 0; i < N + 2; ++i) { + data = 0x00000000; + for (k = 0; k < 4; ++k) { + data = (data << 8) | key[j]; + j = j + 1; + if (j >= keyLen) + j = 0; + } + ctx->P[i] = ctx->P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for (i = 0; i < N + 2; i += 2) { + EncryptByBlowfish(ctx, &datal, &datar); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 256; j += 2) { + EncryptByBlowfish(ctx, &datal, &datar); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } + +} + + +void EncryptByBlowfish(const BLOWFISH_CTX *ctx, u32 *xl, u32 *xr) +{ + u32 Xl; + u32 Xr; + u32 temp; + int i; + + Xl = *xl; + Xr = *xr; + + for (i = 0; i < N; ++i) { + Xl = Xl ^ ctx->P[i]; + Xr = F(ctx, Xl) ^ Xr; + + temp = Xl; + + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[N]; + Xl = Xl ^ ctx->P[N + 1]; + + *xl = Xl; + *xr = Xr; +} + +void DecryptByBlowfish(const BLOWFISH_CTX *ctx, u32 *xl, u32 *xr) +{ + u32 Xl; + u32 Xr; + u32 temp; + int i; + + + Xl = *xl; + Xr = *xr; + + for (i = N + 1; i > 1; --i) { + Xl = Xl ^ ctx->P[i]; + Xr = F(ctx, Xl) ^ Xr; + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + } + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[1]; + Xl = Xl ^ ctx->P[0]; + + *xl = Xl; + *xr = Xr; +} + + +static u32 F(const BLOWFISH_CTX *ctx, u32 x) { + u32 a, b, c, d; + u32 y; + + d = x & 0x00FF; + x >>= 8; + + c = x & 0x00FF; + x >>= 8; + + b = x & 0x00FF; + x >>= 8; + + a = x & 0x00FF; + + y = ctx->S[0][a] + ctx->S[1][b]; + + y = y ^ ctx->S[2][c]; + y = y + ctx->S[3][d]; + + return y; +} + + diff --git a/build/libraries/gcd/common/ds_blowfish.c b/build/libraries/gcd/common/ds_blowfish.c new file mode 100644 index 0000000..1a6b3bd --- /dev/null +++ b/build/libraries/gcd/common/ds_blowfish.c @@ -0,0 +1,186 @@ +/*---------------------------------------------------------------------------* + Project: TwlBrom - libraries - GCD + File: ds_blowfish.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +#include + + +#ifdef PRINT_DEBUG +#define DBG_PRINTF vlink_dos_printf +#define DBG_CHAR vlink_dos_put_console +#else +#define DBG_PRINTF( ... ) ((void)0) +#define DBG_CHAR( c ) ((void)0) +#endif + +static void my_memcopy(void *src, void *dst, int size); + + +// DS + +static char *normal_mode_key ATTRIBUTE_ALIGN(4) = "NmMdOnly"; +static char *png_off_key ATTRIBUTE_ALIGN(4) = "enPngOFF"; +static char *encrypt_object_key ATTRIBUTE_ALIGN(4) = "encryObj"; + +extern GCDSharedWork GCDi_SharedWork[2]; +extern GCDSecureWork GCDi_SecureWork[2]; + +static void GCDi_InitBlowfishKeyAndTableDS(BLOWFISH_CTX *ctx, u32 *keyBufp, s32 keyLen) +{ + EncryptByBlowfish(ctx, &(keyBufp)[2], &(keyBufp)[1]); + EncryptByBlowfish(ctx, &(keyBufp)[1], &(keyBufp)[0]); + InitBlowfish(ctx, (u8 *)keyBufp, keyLen); +} + +static void GCDi_MakeBlowfishTableDS(GCDSlot slot, BLOWFISH_CTX *tableBufp, const u32 *keyp, u32 *keyBufp, s32 keyLen) +{ + const BLOWFISH_CTX *blowfishInitTablep = &GCDi_BlowfishInitTableDS; + GCDRomHeader *rh = GCDi_GetRomHeaderAddr( slot ); + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + u32 *blowfishedKeyp; + + MI_CpuCopy32((void *)blowfishInitTablep, (void *)tableBufp, sizeof(BLOWFISH_CTX)); + + keyBufp[0] = *keyp; + keyBufp[1] = (*keyp >> 1); + keyBufp[2] = (*keyp << 1); + + GCDi_InitBlowfishKeyAndTableDS(tableBufp, keyBufp, keyLen); + + *(u64 *)sec->cardNormalModeKey = *(u64 *)rh->l.romNormalModeKey; + blowfishedKeyp = sec->cardNormalModeKey; + + DecryptByBlowfish(tableBufp, &(blowfishedKeyp)[1], &(blowfishedKeyp)[0]); + + if (keyLen > 8) { + sec->isGenUnScrambleKey = 1; + } + GCDi_InitBlowfishKeyAndTableDS(tableBufp, keyBufp, keyLen); +} + +void GCDi_InitCardOpBlowfishDS( GCDSlot slot ) +{ + GCDRomHeader *rh = GCDi_GetRomHeaderAddr( slot ); + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + GCDi_MakeBlowfishTableDS(slot, &sec->blowfishCardTable, &rh->l.initialCode, sec->cardKeyBuf, 8); +} + +static void GCDi_ChangeObjectTableDS(GCDSlot slot, s32 keyLen) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + BLOWFISH_CTX *tableBufp = &sec->blowfishCardTable; + u32 *keyBufp = sec->cardKeyBuf; + + keyBufp[1] = (keyBufp[1] << 1); + keyBufp[2] = (keyBufp[2] >> 1); + GCDi_InitBlowfishKeyAndTableDS(tableBufp, keyBufp, keyLen); +} + + +#define UNDEF_CODE 0xe7ffdeff +#define ENCRYPT_DEF_SIZE 0x800 +/* ƂŖOς */ +#define ENC_DESTINATION_BUF_SIZE 0x4000 +static u32 encDestBuf[ENC_DESTINATION_BUF_SIZE/sizeof(u32)]; + +void GCDi_DecryptObjectFileDS( GCDSlot slot ) +{ + GCDRomHeader *rh = GCDi_GetRomHeaderAddr( slot ); + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + GCDSharedWork* sh = &GCDi_SharedWork[slot]; + BLOWFISH_CTX *tableBufp = &sec->blowfishCardTable; + u32 *encBufp = (u32 *)&sec->blowfishFlashTable; + u32 *encDestp = (u32 *)rh->l.arm9.ramAddr; + s32 size = sec->secureSize; + s32 restSize; + BOOL exist = TRUE; + int i; + + sec->enableReadSecure = 1; // SECURË惊[hECl[u + + encDestp = GCDi_SecureAreaBuf[slot]; + encBufp = encDestBuf; + + if (size > ENCRYPT_DEF_SIZE) { + size = ENCRYPT_DEF_SIZE; + } + restSize = size; + + if (sec->enableReadSecure) { + MI_CpuCopy32(encDestp, encBufp, (u32)size); + DBG_PRINTF("%s %d\n",__FUNCTION__,__LINE__); + DecryptByBlowfish(tableBufp, &(encBufp)[1], &(encBufp)[0]); + } + + GCDi_ChangeObjectTableDS( slot, 8 ); + + if (sec->enableReadSecure) { + DecryptByBlowfish(tableBufp, &(encBufp)[1], &(encBufp)[0]); + DBG_PRINTF("%s %d\n",__FUNCTION__,__LINE__); + +#if 1 + for ( i=0; i<8; i++ ) + { + if ( encrypt_object_key[i] != ((char*)encBufp)[i] ) + { + exist = FALSE; + break; + } + } + + // ÍIuWFNgL + if ( exist ) + { +#else + if ((encBufp[0] == encrypt_object_key[0]) // ÍIuWFNgL + && (encBufp[1] == encrypt_object_key[1])) { +#endif + u32 *bufp = encBufp; + + bufp[0] = UNDEF_CODE; + bufp[1] = UNDEF_CODE; + while ((restSize -= 8) > 0) { + bufp += 2; // + DecryptByBlowfish(tableBufp, &(bufp)[1], &(bufp)[0]); + } + DBG_PRINTF("SUCCESS %s %d\n",__FUNCTION__,__LINE__); + } + else { + DBG_PRINTF("ERROR %s %d\n",__FUNCTION__,__LINE__); + // CpuClearFast32(UNDEF_CODE, encBufp, size); // `R[hŃNA + sh->disableEncryptedCardData = 1; // ÍIuWFNg ʒm + } + MI_CpuCopy32(encBufp, encDestp, (u32)size); + DBG_PRINTF("%s %d\n",__FUNCTION__,__LINE__); + } +} + + +/*************************************************** + + utility functions + + ***************************************************/ +static void my_memcopy(void *src, void *dst, int size) +{ + u8 *s,*d; + int i; + s = (u8 *)src; + d = (u8 *)dst; + for( i = 0 ; i < size ; i++ ) { + *d++ = *s++; + } +} + diff --git a/build/libraries/gcd/common/ds_blowfish_table.c b/build/libraries/gcd/common/ds_blowfish_table.c new file mode 100644 index 0000000..2ab70da --- /dev/null +++ b/build/libraries/gcd/common/ds_blowfish_table.c @@ -0,0 +1,286 @@ +/*---------------------------------------------------------------------------* + Project: TwlBrom - libraries - GCD + File: ds_blowfish_table.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include + + +const BLOWFISH_CTX GCDi_BlowfishInitTableDS = { + 0x5f20d599, 0xb9f54457, 0xd9a4196e, 0x945a6a9e, + 0xebf1aed8, 0x3ae27541, 0x32d08293, 0xd531ee33, + 0x9a6157cc, 0x1ba20637, 0xf5723979, 0xbef6ae55, + 0xfb691b5f, 0xe9f19de5, 0xa1d92cce, 0xe605325e, + 0xcffed3fe, 0x0d0462d4 , + + 0xb7ecf58b, 0xbb79602b, 0x0d319512, 0x2bda3f6e, + 0xf1f08488, 0x257e123d, 0xbbf12245, 0x061a0624, + 0x28dfad11, 0x3481648b, 0x2933eb2b, 0xbdf2aa99, + 0x9d95149c, 0x8cf5f79f, 0x29a19772, 0xcf5fd19d, + 0x1a074d66, 0x4b4ad3de, 0xa3a7c985, 0x3a059517, + 0xbf0a493d, 0xa28b890a, 0xdd49824a, 0x0bf19027, + 0x6a1cebe9, 0x05457683, 0x617081ba, 0xde4b3f17, + 0x39abcfae, 0x563af257, 0x8aad1148, 0x3f45e140, + 0x54029bfa, 0xfb93a6ca, 0x6ffe4def, 0x9c87d8a3, + 0x48d5ba08, 0xfd2d8d6a, 0x74f8156e, 0x8b52bebd, + 0x9e8a2218, 0x073774fb, 0x4a6c361b, 0x6242ba19, + 0x109179b9, 0x9665677b, 0xe82302fe, 0x778c99ee, + 0x64865c3e, 0x86786d4d, 0xe2654fa5, 0x5adfb21e, + 0x087ed00a, 0xac71b014, 0x1c83dbbd, 0x62a1d7b9, + 0x7c63c6cd, 0xe6c36952, 0x12ce75bf, 0x04215d44, + 0x3cd3fbfa, 0xd4631138, 0x49418595, 0x08f20946, + 0x1fdc1143, 0x6d15c076, 0x70633c1f, 0x6c8087ea, + 0x8b63bdc3, 0x372137c2, 0x2309eedc, 0x4d6a372e, + 0x50f79073, 0x921cac30, 0x91231004, 0xaa07d24f, + 0x9a4f3e68, 0x6a6064c9, 0xf32114c8, 0x124122d6, + 0xe6cf2444, 0x0ddd568a, 0x85e14d53, 0x5a528c1e, + 0xc284199c, 0x6ff15703, 0x58be00e3, 0xd5ed4cf6, + 0x1f9c6421, 0x3c0355be, 0xaaffdc4a, 0x5de0dac9, + 0xdee6bf5e, 0xf8b1d8f5, 0xb9b336ff, 0xdb956762, + 0xed375f31, 0x9967704c, 0x3118b590, 0x99993d6c, + 0xd3da42e4, 0xa0134225, 0x6c70d7ae, 0xc7cf55b1, + 0x43d546d7, 0x443d1761, 0x8533e928, 0x93a2d0d5, + 0x1f1225aa, 0x460bc5fb, 0x567697f5, 0x87bea645, + 0xe86b94b1, 0x9933feb1, 0x6c3e1fae, 0x091d7139, + 0xe4379000, 0x74753e10, 0x3b838cff, 0xf9b0f1b0, + 0x42470501, 0xacd6f195, 0x9ee6387e, 0x3f267495, + 0x185068b4, 0xb43043d0, 0x68e34b4c, 0xb64de5bf, + 0xa00a8b95, 0x77322574, 0x2cf7a1cf, 0x5a1371d8, + 0x51c9eaab, 0xefee0de8, 0x197e93e9, 0x38431ea7, + 0xa12c1681, 0xcc73e348, 0xd36c2129, 0xd9a0ce5d, + 0xa0437161, 0x64b51315, 0x192acf92, 0xa5b7addc, + 0xf865869f, 0xfbe79f1a, 0x13b8fdf7, 0x6fdb276c, + 0xf71c35df, 0x9b5b2c8d, 0x6438ab12, 0x31decc06, + 0x11754ee8, 0xeafae364, 0xc25434eb, 0xeb343fad, + 0x267d2c93, 0xf3569d36, 0xb3f6e15a, 0x9e4a6398, + 0x9ae48332, 0x907d6084, 0xee0e132e, 0xa2364b93, + 0x3816ec85, 0x020688e8, 0x3aa0f0bf, 0x9a6ad7ed, + 0xcf57e173, 0xdcb844f8, 0xd159232e, 0x715295df, + 0x4ba06199, 0x786e7fd5, 0x30c5a9ba, 0x328640d3, + 0x9c0c329d, 0x2f02b737, 0xa99854ba, 0xc90413c4, + 0xe7c8be8d, 0x2e50975d, 0x5922d693, 0x22bc270c, + 0x20a7e092, 0x7f6f930f, 0xb5d39f4c, 0x740b2aa6, + 0x107d4967, 0xc5d1cb26, 0x8ce77186, 0x5be99ca0, + 0x01f61ab2, 0x5e9e8cee, 0xdb1af283, 0x84eae5e6, + 0x7cd27659, 0x49a58df6, 0x16c24836, 0xa383bb52, + 0x0c07b974, 0x2861ff3b, 0xe4e961e1, 0xaa156eef, + 0x5de8ba4e, 0x32bb9605, 0x72fbb056, 0xc80e0f52, + 0x76652542, 0xdef2af89, 0x01f02710, 0x97a7744b, + 0x5426d507, 0x821f0954, 0x307d860a, 0x26b30e39, + 0xbb570b9b, 0xaf310636, 0xd9fc79fd, 0x0c2b1030, + 0xd79be1b3, 0xef5fdc7b, 0x4513f8d2, 0xbd75474d, + 0x7e3c9646, 0xb53ef375, 0x3b9ac567, 0x6b295bb0, + 0xc85b80de, 0x31b10515, 0xdd49ceb6, 0xaeb584ad, + 0x3167dc60, 0x4efe3034, 0xa62f80bd, 0x213963bf, + 0x7f35d986, 0x05226816, 0x2690e954, 0x516c078c, + 0xd75531a4, 0x3ea80709, 0xc166532e, 0xc47bf2f8, + 0xf1cf58f2, 0xe7a2c587, 0x87308f27, 0x6264a058, + 0x88b91823, 0xc4cefa7c, 0x17adae98, 0xf35b4acc, + 0x56d548e9, 0xc8f20dd3, 0xdb8c7392, 0xac562fd7, + + 0x6992f981, 0xf632c64d, 0x218dc0e6, 0x618076e2, + 0x6cdcbc11, 0x6919af93, 0xb9bfd09b, 0x67029f31, + 0x83ee51a3, 0x0c7b2206, 0x404249ab, 0x7d01d5b8, + 0x55f75ece, 0x99c53953, 0x9f87d846, 0xb464f7ba, + 0xa1fa9ae3, 0x1068906d, 0x548aca30, 0xc3609fa7, + 0x0d6bf519, 0xe698517a, 0xb4514398, 0x4fe935d6, + 0x7b0fdfc3, 0xbd5c2fd6, 0x1961153a, 0xaacb4bf1, + 0xc9646ddc, 0x561ec6d3, 0x504c38ef, 0xcc758671, + 0xe94e0d0d, 0x5d06f628, 0xd3aa1b70, 0x39a8cf45, + 0x2ea695ac, 0xd422e4b4, 0x5f37a874, 0xcc047a48, + 0xd8404ca5, 0x0828b428, 0x52721c0d, 0x477df041, + 0x4e533a19, 0x6b628458, 0x818ab593, 0xdc0d4e21, + 0xc6a23fb4, 0x402bc9fc, 0xe90438da, 0x6b865a5e, + 0x8525220c, 0x7c8d1168, 0x55951d92, 0xbb8eab4d, + 0xb7e6a6da, 0x5a32b651, 0x05dd4105, 0x50560a2a, + 0xcc471791, 0xb57ee6c9, 0x73db4a61, 0x33c85167, + 0x746edaf5, 0x37c3542e, 0x08af6d0d, 0x5f8a15e8, + 0xcd2159e2, 0x060cdea8, 0x5f6b775a, 0x3e6518db, + 0x78de50c8, 0xb382b8e0, 0x32724e5d, 0x34c14f07, + 0xb796ba23, 0x28a44e67, 0xeb62341e, 0xe9706a2d, + 0x70c4422f, 0x9c315a4e, 0x28475bf9, 0x6f71daaa, + 0x78b31f38, 0x1c6b92c4, 0x9a35f69e, 0xbf0e4db7, + 0x412918cc, 0x5d354803, 0xc62bd055, 0x605caf29, + 0x5e8e6974, 0xbdd47c9b, 0x7d64447b, 0x695d923f, + 0x4b001fb6, 0xcf3583d4, 0x174e647e, 0x2ed58dae, + 0x4e12289a, 0x08492b2e, 0x46c6ae5c, 0x6141ae85, + 0xd2826f1e, 0x1f163751, 0xa459f60b, 0xaf5aca9a, + 0x8b33d40d, 0x84f16320, 0xcfcb5c80, 0xd3b9b408, + 0x62bd0516, 0x569b3183, 0xba9f9851, 0xb2aa5bb2, + 0xb52c6b22, 0x63fa48d4, 0xfa585f2b, 0x0964fa61, + 0xb8e038bb, 0xa860929d, 0x0e6f670d, 0x010df537, + 0xd477c29f, 0x73f1ecfe, 0x7de03930, 0xe49861f5, + 0x0455282c, 0x2fdb5556, 0x58e5ec6b, 0x8064b606, + 0x4e1a2a6a, 0xc4d80f5b, 0x19522e0a, 0x30f562d9, + 0x7b8cbe48, 0xa29b384f, 0xd3c9afc3, 0x4162c1c7, + 0x2161b986, 0x4f996f57, 0x7bcebac1, 0x5e4d3bb5, + 0x57448b8a, 0x705f135f, 0x47295b6d, 0xece238dc, + 0x12655504, 0x4317e82a, 0x2add8ee1, 0xf794e2b3, + 0xe65c6e09, 0x6df88aeb, 0x48544989, 0xbfad2ff5, + 0xca4b94ea, 0x828739fc, 0xf2018a5f, 0x71e6f275, + 0xde42d8d6, 0x281d2df1, 0xa37e88a6, 0x301d47a0, + 0xdf71a3d9, 0x01cb1c49, 0xf2b136f8, 0x5d5822f0, + 0xa0bd6b45, 0x4288b2bb, 0xce288cc7, 0x6390e893, + 0x897c9008, 0xb77df53c, 0x554f2d04, 0x7efd1651, + 0xc1bee879, 0xf8d412f2, 0x230584b4, 0x2bd2cca0, + 0xadabe1fd, 0x6c55d10d, 0x4d944123, 0x054f3777, + 0x17bf0c28, 0x6c6712b3, 0xf75ac38c, 0x6d2a8441, + 0x271294d0, 0x9cedb42c, 0x8247ec4d, 0xb967d597, + 0x55c09d1b, 0x8ee57e07, 0x3ee7a8e2, 0x3a0ee412, + 0x3455452a, 0x5a2df9a2, 0x7c52ab1b, 0x555f1083, + 0x435af1d2, 0xa4a7c62b, 0xe8951589, 0xf89d4bb4, + 0x609fe375, 0xe6d65b78, 0x21e6440d, 0x2247bd06, + 0xad00a453, 0x8513438d, 0xfcaaf739, 0xed7baf38, + 0x542be4fc, 0xfc4c9850, 0xdff78085, 0xe122803c, + 0x24deda94, 0x397ab0c6, 0xa10fdc38, 0x6ff9f4a7, + 0x8b571863, 0x2e2a4184, 0xd9f253d4, 0xddd00f00, + 0xa6196e99, 0x5becd00a, 0xc0ab2458, 0xec6506cb, + 0x9438131a, 0x2f03670a, 0x77e3f73f, 0xc6337744, + 0xe3d03914, 0x7908a2c0, 0x579940bb, 0x90010b41, + 0x48cce1cd, 0xafb3db67, 0x4cf37488, 0xb1728f82, + 0xc42923b5, 0xfc196c12, 0x9ca4468e, 0x876525c4, + 0x8abe6dd3, 0x38031193, 0xf32b83ed, 0xea93a446, + 0x1d85533b, 0x08f1d4ce, 0xfced2783, 0xbc181a9b, + 0xdcae8bf9, 0x3850ab24, 0x104b72e9, 0x467b1722, + + 0x6459ab5d, 0xf8ae40f3, 0xf9c8e5bb, 0x554e0326, + 0xfeebeb7d, 0xe0e639f7, 0x2ebe110a, 0xed98ff28, + 0x5642c9c0, 0x00fdc342, 0xa287aff6, 0x323f015b, + 0x9a954792, 0x3d32a572, 0x9bd06bae, 0x9249d207, + 0xfa4a78e3, 0xf27d06a1, 0x7477cf41, 0x0cb21404, + 0x16648486, 0xa151bbd5, 0xd1f16fe5, 0x5ff7e2f2, + 0xb84d2058, 0xddcfc757, 0x76bed8c5, 0x7e5ff63d, + 0x888b2ae7, 0x3f381b24, 0x7723410e, 0xd44bf0f5, + 0xa4fa1f0c, 0xcf5f800b, 0xdae0f645, 0x5359342f, + 0x523c20fb, 0xb5355e62, 0x608bfe62, 0x5a86e363, + 0xd16e1a15, 0x32bc4547, 0x3867ebb4, 0x336ee4ab, + 0xa3edb53a, 0x4ee067ad, 0x62ee9541, 0x1d267162, + 0x3062ef31, 0xac82d7af, 0x0405dcc2, 0xbf0797f5, + 0x07235911, 0xe80264c0, 0xaf3ee597, 0xa659ac18, + 0x90334a8b, 0x9c7c6e1c, 0x3c4c7e20, 0xbb64613e, + 0x7e7c6bc5, 0x4cc59f3e, 0xf573ea9f, 0x4cc089d7, + 0x2df4fbf4, 0x511b14ec, 0xc812c1d5, 0x4a0bdf10, + 0x93bc9c8b, 0x3e3e6a45, 0xbaa9c17d, 0x07b4c1cd, + 0x8668e1e4, 0x386db243, 0x5c0cfbf3, 0xde713766, + 0xa06eef56, 0xa7654010, 0xbed0f798, 0x3637c80e, + 0x7cca10ec, 0x1e84ab9c, 0x02761705, 0xaa524f1c, + 0xa0c6c15f, 0x04d8b956, 0xa74d4484, 0x60ded859, + 0x050e38e6, 0x3be1038f, 0x3304816d, 0xce0b306f, + 0x33210569, 0x89bb26fb, 0x87aeb67d, 0xe007517e, + 0x0a96f7ac, 0x5cc4f96b, 0x4744e41d, 0xe3fa5eb8, + 0x42558478, 0xf75e484b, 0x8635477d, 0x05432b1d, + 0xb88aec03, 0x763c061e, 0x431a480c, 0xed8ab7a7, + 0x43c6131e, 0xdbef10ee, 0x833cfbec, 0xef4495b2, + 0x4e5154d8, 0x1d44112d, 0x1e5936fb, 0xc3c1347a, + 0x610057ca, 0x16a567ea, 0x55d0559b, 0x36d97fe1, + 0xae7640d2, 0xb0ce01dc, 0xcbd5837a, 0x6bec9820, + 0x349272c1, 0x375782f3, 0x36328a62, 0xae43900c, + 0x789b5cae, 0x0265138e, 0xc17168fd, 0xa031b0fe, + 0xc3b08224, 0xa76979b1, 0xd0ebd2f5, 0xdc32c082, + 0x3c26c79e, 0xc1988d6d, 0xd0d422bb, 0x3eec330f, + 0xdce1ccb9, 0x36774c6a, 0xbff91c14, 0x5f289f81, + 0x29328571, 0xc4487590, 0xd8ce4ab3, 0x2f148f44, + 0xef5740fd, 0xd97508aa, 0x6ed6d146, 0xc31f5532, + 0x1f84fe18, 0xffd584fc, 0x481b5e71, 0x0e9586c3, + 0xd3270828, 0x7b718338, 0x5463804c, 0xacb0569a, + 0x31ca80cf, 0xf3feef09, 0x7e24afbe, 0x3f53fea6, + 0x334a8dc2, 0xa622d168, 0xea7bad66, 0xb043b6de, + 0x009525a1, 0x46753fa3, 0xec441114, 0x92bc95d7, + 0x16a94ff0, 0x60976253, 0xf1410f2a, 0xeebe2471, + 0xcd087f94, 0x85b39360, 0x3f00075b, 0x83280fd8, + 0x9f69d19a, 0xc32edad1, 0xb9a20190, 0x662a4e6b, + 0xa6aeda9d, 0x68d32aea, 0x9c0c0c2f, 0xed4a8cd2, + 0x65579ee2, 0xa387099d, 0x5d32c4b4, 0x2b32d4c9, + 0x1e71e0b1, 0x90e64d64, 0x401ee371, 0x84f37ded, + 0x78c8ed0e, 0x71c0ae76, 0x05bb7227, 0xfb6402ea, + 0xb56b48f3, 0xed3f9342, 0xd253139f, 0xec2afef7, + 0xdb25471d, 0xc686913c, 0xfd11f08e, 0xf7367423, + 0x7a9ef5a4, 0x4450537e, 0xd3ca47d4, 0xe66d38eb, + 0x7f9471d9, 0x4b69c64a, 0xea52f411, 0xb08afe22, + 0x598b6736, 0x2a80e6e8, 0x130465eb, 0x9edcecee, + 0x05ecb15f, 0x9fe6596a, 0x896b595e, 0xca1af7bf, + 0x6a5bf944, 0xe4038571, 0x70e06229, 0xcfc4416f, + 0xe3ccb1b2, 0xa807a67e, 0x847fe787, 0x4b52db93, + 0xdd7eec6c, 0x104824d4, 0x60049f69, 0x1848e674, + 0xb92ce4f3, 0x7a502e4f, 0x6954d4df, 0xf3a78b2b, + 0xf31fffce, 0x3901263e, 0x89849517, 0x4b4cf0b0, + 0xc49f9182, 0xa59dac4b, 0x2517af74, 0xd332cac9, + 0x848a89bc, 0xae0dcc89, 0x9cdba27c, 0xee91786a, + 0x4e5d76ea, 0x69f56087, 0x02d46715, 0x3648afcf, + + 0x6fbfea07, 0x8f062d66, 0xf9fe9ac4, 0x758790f6, + 0x0fadf7b8, 0x3d5a1076, 0xb32eb059, 0xcc2c35c7, + 0xcb2b5670, 0xc59637e3, 0x8a1b462f, 0x88c74622, + 0x983226a7, 0x2286df61, 0x2f1cf48a, 0xaa09a187, + 0xd3aea9cc, 0x1c4500bd, 0x8687549a, 0xffef8752, + 0x8fa18f1e, 0x355c89c1, 0x3a2dda1b, 0xc2b2162c, + 0x78e256f1, 0x97636bc1, 0xc98f56c5, 0xaa2c7f32, + 0xaca8a6af, 0x88229120, 0x8b60e4de, 0x25424bf9, + 0x9c7fe31a, 0x3a89192c, 0x36d4057e, 0xc25869cc, + 0x2f8b32c1, 0x7aeb8590, 0xa1a55039, 0x66c59227, + 0x584f20b0, 0x4383557e, 0x9ce2452b, 0x9012d8e4, + 0x5683162c, 0xb3037916, 0x18612dad, 0x371f131a, + 0x739ce1e2, 0xfdd5807b, 0xfc87512d, 0x1fd7aa7b, + 0xaf8e7a2c, 0xcdbb8df4, 0x727c1195, 0xe26fee0b, + 0x37deafb9, 0x8d8cde83, 0xb7670562, 0x568dc696, + 0x62d70db6, 0x3646d6ba, 0xe6c88ebd, 0x106c2aea, + 0x5b6bff14, 0x463c82fa, 0x464330b1, 0x9b7d8a51, + 0x79833e92, 0xb25d555b, 0x90ce5e6c, 0x98538e62, + 0xe56d0dc9, 0xc5cd572d, 0xe1ba5781, 0x728fb8e8, + 0xdc134fe5, 0x15719dea, 0x8811b210, 0x7fd409d5, + 0x2c7f655b, 0x114c383b, 0xfb8d5068, 0xbf59b09e, + 0x4a898094, 0x12181ac5, 0x4ad15389, 0x8ce82910, + 0xeab6ec1c, 0x8b17c746, 0xa8311525, 0xb1436ba2, + 0x0bdbe29d, 0x11b09b87, 0xd2710e04, 0x82897729, + 0x7f41660a, 0xff480b1d, 0xfd24bb72, 0x9ba148c2, + 0xce7f7bfe, 0xd986db88, 0xb01c3b85, 0x0733a8dc, + 0xe32e51bf, 0x97009a0e, 0x97c0061e, 0xb6d89d43, + 0x6786c445, 0x88f8005f, 0x9e52a49a, 0x838aaac7, + 0x18c5ec75, 0x2fc3ceae, 0x18f92b1a, 0xf51aaeff, + 0x33b50b53, 0xe8fda751, 0x64a2e1a8, 0x431722b6, + 0xd80acc80, 0x40ba3bae, 0x4a92d9d7, 0x1004df89, + 0x2b189bee, 0x8a69776a, 0xb9f9f468, 0x6e1521a2, + 0x033b1ee6, 0x609b3062, 0x9b257e41, 0x52c58f9e, + 0xc2f80810, 0x1121a169, 0x795e3788, 0x10ff6635, + 0xed6e1842, 0x1c6bb697, 0x6de5364e, 0xbfe4b47d, + 0x05e0b920, 0xb8d5693a, 0xe0dcd5e3, 0x3e53acb9, + 0xad57a407, 0x1848ff77, 0x49ac2a76, 0x75478e2a, + 0x63679f6d, 0x398c3530, 0x6fd53905, 0xad5b3a64, + 0x82bb0bca, 0xb1459952, 0x99363693, 0x442013af, + 0x4402d836, 0x85923909, 0x974a4aff, 0xd763a687, + 0x24b5b5c7, 0x6fb40fed, 0x1452580c, 0xd37ba6d9, + 0x5838bc79, 0x843bbda1, 0x061ad806, 0xeaa86bfd, + 0x0428694b, 0x9982ad37, 0x851b0efb, 0x735da8bd, + 0x7558dccd, 0x6c63be0a, 0xe44ce748, 0x60042b30, + 0xdad815b9, 0x8f758186, 0x1c8dd496, 0x7c85705d, + 0xd57b671c, 0xcea66708, 0x70660a4b, 0xd463e5b7, + 0xea828a5b, 0xe2ca6710, 0x8517eff4, 0x8a5f2a2f, + 0x6af88297, 0xea1034d6, 0x3c5cc9eb, 0x46f849e1, + 0xf6bddeeb, 0xaaf192a9, 0xb018a0a6, 0x1f0fd33a, + 0x31ff6ff3, 0xd3444345, 0x88f79a50, 0xcec19609, + 0x2cf2cc76, 0x82adba2c, 0x84188f77, 0x9c07d2c0, + 0x4e839036, 0x434fa50b, 0x78ab043e, 0x09fbd64f, + 0xda902401, 0x613a3c6f, 0x4a697f0d, 0x02302beb, + 0x84e0dbb4, 0x35d7eca9, 0x857d37bf, 0x4ea9ce58, + 0xa8c780e4, 0x486730d3, 0x2faf29eb, 0xa7b46a74, + 0x923f0f3f, 0xaccaf3af, 0x94d94baf, 0x81ca43c0, + 0xa1482f0d, 0xd2d527b0, 0x85054bef, 0x934ddea3, + 0xbbf03c30, 0x27308f4a, 0x3ee3eb4c, 0x2f9aed64, + 0xf082f13b, 0x7fcff4ba, 0xe1b0cb40, 0x57aabc7f, + 0xf274c9d3, 0x220d43fa, 0x4e77f4d0, 0x7085d793, + 0xb6bf991f, 0x30f135de, 0xf0715ea7, 0x7b2d016b, + 0x5333f064, 0xf388390a, 0x6ba63a6b, 0x432fd235, + 0xb5fd02cd, 0xaa5bbce9, 0x7e19a4d8, 0x81945d0e, + 0xad776f9e, 0x93740ed6, 0x18c4e796, 0x19f5ad5f +}; + diff --git a/build/libraries/gcd/common/gcd.c b/build/libraries/gcd/common/gcd.c new file mode 100644 index 0000000..0f277b1 --- /dev/null +++ b/build/libraries/gcd/common/gcd.c @@ -0,0 +1,1215 @@ +/*---------------------------------------------------------------------------* + Project: TwlBrom - GCD - libraries + File: gcd.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ + +#include +#include + +// use this functions for DS mode only + +//#define PRINT_DEBUG + +#ifdef PRINT_DEBUG +#define DBG_PRINTF vlink_dos_printf +#define DBG_CHAR vlink_dos_put_console +#else +#define DBG_PRINTF( ... ) ((void)0) +#define DBG_CHAR( c ) ((void)0) +#endif + + +static BOOL GCDi_ReadRomPreCore( GCDSlot slot, u32 romp, void *ramp, s32 size ); +static void GCDi_ReadGameModeRomCore( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDRomCtrls *ctrls ); +static void GCDi_WriteGameModeRomCore( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDRomCtrls *ctrls ); + +static void GCD_DmaRecvRomAsync( GCDSlot slot, u32 dmaNo, void *dest ); +static void GCD_DmaSendRomAsync( GCDSlot slot, u32 dmaNo, void *src ); + + +u32 GCDi_HeaderBuf[2][ GCD_ROM_HEADER_SIZE/sizeof(u32) ]; +u32 GCDi_SecureAreaBuf[2][ GCD_SECURE_AREA_SIZE/sizeof(u32) ]; +u32 GCDi_Secure2AreaBuf[2][ GCD_SECURE_AREA_SIZE/sizeof(u32) ]; + +GCDSharedWork GCDi_SharedWork[2]; +GCDSecureWork GCDi_SecureWork[2]; + + +/*---------------------------------------------------------------------------* + Name: GCDi_Enable + + Description: enable game card master control + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_Enable( GCDSlot slot ) +{ + REGType16v* cnt0 = GCDi_SelectRegAddr( slot, REG_MCCNT0_ADDR ); + + OSIntrMode enabled = OS_DisableInterrupts(); + + GCDi_WaitCtrl( slot ); + + *cnt0 |= REG_MI_MCCNT0_A_E_MASK | REG_MI_MCCNT0_A_I_MASK; + + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_Disable + + Description: disable game card master control + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_Disable( GCDSlot slot ) +{ + REGType16v* cnt0 = GCDi_SelectRegAddr( slot, REG_MCCNT0_ADDR ); + + OSIntrMode enabled = OS_DisableInterrupts(); + + GCDi_WaitCtrl( slot ); + + *cnt0 &= ~(REG_MI_MCCNT0_A_E_MASK | REG_MI_MCCNT0_A_I_MASK); + + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_SelectRom + + Description: select game card rom + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_SelectRom( GCDSlot slot ) +{ + REGType16v* cnt0 = GCDi_SelectRegAddr( slot, REG_MCCNT0_ADDR ); + + OSIntrMode enabled = OS_DisableInterrupts(); + + *cnt0 &= ~REG_MI_MCCNT0_A_SEL_MASK; + + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_SelectSpi + + Description: select game card spi + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_SelectSpi( GCDSlot slot ) +{ + REGType16v* cnt0 = GCDi_SelectRegAddr( slot, REG_MCCNT0_ADDR ); + + OSIntrMode enabled = OS_DisableInterrupts(); + + *cnt0 |= REG_MI_MCCNT0_A_SEL_MASK; + + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_GenCtrl + + Description: generate game card control + + Arguments: op : command + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_GenCtrl( GCDCtrlRegs* regs, + GCDRw rw, + GCDPageCount pcount, + GCDClockType ckt, u32 lt1, u32 lt2, + BOOL cpn, BOOL dpn, BOOL csc, BOOL dsc ) +{ + regs->latency = ((lt1 << REG_MI_MCCNT1_A_L1_SHIFT) & REG_MI_MCCNT1_A_L1_MASK) + | ((lt2 << REG_MI_MCCNT1_A_L2_SHIFT) & REG_MI_MCCNT1_A_L2_MASK); + + regs->ctrl = REG_MI_MCCNT1_A_START_MASK | REG_MI_MCCNT1_A_RESB_MASK + | rw + | pcount + | ckt + | ((lt1 << REG_MI_MCCNT1_A_L1_SHIFT) & REG_MI_MCCNT1_A_L1_MASK) + | ((lt2 << REG_MI_MCCNT1_A_L2_SHIFT) & REG_MI_MCCNT1_A_L2_MASK) + | ((cpn || dpn) ? (u32)REG_MI_MCCNT1_A_SE_MASK : 0) + | (csc ? REG_MI_MCCNT1_A_CSC_MASK : 0) + | (dsc ? REG_MI_MCCNT1_A_DS_MASK : 0); + +#if 1 + regs->scramble = (cpn || dpn) ? (u32)REG_MI_MCCNT1_A_SE_MASK : 0 + | csc ? REG_MI_MCCNT1_A_CSC_MASK : 0 + | dsc ? REG_MI_MCCNT1_A_DS_MASK : 0; +#endif +} + +/*---------------------------------------------------------------------------* + Name: GCDi_SetCtrl + + Description: set game card control + + Arguments: op : command + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_SetCtrl( GCDSlot slot, GCDCtrlRegs* regs ) +{ + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + + *cnt1 = regs->ctrl | regs->latency | regs->scramble; +} + +/*---------------------------------------------------------------------------* + Name: GCDi_SetOp + + Description: set game card command + + Arguments: op : command + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_SetOp( GCDSlot slot, GCDCmd64* op ) +{ + GCDi_SelectRom( slot ); + + { + REGType8v* cmd = GCDi_SelectRegAddr( slot, REG_MCCMD0_ADDR ); + + cmd[0] = op->b[7]; + cmd[1] = op->b[6]; + cmd[2] = op->b[5]; + cmd[3] = op->b[4]; + cmd[4] = op->b[3]; + cmd[5] = op->b[2]; + cmd[6] = op->b[1]; + cmd[7] = op->b[0]; + } +} + +/*---------------------------------------------------------------------------* + Name: GCD_SendOnlyCardOpCore + + Description: send only rom command + sync version + + Arguments: ctrls : rom control + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_SendOnlyCardOpCore( GCDSlot slot, GCDRomCtrls *ctrls ) +{ + GCDi_WaitCtrl( slot ); + + GCDi_SetOp( slot, &ctrls->gcdOp ); + + GCDi_SetCtrl( slot, ctrls->gcdRegs ); +} + +/*---------------------------------------------------------------------------* + Name: GCD_ReadRomID + + Description: read rom ID + sync version + + Arguments: None + + Returns: rom ID + *---------------------------------------------------------------------------*/ +u32 GCD_ReadRomID( GCDSlot slot ) +{ + return GCD_ReadGameModeID( slot ); +} + +/*---------------------------------------------------------------------------* + Name: GCD_ReadGameModeID + + Description: read rom ID on game mode + sync version + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +u32 GCD_ReadGameModeID( GCDSlot slot ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + u32 romID = 0; + u16 id = (u16)OS_GetLockID(); + + if ( !GCD_IsExisting( slot ) ) + { + return romID; + } + + if ( slot == GCD_PRIMARY_SLOT ) + { + OS_LockCard( id ); + } + else + { + OS_LockExCard( id ); + } + + ctrls->gcdRegs = &ctrls->gIDRegs; + ctrls->gcdOp.dw = GCDOP_G_OP_RD_ROM_ID; + + romID = GCDi_ReadRomIDCore( slot, ctrls ); + + if ( slot == GCD_PRIMARY_SLOT ) + { + OS_UnlockCard( id ); + } + else + { + OS_UnlockExCard( id ); + } + OS_ReleaseLockID( id ); + + return romID; +} + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadRomIDCore + + Description: read rom ID + sync version + + Arguments: ctrls : rom control + + Returns: None + *---------------------------------------------------------------------------*/ +u32 GCDi_ReadRomIDCore( GCDSlot slot, GCDRomCtrls *ctrls ) +{ + REGType32v* data1 = GCDi_SelectRegAddr( slot, REG_MCD1_ADDR ); + + GCDi_WaitCtrl( slot ); + + GCDi_SetOp( slot, &ctrls->gcdOp ); + + GCDi_SetCtrl( slot, ctrls->gcdRegs ); + GCDi_WaitData( slot ); + + return *data1; +} + + +/*---------------------------------------------------------------------------* + Name: GCD_ReadRom + + Description: read rom data + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadRom( GCDSlot slot, u32 romp, void *ramp, s32 size ) +{ + GCDWork *gw = &GCDi_Work[slot]; + u16 id; + + if ( !GCD_IsExisting( slot ) ) + { + return; + } + + id = (u16)OS_GetLockID(); + if ( slot == GCD_PRIMARY_SLOT ) + { + OS_LockCard( id ); + } + else + { + OS_LockExCard( id ); + } + + if ( GCDi_ReadRomPreCore( slot, romp, ramp, size ) ) + { + GCD_ReadGameModeRom( slot, gw->romp, gw->ramp, gw->restSize ); + } + + if ( slot == GCD_PRIMARY_SLOT ) + { + OS_UnlockCard( id ); + } + else + { + OS_UnlockExCard( id ); + } + OS_ReleaseLockID( id ); +} + +/*---------------------------------------------------------------------------* + Name: GCD_ReadRomAsync + + Description: read rom data + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ) +{ + GCDWork *gw = &GCDi_Work[slot]; + + if ( GCDi_ReadRomPreCore( slot, romp, ramp, size ) ) + { + GCD_ReadGameModeRomAsync( slot, gw->romp, gw->ramp, gw->restSize ); + } +} + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadRomPreCore + + Description: read rom data + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +static BOOL GCDi_ReadRomPreCore( GCDSlot slot, u32 romp, void *ramp, s32 size ) +{ + BOOL game_area = GCDi_ReadRomCommonPreCore( slot, romp, ramp, size ); + { + GCDWork *gw = &GCDi_Work[slot]; + romp = gw->romp; + ramp = gw->ramp; + size = gw->restSize; + } + + return game_area; +} + +BOOL GCDi_ReadRomCommonPreCore( GCDSlot slot, u32 romp, void *ram, s32 size ) +{ + GCDRomHeader *rh = GCDi_GetRomHeaderAddr( slot ); + u32 romEndp = romp + size; + u32 secure2 = (u32)rh->l.twlAreaOffset * GCD_TWL_AREA_ALIGN + GCD_SECURE2_AREA_OFFSET; + u32 game2 = secure2 + GCD_SECURE2_AREA_SIZE; + u8 *ramp = ram; + + // header + if ( romp < GCD_ROM_HEADER_SIZE + && size > 0 ) + { + s32 otherSize = (s32)romEndp - GCD_ROM_HEADER_SIZE; + s32 hdrSize = size; + if ( otherSize > 0 ) + { + hdrSize -= otherSize; + } + MI_CpuCopyFast( &GCDi_HeaderBuf[slot][romp/4], ramp, (u32)hdrSize ); + romp += hdrSize; + ramp += hdrSize; + size -= hdrSize; + } + + // pad + if ( romp >= GCD_ROM_HEADER_SIZE && romp < GCD_SECURE_AREA_OFFSET + && size > 0 ) + { + s32 otherSize = (s32)romEndp - (GCD_SECURE_AREA_OFFSET - GCD_ROM_HEADER_SIZE); + s32 padSize = size; + if ( otherSize > 0 ) + { + padSize -= otherSize; + } + MI_CpuClearFast( ramp, (u32)padSize ); + romp += padSize; + ramp += padSize; + size -= padSize; + } + + //secure + if ( romp >= GCD_SECURE_AREA_OFFSET && romp < GCD_GAME_AREA_OFFSET + && size > 0 ) + { + s32 gameSize = (s32)romEndp - GCD_GAME_AREA_OFFSET; + s32 secureSize = size; + if ( gameSize > 0 ) + { + secureSize -= gameSize; + } + MI_CpuCopyFast( &GCDi_SecureAreaBuf[slot][(romp - GCD_SECURE_AREA_OFFSET)/4], ramp, (u32)secureSize ); + romp += secureSize; + ramp += secureSize; + size -= secureSize; + } + + //secure2 + if ( rh->l.twlAreaOffset + && romp >= secure2 && romp < game2 + && size > 0 ) + { + s32 game2Size = (s32)(romEndp - game2); + s32 secure2Size = size; + if ( game2Size > 0 ) + { + secure2Size -= game2Size; + } + MI_CpuCopyFast( &GCDi_Secure2AreaBuf[slot][(romp - secure2)/4], ramp, (u32)secure2Size ); + romp += secure2Size; + ramp += secure2Size; + size -= secure2Size; + } + + GCD_WaitRomAsync( slot ); + + { + GCDWork *gw = &GCDi_Work[slot]; + gw->romp = romp; + gw->ramp = ramp; + gw->restSize = size; + } + + // game + if ( romp >= GCD_GAME_AREA_OFFSET + && size > 0 ) + { + return TRUE; + } + + return FALSE; +} + +/*---------------------------------------------------------------------------* + Name: GCD_ReadNormalModeRom + + Description: read rom data on normal mode + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadNormalModeRom( GCDSlot slot, u32 romp, void *ramp, s32 size ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + s32 restSize = size; + s32 oneShotSize; + + ctrls->gcdRegs = &ctrls->nReadRomRegs; + oneShotSize = GCDi_GetOneShotSizeFromCtrl( ctrls->gcdRegs->ctrl ); + + if ( GCDi_SharedWork[slot].nCardID & GCD_ROMID_1TROM_MASK ) + { + // 3Dpݒ + { + ctrls->gcdRegs->ctrl &= ~REG_MI_MCCNT1_A_PC_MASK; + ctrls->gcdRegs->ctrl |= GCD_PAGE_1; + } + } + + while ( restSize > 0 ) // ubNǂݍ + { + GCDi_ReadNormalModeRomCore( slot, romp, ramp, oneShotSize, ctrls ); + + romp += oneShotSize; + *(u8 **)&ramp += oneShotSize; + restSize -= oneShotSize; + } + + GCDi_WaitDma( slot, ctrls->dmaNo ); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadNormalModeRomCore + + Description: read rom data on game mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_ReadNormalModeRomCore( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDRomCtrls *ctrls ) +{ + ctrls->gcdOp.dw = GCDOP_N_OP_RD_PAGE + | ((u64 )(romp/GCD_ROM_PAGE_SIZE) << GCDOP_N_RD_PAGE_ADDR_SHIFT); + + GCDi_ReadRomCore( slot, ramp, size, ctrls ); +} + +/*---------------------------------------------------------------------------* + Name: GCD_ReadGameModeRom + + Description: read rom data on game mode + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadGameModeRom( GCDSlot slot, u32 romp, void *ramp, s32 size ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + s32 restSize = size; + s32 oneShotSize; + + ctrls->gcdRegs = &ctrls->gReadRomRegs; + oneShotSize = GCDi_GetOneShotSizeFromCtrl( ctrls->gcdRegs->ctrl ); + + while ( restSize > 0 ) // ubNǂݍ + { + GCDi_ReadGameModeRomCore( slot, romp, ramp, oneShotSize, ctrls ); + + romp += oneShotSize; + *(u8 **)&ramp += oneShotSize; + restSize -= oneShotSize; + } + + GCDi_WaitDma( slot, ctrls->dmaNo ); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadGameModeRomCore + + Description: read rom data on game mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCDi_ReadGameModeRomCore( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDRomCtrls *ctrls ) +{ + ctrls->gcdOp.dw = GCDOP_G_OP_RD_PAGE + | ((u64 )(romp/GCD_ROM_PAGE_SIZE) << GCDOP_G_RD_PAGE_ADDR_SHIFT); + + GCDi_ReadRomCore( slot, ramp, size, ctrls ); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadRomCore + + Description: read rom data on game mode + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_ReadRomCore( GCDSlot slot, void *ramp, s32 size, GCDRomCtrls *ctrls ) +{ + u32 dmaNo = ctrls->dmaNo; + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + REGType32v* data1 = GCDi_SelectRegAddr( slot, REG_MCD1_ADDR ); + + if ( !GCD_IsExisting( slot ) ) + { + return; + } + + GCDi_WaitDma( slot, dmaNo ); + + GCDi_SetOp( slot, &ctrls->gcdOp ); // R}hݒ + + if ( MI_EXDMA_CH_MIN <= dmaNo && dmaNo <= MI_EXDMA_CH_MAX ) + { + GCD_DmaRecvRomAsync( slot, dmaNo, ramp ); + GCDi_SetCtrl( slot, ctrls->gcdRegs ); // Rg[ݒ & DMAX^[g + } + else + { + void *ramEndp; + u32 ctrlTmp; + + GCDi_SetCtrl( slot, ctrls->gcdRegs ); // Rg[ݒ + + ramEndp = (u8 *)ramp + size; // i[IAhXZo + + do { // CPUǂݍ + ctrlTmp = *cnt1; + + if (ctrlTmp & REG_MI_MCCNT1_A_RDY_MASK) { + u32 dataTmp = *data1; + + if (ramp < ramEndp) + { + *((vu32 *)ramp) = dataTmp; // wTCY܂Ŋi[i㑱f[^͓ǂݎ̂āj + (*(vu32 **)&ramp)++; + } + } + } + while (ctrlTmp & REG_MI_MCCNT1_A_START_MASK); + } +} + + +/*---------------------------------------------------------------------------* + Name: GCD_WriteGameModeRom + + Description: write rom data on game mode + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_WriteGameModeRom( GCDSlot slot, u32 romp, void *ramp, s32 size ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + s32 restSize = size; + s32 oneShotSize; + + ctrls->gcdRegs = &ctrls->gWriteRomRegs; + + oneShotSize = GCDi_GetOneShotSizeFromCtrl( ctrls->gcdRegs->ctrl ); + + while ( restSize > 0 ) // ubNǂݍ + { + GCDi_WriteGameModeRomCore( slot, romp, ramp, oneShotSize, ctrls ); + + romp += oneShotSize; + *(u8 **)&ramp += oneShotSize; + restSize -= oneShotSize; + } + + GCDi_WaitDma( slot, ctrls->dmaNo ); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_WriteGameModeRomCore + + Description: write rom data on game mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCDi_WriteGameModeRomCore( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDRomCtrls *ctrls ) +{ + ctrls->gcdOp.dw = GCDOP_G_OP_WR_PAGE + | ((u64 )(romp/GCD_ROM_PAGE_SIZE) << GCDOP_G_RD_PAGE_ADDR_SHIFT); + + GCDi_WriteRomCore( slot, ramp, size, ctrls ); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_WriteRomCore + + Description: write rom data on game mode + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WriteRomCore( GCDSlot slot, void *ramp, s32 size, GCDRomCtrls *ctrls ) +{ + u32 dmaNo = ctrls->dmaNo; + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + REGType32v* data1 = GCDi_SelectRegAddr( slot, REG_MCD1_ADDR ); + +// OS_TPrintf( "\nwrite size = %#x\n\n", size ); + + GCDi_WaitDma( slot, dmaNo ); + + GCDi_SetOp( slot, &ctrls->gcdOp ); // R}hݒ + + if ( MI_EXDMA_CH_MIN <= dmaNo && dmaNo <= MI_EXDMA_CH_MAX ) + { + GCD_DmaSendRomAsync( slot, dmaNo, ramp ); + GCDi_SetCtrl( slot, ctrls->gcdRegs ); // Rg[ݒ & DMAX^[g + } + else + { + void *ramEndp; + u32 ctrlTmp; + + GCDi_SetCtrl( slot, ctrls->gcdRegs ); // Rg[ݒ + + ramEndp = (u8 *)ramp + size; // i[IAhXZo + + do { // CPUǂݍ + ctrlTmp = *cnt1; + + if (ctrlTmp & REG_MI_MCCNT1_A_RDY_MASK) { + u32 dataTmp = 0; + + if (ramp < ramEndp) + { + dataTmp = *((vu32 *)ramp); + (*(vu32 **)&ramp)++; + } + *data1 = dataTmp; + } + } + while (ctrlTmp & REG_MI_MCCNT1_A_START_MASK); + } +} + +/*---------------------------------------------------------------------------* + Name: GCD_DmaRecvRomAsync + + Description: receive data with DMA + async version + + Arguments: dmaNo : DMA channel No. + dest : destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCD_DmaRecvRomAsync( GCDSlot slot, u32 dmaNo, void *dest ) +{ + const void* data1 = GCDi_SelectRegAddr( slot, REG_MCD1_ADDR ); + u32 timing = MI_NDMA_TIMING_CARD_A; + u32 blockSize = MI_NDMA_BWORD_1; + u32 interval = 1; + u32 prescale = MI_NDMA_INTERVAL_PS_1; + + if ( slot == GCD_SECONDARY_SLOT ) + { + timing = MI_NDMA_TIMING_CARD_B; + } + + MIi_ExDmaRecvAsyncCore(dmaNo, data1, dest, 4, 4, + blockSize, interval, prescale, + MI_NDMA_CONTINUOUS_ON, MI_NDMA_SRC_RELOAD_ENABLE, MI_NDMA_DEST_RELOAD_DISABLE, + timing); +} + +/*---------------------------------------------------------------------------* + Name: GCD_DmaSendRomAsync + + Description: receive data with DMA + async version + + Arguments: dmaNo : DMA channel No. + dest : destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCD_DmaSendRomAsync( GCDSlot slot, u32 dmaNo, void *src ) +{ + const void* data1 = GCDi_SelectRegAddr( slot, REG_MCD1_ADDR ); + u32 timing = MI_NDMA_TIMING_CARD_A; + u32 blockSize = MI_NDMA_BWORD_1; + u32 interval = 1; + u32 prescale = MI_NDMA_INTERVAL_PS_1; + + if ( slot == GCD_SECONDARY_SLOT ) + { + timing = MI_NDMA_TIMING_CARD_B; + } + + MIi_ExDmaSendAsyncCore(dmaNo, src, (void*)REG_MCD1_ADDR, 4, 4, + blockSize, interval, prescale, + MI_NDMA_CONTINUOUS_ON, MI_NDMA_SRC_RELOAD_DISABLE, MI_NDMA_DEST_RELOAD_ENABLE, + timing); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_GetOneShotSizeFromCtrl + + Description: get block size + + Arguments: ctrl : rom control + + Returns: None + *---------------------------------------------------------------------------*/ +s32 GCDi_GetOneShotSizeFromCtrl( u32 ctrl ) +{ + s32 oneShotSize = 0; + u32 pages = (ctrl & REG_MI_MCCNT1_A_PC_MASK) >> REG_MI_MCCNT1_A_PC_SHIFT; + s32 pageSize = 512; + + oneShotSize = pageSize << (pages - 1); + + return oneShotSize; +} + + +/*---------------------------------------------------------------------------* + Name: GCD_ReadNormalModeRomAsync + + Description: read rom data on normal mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadNormalModeRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ) +{ + GCDWork *gw = &GCDi_Work[slot]; + GCDRomCtrls *ctrls = &gw->ctrls; + + ctrls->gcdRegs = &ctrls->nReadRomRegs; + + gw->funcp = GCDi_ReadNormalModeRomCore; + + GCD_SetInterrupt( slot, romp, ramp, size, gw ); + + gw->funcp( slot, gw->romp, gw->ramp, gw->oneShotSize, ctrls ); +} + + +/*---------------------------------------------------------------------------* + Name: GCD_ReadGameModeRomAsync + + Description: read rom data on game mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadGameModeRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ) +{ + GCDWork *gw = &GCDi_Work[slot]; + GCDRomCtrls *ctrls = &gw->ctrls; + + ctrls->gcdRegs = &ctrls->gReadRomRegs; + + gw->funcp = GCDi_ReadGameModeRomCore; + + GCD_SetInterrupt( slot, romp, ramp, size, gw ); + + gw->funcp( slot, gw->romp, gw->ramp, gw->oneShotSize, ctrls ); +} + + +/*---------------------------------------------------------------------------* + Name: GCD_WriteGameModeRomAsync + + Description: write rom data on game mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_WriteGameModeRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ) +{ + GCDWork *gw = &GCDi_Work[slot]; + GCDRomCtrls *ctrls = &gw->ctrls; + + ctrls->gcdRegs = &ctrls->gWriteRomRegs; + + gw->funcp = GCDi_WriteGameModeRomCore; + + GCD_SetInterrupt( slot, romp, ramp, size, gw ); + + gw->funcp( slot, gw->romp, gw->ramp, gw->oneShotSize, ctrls ); +} + + +/*---------------------------------------------------------------------------* + Name: GCD_SetInterrupt + + Description: set interrupt + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_SetInterrupt( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDWork *gw ) +{ + GCDRomCtrls *ctrls = &gw->ctrls; + u32 dmaNo = ctrls->dmaNo; + u32 mask = GCDi_SelectIrqMask( slot, OS_IE_CARD_DATA ); + OSIrqFunction intr = GCDi_InterruptHandlerPRIME; + + gw->romp = romp; + gw->ramp = ramp; + gw->restSize = size; + gw->oneShotSize = GCDi_GetOneShotSizeFromCtrl( ctrls->gcdRegs->ctrl ); + + if ( dmaNo < MI_EXDMA_CH_MIN || MI_EXDMA_CH_MAX < dmaNo ) + { + ctrls->lastDmaNo = ctrls->dmaNo; + ctrls->dmaNo = GCD_DEFAULT_DMA_A_NO; + if ( slot == GCD_SECONDARY_SLOT ) + { + ctrls->dmaNo = GCD_DEFAULT_DMA_B_NO; + } + } + + GCDi_WaitDma( slot, dmaNo ); + + (void)OS_DisableInterrupts(); + + if ( slot ) + { + intr = GCDi_InterruptHandlerSECOND; + } + + OS_SetIrqFunction( mask, intr ); + + gw->isAsync = TRUE; + + gw->intrDone = FALSE; + + reg_OS_IF = mask; + reg_OS_IE |= mask; + + (void)OS_EnableInterrupts(); + (void)OS_EnableIrq(); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_InterruptHandler + + Description: interrupt handler + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_InterruptHandlerCommon( GCDSlot slot ) +{ + GCDWork *gw = &GCDi_Work[slot]; + s32 oneShotSize = gw->oneShotSize; + + // read block + + gw->romp += oneShotSize; + gw->ramp += oneShotSize; + gw->restSize -= oneShotSize; + + if (gw->restSize > 0) { + GCDRomCtrls *ctrls = &gw->ctrls; + gw->oneShotSize = GCDi_GetOneShotSizeFromCtrl( ctrls->gcdRegs->ctrl ); + gw->funcp( slot, gw->romp, gw->ramp, oneShotSize, &gw->ctrls ); + } else { + gw->intrDone = TRUE; // J[h̒ʒm + } +} + +void GCDi_InterruptHandlerPRIME( void ) +{ + GCDi_InterruptHandlerCommon( GCD_PRIMARY_SLOT ); +} + +void GCDi_InterruptHandlerSECOND( void ) +{ + GCDi_InterruptHandlerCommon( GCD_SECONDARY_SLOT ); +} + + +//================================================================================ +// WAIT/STOP +//================================================================================ +/*---------------------------------------------------------------------------* + Name: GCD_IsBusy + + Description: check whether game card is busy or not + + Arguments: None + + Returns: TRUE if game card is busy, FALSE if not + *---------------------------------------------------------------------------*/ +BOOL GCD_IsBusy( GCDSlot slot ) +{ + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + + return (BOOL)((*cnt1 & REG_MI_MCCNT1_A_START_MASK) >> REG_MI_MCCNT1_A_START_SHIFT); +} + +/*---------------------------------------------------------------------------* + Name: GCD_IsDataReady + + Description: check whether data is ready or not + + Arguments: None + + Returns: TRUE if game card is busy, FALSE if not + *---------------------------------------------------------------------------*/ +BOOL GCD_IsDataReady( GCDSlot slot ) +{ + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + + return (BOOL)((*cnt1 & REG_MI_MCCNT1_A_RDY_MASK) >> REG_MI_MCCNT1_A_RDY_SHIFT); +} + +/*---------------------------------------------------------------------------* + Name: GCD_Stop + + Description: stop game card access + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_Stop( GCDSlot slot ) +{ + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + + OSIntrMode enabled = OS_DisableInterrupts(); + + *cnt1 &= ~REG_MI_MCCNT1_A_START_MASK; + + (void)OS_RestoreInterrupts(enabled); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_WaitCtrl + + Description: wait while game card is busy + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WaitCtrl( GCDSlot slot ) +{ + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + + while (*cnt1 & REG_MI_MCCNT1_A_START_MASK) + { + } +} + +/*---------------------------------------------------------------------------* + Name: GCDi_WaitData + + Description: wait until data is ready + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WaitData( GCDSlot slot ) +{ + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + + while ( !(*cnt1 & REG_MI_MCCNT1_A_RDY_MASK) ) + { + } +} + +/*---------------------------------------------------------------------------* + Name: GCDi_WaitDma + + Description: wait for stopping game card DMA + + Arguments: dmaNo : DMA channel No. + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WaitDma( GCDSlot slot, u32 dmaNo ) +{ + GCDi_WaitCtrl( slot ); + + if ( MI_EXDMA_CH_MIN <= dmaNo && dmaNo <= MI_EXDMA_CH_MAX ) + { + MIi_StopExDma( dmaNo ); + } +} + + +/*---------------------------------------------------------------------------* + Name: GCDi_WaitInterrupt + + Description: wait for game card interrupt + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WaitInterrupt( GCDSlot slot ) +{ + GCDWork *gw = &GCDi_Work[slot]; + + if ( gw->isAsync ) + { + while ( !gw->intrDone ) + { + } + } + gw->intrDone = FALSE; + gw->isAsync = FALSE; + + GCDi_WaitDma( slot, gw->ctrls.dmaNo ); +} + +/*---------------------------------------------------------------------------* + Name: GCD_WaitRomAsync + + Description: wait for game card async access + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_WaitRomAsync( GCDSlot slot ) +{ + GCDi_WaitInterrupt( slot ); + + { + GCDWork *gw = &GCDi_Work[slot]; + GCDRomCtrls *ctrls = &gw->ctrls; + u32 mask = GCDi_SelectIrqMask( slot, OS_IE_CARD_DATA ); + + OSIntrMode enabled = OS_DisableInterrupts(); + + ctrls->dmaNo = ctrls->lastDmaNo; + +#define IOP_DISABLE_OS_TIMER +#ifdef IOP_DISABLE_OS_TIMER + reg_OS_IE &= ~REG_OS_IE_T1_MASK; +#endif // IOP_DISABLE_OS_TIMER + + reg_OS_IE &= ~mask; // disable card interrupt + + (void)OS_RestoreInterrupts( enabled ); + } +} + + diff --git a/build/libraries/gcd/common/gcd_init.c b/build/libraries/gcd/common/gcd_init.c new file mode 100644 index 0000000..43d5c83 --- /dev/null +++ b/build/libraries/gcd/common/gcd_init.c @@ -0,0 +1,1696 @@ +/*---------------------------------------------------------------------------* + Project: TwlBrom - GCD - libraries + File: gcd_init.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +//#define PRINT_DEBUG + +#ifdef PRINT_DEBUG +#define DBG_PRINTF vlink_dos_printf +#define DBG_CHAR vlink_dos_put_console +#else +#define DBG_PRINTF( ... ) ((void)0) +#define DBG_CHAR( c ) ((void)0) +#endif + + +//#define FIRM_FORCE_DEBUGGER +#define FIRM_FORCE_FIRMBLOWFISH + +#ifndef FIRM_FORCE_DEBUGGER +#define GCD_ENABLE_SCRAMBLE +#endif // FIRM_FORCE_DEBUGGER + +static void GCDi_GetExistingSlots( GCDSlot* start, GCDSlot* end ); +void GCDi_CallbackForReset(PXIFifoTag tag, u32 data, BOOL err); +void GCDi_CallbackForResetAll(PXIFifoTag tag, u32 data, BOOL err); + +static void GCDi_SetPngIntf( GCDSlot slot, u32 pnA_l, u8 pnA_h, u32 pnB_l, u8 pnB_h ); +static void GCDi_SendOnlyCardSecureOpCore( GCDSlot slot, GCDRomCtrls *ctrls ); +static void GCDi_ReadSecureModeRomCore( GCDSlot slot, void *ramp, s32 size, GCDRomCtrls *ctrls ); +static void Encrypt2SetTimer4Secure( GCDSlot slot, GCDRomCtrls *ctrls ); + +static BOOL IsCtrApp( GCDSlot slot ); +static BOOL IsDsApp( GCDSlot slot ); + +static BOOL GCDi_SecureInitialized[2]; + + +static void GCDi_LoadHeader( GCDSlot slot ); +static void GCDi_LoadHeaderAll( void ); +static void GCDi_LoadTable( GCDSlot slot ); +static void GCDi_LoadTableAsync( GCDSlot slot ); +static void GCDi_ReadShortHeader( GCDSlot slot, void *ramp ); +static void GCDi_ReadShortHeaderAsync( GCDSlot slot, void *ramp ); +static void GCDi_LoadSecure( GCDSlot slot ); +static void GCDi_LoadSecure2( GCDSlot slot ); +static void GCDi_LoadSecureAll( void ); +static void GCDi_LoadSecure2All( void ); + +static BOOL GCD_Initialized[2]; +extern GCDSharedWork GCDi_SharedWork[2]; +extern GCDSecureWork GCDi_SecureWork[2]; + +GCDWork GCDi_Work[2]; + + + +void* GCDi_GetRomHeaderAddr( GCDSlot slot ) +{ + return ((void*)GCDi_HeaderBuf[slot]); +} + + +// SDKSecondarySlot̃J[hvZbTݒ肪pӂĂȂ̂ŁAƂ肠[JŗpӁB +#ifdef SDK_ARM9 +static inline void MIi_SetExCardProcessor(MIProcessor proc) +{ + MI_PROCESSOR_ASSERT(proc); + reg_MI_EXMEMCNT = + (u16)((reg_MI_EXMEMCNT & ~REG_MI_EXMEMCNT_MPB_MASK) | (proc << REG_MI_EXMEMCNT_MPB_SHIFT)); +} +#endif +#ifdef SDK_ARM7 +#define REG_MI_EXMEMCNT_MPB_MASK 0x0400 +#define REG_MI_EXMEMCNT_MPB_SHIFT 10 +#endif +static inline MIProcessor MI_GetExCardProcessor(void) +{ + return (MIProcessor)((reg_MI_EXMEMCNT & REG_MI_EXMEMCNT_MPB_MASK) >> REG_MI_EXMEMCNT_MPB_SHIFT); +} + +// SDKSecondarySlot̃J[hbNpӂĂȂ̂ŁAƂ肠PrimarySlotƋpŁB +#ifdef SDK_ARM9 +#define OSi_ASSERT_ID( id ) SDK_ASSERTMSG( id >= OS_MAINP_LOCK_ID_START && id <= OS_MAINP_SYSTEM_LOCK_ID, \ + "lock ID %d is out of bounds", id ) +#else +#define OSi_ASSERT_ID( id ) SDK_ASSERTMSG( id >= OS_SUBP_LOCK_ID_START && id <= OS_SUBP_SYSTEM_LOCK_ID, \ + "lock ID %d is out of bounds", id ) +#endif + +static void OSi_AllocateExCardBus(void) +{ +#ifdef SDK_ARM9 + MIi_SetExCardProcessor(MI_PROCESSOR_ARM9); // Card for MAIN +#endif +} + +static void OSi_FreeExCardBus(void) +{ +#ifdef SDK_ARM9 + MIi_SetExCardProcessor(MI_PROCESSOR_ARM7); // Card for SUB +#endif +} + +#define HW_CARD_B_LOCK_BUF HW_CTRDG_LOCK_BUF + +s32 OS_LockExCard(u16 lockID) +{ + OSi_ASSERT_ID(lockID); + + return OS_LockByWord(lockID, (OSLockWord *)HW_CARD_B_LOCK_BUF, OSi_AllocateExCardBus); +} + +s32 OS_UnlockExCard(u16 lockID) +{ + OSi_ASSERT_ID(lockID); + + return OS_UnlockByWord(lockID, (OSLockWord *)HW_CARD_B_LOCK_BUF, OSi_FreeExCardBus); +} + + +/*---------------------------------------------------------------------------* + Name: GCD_Init + + Description: initialize for game card access + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_Init( void ) +{ + GCDSlot slot; + MIProcessor lastProc = MI_GetCardProcessor(); + MIProcessor lastProcB = MI_GetExCardProcessor(); + u16 id = (u16)OS_GetLockID(); + + OS_LockCard( id ); + OS_LockExCard( id ); + +#ifdef SDK_ARM9 + MIi_SetCardProcessor( MI_PROCESSOR_ARM9 ); + MIi_SetExCardProcessor( MI_PROCESSOR_ARM9 ); +#else // SDK_ARM9 + while ( MI_GetCardProcessor() != MI_PROCESSOR_ARM7 ) + { + } + while ( MI_GetExCardProcessor() != MI_PROCESSOR_ARM7 ) + { + } +#endif // SDK_ARM7 + + if ( GCD_Initialized[GCD_PRIMARY_SLOT] == FALSE || + GCD_Initialized[GCD_SECONDARY_SLOT] == FALSE ) + { + GCDi_Init( TRUE ); + GCDi_LoadHeaderAll(); + GCDi_LoadSecureAll(); + } + + for (slot=GCD_PRIMARY_SLOT; slot<=GCD_SECONDARY_SLOT; slot++) + { + if ( GCD_Initialized[slot] == FALSE ) + { + if ( GCD_IsExisting( slot ) ) + { + if ( GCDi_IsDsApp( slot ) ) + { + GCDRomHeader *rh = GCDi_GetRomHeaderAddr( slot ); + + if ( rh->l.twlAreaOffset ) // && (sh->nCardID & GCD_ROMID_TWLROM_MASK) ) + { + u32 chat_cycles = OS_MSEC_TO_CPUCYC( 25 ) / GCD_CHATTERING_CYCLES; +#ifdef SDK_ARM9 + chat_cycles /= 2; +#endif // SDK_ARM9 + GCD_Reset( slot, chat_cycles ); + GCDi_LoadHeader( slot ); + GCDi_LoadSecure2( slot ); + } + + GCD_Initialized[slot] = TRUE; + } + } + } + } + +#ifdef SDK_ARM9 + MIi_SetCardProcessor( lastProc ); + MIi_SetExCardProcessor( lastProcB ); +#endif // SDK_ARM9 + + OS_UnlockExCard( id ); + OS_UnlockCard( id ); + + OS_ReleaseLockID( id ); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_Init + + Description: initialize for game card access + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_Init( BOOL reset ) +{ + static BOOL initialized; + + if ( initialized == FALSE ) + { + GCDSlot slot; + + if ( reset ) + { +#ifdef SDK_ARM7 + + OSIntrMode enabled; + OSIrqMask lastIE; + BOOL lastIME; + + lastIE = OS_EnableIrqMask(OS_IE_SPFIFO_RECV); + lastIME = OS_EnableIrq(); + enabled = OS_EnableInterrupts(); + + //---- setting PXI + PXI_Init(); + PXI_SetFifoRecvCallback(PXI_FIFO_TAG_GCD, GCDi_CallbackForResetAll); + + while ( !( GCDi_Work[GCD_PRIMARY_SLOT].isPxiDone == TRUE && + GCDi_Work[GCD_SECONDARY_SLOT].isPxiDone == TRUE ) ) + { + } + + (void)OS_RestoreIrq(lastIME); + (void)OS_SetIrqMask(lastIE); + (void)OS_RestoreInterrupts(enabled); + +#else // SDK_ARM9 + + u32 chat_cycles = OS_MSEC_TO_CPUCYC( 25 ) / GCD_CHATTERING_CYCLES; + chat_cycles /= 2; + GCD_ResetAll( chat_cycles ); + +#endif // SDK_ARM9 + } + + for (slot=GCD_PRIMARY_SLOT; slot<=GCD_SECONDARY_SLOT; slot++) + { + GCDWork *gw = &GCDi_Work[slot]; + GCDRomCtrls *ctrls = &gw->ctrls; + + GCDi_GenCtrl( &ctrls->nLoadTableRegs, GCD_RW_READ, + GCD_PAGE_16, + GCD_CKT_240NS, 0, 0x18, + FALSE, FALSE, FALSE, FALSE ); + + GCDi_GenCtrl( &ctrls->nSendOnlyOpRegs, GCD_RW_READ, + GCD_PAGE_0, + GCD_CKT_240NS, 0x18, 0, + FALSE, FALSE, FALSE, FALSE ); + + GCDi_GenCtrl( &ctrls->nIDRegs, GCD_RW_READ, + GCD_PAGE_STAT, + GCD_CKT_240NS, 0x18, 0, + FALSE, FALSE, FALSE, FALSE ); + + GCDi_GenCtrl( &ctrls->nReadShortHeaderRegs, GCD_RW_READ, + GCD_PAGE_1, + GCD_CKT_240NS, REG_MI_MCCNT1_L1_MASK, REG_MI_MCCNT1_L2_MASK >> REG_MI_MCCNT1_L2_SHIFT, + FALSE, FALSE, FALSE, FALSE ); + + GCDi_GenCtrl( &ctrls->nReadRomRegs, GCD_RW_READ, + GCD_PAGE_8, + GCD_CKT_240NS, 0x657, 0x1, + FALSE, FALSE, FALSE, FALSE ); + + GCDi_GenCtrl( &ctrls->sSendOnlyOpRegs, GCD_RW_READ, + GCD_PAGE_0, + GCD_CKT_240NS, 0x8f8+0x18, 0, + FALSE, FALSE, FALSE, FALSE ); // enable after PNG ON + + GCDi_GenCtrl( &ctrls->sIDRegs, GCD_RW_READ, + GCD_PAGE_STAT, + GCD_CKT_240NS, 0x8f8+0x18, 0, + FALSE, TRUE, FALSE, TRUE ); + + GCDi_GenCtrl( &ctrls->sReadRomRegs, GCD_RW_READ, + GCD_PAGE_8, + GCD_CKT_240NS, 0x8f8, 0x18, + FALSE, TRUE, FALSE, TRUE ); + + GCDi_GenCtrl( &ctrls->gIDRegs, GCD_RW_READ, + GCD_PAGE_STAT, + GCD_CKT_150NS, 0, 0x1, +#ifdef GCD_ENABLE_SCRAMBLE + TRUE, TRUE, TRUE, TRUE ); +#else // GCD_ENABLE_SCRAMBLE + FALSE, FALSE, FALSE, FALSE ); +#endif // GCD_ENABLE_SCRAMBLE + + GCDi_GenCtrl( &ctrls->gReadRomRegs, GCD_RW_READ, + GCD_PAGE_1, + GCD_CKT_150NS, 0x657, 0x1, +#ifdef GCD_ENABLE_SCRAMBLE + TRUE, TRUE, TRUE, TRUE ); +#else // GCD_ENABLE_SCRAMBLE + FALSE, FALSE, FALSE, FALSE ); +#endif // GCD_ENABLE_SCRAMBLE + + GCDi_GenCtrl( &ctrls->gWriteRomRegs, GCD_RW_WRITE, + GCD_PAGE_1, + GCD_CKT_150NS, 0x21, 0x1, +#ifdef GCD_ENABLE_SCRAMBLE + TRUE, TRUE, TRUE, TRUE ); +#else // GCD_ENABLE_SCRAMBLE + FALSE, FALSE, FALSE, FALSE ); +#endif // GCD_ENABLE_SCRAMBLE + } + + initialized = TRUE; + } +} + + +/*---------------------------------------------------------------------------* + Name: GCD_SetPrimarySlot + + Description: set primary game card slot + + Arguments: primary slot + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_SetPrimarySlot( u8 slot ) +{ + if ( slot <= 1 ) + { + reg_MI_MC_SWP = (u8)(slot * REG_MI_MC_SWP_E_MASK); + } +} + +/*---------------------------------------------------------------------------* + Name: GCD_GetPrimarySlot + + Description: get primary game card slot + + Arguments: None + + Returns: primary slot + *---------------------------------------------------------------------------*/ +u8 GCD_GetPrimarySlot( void ) +{ + return (u8)((reg_MI_MC_SWP & REG_MI_MC_SWP_E_MASK) >> REG_MI_MC_SWP_E_SHIFT); +} + + +/*---------------------------------------------------------------------------* + Name: GCDi_SendtoPxi + + Description: send data via PXI + + Arguments: data : data to send + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_SendtoPxi(u32 data) +{ + while (PXI_SendWordByFifo(PXI_FIFO_TAG_GCD, data, FALSE) != PXI_FIFO_SUCCESS) + { + SVC_WaitByLoop(1); + } +} + +/*---------------------------------------------------------------------------* + Name: GCDi_CallbackForReset + + Description: callback to receive data from PXI + + Arguments: tag : tag from PXI (unused) + data : data from PXI + err : error bit (unused) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_CallbackForReset(PXIFifoTag tag, u32 data, BOOL err) +{ +#pragma unused( tag, err ) + GCDPxiCmd pxi; + pxi.raw = data; + + if (pxi.e.cmd == GCD_PXI_COMMAND_RESET) + { +#ifdef SDK_ARM7 + GCD_Reset( (GCDSlot)pxi.e.slot, pxi.e.param ); + //---- send message to ARM9 + GCDi_SendtoPxi( GCD_PXI_COMMAND_RESET ); +#endif // SDK_ARM7 + + GCDi_Work[pxi.e.slot].isPxiDone = TRUE; + } + else + { +#ifndef SDK_FINALROM + OS_Panic("illegal GCD pxi command."); +#else + OS_Panic(""); +#endif + } +} + +/*---------------------------------------------------------------------------* + Name: GCDi_CallbackForResetAll + + Description: callback to receive data from PXI + + Arguments: tag : tag from PXI (unused) + data : data from PXI + err : error bit (unused) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_CallbackForResetAll(PXIFifoTag tag, u32 data, BOOL err) +{ +#pragma unused( tag, err ) + GCDPxiCmd pxi; + pxi.raw = data; + + if (pxi.e.cmd == GCD_PXI_COMMAND_RESET) + { +#ifdef SDK_ARM7 + GCD_ResetAll( pxi.e.param ); + //---- send message to ARM9 + GCDi_SendtoPxi( GCD_PXI_COMMAND_RESET ); +#endif // SDK_ARM7 + + GCDi_Work[GCD_PRIMARY_SLOT].isPxiDone = TRUE; + GCDi_Work[GCD_SECONDARY_SLOT].isPxiDone = TRUE; + } + else + { +#ifndef SDK_FINALROM + OS_Panic("illegal GCD pxi command."); +#else + OS_Panic(""); +#endif + } +} + + +/*---------------------------------------------------------------------------* + Name: GCDi_GetExistingSlots + + Description: get enabled slots + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCDi_GetExistingSlots( GCDSlot* start, GCDSlot* end ) +{ + if ( GCD_IsExisting( GCD_PRIMARY_SLOT ) ) + { + *start = GCD_PRIMARY_SLOT; + if ( GCD_IsExisting( GCD_SECONDARY_SLOT ) ) + { + *end = GCD_SECONDARY_SLOT; + } + else + { + *end = GCD_PRIMARY_SLOT; + } + } + else + { + *start = GCD_SECONDARY_SLOT; + if ( GCD_IsExisting( GCD_SECONDARY_SLOT ) ) + { + *end = GCD_SECONDARY_SLOT; + } + else + { + *end = GCD_NO_SLOT; + } + } +} + + +/*---------------------------------------------------------------------------* + Name: GCD_Reset + + Description: reset game card + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_Reset( GCDSlot slot, u32 chat_cycles ) +{ +#ifdef SDK_ARM9 +#pragma unused( chat_cycles, slot ) + + OSIntrMode enabled; + OSIrqMask lastIE; + BOOL lastIME; + + GCDPxiCmd pxi; + GCDi_Work[GCD_PRIMARY_SLOT].isPxiDone = FALSE; + GCDi_Work[GCD_SECONDARY_SLOT].isPxiDone = FALSE; + + lastIE = OS_EnableIrqMask(OS_IE_SPFIFO_RECV); + lastIME = OS_EnableIrq(); + enabled = OS_EnableInterrupts(); + + //---- setting PXI + PXI_Init(); + while (!PXI_IsCallbackReady(PXI_FIFO_TAG_GCD, PXI_PROC_ARM7)) + { + } + PXI_SetFifoRecvCallback(PXI_FIFO_TAG_GCD, GCDi_CallbackForReset); + + pxi.e.cmd = GCD_PXI_COMMAND_RESET; + pxi.e.param = chat_cycles; + pxi.e.slot = (u32)slot; + + //---- send message to ARM7 + GCDi_SendtoPxi( pxi.raw ); + + while ( !( GCDi_Work[GCD_PRIMARY_SLOT].isPxiDone == TRUE && + GCDi_Work[GCD_SECONDARY_SLOT].isPxiDone == TRUE ) ) + { + } + + (void)OS_RestoreIrq(lastIME); + (void)OS_SetIrqMask(lastIE); + (void)OS_RestoreInterrupts(enabled); + + PXI_SetFifoRecvCallback(PXI_FIFO_TAG_GCD, NULL); + + GCDi_Enable( slot ); + +#else // SDK_ARM7 + + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + + reg_MI_MCCHAT = (u16)chat_cycles; + + OS_SpinWait( chat_cycles * GCD_CHATTERING_CYCLES ); + + if ( !GCD_IsExisting( slot ) ) + { + return; + } + + GCDi_Enable( slot ); + + if ( GCD_GetDetectMode( slot ) != 0 ) + { + GCD_SetDetectMode( slot, 3 ); + + while ( GCD_GetDetectMode( slot ) != 0 ) + { + } + } + + OS_SpinWait( OS_MSEC_TO_CPUCYC( 50 ) ); + + GCD_SetDetectMode( slot, 1 ); + + OS_SpinWait( OS_MSEC_TO_CPUCYC( 50 ) ); + + GCD_SetDetectMode( slot, 2 ); + + OS_SpinWait( OS_MSEC_TO_CPUCYC( 50 ) ); + + *cnt1 = REG_MI_MCCNT1_RESB_MASK; // preset + + OS_SpinWait( OS_MSEC_TO_CPUCYC( 50 ) ); + +#endif // SDK_ARM7 +} + +/*---------------------------------------------------------------------------* + Name: GCD_ResetAll + + Description: reset game cards + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ResetAll( u32 chat_cycles ) +{ +#ifdef SDK_ARM9 +#pragma unused( chat_cycles ) + + GCDWork *gw = &GCDi_Work[GCD_PRIMARY_SLOT]; + OSIntrMode enabled; + OSIrqMask lastIE; + BOOL lastIME; + + GCDSlot slot; + GCDPxiCmd pxi; + gw->isPxiDone = FALSE; + + lastIE = OS_EnableIrqMask(OS_IE_SPFIFO_RECV); + lastIME = OS_EnableIrq(); + enabled = OS_EnableInterrupts(); + + //---- setting PXI + PXI_Init(); + while (!PXI_IsCallbackReady(PXI_FIFO_TAG_GCD, PXI_PROC_ARM7)) + { + } + PXI_SetFifoRecvCallback(PXI_FIFO_TAG_GCD, GCDi_CallbackForResetAll); + + pxi.e.cmd = GCD_PXI_COMMAND_RESET; + pxi.e.param = chat_cycles; + pxi.e.slot = (u32)NULL; + + //---- send message to ARM7 + GCDi_SendtoPxi( pxi.raw ); + + while (gw->isPxiDone == FALSE) + { + } + + (void)OS_RestoreIrq(lastIME); + (void)OS_SetIrqMask(lastIE); + (void)OS_RestoreInterrupts(enabled); + + PXI_SetFifoRecvCallback(PXI_FIFO_TAG_GCD, NULL); + + for (slot=GCD_PRIMARY_SLOT; slot<=GCD_SECONDARY_SLOT; slot++) + { + GCDi_Enable( slot ); + } + +#else // SDK_ARM7 + + GCDSlot slot, start, end; + + reg_MI_MCCHAT = (u16)chat_cycles; + + OS_SpinWait( chat_cycles * GCD_CHATTERING_CYCLES ); + + GCDi_GetExistingSlots( &start, &end ); + + for (slot=start; slot<=end; slot++) + { + GCDi_Enable( slot ); + + if ( GCD_GetDetectMode( slot ) != 0 ) + { + GCD_SetDetectMode( slot, 3 ); + + while ( GCD_GetDetectMode( slot ) != 0 ) + { + } + } + } + + if ( end != GCD_NO_SLOT ) + { + OS_SpinWait( OS_MSEC_TO_CPUCYC( 50 ) ); + } + + for (slot=start; slot<=end; slot++) + { + GCD_SetDetectMode( slot, 1 ); + } + + if ( end != GCD_NO_SLOT ) + { + OS_SpinWait( OS_MSEC_TO_CPUCYC( 50 ) ); + } + + for (slot=start; slot<=end; slot++) + { + GCD_SetDetectMode( slot, 2 ); + } + + if ( end != GCD_NO_SLOT ) + { + OS_SpinWait( OS_MSEC_TO_CPUCYC( 50 ) ); + } + + for (slot=start; slot<=end; slot++) + { + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + *cnt1 = REG_MI_MCCNT1_RESB_MASK; // preset + } + + if ( end != GCD_NO_SLOT ) + { + OS_SpinWait( OS_MSEC_TO_CPUCYC( 50 ) ); + } + +#endif // SDK_ARM7 +} + +/*---------------------------------------------------------------------------* + Name: GCDi_LoadSecure + + Description: load secure area + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ + +static BOOL isCtrApp[2]; +static BOOL isDsApp[2]; + + +/*************************************************** + + ***************************************************/ + +BOOL GCDi_IsDsApp( GCDSlot slot ) +{ + return isDsApp[slot]; +} + +static const u8 dsNinLogo[] = { +0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21,0x3d,0x84,0x82,0x0a,0x84,0xe4,0x09,0xad, +0x11,0x24,0x8b,0x98,0xc0,0x81,0x7f,0x21,0xa3,0x52,0xbe,0x19,0x93,0x09,0xce,0x20, +0x10,0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec,0x58,0xc7,0xe8,0x33,0x82,0xe3,0xce,0xbf, +0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09,0xc1,0x94,0x56,0x8a,0xc0,0x13,0x72,0xa7,0xfc, +0x9f,0x84,0x4d,0x73,0xa3,0xca,0x9a,0x61,0x58,0x97,0xa3,0x27,0xfc,0x03,0x98,0x76, +0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56,0xbf,0x38,0x84,0x00,0x40,0xa7,0x0e,0xfd, +0xff,0x52,0xfe,0x03,0x6f,0x95,0x30,0xf1,0x97,0xfb,0xc0,0x85,0x60,0xd6,0x80,0x25, +0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2,0xf9,0xa2,0x34,0xff,0xbb,0x3e,0x03,0x44, +0x78,0x00,0x90,0xcb,0x88,0x11,0x3a,0x94,0x65,0xc0,0x7c,0x63,0x87,0xf0,0x3c,0xaf, +0xd6,0x25,0xe4,0x8b,0x38,0x0a,0xac,0x72,0x21,0xd4,0xf8,0x07,0x56,0xcf +}; + +static BOOL IsDsApp( GCDSlot slot ) +{ + GCDRomHeader *rh = GCDi_GetRomHeaderAddr( slot ); + BOOL isDsNinLogo = TRUE; + int i; + + isDsApp[slot] = FALSE; + + for ( i=0; il.nintendoLogo)[i] ) + { + isDsNinLogo = FALSE; + break; + } + } + if ( isDsNinLogo ) + { + isDsApp[slot] = TRUE; + } + + return isDsApp[slot]; +} + +/*************************************************** + + ***************************************************/ +static void SetVAE( GCDSlot slot, GCDCmd64* op ) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + op->dw |= ((u64)(sec->va) << GCDOP_N_VAE_SHIFT) & GCDOP_N_VAE_MASK; +} + +static void SetVBI( GCDSlot slot, GCDCmd64* op ) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + op->dw |= sec->vb; + sec->vb >>= GCDOP_N_VBI_SHIFT; +} + +static void SetVA( GCDSlot slot, GCDCmd64* op ) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + op->dw |= ((u64)(sec->va) << GCDOP_S_VA_SHIFT) & GCDOP_S_VA_MASK; +} + +static void SetVB( GCDSlot slot, GCDCmd64* op ) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + op->dw |= sec->vb & GCDOP_S_VB_MASK; + sec->vb++; +} + +static void SetDummyVC( GCDSlot slot, GCDCmd64* op ) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + op->dw |= ((u64)(sec->vc_dummy) << GCDOP_S_VC_SHIFT) & GCDOP_S_VC_MASK; +} + +static void SetVD( GCDSlot slot, GCDCmd64* op ) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + op->dw |= ((u64)(sec->vd) << GCDOP_S_VD_SHIFT) & GCDOP_S_VD_MASK; +} + +static void GCDi_GenVA_VB_VD( GCDSlot slot ) +{ + GCDHeader* fh = GCDi_GetRomHeaderAddr( slot ); + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + + sec->va = fh->sign.raw[0]; + sec->vb = fh->sign.raw[1]; + sec->vd = fh->sign.raw[2]; + sec->vc_dummy = fh->sign.raw[3]; + + EncryptByBlowfish(&sec->blowfishCardTable, &sec->va, &sec->vb); + EncryptByBlowfish(&sec->blowfishCardTable, &sec->vd, &sec->vc_dummy); +} + +// TWLFIRM_DSCARD_DEV + +#ifndef FIRM_FORCE_DEBUGGER + +void GCDi_InitCardOpBlowfish( GCDSlot slot ) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + const BLOWFISH_CTX *blowfishInitTablep = &GCDi_BlowfishInitTableGCDFIRM; + BLOWFISH_CTX *tableBufp = &sec->blowfishCardTable; + + MI_CpuCopyFast( (void*)blowfishInitTablep, (void *)tableBufp, sizeof(BLOWFISH_CTX) ); + InitBlowfish( tableBufp, &((u8*)GCDi_HeaderBuf[slot])[0xc], 4 ); +} + +void GCDi_InitSecureParam( GCDSlot slot, BOOL twl_ex ) +{ + GCDRomHeaderDS *rh = GCDi_GetRomHeaderAddr( slot ); + u32 code = rh->initialCode; + + if ( twl_ex ) + { + rh->initialCode = 'ALWT'; + } + +#ifdef FIRM_FORCE_FIRMBLOWFISH + GCDi_InitCardOpBlowfish( slot ); +#else // FIRM_FORCE_FIRMBLOWFISH + GCDi_InitCardOpBlowfishDS( slot ); +#endif // FIRM_FORCE_FIRMBLOWFISH + + rh->initialCode = code; + + GCDi_GenVA_VB_VD( slot ); // VA & VB & VD +} + +void GCDi_InitPngIntf( GCDSlot slot ) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + +#define PNA_INDEX (((u32)GCDi_GetRomHeaderAddr( slot )) + 0x12) // PNAe[uECfbNX +static u32 default_pnB_l = 0x879b9b05; +static u8 default_pnB_h = 0x5c; +static u8 default_pnA_l_1 = 0x60; +static u8 default_pnA_l_0_table[8] = { 0xe8, 0x4d, 0x5a, 0xb1, 0x17, 0x8f }; + + u32 pnA_l; + u8 pnA_h; + + pnA_l = sec->vd <<15 + | default_pnA_l_0_table[(*(vu16 *)PNA_INDEX & 0x0700) >>8] | default_pnA_l_1 <<8; + pnA_h = (u8)((sec->vd >>(32-15)) & 0x7f); + + GCDi_SetPngIntf( slot, pnA_l, pnA_h, default_pnB_l, default_pnB_h ); +} + +#endif // FIRM_FORCE_DEBUGGER + +/*************************************************** + + ***************************************************/ +static void GCDi_SetPngIntf( GCDSlot slot, u32 pnA_l, u8 pnA_h, u32 pnB_l, u8 pnB_h ) +{ + REGType32v* cnt1 = GCDi_SelectRegAddr( slot, REG_MCCNT1_ADDR ); + REGType32v* scra_l = GCDi_SelectRegAddr( slot, REG_MCSCRA_L_ADDR ); + REGType8v* scra_h = GCDi_SelectRegAddr( slot, REG_MCSCRA_H_ADDR ); + REGType32v* scrb_l = GCDi_SelectRegAddr( slot, REG_MCSCRB_L_ADDR ); + REGType8v* scrb_h = GCDi_SelectRegAddr( slot, REG_MCSCRB_H_ADDR ); + + // omlݒ + + GCDi_WaitCtrl( slot ); + + *scra_l = pnA_l; + *scra_h = pnA_h; + + *scrb_l = pnB_l; + *scrb_h = pnB_h; + + *cnt1 = REG_MI_MCCNT1_A_SCR_MASK | REG_MI_MCCNT1_A_SE_MASK | REG_MI_MCCNT1_A_DS_MASK | REG_MI_MCCNT1_A_RESB_MASK; + + GCDi_WaitCtrl( slot ); + + // f[^XNuݒ + GCDi_Work[slot].ctrls.sSendOnlyOpRegs.scramble |= REG_MI_MCCNT1_A_SE_MASK | REG_MI_MCCNT1_A_DS_MASK; +} + + +void GCDi_DecryptObjectFile( GCDSlot slot ) +{ + if ( GCDi_IsDsApp( slot ) ) + { + } +} + +/*************************************************** + + ***************************************************/ +static void ReadCardAsync4Secure_1( GCDSlot slot, void *romp ) +{ + GCDWork *gw = &GCDi_Work[slot]; + GCDRomCtrls *ctrls = &gw->ctrls; + + if ( GCDi_SharedWork[slot].nCardID & GCD_ROMID_1TROM_MASK ) + { + // 3Dpݒ + { + ctrls->gcdRegs->ctrl &= ~REG_MI_MCCNT1_PC_MASK; + ctrls->gcdRegs->ctrl |= GCD_PAGE_1; + } + } + ctrls->gcdOp.dw = GCDOP_S_OP_RD_SEGMENT // R}hݒ + | (((u64)romp/GCD_SECURE_SEGMENT_SIZE) << GCDOP_S_VC_SHIFT); + + gw->oneShotSize = GCDi_GetOneShotSizeFromCtrl( ctrls->gcdRegs->ctrl ); + SetVA( slot, &ctrls->gcdOp ); + Encrypt2SetTimer4Secure( slot, ctrls ); + + if ( (GCDi_SharedWork[slot].nCardID & GCD_ROMID_1TROM_MASK) == 0 ) + { + ctrls->ltckReq = TRUE; + } +} + +/*************************************************** + + ***************************************************/ +static void ReadCardAsync4Secure_2( GCDSlot slot ) +{ + GCDWork *gw = &GCDi_Work[slot]; + GCDRomCtrls *ctrls = &gw->ctrls; + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + + /* CardTimerIntr4Secure(void)̂ */ + s32 oneShotSize; + s32 offset; + + // ZOgEɂ + // 3D1ZOg8y[Wɕēǂ + do { + oneShotSize = gw->oneShotSize; + offset = sec->segmentOffset + sec->blockOffset; + + GCDi_ReadSecureModeRomCore( slot, gw->ramp + offset, oneShotSize, ctrls ); + + gw->restSize -= oneShotSize; + sec->blockOffset += oneShotSize; + } + while( gw->restSize % GCD_SECURE_SEGMENT_SIZE ); +} + +/*************************************************** + + ***************************************************/ +u8 GCDi_SegmentIndexTable4Secure[] = +{ + (0<<6)|(1<<4)|(3<<2)|(2<<0), (0<<6)|(2<<4)|(1<<2)|(3<<0), (0<<6)|(2<<4)|(3<<2)|(1<<0), (0<<6)|(3<<4)|(1<<2)|(2<<0), + (1<<6)|(0<<4)|(2<<2)|(3<<0), (1<<6)|(2<<4)|(0<<2)|(3<<0), (1<<6)|(3<<4)|(0<<2)|(2<<0), (1<<6)|(3<<4)|(2<<2)|(0<<0), + (2<<6)|(1<<4)|(0<<2)|(3<<0), (2<<6)|(1<<4)|(3<<2)|(0<<0), (2<<6)|(3<<4)|(0<<2)|(1<<0), (2<<6)|(3<<4)|(1<<2)|(0<<0), + (3<<6)|(0<<4)|(1<<2)|(2<<0), (3<<6)|(0<<4)|(2<<2)|(1<<0), (3<<6)|(1<<4)|(2<<2)|(0<<0), (3<<6)|(2<<4)|(0<<2)|(1<<0), +}; + +/* + DCB 4_0132, 4_0213, 4_0231, 4_0312 ; - 4_0123, 4_0321 + DCB 4_1023, 4_1203, 4_1302, 4_1320 ; - 4_1032, 4_1230 + DCB 4_2103, 4_2130, 4_2301, 4_2310 ; - 4_2013, 4_2031 + DCB 4_3012, 4_3021, 4_3120, 4_3201 ; - 4_3102, 4_3210 +*/ + +void GCDi_ReadCardSegmentAsync4Secure( GCDSlot slot, BOOL twl_ex ) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + s16 *blockOffsetp = &sec->blockOffset; + s16 *segmentOffsetp = &sec->segmentOffset; + s16 *tblShiftp = &sec->segmentTblShift; + s32 diffSegmentNo; + s32 offset; + + GCDWork *gw = &GCDi_Work[slot]; + GCDRomCtrls *ctrls = &gw->ctrls; + +// GCDi_WaitCtrl(); + + GCDi_SecureWork[slot].segmentTblp = &(((u8 *)GCDi_SegmentIndexTable4Secure)[GCDi_SecureWork[slot].vd >>28]); // ZOge[uݒ + GCDi_SecureWork[slot].numSecureSegment = GCD_SECURE_AREA_SIZE / GCD_SECURE_SEGMENT_SIZE; // SECUREZOg 1segment 4096 + + ctrls->gcdRegs = &ctrls->sReadRomRegs; + gw->romp = GCD_SECURE_AREA_OFFSET; + if ( !twl_ex ) + { + gw->ramp = (void*)GCDi_SecureAreaBuf[slot]; + } + else + { + gw->ramp = (void*)GCDi_Secure2AreaBuf[slot]; + } + gw->restSize = sizeof( GCDi_SecureAreaBuf[slot] ); + gw->oneShotSize = GCDi_GetOneShotSizeFromCtrl( ctrls->gcdRegs->ctrl ); + + sec->secureSize = gw->restSize; + + do { + // SECURË𒴂Ȃ悤ɒ + while ((diffSegmentNo = ((*sec->segmentTblp) >>*tblShiftp) & 0x3) >= sec->numSecureSegment) + *tblShiftp += 2; + + *segmentOffsetp = (s16)(GCD_SECURE_SEGMENT_SIZE * diffSegmentNo); // ZOgItZbg Zbg + *blockOffsetp = 0; // ubNItZbg NA + + offset = *segmentOffsetp + *blockOffsetp; + + ReadCardAsync4Secure_1( slot, (u8*)gw->romp + offset ); + ReadCardAsync4Secure_2( slot ); + + *tblShiftp += 2; + *tblShiftp &= 0x7; + } + while( gw->restSize > 0 ); +} + + +/*---------------------------------------------------------------------------* + Name: GCD_SendOnlyCardOpCore + + Description: send only rom command + sync version + + Arguments: ctrls : rom control + + Returns: None + *---------------------------------------------------------------------------*/ + +#define AddLatency2ToLatency1(param) \ + ( (((param) & CARD_LATENCY2_CYCLES_MASK) \ + >> CARD_LATENCY2_CYCLES_SHIFT) \ + + ((param) & ~CARD_LATENCY2_CYCLES_MASK) \ + ) + + +static void Encrypt2SetTimer4Secure( GCDSlot slot, GCDRomCtrls *ctrls ) +{ + GCDSecureWork* sec = &GCDi_SecureWork[slot]; + GCDSharedWork* sh = &GCDi_SharedWork[slot]; + + SetVB( slot, &ctrls->gcdOp ); // VB Zbg + + //GCDi_SecureWork.paramBak = *paramp; // ÍÕobvAbv + // my_memcopy((void *)paramp, (void *)&(GCDi_SecureWork.paramBak),sizeof(CardCtrlParam)); // ÍÕobvAbv + + // R}hÍ + EncryptByBlowfish( &sec->blowfishCardTable, &((u32*)&ctrls->gcdOp)[1], (u32*)&ctrls->gcdOp ); + + // 3DpvR}hs + if ( sh->nCardID & GCD_ROMID_1TROM_MASK ) { + GCDCtrlRegs *preRegs = ctrls->gcdRegs; + ctrls->gcdRegs = &ctrls->sSendOnlyOpRegs; + GCD_SendOnlyCardOpCore( slot, ctrls ); + ctrls->gcdRegs = preRegs; + + OS_SpinWait( OS_MSEC_TO_CPUCYC(30) ); /* wait 27 milli sec. for 3D-MEMROY? */ + } +} + + +static void GCDi_SendOnlyCardSecureOpCore( GCDSlot slot, GCDRomCtrls *ctrls ) +{ + GCDCtrlRegs *regs = ctrls->gcdRegs; + + // CeVQCeVP։Z +#if 0 + paramp->cardCnt = AddLatency2ToLatency1(GetCardCnt4Secure()) + | CARD_READ_MODE | CARD_0_PAGE + | CARD_START | CARD_RESET_HI; +#endif + + SetDummyVC( slot, &ctrls->gcdOp ); + Encrypt2SetTimer4Secure( slot, ctrls ); + + if ( (GCDi_SharedWork[slot].nCardID & GCD_ROMID_1TROM_MASK) == 0 ) { + ctrls->gcdRegs->ctrl |= GCD_LTCK_ENABLE; // }XNROMpݒF CeVԂɃNbN +// ctrls->ltckReq = TRUE; + } + GCD_SendOnlyCardOpCore( slot, ctrls ); +} + + +/*************************************************** + + ***************************************************/ +void GCDi_ChangeIntoSecureMode( GCDSlot slot ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + + ctrls->gcdRegs = &ctrls->nSendOnlyOpRegs; + ctrls->gcdOp.dw = GCDOP_N_OP_CHG_MODE; // R}hݒ + SetVAE( slot, &ctrls->gcdOp ); + SetVBI( slot, &ctrls->gcdOp ); + + GCD_SendOnlyCardOpCore( slot, ctrls ); +} + +void GCDi_ChangeIntoSecure2Mode( GCDSlot slot ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + + ctrls->gcdRegs = &ctrls->nSendOnlyOpRegs; + ctrls->gcdOp.dw = GCDOP_N_OP_CHG2_MODE; // R}hݒ + SetVAE( slot, &ctrls->gcdOp ); + SetVBI( slot, &ctrls->gcdOp ); + + GCD_SendOnlyCardOpCore( slot, ctrls ); +} + + +void GCDi_SendPngON( GCDSlot slot ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + + ctrls->gcdRegs = &ctrls->sSendOnlyOpRegs; + ctrls->gcdOp.dw = GCDOP_S_OP_PNG_ON; // R}hݒ + SetVD( slot, &ctrls->gcdOp ); + + GCDi_SendOnlyCardSecureOpCore( slot, ctrls ); +} + +void GCDi_SendPngOFF( GCDSlot slot ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + + ctrls->gcdRegs = &ctrls->sSendOnlyOpRegs; + ctrls->gcdOp.dw = GCDOP_S_OP_PNG_OFF; // R}hݒ + SetVA( slot, &ctrls->gcdOp ); + + GCDi_SendOnlyCardSecureOpCore( slot, ctrls ); +} + +void GCDi_ChangeIntoGameMode( GCDSlot slot ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + + ctrls->gcdRegs = &ctrls->sSendOnlyOpRegs; + ctrls->gcdOp.dw = GCDOP_S_OP_CHG_MODE; // R}hݒ + SetVA( slot, &ctrls->gcdOp ); + + GCDi_SendOnlyCardSecureOpCore( slot, ctrls ); +} + +/*---------------------------------------------------------------------------* + Name: GCD_SendOnlyCardNormalOpCore + + Description: send only rom command + sync version + + Arguments: ctrls : rom control + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCD_SendOnlyCardNormalOpCore( GCDSlot slot, GCDRomCtrls *ctrls ) +{ + ctrls->gcdRegs = &ctrls->nSendOnlyOpRegs; + + GCD_SendOnlyCardOpCore( slot, ctrls ); +} + +/*---------------------------------------------------------------------------* + Name: GCD_SendOnlyCardSecureOpCore + + Description: send only rom command + sync version + + Arguments: ctrls : rom control + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCD_SendOnlyCardSecureOpCore( GCDSlot slot, GCDRomCtrls *ctrls ) +{ + ctrls->gcdRegs = &ctrls->sSendOnlyOpRegs; + + if ( ctrls->ltckReq ) + { + ctrls->gcdRegs->ctrl |= GCD_LTCK_ENABLE; // }XNROMpݒF CeVԂɃNbN + ctrls->ltckReq = FALSE; + } + + GCD_SendOnlyCardOpCore( slot, ctrls ); +} + +/*************************************************** + + ***************************************************/ +static u32 GCDi_ReadSecureModeIDCore( GCDSlot slot, GCDRomCtrls *ctrls ) +{ + ctrls->gcdRegs = &ctrls->sIDRegs; + + if ( ctrls->ltckReq ) + { + ctrls->gcdRegs->ctrl |= GCD_LTCK_ENABLE; // }XNROMpݒF CeVԂɃNbN + ctrls->ltckReq = FALSE; + } + + return GCDi_ReadRomIDCore( slot, ctrls ); +} + +static void GCDi_ReadSecureModeRomCore( GCDSlot slot, void *ramp, s32 size, GCDRomCtrls *ctrls ) +{ + ctrls->gcdRegs = &ctrls->sReadRomRegs; + + if ( ctrls->ltckReq ) + { + ctrls->gcdRegs->ctrl |= GCD_LTCK_ENABLE; // }XNROMpݒF CeVԂɃNbN + ctrls->ltckReq = FALSE; + } + + GCDi_ReadRomCore( slot, ramp, size, ctrls ); +} + + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadSecureModeID + + Description: read rom ID on secure mode + sync version + + Arguments: None + + Returns: rom ID + *---------------------------------------------------------------------------*/ +u32 GCDi_ReadSecureModeID( GCDSlot slot ) +{ + GCDSharedWork* sh = &GCDi_SharedWork[slot]; + + if ( GCDi_IsSecureInitialized( slot ) == FALSE ) + { + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + + ctrls->gcdRegs = &ctrls->sIDRegs; + ctrls->gcdOp.dw = GCDOP_S_OP_RD_ROM_ID; // R}hݒ + SetVA( slot, &ctrls->gcdOp ); + SetDummyVC( slot, &ctrls->gcdOp ); + Encrypt2SetTimer4Secure( slot, ctrls ); + + if ( (sh->nCardID & GCD_ROMID_1TROM_MASK) == 0 ) { + ctrls->ltckReq = TRUE; + } + sh->sCardID = GCDi_ReadSecureModeIDCore( slot, ctrls ); + DBG_PRINTF("%s %d CardID Secure 0x%08x\n",__FUNCTION__,__LINE__, sh->sCardID); + } + + return sh->sCardID; +} + +/*---------------------------------------------------------------------------* + Name: GCD_ReadNormalModeID + + Description: read rom ID on normal mode + sync version + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +u32 GCD_ReadNormalModeID( GCDSlot slot ) +{ + GCDSharedWork* sh = &GCDi_SharedWork[slot]; + + if ( GCDi_IsSecureInitialized( slot ) == FALSE ) + { + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + + ctrls->gcdRegs = &ctrls->nIDRegs; + ctrls->gcdOp.dw = GCDOP_N_OP_RD_ROM_ID; // R}hݒ + + return GCDi_ReadRomIDCore( slot, ctrls ); + } else { + return sh->nCardID; + } +} + + +/*---------------------------------------------------------------------------* + Name: GCDi_LoadHeader + + Description: load header + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCDi_LoadHeader( GCDSlot slot ) +{ + if ( GCDi_IsSecureInitialized( slot ) == FALSE ) + { + GCDSharedWork* sh = &GCDi_SharedWork[slot]; + + // load table from dev flash into ASIC + GCDi_LoadTable( slot ); + + // read ROM header + GCD_ReadNormalModeRom( slot, 0, GCDi_HeaderBuf[slot], sizeof( GCDi_HeaderBuf[slot] ) ); + + if ( ! IsDsApp( slot ) ) + { + MI_CpuFillFast( GCDi_HeaderBuf[slot], 0, sizeof( GCDi_HeaderBuf[slot] ) ); + } + + // read ROM-ID + sh->nCardID = GCD_ReadNormalModeID( slot ); + DBG_PRINTF("%s %d CardID Normal 0x%08x\n",__FUNCTION__,__LINE__, sh->nCardID); + } +} + +/*---------------------------------------------------------------------------* + Name: GCDi_LoadHeaderAll + + Description: load header + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCDi_LoadHeaderAll( void ) +{ + GCDSlot slot, start, end; + + GCDi_GetExistingSlots( &start, &end ); + + if ( GCDi_IsSecureInitialized( GCD_PRIMARY_SLOT ) == FALSE ) + { + for (slot=start; slot<=end; slot++) + { + // load table from dev flash into ASIC + GCDi_LoadTableAsync( slot ); + } + + for (slot=start; slot<=end; slot++) + { + GCD_WaitRomAsync( slot ); + + // read short ROM header + GCDi_ReadShortHeaderAsync( slot, GCDi_HeaderBuf[slot] ); + } + + for (slot=start; slot<=end; slot++) + { + GCD_WaitRomAsync( slot ); + + if ( ! IsDsApp( slot ) ) + { + MI_CpuFillFast( GCDi_HeaderBuf[slot], 0, sizeof( GCDi_HeaderBuf[slot] ) ); + } + } + + for (slot=start; slot<=end; slot++) + { + // read ROM-ID + GCDSharedWork* sh = &GCDi_SharedWork[slot]; + sh->nCardID = GCD_ReadNormalModeID( slot ); + DBG_PRINTF("%s %d CardID Normal 0x%08x\n",__FUNCTION__,__LINE__, sh->nCardID); + + // read ROM header + GCD_ReadNormalModeRomAsync( slot, 0, GCDi_HeaderBuf[slot], sizeof( GCDi_HeaderBuf[slot] ) ); + } + + for (slot=start; slot<=end; slot++) + { + GCD_WaitRomAsync( slot ); + } + } +} + +/*---------------------------------------------------------------------------* + Name: GCDi_LoadTable + + Description: load table from dev flash into ASIC + sync version + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCDi_LoadTable( GCDSlot slot ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + + ctrls->gcdRegs = &ctrls->nLoadTableRegs; + ctrls->gcdOp.dw = GCDOP_N_OP_LD_TABLE; + + GCDi_ReadRomCore( slot, NULL, 0, ctrls ); +} + +static void GCDi_LoadTableCore( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDRomCtrls *ctrls ) +{ +#pragma unused( romp ) + + GCDi_ReadRomCore( slot, ramp, size, ctrls ); +} + +static void GCDi_LoadTableAsync( GCDSlot slot ) +{ + GCDWork *gw = &GCDi_Work[slot]; + GCDRomCtrls *ctrls = &gw->ctrls; + + ctrls->gcdRegs = &ctrls->nLoadTableRegs; + ctrls->gcdOp.dw = GCDOP_N_OP_LD_TABLE; + + gw->funcp = GCDi_LoadTableCore; + + GCD_SetInterrupt( slot, 0, GCDi_Secure2AreaBuf[slot], GCD_LOAD_TABLE_SIZE, gw ); + + gw->funcp( slot, gw->romp, gw->ramp, gw->oneShotSize, ctrls ); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadShortHeader + + Description: load table from dev flash into ASIC + sync version + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCDi_ReadShortHeader( GCDSlot slot, void *ramp ) +{ + GCDRomCtrls *ctrls = &GCDi_Work[slot].ctrls; + + ctrls->gcdRegs = &ctrls->nReadShortHeaderRegs; + + GCDi_ReadNormalModeRomCore( slot, 0, ramp, GCD_ROM_PAGE_SIZE, ctrls ); +} + +static void GCDi_ReadShortHeaderAsync( GCDSlot slot, void *ramp ) +{ + GCDWork *gw = &GCDi_Work[slot]; + GCDRomCtrls *ctrls = &gw->ctrls; + + ctrls->gcdRegs = &ctrls->nReadShortHeaderRegs; + + gw->funcp = GCDi_ReadNormalModeRomCore; + + GCD_SetInterrupt( slot, 0, ramp, GCD_ROM_PAGE_SIZE, gw ); + + gw->funcp( slot, gw->romp, gw->ramp, gw->oneShotSize, ctrls ); +} + +/*---------------------------------------------------------------------------* + Name: GCDi_LoadSecure + + Description: load secure area + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static void GCDi_LoadSecureCore( GCDSlot slot, BOOL twl_ex ) +{ + if ( GCDi_IsSecureInitialized( slot ) == FALSE ) + { + GCDRomHeader *rh = GCDi_GetRomHeaderAddr( slot ); + +#ifndef FIRM_FORCE_DEBUGGER + + GCDi_InitSecureParam( slot, twl_ex ); + +#endif // FIRM_FORCE_DEBUGGER + + if ( !twl_ex ) + { + GCDi_ChangeIntoSecureMode( slot ); + } + else + { + GCDi_ChangeIntoSecure2Mode( slot ); + } + +#ifdef FIRM_FORCE_DEBUGGER + + if ( !twl_ex ) + { + GCD_ReadNormalModeRom( slot, GCD_SECURE_AREA_OFFSET, GCDi_SecureAreaBuf[slot], sizeof( GCDi_SecureAreaBuf[slot] ) ); + } + else if ( rh->l.twlAreaOffset ) + { + GCD_ReadNormalModeRom( slot, (u32)rh->l.twlAreaOffset * GCD_TWL_AREA_ALIGN + GCD_SECURE2_AREA_OFFSET, + GCDi_Secure2AreaBuf[slot], sizeof( GCDi_Secure2AreaBuf[slot] ) ); + } + +#else // FIRM_FORCE_DEBUGGER + + GCDi_SendPngON( slot ); + GCDi_InitPngIntf( slot ); + + GCDi_ReadSecureModeID( slot ); + + GCDi_ReadCardSegmentAsync4Secure( slot, twl_ex ); + +#ifndef GCD_ENABLE_SCRAMBLE + GCDi_SendPngOFF( slot ); +#endif // GCD_ENABLE_SCRAMBLE + +#endif // FIRM_FORCE_DEBUGGER + + GCDi_ChangeIntoGameMode( slot ); + + // ÍIuWFNg̕ + if ( !twl_ex ) + { +#ifndef FIRM_FORCE_FIRMBLOWFISH + GCDi_DecryptObjectFileDS( slot ); +#endif // FIRM_FORCE_FIRMBLOWFISH + } + + if ( twl_ex || !rh->l.twlAreaOffset ) + { + GCDi_SecureInitialized[slot] = TRUE; + } + } +} + +static void GCDi_LoadSecure( GCDSlot slot ) +{ + GCDi_LoadSecureCore( slot, FALSE ); + +} + +static void GCDi_LoadSecure2( GCDSlot slot ) +{ + GCDi_LoadSecureCore( slot, TRUE ); + +} + +static void GCDi_LoadSecureAllCore( BOOL twl_ex ) +{ + GCDSlot slot, start, end; + + GCDi_GetExistingSlots( &start, &end ); + + if ( GCDi_IsSecureInitialized( GCD_PRIMARY_SLOT ) == FALSE ) + { + +#ifndef FIRM_FORCE_DEBUGGER + + for (slot=start; slot<=end; slot++) + { + GCDi_InitSecureParam( slot, twl_ex ); + } + +#endif // FIRM_FORCE_DEBUGGER + + if ( !twl_ex ) + { + for (slot=start; slot<=end; slot++) + { + GCDi_ChangeIntoSecureMode( slot ); + } + } + else + { + for (slot=start; slot<=end; slot++) + { + GCDi_ChangeIntoSecure2Mode( slot ); + } + } + +#ifdef FIRM_FORCE_DEBUGGER + + for (slot=start; slot<=end; slot++) + { + GCDRomHeader *rh = GCDi_GetRomHeaderAddr( slot ); + GCD_ReadNormalModeRomAsync( slot, GCD_SECURE_AREA_OFFSET, GCDi_SecureAreaBuf[slot], sizeof( GCDi_SecureAreaBuf[slot] ) ); + } + + for (slot=start; slot<=end; slot++) + { + GCDRomHeader *rh = GCDi_GetRomHeaderAddr( slot ); + GCD_WaitRomAsync( slot ); + + if ( rh->l.twlAreaOffset ) + { + GCD_ReadNormalModeRomAsync( slot, (u32)rh->l.twlAreaOffset * GCD_TWL_AREA_ALIGN + GCD_SECURE2_AREA_OFFSET, + GCDi_Secure2AreaBuf[slot], sizeof( GCDi_Secure2AreaBuf[slot] ) ); + } + } + + for (slot=start; slot<=end; slot++) + { + GCD_WaitRomAsync( slot ); + } + +#else // FIRM_FORCE_DEBUGGER + + for (slot=start; slot<=end; slot++) + { + GCDi_SendPngON( slot ); + } + + for (slot=start; slot<=end; slot++) + { + GCDi_InitPngIntf( slot ); + } + + for (slot=start; slot<=end; slot++) + { + GCDi_ReadSecureModeID( slot ); + } + + for (slot=start; slot<=end; slot++) + { + GCDi_ReadCardSegmentAsync4Secure( slot, twl_ex ); + } + +#ifndef GCD_ENABLE_SCRAMBLE + for (slot=start; slot<=end; slot++) + { + GCDi_SendPngOFF( slot ); + } +#endif // GCD_ENABLE_SCRAMBLE + +#endif // FIRM_FORCE_DEBUGGER + + for (slot=start; slot<=end; slot++) + { + GCDi_ChangeIntoGameMode( slot ); + } + + // ÍIuWFNg̕ + for (slot=start; slot<=end; slot++) + { + GCDRomHeader *rh = GCDi_GetRomHeaderAddr( slot ); + + if ( !twl_ex ) + { +#ifndef FIRM_FORCE_FIRMBLOWFISH + GCDi_DecryptObjectFileDS( slot ); +#endif // FIRM_FORCE_FIRMBLOWFISH + } + + if ( twl_ex || !rh->l.twlAreaOffset ) + { + GCDi_SecureInitialized[slot] = TRUE; + } + } + } +} + +static void GCDi_LoadSecureAll( void ) +{ + GCDi_LoadSecureAllCore( FALSE ); + +} + +static void GCDi_LoadSecure2All( void ) +{ + GCDi_LoadSecureAllCore( TRUE ); + +} + +// +BOOL GCDi_IsSecureInitialized( GCDSlot slot ) +{ + return GCDi_SecureInitialized[slot]; +} + diff --git a/build/libraries/gcd/common/gcdfirm_blowfish_table.c b/build/libraries/gcd/common/gcdfirm_blowfish_table.c new file mode 100644 index 0000000..ec61d6d --- /dev/null +++ b/build/libraries/gcd/common/gcdfirm_blowfish_table.c @@ -0,0 +1,288 @@ +/*---------------------------------------------------------------------------* + Project: TwlBrom - libraries - GCD + File: gcdfirm_blowfish_table.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include + + +const BLOWFISH_CTX GCDi_BlowfishInitTableGCDFIRM = { + + 0x7595a8ee, 0x84fff32d, 0x58f8aec6, 0x6f6444c2, + 0x10a6cfbc, 0xbee1b813, 0x88efabc3, 0xc72026cd, + 0xc00b913a, 0x9fb074c0, 0x56d4830f, 0x69abdee5, + 0xcf6e5ff2, 0xd7febe2f, 0x84f5d5e2, 0x73a1ccda, + 0x44205999, 0x74278f63, + + 0xf0907253, 0x1c95d48f, 0x7cdbce99, 0xa8b9508a, + 0x79379f9e, 0x129144fe, 0xd2b3554d, 0x72d702c6, + 0xce058143, 0x72b411b8, 0x9acf2ae7, 0x62c0d195, + 0x7d0861e5, 0x333ac8f6, 0xafc17b59, 0x7fabab12, + 0x5a20b8df, 0x43c908e1, 0xdf057b54, 0x65237d17, + 0x8988581c, 0x1d02cad9, 0xdde63c8a, 0x302fee12, + 0x0abedd9d, 0x586fb574, 0x10130aad, 0x0a1ead35, + 0xfe6f0870, 0x8cac4f02, 0x9c56ef2c, 0xc0ab9bcd, + 0x7faf9a52, 0xef822dcd, 0x2bc0fdc2, 0xde22a557, + 0xccf82867, 0x582a9d19, 0xd2790715, 0xdc8df689, + 0x250ca6e2, 0xfe35236d, 0x8648e2d6, 0xaa0bf6e7, + 0xd1240620, 0x413a5ea7, 0x4cf59143, 0x4f4f5472, + 0xa5f29a08, 0x1fff4e8f, 0x14f0ec2d, 0x47d6f42a, + 0x85b021f0, 0x7836f20a, 0xd908d0d7, 0xbdcc9dd5, + 0xa6ac0bfb, 0x96fb7daf, 0xb65476ff, 0xbde99b51, + 0xe8c84b8e, 0x72c88630, 0x3f8d0979, 0x5c1e45dc, + 0x7555b1db, 0x3edb5a90, 0xb07fac66, 0xf7316aba, + 0x84a088bd, 0xf0b2fb9d, 0x014b48e1, 0x6d0967e3, + 0xa38d60e4, 0x148eedf2, 0x81898864, 0xfe0d73aa, + 0x58c37bd5, 0x8ce2c345, 0x82951de7, 0x17be1aa6, + 0xbfe8ad1b, 0x4d6b4176, 0x3a0da43d, 0x50a4dcac, + 0x69f1282e, 0x16b49576, 0x6b521ffe, 0x67588174, + 0xb3de1d28, 0x06198cbd, 0xeea240ea, 0xd13e358e, + 0x3664b06c, 0x59f4e227, 0xb54122d3, 0x94bb71e3, + 0x0315fb94, 0x647301d6, 0x943f1f0d, 0x7a2aaec4, + 0x51bf88f7, 0x712c091a, 0x6d3b6e3e, 0x6eb24d52, + 0x9fc82ca4, 0x8ffc188e, 0xbe31140a, 0x1d3e5756, + 0xc574e16e, 0xb105a793, 0x94f658ec, 0x6ed4864c, + 0xb2bae3cf, 0xe342cf15, 0xf2bc4d27, 0x090334b1, + 0xc2632a42, 0x884f0092, 0xa59abd51, 0xe9d203f9, + 0x7d122257, 0x02a709aa, 0xac9fc39b, 0x4840beed, + 0x74be37a4, 0x24b9a4d3, 0x8178bca7, 0x606b85e5, + 0x1dcb46b2, 0xe6112060, 0xbd44008a, 0xd1be2964, + 0xcfcc5032, 0x74e10e43, 0x53fac5ab, 0x84a6e0a4, + 0x9080997a, 0xa31a0100, 0xcee21c1c, 0xebcee973, + 0x77e9a4c7, 0x3a261b9b, 0xce49ca16, 0xec3a432d, + 0x1410c1bf, 0x8d22c824, 0xb0018266, 0x7964e2e2, + 0xfcc6eb14, 0x12e6e035, 0xca689d0a, 0x5f9f39fc, + 0xbf14f7e9, 0x5d7813f2, 0x87347401, 0x1a107660, + 0xfeaa1bb7, 0x53ebb1a2, 0xfc47a457, 0xf71cde17, + 0x25379a36, 0xb2ed205d, 0x1225bf36, 0x14536bd4, + 0x31138cdf, 0xeeecb7f4, 0xbb6e5b19, 0x39877d0f, + 0x4366ac24, 0xfb13893c, 0x3a7039b2, 0x3a1b8037, + 0xfc668634, 0x0a3fb783, 0x50380526, 0x9c0e4b1a, + 0x462b9398, 0x0e6c7d2d, 0x689a929e, 0x715701e6, + 0x2e61d17d, 0x09da9145, 0xfb143ba1, 0x5b199259, + 0xc4e3a5ee, 0x0b4bda9a, 0xe18c526c, 0x73171c1a, + 0x1572a94b, 0x6d15b729, 0x71509e91, 0x571bc76e, + 0x8c721018, 0x1fcc1742, 0xa6602c75, 0x787f88a9, + 0x0598f9c4, 0x5addc61b, 0x8e9b7b41, 0x2f4daf72, + 0xd9f09e2a, 0xe76054ca, 0x28bc0b4e, 0x4a320c32, + 0xdf2b687e, 0x2cdffbcc, 0x77f16b69, 0x5d425665, + 0xcf207fd9, 0x2e4d166d, 0x46e57957, 0x37f50f39, + 0x6742b74a, 0xbb21df47, 0xe2df0964, 0x0dd6d989, + 0x6f635a6e, 0x8f05a457, 0x6e5dc010, 0xeae76f43, + 0x135c206a, 0x876bd938, 0x1ccbc607, 0xaf600e28, + 0x0daa4fe0, 0x95e0fe33, 0x093e44b1, 0x1d16b2ad, + 0x8d710ba2, 0x3ca3c1d9, 0x8f54a8e1, 0x7eb11ec8, + 0xcdb82a0e, 0xde1aff6d, 0x68ae2ce2, 0x80e1ca3e, + 0x67d60c2c, 0xac6ad1da, 0x5330c802, 0x5f67a04d, + 0x5d6f3c9d, 0x1f4725b0, 0x094a4c69, 0x4c1dea21, + 0xfd09ced5, 0x270fc341, 0xf16081f5, 0x54dcbdb4, + 0x72a36bf5, 0xbeabc16a, 0xdd82bb02, 0xf0e75d20, + 0xea6a64b0, 0x85cb5c2c, 0xd53a5aaa, 0x400f91d1, + + 0xc020695e, 0xa3d05c76, 0x8ac00446, 0xe0ebe1ce, + 0x7ed2ca13, 0x7f41bbca, 0x09daffc0, 0x16d39c09, + 0xd417fe9e, 0x11fc4b36, 0x87b92111, 0x581cea89, + 0x6a51516d, 0xa691f994, 0x06e5c6ab, 0x81200780, + 0xe6ea60b7, 0x8d0967af, 0x32f81d79, 0x1bf63b78, + 0xeefe70bb, 0x74123b42, 0xf7345b16, 0x7aaa1388, + 0x0152a394, 0xb5463ea1, 0xe7968633, 0xf6b00f17, + 0xfee65926, 0xfac95f88, 0xf7788838, 0x404d27c8, + 0x0a40725a, 0xac948618, 0xb2fb966f, 0x730b40c3, + 0x3fa5b3a0, 0x2a4a7b57, 0xe2ee0994, 0xe2662b03, + 0xa517c253, 0x5fcd9ac2, 0x7cf1861a, 0xfb9c6d92, + 0x726cfcf6, 0x6bc20855, 0xe03c7757, 0x15f7aefc, + 0x0490f4b2, 0xc5c49d9e, 0xd91bc403, 0x84799016, + 0x5e8b5d2f, 0xdd8aef68, 0x4225b87a, 0xd3912770, + 0x56f84df2, 0xe191d469, 0xb6306514, 0xf66b7461, + 0xaa528b42, 0xd7d8d211, 0x0409e809, 0x3e995489, + 0x984e2cd0, 0x21da8726, 0xa901dcce, 0xc59ed627, + 0xa508a395, 0xe67e1c10, 0x7786c594, 0x7db49c12, + 0xf3a048fa, 0x6c03c939, 0x5fe538b2, 0xe68d94f1, + 0x74116818, 0xbc041b38, 0x37e9f59f, 0xd5f0d6b4, + 0x3abedc09, 0xf2277fcf, 0xb1c090ca, 0x179fbeaf, + 0x6799f269, 0x4ef2e1ba, 0x9a8530fe, 0xe629bad3, + 0xef2d1806, 0xefe0d41a, 0x8fbd8038, 0xae93b3b8, + 0xb96af69a, 0xe976f30a, 0x3735edf2, 0xa10aab80, + 0x572bc346, 0xd9d352e5, 0xa88382fb, 0xc36d9a6a, + 0x622169f5, 0x2b668147, 0xc68d8e94, 0xd83725df, + 0x75ca8dc0, 0xe0fef07d, 0x3020348f, 0xd7e941c5, + 0x0f18da00, 0x9909caca, 0x1b5f4c03, 0x611ba66e, + 0xe3c25c8d, 0x87fe1654, 0x20ed099e, 0x2eef6251, + 0xf8b62747, 0xa8863716, 0x2e654e0a, 0x17985515, + 0xd121a7f0, 0xf0545a5b, 0xed9f9da3, 0xfe607b10, + 0x3afc599b, 0xa3c13305, 0x9667a20a, 0xbd639f0c, + 0xe647e3a0, 0x0e1304b2, 0x26a31cec, 0xd1435273, + 0x33845341, 0xbe3383f5, 0x22e5e07f, 0xb516aed2, + 0xe7dad3c1, 0x7e0b2eec, 0x7709d235, 0x48923397, + 0x086b62a6, 0x05270843, 0x48073d32, 0x3e22db8e, + 0x7b0fd2eb, 0x9199531d, 0xa47e9efc, 0x76b1bf31, + 0xee7b6f31, 0xdc6de2c0, 0x120d4d2c, 0x1c7d1a8b, + 0xd9192142, 0x5251ce66, 0x26dd0acf, 0x18073f04, + 0x5901f0a3, 0xfc24fea0, 0xe9d4474b, 0xbbda7bdd, + 0x66cb45f6, 0x66137a90, 0xa010a036, 0xa3fff96c, + 0x61c8194f, 0x553e0b2b, 0x72b54de2, 0x59aeefe9, + 0xda01dab4, 0xdac48b91, 0xbba66e7a, 0xa3819de2, + 0x1f950fce, 0xa3c4d697, 0xc4e28dce, 0x530179ee, + 0xaa7cc068, 0x1b44146a, 0xb267d209, 0x984ff1be, + 0x90fd796b, 0xe0e42a5f, 0x36d033fb, 0x13c2f482, + 0x3b19a86d, 0xff0ad256, 0xf06acb47, 0x0d4fbfa0, + 0x53246fd3, 0xf9296dd5, 0x42bb5d4a, 0xd4d86e75, + 0x96442650, 0x0bdebc51, 0xb3cee98d, 0x188c83e2, + 0xbe632850, 0x9a0ce659, 0xc51250cd, 0x141b9f77, + 0x292844d4, 0xa8ce50d4, 0xe6f471a3, 0xe51b7ef9, + 0xece33b79, 0x1ec17a6a, 0x01a0125e, 0x09071e04, + 0xbfe72df4, 0x170ed1cf, 0x2fa259ac, 0x4821704f, + 0x95b82704, 0xcd1e0c6a, 0xb57a33ce, 0x057204fe, + 0x7617de6b, 0xaa72f1d5, 0x4b46d61a, 0xac797378, + 0x4984d9cf, 0x40726022, 0x2b425b5c, 0x4ca25dab, + 0xa0e23aa3, 0x4fe1527a, 0x6fd3b7ac, 0xeb47ba60, + 0xcde7c8b7, 0x9aef5d0f, 0x821674cd, 0xc258ea7d, + 0xa6a813a5, 0x93e88a84, 0x8f32d2e3, 0x58ae440d, + 0xc5799715, 0x425284d0, 0x1b696e64, 0x7d3ce93a, + 0xdad0f25c, 0xc4b0dd14, 0x7079e2e5, 0xa9e8e61d, + 0xfaf686b7, 0x1cf1b87b, 0x31ab43c7, 0xdc45d1bb, + 0x386cb6ec, 0xcad283f2, 0x4dccbfaf, 0x4934f28b, + 0x2fbc3dd4, 0x789b64f7, 0xb2e8918f, 0x506acbf7, + + 0x50a13360, 0xd128d4d3, 0xba687526, 0xc5474940, + 0x6bb5dfc7, 0xef9bdf1f, 0x92cc643b, 0xfb2ad4f0, + 0x4ff9410b, 0xb013c81e, 0x9fe69574, 0x5fed0d88, + 0xcfe87720, 0x09cddf06, 0x9e57696f, 0xc429dfb9, + 0x460c5dd2, 0x9b9e505b, 0xc012bcf6, 0xd955bdda, + 0x7310ed31, 0xcdaaebe2, 0xc9761ff6, 0x5de00f45, + 0x66a5e949, 0x45c5df1d, 0x96a38fab, 0x18939d5b, + 0x94015083, 0xd27b1379, 0xe10107e7, 0xdaef6ef8, + 0xaf8f83b3, 0xafd37029, 0x7d6803e0, 0x3a545055, + 0xfd419925, 0xb49fa25f, 0x533ad3f4, 0xc49f3fe4, + 0x9b9eb196, 0x2015408e, 0xd6f46485, 0xa8e66479, + 0x5b8866e1, 0xc97d478d, 0xb7fcb30a, 0xddefdff0, + 0x34afb94c, 0xa155d92f, 0xf53979b1, 0xf0cdd075, + 0xf25accae, 0xe4208afd, 0x5b11bb77, 0x37b337e4, + 0xa69da8be, 0x28a9ee86, 0xb284b30e, 0xc3527598, + 0xf423936e, 0x7e2e1d51, 0xcaf2613d, 0x7505391e, + 0x252d3dd5, 0x00d18203, 0x7ef4577e, 0x244e98a9, + 0xb73b5840, 0xb0f9c9ed, 0xa8d4bc23, 0xb7228243, + 0x241418d3, 0x39fd4429, 0xe8ab9b37, 0x3a74ecdf, + 0xbf99499c, 0x70c3eb26, 0xc6ac5d10, 0x7085410a, + 0x9bc5ca24, 0x37cf4d32, 0x5a407af1, 0x7f38c2af, + 0x6cf95726, 0x2934cce9, 0x478e4a5e, 0x86bccd71, + 0x46673804, 0x5cd7e9da, 0x601c0e47, 0x32f3c95c, + 0x98f3b207, 0x2a9f09f2, 0xa68e3b9b, 0xe0a67f44, + 0x8d4801eb, 0x0d650900, 0x2dbd9d8f, 0x9113fe47, + 0x5a317b0e, 0x3d5a8d71, 0xfbd60e45, 0x86f6eedc, + 0x3f77fec6, 0xe56a0bb2, 0x32ab5ef7, 0x2262c429, + 0x7ed387c6, 0x0087c87e, 0x6570e4b7, 0x648d80e1, + 0xc3bd761a, 0x5c3c0c47, 0x9ac5b07c, 0x6ecb158f, + 0x73e2d323, 0x5095435e, 0x21a97ee4, 0x0c599519, + 0x1f6c6441, 0xee52efd7, 0xbd886ee2, 0x66ec3c66, + 0x0e42820c, 0xb4f244cb, 0xa56f2efc, 0xc0302f16, + 0xf9b795aa, 0x60a00f3f, 0xa83fb0a9, 0xe9b2f724, + 0xa3c3b44f, 0x8151cc80, 0x2ae0e99c, 0x0cb0ff00, + 0x2e9a646d, 0x991d2cd6, 0xef2bf16b, 0x0a610ad2, + 0x1674ea07, 0x567fcfe7, 0xf05ef5af, 0xdfdf47cb, + 0x6c3ebb59, 0x2f052cad, 0x4701ca04, 0x0c65164a, + 0xa285ecb3, 0x348fd20a, 0x7915f8ff, 0xdc269d33, + 0x74578f72, 0x763ced80, 0x53275951, 0x8c51eebd, + 0x6d8b4452, 0x5267c34e, 0xe9b7197b, 0x912800ab, + 0x10d207a4, 0x4238eaf7, 0x2171bd12, 0x9c7eff0b, + 0x251b79ff, 0x41bb7753, 0xecea6583, 0x031393e5, + 0x49a58fe9, 0x83bb7587, 0x4a2a3156, 0xa3ab8da7, + 0x38f774aa, 0xd3844d4e, 0x7cc81418, 0x894ca09d, + 0x341ade56, 0x9574d6a5, 0xd2299751, 0xdbd43293, + 0x253d53e8, 0x64005cc4, 0x813de56f, 0x631c3cda, + 0x931681bd, 0x77dd0ab8, 0x15d6b56f, 0x2a3106b1, + 0x603102bf, 0xfef29a3d, 0x648baa38, 0x470ae791, + 0x02e625ab, 0x04904d5d, 0x3b31cea4, 0xa9a2126d, + 0x76814575, 0x4c6a5511, 0xe2d7c619, 0x840d8ca5, + 0x4d15e8f8, 0x59256a95, 0xf1ed6a56, 0xb996efab, + 0x5da9c913, 0x7652bed8, 0xedbda0be, 0x59f81908, + 0xd1d45ed7, 0x00b5f876, 0x986b97e4, 0x0bf99862, + 0xf3a448c6, 0x05f92573, 0x9ab2c7c4, 0xbf92bbf2, + 0xa8e5e036, 0x3030a02b, 0xab1e833b, 0x5190d039, + 0x3d31eec2, 0x4eadf427, 0xea65d217, 0xafac4dd3, + 0xdf5ef6fe, 0xe88cdd6c, 0xab55d1df, 0x77689e8b, + 0x3ba6b081, 0x9ed37908, 0x42383678, 0xf9f221a6, + 0xb6cf355d, 0x1c10aa09, 0x38645486, 0xab46320e, + 0x6c01bdce, 0xaa9b77bf, 0xdc8a7085, 0x843c40c0, + 0x35218b12, 0x57c15a35, 0x37a879d4, 0x41fa8671, + 0xe9bae4f3, 0x9521c923, 0x2a32bab3, 0x5415b46b, + 0xcb7245dd, 0x6e6407bd, 0x88477782, 0x18424ea6, + 0x48214427, 0xd266b8b8, 0x70b796d4, 0xe4e48223, + + 0xf6a5bf45, 0xa34cc400, 0x0b62f21c, 0xf0eb6ca7, + 0x4f8566a3, 0xd23e5904, 0x86eac0fd, 0x95080a7d, + 0xe2926a24, 0x9983c4a1, 0x7e398b84, 0x9fccb2f1, + 0xff70696b, 0xccb47af7, 0x61d3bf96, 0xf4170385, + 0x0bc86fef, 0x06fb5c90, 0xce92d9fe, 0x120ca3cf, + 0xdcde2f59, 0xd6fd2b38, 0x4258d974, 0x4b2c0a3c, + 0x1f0967ec, 0x25987e51, 0x4e7acfc7, 0x1f7f9694, + 0x18de3230, 0x85d9095d, 0x54737616, 0x6ec26956, + 0x9eb3637b, 0x908a5192, 0x839fb43e, 0xefe70f2a, + 0x42e168a5, 0x776e5c22, 0x736be3a9, 0xb72d66ed, + 0xa4f94794, 0xb414bd55, 0x5de623d3, 0x9cd1e1a9, + 0x42957f7e, 0x381cf593, 0x678a7d07, 0x158bb604, + 0xe64926bd, 0x5a047438, 0x360d68cb, 0xab487a8e, + 0x0d769a0b, 0xde3fc939, 0xf33ea9c0, 0x28b87455, + 0xd5f6c00c, 0x853f8ffe, 0xc8d238c3, 0x3bb5473e, + 0xc9779097, 0xc4af3a0c, 0x899098c0, 0x3c51c0e4, + 0x7e02214e, 0xe65f85a4, 0xe7c4a857, 0x6096179e, + 0x9c9eb559, 0x709a5f7d, 0x548f6fd5, 0xf1ad58cb, + 0xe4bce783, 0x43ca2b6c, 0x6f43de8f, 0xa60a02f9, + 0xbcdd0f35, 0x58f582b3, 0x30633b0d, 0xf17c7d49, + 0x35f809f7, 0x9ee90417, 0x6360674f, 0x44375b7b, + 0x72949c97, 0xff78dcd2, 0x08bff59a, 0x00b14d4e, + 0xf37ef8c1, 0x6760a010, 0x87dd4dee, 0x31f5208a, + 0x721c3add, 0x6eb9ab46, 0x29250341, 0x2fdcc721, + 0x9d812ebb, 0x60a078a0, 0x20fcdc2d, 0xe8c594f9, + 0x4956e488, 0x81873803, 0xf51a953d, 0x9b43c7e1, + 0xdfd95440, 0x8dbdb07e, 0x1ecaf22f, 0xb14dceca, + 0xc4c8003d, 0xdc26051b, 0x8bdc1011, 0x6df204db, + 0xc72491cf, 0x9fd74623, 0xa663c57f, 0xd0f6f96d, + 0x60f5d249, 0x10b66b81, 0xeeb26437, 0xe739332c, + 0xeb94bdfd, 0xbfc4e0e3, 0x5d8ee7a8, 0xf676c5c3, + 0x38357061, 0x8d3e4d68, 0xd560280b, 0x7a85b438, + 0x00e7da19, 0x44e3021b, 0xb22bee73, 0x7af11114, + 0x9a4aacd3, 0xbb5ea97a, 0x7993ac0b, 0x3dc12ed7, + 0x7ac7eda8, 0x26528e57, 0xb15b78c9, 0xeae2b177, + 0xa9bd7a3c, 0x03812180, 0x0ed1451f, 0x9ab1c57d, + 0xa0acc3c5, 0xbf0b533d, 0x017f8413, 0x3228452a, + 0x86eb48e1, 0x379cbcff, 0x3b200f75, 0x0cbbb62b, + 0x7467627f, 0xc782b5e3, 0xd402c537, 0x026be842, + 0x41a32d7a, 0x5910b6ff, 0x909926b4, 0x05bd811e, + 0x92fd98c8, 0xcf66e980, 0x1f5eb79c, 0x4e2c31e4, + 0x5f9b7f0c, 0x91972e91, 0xf70f2e5a, 0xd5b6b627, + 0x3b1f243a, 0xf404cb7b, 0xe6232ec3, 0x22da8906, + 0x0cb348ff, 0x0da6349d, 0x7c858b98, 0xd9b258f1, + 0x623c9dd4, 0x8493c626, 0x91551f3b, 0x6ed97a53, + 0xb5a10c32, 0x23d39f3e, 0x57e7da04, 0x8f0b2689, + 0xebb54529, 0x0f015572, 0x2f4db833, 0x407e1d2b, + 0xfd815f1a, 0xdeacbb64, 0xe8c38859, 0xde04110b, + 0xb6c901ab, 0x153aee1a, 0x6b5af720, 0xc3bfe796, + 0x8b412bc7, 0xe8cbe167, 0x60d83df2, 0x35506981, + 0x2b8f1fc7, 0x311029cf, 0xf46fad6e, 0x7440056b, + 0x61df9779, 0x693d02da, 0xe7d93ccc, 0x861bd3d3, + 0xad0b85a0, 0x8bcd277a, 0xb72fceb7, 0x8ca5d84f, + 0xc0847150, 0x1bd88428, 0x4673ca0d, 0xb030dbe5, + 0xb51c06c1, 0x642baffb, 0xccb5043b, 0xb84aebcb, + 0xbcd80352, 0x385520d6, 0x3b4518aa, 0xfed91bbe, + 0x95f68932, 0x3a10ae0e, 0xd733aeaf, 0xf9f85ba7, + 0x978ac3d1, 0x6a64540c, 0xc5a1575c, 0xc2adcd2b, + 0xc3d45465, 0x47671f05, 0x8542fff3, 0x0f528f92, + 0x3da8b9cd, 0x13e96928, 0x0ae5cb86, 0x55602423, + 0x1acfb022, 0x68c9f16b, 0xbebc28a5, 0xb1d1d15e, + 0xa9f54130, 0x0ebb0b93, 0xaf3ffdb9, 0x52078aad, + 0xb3bf2160, 0xfb4d9d05, 0xe32785a3, 0xd05a87e5, + 0x688e68a5, 0x38840376, 0x9b46ac8d, 0x23f286fd, + +}; + diff --git a/build/libraries/init/ARM7/Makefile b/build/libraries/init/ARM7/Makefile new file mode 100644 index 0000000..ae15c2b --- /dev/null +++ b/build/libraries/init/ARM7/Makefile @@ -0,0 +1,58 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - libraries - init +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = +#SUBMAKES = Makefile.CALLTRACE \ +# Makefile.FUNCTIONCOST + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= TRUE + +# Codegen for sub processer +FIRM_PROC = ARM7 + +SRCS = crt0_firm.c \ + +TARGET_OBJ = crt0_firm.o + + +#---------------------------------------------------------------------------- + +# DEBUGŃrh̏ꍇARELEASEłŃrh +# DEBUGł̃Cu𑕂܂B + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/init/ARM7/crt0_firm.c b/build/libraries/init/ARM7/crt0_firm.c new file mode 100644 index 0000000..f4eea19 --- /dev/null +++ b/build/libraries/init/ARM7/crt0_firm.c @@ -0,0 +1,447 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - init + File: crt0.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include + +#define FIRM_ENABLE_JTAG + +void _start(void); +void _start_AutoloadDoneCallback(void *argv[]); + +#define SDK_NITROCODE_LE 0x2106c0de +#define SDK_NITROCODE_BE 0xdec00621 + +#define SDK_TWLCODE_LE 0x6314c0de +#define SDK_TWLCODE_BE 0xdec01463 + +// volatile parameters in IPL's work memory +#define IPL_PARAM_CARD_ROM_HEADER 0x023FE940 +#define IPL_PARAM_DOWNLOAD_PARAMETER 0x023FE904 + +extern void OS_IrqHandler(void); +extern void _fp_init(void); +extern void __call_static_initializers(void); +extern void TwlMain(void); + +static void INITi_DoAutoload(void); +static void INITi_ShelterLtdBinary(void); +static void detect_main_memory_size(void); + +// from LCF +extern unsigned long SDK_IRQ_STACKSIZE[]; + +extern void SDK_STATIC_BSS_START(void); // static bss start address +extern void SDK_STATIC_BSS_END(void); // static bss start address +extern void SDK_AUTOLOAD_LIST(void); // start pointer to autoload information +extern void SDK_AUTOLOAD_LIST_END(void); // end pointer to autoload information +extern void SDK_AUTOLOAD_START(void); // autoload data will start from here +extern void SDK_LTDAUTOLOAD_LIST(void); // start pointer to autoload information +extern void SDK_LTDAUTOLOAD_LIST_END(void); // end pointer to autoload information +extern void SDK_LTDAUTOLOAD_START(void); // autoload data will start from here + +//---- IRQ+SVC stack size in boot (this area is not cleared) +#define INITi_Initial_Stack 0x100 + +void *const _start_ModuleParams[] = +{ + (void *)SDK_AUTOLOAD_LIST, + (void *)SDK_AUTOLOAD_LIST_END, + (void *)SDK_AUTOLOAD_START, + (void *)SDK_STATIC_BSS_START, + (void *)SDK_STATIC_BSS_END, + (void*)0, // CompressedStaticEnd. This fixed number will be updated by compstatic tool. + (void*)0, // SDK_VERSION_ID // SDK version info /* [TODO] rhʂ */ + (void*)SDK_NITROCODE_BE, + (void*)SDK_NITROCODE_LE, +}; + +void* const _start_LtdModuleParams[] = +{ + (void*)SDK_LTDAUTOLOAD_LIST, + (void*)SDK_LTDAUTOLOAD_LIST_END, + (void*)SDK_LTDAUTOLOAD_START, + (void*)0, // CompressedLtdautoloadEnd. This fixed number will be updated by compstatic tool. + (void*)SDK_TWLCODE_BE, + (void*)SDK_TWLCODE_LE, +}; + +/*---------------------------------------------------------------------------* + Name: _start + + Description: Start up + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +SDK_WEAK_SYMBOL asm void _start( void ) +{ +#ifdef FIRM_ENABLE_JTAG + ldr r1, =REG_JTAG_ADDR + ldrh r2, [r1] + orr r2, r2, #REG_SCFG_JTAG_CPUJE_MASK | REG_SCFG_JTAG_ARM7SEL_MASK + strh r2, [r1] +#endif + + //---- set IME = 0 + // ( use that LSB of HW_REG_BASE equal to 0 ) + mov r12, #HW_REG_BASE + str r12, [r12, #REG_IME_OFFSET] + + //---- initialize stack pointer + // SVC mode + mov r0, #HW_PSR_SVC_MODE + msr cpsr_c, r0 + ldr sp, =HW_PRV_WRAM_SVC_STACK_END + + // IRQ mode + mov r0, #HW_PSR_IRQ_MODE + msr cpsr_c, r0 + ldr r0, =HW_PRV_WRAM_IRQ_STACK_END + mov sp, r0 + + // System mode + ldr r1, =SDK_IRQ_STACKSIZE + sub r1, r0, r1 + mov r0, #HW_PSR_SYS_MODE + msr cpsr_csfx, r0 + sub sp, r1, #4 // 4byte for stack check code + + //---- read reset flag from pmic +#ifdef TWL_PLATFORM_TS +#if 0 + mov r0, #REG_PMIC_SW_FLAGS_ADDR + bl PMi_GetRegister + ands r0, r0, #PMIC_SW_FLAGS_WARMBOOT +#else + mov r0, #I2C_SLAVE_MICRO_CONTROLLER + mov r1, #MCU_REG_TEMP_ADDR + bl I2Ci_ReadRegister + ands r0, r0, #0x01 // under construction +#endif + movne r0, #FIRM_PXI_ID_WARMBOOT + moveq r0, #FIRM_PXI_ID_COLDBOOT + bl PXI_SendByIntf + mov r0, #FIRM_PXI_ID_INIT_MMEM + bl PXI_WaitByIntf +#endif // TWL_PLATFORM_TS + + //---- wait for main memory mode into burst mode + ldr r3, =REG_EXMEMCNT_L_ADDR + mov r1, #REG_MI_EXMEMCNT_L_ECE2_MASK +@1: + ldrh r2, [r3] + tst r2, r1 + beq @1 + +#if 0 + // move parameters from IPL's work memory to shared area + ldr r0, =IPL_PARAM_CARD_ROM_HEADER + ldr r1, =HW_CARD_ROM_HEADER + add r2, r1, #HW_CARD_ROM_HEADER_SIZE +@1_1: + ldr r3, [r0], #4 + str r3, [r1], #4 + cmp r1, r2 + bmi @1_1 + ldr r0, =IPL_PARAM_DOWNLOAD_PARAMETER + add r2, r1, #HW_DOWNLOAD_PARAMETER_SIZE +@1_2: + ldr r3, [r0], #4 + str r3, [r1], #4 + cmp r1, r2 + bmi @1_2 +#endif + + //---- load autoload block and initialize bss + //bl INITi_DoAutoload +#ifndef SDK_FINALROM // for IS-TWL-DEBUGGER + bl _start_AutoloadDoneCallback +#endif + + //---- fill static static bss with 0 + ldr r0, =_start_ModuleParams + ldr r1, [r0, #12] // BSS segment start + ldr r2, [r0, #16] // BSS segment end + mov r0, #0 +@2: cmp r1, r2 + strcc r0, [r1], #4 + bcc @2 + + //---- detect main memory size + //bl detect_main_memory_size + + //---- set interrupt vector + ldr r1, =HW_INTR_VECTOR_BUF + ldr r0, =OS_IrqHandler + str r0, [r1, #0] + +#ifndef SDK_NOINIT + //---- for C++ + bl _fp_init + bl TwlSpStartUp + bl __call_static_initializers +#endif + + //---- start (to 16bit code) + ldr r1, =TwlSpMain + ldr lr, =HW_RESET_VECTOR + + bx r1 +} +/*---------------------------------------------------------------------------* + Name: INITi_DoAutoload + Description: NɉāAeI[g[hubŇŒf[^̓WJ + yѕϐ 0 NAsB + Arguments: ȂB + Returns: ȂB + *---------------------------------------------------------------------------*/ +/* + * < iKI[g[h > + * 0x02f88000 crt0 yшiڃ[hoCizuĂB + * NITRO ƋL”\ WRAM ɔzuׂoCif[^ 0x037c0000 Ƀ[hB + * TWL ł삵Ȃ WRAM ɔzuׂoCif[^𑱂̃AhXɃ[hB + * 0x02e80000 ɓiڃ[hoCizuĂB + * 0x04000 oCg̓J[h ROM ēǂݏos‚Ȃ̂ŁA0x02f84000 - 0x02f88000 ɑޔB + * NITRO ƋL”\ MAIN ɔzuׂoCif[^ 0x02f88000 + sizeof(crt0) Ƀ[hB + * TWL ł삵Ȃ MAIN ɔzuׂoCif[^𑱂̃AhXɃ[hB + */ +static asm void +INITi_DoAutoload(void) +{ +@000: + stmdb sp!, {lr} + /* WRAM pubNI[g[h */ + ldr r1, =_start_ModuleParams + ldr r12, [r1] // r12 = SDK_AUTOLOAD_LIST + ldr r0, [r1, #4] // r0 = SDK_AUTOLOAD_LIST_END + ldr r1, [r1, #8] // r1 = SDK_AUTOLOAD_START +@001: cmp r12, r0 + bge @010 + /* ŒZNV[h */ + stmdb sp!, {r0} + ldr r2, [r12], #4 // r2 = start address of destination range + ldr r3, [r12], #4 // r3 = size of fixed section + add r3, r3, r2 // r3 = end address of destination range of fixed section +@002: cmp r2, r3 + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt @002 + /* .bss ZNV 0 NA */ + mov r0, #0 + ldr r3, [r12], #4 // r3 = size of .bss section + add r3, r3, r2 // r3 = end address of destination range of .bss section +@003: cmp r2, r3 + strlt r0, [r2], #4 + blt @003 +@004: ldmia sp!, {r0} + b @001 + +@010: /* CpubN݂̑mF */ + ldr r1, =HW_TWL_ROM_HEADER_BUF + 0x1dc /* ARM7 pg풓W[ ROM TCY */ + ldr r0, [r1] + cmp r0, #0 + beq @020 + + /* ēǂݏos•ޔ */ + bl INITi_ShelterLtdBinary + + /* CpubNI[g[h */ + ldr r1, =_start_LtdModuleParams + ldr r12, [r1] // r12 = SDK_LTDAUTOLOAD_LIST + ldr r0, [r1, #4] // r0 = SDK_LTDAUTOLOAD_LIST_END + ldr r1, [r1, #8] // r1 = SDK_LTDAUTOLOAD_START +@011: cmp r12, r0 + bge @020 + /* ŒZNV[h */ + stmdb sp!, {r0} + ldr r2, [r12], #4 // r2 = start address of destination range + ldr r3, [r12], #4 // r3 = size of fixed section + add r3, r3, r2 // r3 = end address of destination range of fixed section +@012: cmp r2, r3 + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt @012 + /* .bss ZNV 0 NA */ + mov r0, #0 + ldr r3, [r12], #4 // r3 = size of .bss section + add r3, r3, r2 // r3 = end address of destination range of .bss section +@013: cmp r2, r3 + strlt r0, [r2], #4 + blt @013 +@014: ldmia sp!, {r0} + b @011 + +@020: /* I[g[hR[obN֐Ăяo */ + ldr r0, =_start_ModuleParams + ldr r1, =_start_LtdModuleParams + ldmia sp!, {lr} + b _start_AutoloadDoneCallback +} + +/*---------------------------------------------------------------------------* + Name: INITi_ShelterLtdBinary + Description: TWL p̃I[g[hoCif[^̓AJ[h ROM + ēǂݏołȂ̈̃f[^ޔGAɑޔB + ēǂݏołȂ̈̃f[^ ARM7 p ARM9 p̊g풓 + W[̂Q‚ɕÔ\̂ŁA璷ł͂邪 + ̐擪 0x4000 ꂼޔB + Arguments: ȂB + Returns: ȂB + *---------------------------------------------------------------------------*/ +static asm void +INITi_ShelterLtdBinary(void) +{ + /* ޔEAhX𒲍 */ + ldr r1, =HW_TWL_ROM_HEADER_BUF + 0x1d8 /* ARM7 pg풓W[ RAM AhX */ + ldr r1, [r1] + ldr r3, =HW_TWL_ROM_HEADER_BUF + 0x038 /* ARM7 p풓W[ RAM AhX */ + ldr r3, [r3] + sub r2, r3, #0x4000 /* ēǂݏos—̈TCY */ /* ARM7 pޔGA */ + + /* Rs[ */ +@loop: ldr r0, [r1], #4 + str r0, [r2], #4 + cmp r2, r3 + blt @loop + + bx lr +} + +/*---------------------------------------------------------------------------* + Name: _start_AutoloadDoneCallback + Description: I[g[hR[obNB + Arguments: argv - I[g[hp[^ێĂzB + argv[0] = SDK_AUTOLOAD_LIST + argv[1] = SDK_AUTOLOAD_LIST_END + argv[2] = SDK_AUTOLOAD_START + argv[3] = SDK_STATIC_BSS_START + argv[4] = SDK_STATIC_BSS_END + Returns: ȂB + *---------------------------------------------------------------------------*/ +SDK_WEAK_SYMBOL asm void +_start_AutoloadDoneCallback(void* argv[]) +{ + bx lr +} + +/*---------------------------------------------------------------------------* + Name: detect_main_memory_size + + Description: detect main memory size. + result is written into (u32*)HW_MMEMCHECKER_SUB. + value is [OS_CONSOLE_SIZE_4MB|OS_CONSOLE_SIZE_8MB| + OS_CONSOLE_SIZE_16MB|OS_CONSOLE_SIZE_32MB] + + + + + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +#define OSi_IMAGE_DIFFERENCE 0x400000 +#define OSi_IMAGE_DIFFERENCE2 0xb00000 + +static asm void detect_main_memory_size( void ) +{ +#if 0 // NITRO hardware is not supported + mov r0, #OS_CONSOLE_SIZE_4MB + mov r1, #0 + + ldr r2, =HW_MMEMCHECKER_SUB + sub r3, r2, #OSi_IMAGE_DIFFERENCE +@1: + strh r1, [r2] + ldrh r12, [r3] + cmp r1, r12 + + + bne @2 + + add r1, r1, #1 + cmp r1, #2 // check 2 loop + bne @1 + + //---- 4MB + b @4 + + //---- 8MB or 16MB or 32MB +@2: + // check if running on twl/nitro + ldr r1, =REG_CLK_ADDR + ldrh r12, [r1] + tst r12, #REG_SCFG_CLK_WRAMHCLK_MASK + moveq r0, #OS_CONSOLE_SIZE_8MB + beq @4 +#else + ldr r2, =HW_MMEMCHECKER_SUB +#endif + //---- 16MB or 32MB + mov r1, #0 + add r3, r2, #OSi_IMAGE_DIFFERENCE2 +@3: + strh r1, [r2] + ldrh r12, [r3] + cmp r1, r12 + + movne r0, #OS_CONSOLE_SIZE_32MB + bne @4 + + add r1, r1, #1 + cmp r1, #2 // check 2 loop + bne @3 + mov r0, #OS_CONSOLE_SIZE_16MB +@4: + strh r0, [r2] + + //---- detect chiptype + ldr r2, =REG_OP_ADDR + ldrh r0, [r2] + and r0, r0, #REG_SCFG_OP_OPT_MASK + + // check SMX_CNT + ldr r2, =REG_SMX_CNT_ADDR + ldrh r1, [r2] + tst r1, #0 + orrne r0, r0, #OS_CHIPTYPE_SMX_MASK + + //---- detect jtag + ldr r2, =REG_JTAG_ADDR + ldrh r1, [r2] + and r1, r1, #REG_SCFG_JTAG_CPUJE_MASK + orr r0, r0, r1, LSL #1 + + ldr r2, =HW_CHIPTYPE_FLAG + strb r0, [r2] + + bx lr +} + +/*---------------------------------------------------------------------------* + Name: TwlSpStartUp + + Description: hook for user start up + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +SDK_WEAK_SYMBOL void TwlSpStartUp(void) +{ +} diff --git a/build/libraries/init/ARM9/Makefile b/build/libraries/init/ARM9/Makefile new file mode 100644 index 0000000..7481707 --- /dev/null +++ b/build/libraries/init/ARM9/Makefile @@ -0,0 +1,54 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - libraries - init +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = +#SUBMAKES = Makefile.CALLTRACE \ +# Makefile.FUNCTIONCOST + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= TRUE + +SRCS = crt0_firm.c \ + +TARGET_OBJ = crt0_firm.o + +#---------------------------------------------------------------------------- + +# DEBUGŃrh̏ꍇARELEASEłŃrh +# DEBUGł̃Cu𑕂܂B + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/init/ARM9/crt0_firm.c b/build/libraries/init/ARM9/crt0_firm.c new file mode 100644 index 0000000..a0e20ce --- /dev/null +++ b/build/libraries/init/ARM9/crt0_firm.c @@ -0,0 +1,817 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - init + File: crt0.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include + +void _start(void); +void _start_AutoloadDoneCallback(void *argv[]); + +#define SDK_NITROCODE_LE 0x2106c0de +#define SDK_NITROCODE_BE 0xdec00621 + +#define SDK_TWLCODE_LE 0x6314c0de +#define SDK_TWLCODE_BE 0xdec01463 + +extern void OS_IrqHandler(void); +extern void _fp_init(void); +extern void __call_static_initializers(void); +extern void TwlMain(void); + +static void INITi_CpuClear32(register u32 data, register void *destp, register u32 size); +static void INITi_InitCoprocessor(void); +static void INITi_InitRegion(void); +static void INITi_DoAutoload(void); +static void INITi_ShelterLtdBinary(void); + +// from LCF +extern unsigned long SDK_IRQ_STACKSIZE[]; + +extern void SDK_AUTOLOAD_LIST(void); // start pointer to autoload information +extern void SDK_AUTOLOAD_LIST_END(void); // end pointer to autoload information +extern void SDK_AUTOLOAD_START(void); // autoload data will start from here +extern void SDK_STATIC_BSS_START(void); // static bss start address +extern void SDK_STATIC_BSS_END(void); // static bss end address +extern void SDK_LTDAUTOLOAD_LIST(void); // start pointer to autoload information +extern void SDK_LTDAUTOLOAD_LIST_END(void); // end pointer to autoload information +extern void SDK_LTDAUTOLOAD_START(void); // autoload data will start from here + +/*---------------------------------------------------------------------------* + Name: _start_ModuleParams + + Description: autoload/compress/arguments data block + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +//#include +#define SDK_VERSION_ID ((u32)SDK_VERSION_MAJOR<<24|\ + (u32)SDK_VERSION_MINOR<<16|\ + (u32)SDK_VERSION_RELSTEP) + +void *const _start_ModuleParams[] = +{ + (void *)SDK_AUTOLOAD_LIST, + (void *)SDK_AUTOLOAD_LIST_END, + (void *)SDK_AUTOLOAD_START, + (void *)SDK_STATIC_BSS_START, + (void *)SDK_STATIC_BSS_END, + (void *)0, // CompressedStaticEnd + (void *)SDK_VERSION_ID, // SDK version info + (void *)SDK_NITROCODE_BE, // Checker 1 + (void *)SDK_NITROCODE_LE, // Checker 2 +}; +void* const _start_LtdModuleParams[] = +{ + (void*)SDK_LTDAUTOLOAD_LIST, + (void*)SDK_LTDAUTOLOAD_LIST_END, + (void*)SDK_LTDAUTOLOAD_START, + (void*)0, // CompressedLtdautoloadEnd. This fixed number will be updated by compstatic tool. + (void*)SDK_TWLCODE_BE, + (void*)SDK_TWLCODE_LE, +}; + + +/*---------------------------------------------------------------------------* + Name: _start + + Description: Start up + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +#define INITi_HW_DTCM SDK_AUTOLOAD_DTCM_START + +SDK_WEAK_SYMBOL asm void _start( void ) +{ + //---- set IME = 0 + // ( use that LSB of HW_REG_BASE equal to 0 ) + mov r12, #HW_REG_BASE + str r12, [r12, #REG_IME_OFFSET] + + //---- initialize stack pointer + // SVC mode + mov r0, #HW_PSR_SVC_MODE + msr cpsr_c, r0 + ldr r0, =INITi_HW_DTCM + add r0, r0, #0x3fc0 + mov sp, r0 + + // IRQ mode + mov r0, #HW_PSR_IRQ_MODE + msr cpsr_c, r0 + ldr r0, =INITi_HW_DTCM + add r0, r0, #0x3fc0 + sub r0, r0, #HW_SVC_STACK_SIZE + sub sp, r0, #4 // 4byte for stack check code + tst sp, #4 + subeq sp, sp, #4 // for 8byte-alignment + + // System mode + ldr r1, =SDK_IRQ_STACKSIZE + sub r1, r0, r1 + mov r0, #HW_PSR_SYS_MODE + msr cpsr_csfx, r0 + sub sp, r1, #4 // 4byte for stack check code + + //---- read reset flag from pmic +#ifdef TWL_PLATFORM_TS +@0: bl PXI_RecvByIntf + cmp r0, #FIRM_PXI_ID_COLDBOOT + cmpne r0, #FIRM_PXI_ID_WARMBOOT + bne @0 + + //---- initialize Main Memory + cmp r0, #FIRM_PXI_ID_COLDBOOT + moveq r0, #TRUE + movne r0, #FALSE + bl MIi_InitMainMemCR + + mov r0, #FIRM_PXI_ID_INIT_MMEM + bl PXI_SendByIntf + +#else // TWL_PLATFORM_BB + //---- initialize Main Memory + bl MIi_InitMainMemCR + +#endif // TWL_PLATFORM_BB + + /* VXeRvZbT */ + bl INITi_InitCoprocessor + + /* [Wݒ */ + bl INITi_InitRegion + + //---- clear memory + // DTCM (16KB) + mov r0, #0 + ldr r1, =INITi_HW_DTCM + mov r2, #HW_DTCM_SIZE + bl INITi_CpuClear32 + + // BG/OBJ palette (1KB) + mov r0, #0 + ldr r1, =HW_PLTT + mov r2, #HW_PLTT_SIZE + bl INITi_CpuClear32 + + // OAM (1KB) + mov r0, #0x0200 + ldr r1, =HW_OAM + mov r2, #HW_OAM_SIZE + bl INITi_CpuClear32 + + //---- load autoload block and initialize bss +// bl INITi_DoAutoload +#ifndef SDK_FINALROM // for IS-TWL-DEBUGGER + bl _start_AutoloadDoneCallback +#endif + + //---- fill static static bss with 0 + mov r0, #0 + ldr r3, =_start_ModuleParams + ldr r1, [r3, #12] // SDK_STATIC_BSS_START + ldr r2, [r3, #16] // SDK_STATIC_BSS_END + sub r2, r2, r1 + bl INITi_CpuClear32 + + //---- flush static bss region + // (r0 == #0, r3 == _start_ModuleParams::BSS_segment_start) + bic r1, r3, #HW_CACHE_LINE_SIZE - 1 +@cacheflush: + mcr p15, 0, r0, c7, c10, 4 // wait writebuffer empty + mcr p15, 0, r1, c7, c5, 1 // ICache + mcr p15, 0, r1, c7, c14, 1 // DCache + add r1, r1, #HW_CACHE_LINE_SIZE + cmp r1, r2 + blt @cacheflush + + // print buffer (used for ARM7's printing) + ldr r1, =HW_COMPONENT_PARAM + str r0, [r1, #0] + + //---- set interrupt vector + ldr r1, =INITi_HW_DTCM + add r1, r1, #0x3fc0 + add r1, r1, #HW_DTCM_SYSRV_OFS_INTR_VECTOR + ldr r0, =OS_IrqHandler + str r0, [r1, #0] + +#ifndef SDK_NOINIT + //---- for C++ + bl _fp_init + bl TwlStartUp + bl __call_static_initializers +#endif + //---- start (to 16bit code) + ldr r1, =TwlMain + ldr lr, =HW_RESET_VECTOR + + tst sp, #4 + subne sp, sp, #4 // for 8byte-alignment + bx r1 +} + + +/*---------------------------------------------------------------------------* + Name: INITi_CpuClear32 + + Description: fill memory with specified data. + 32bit version + + Arguments: data : fill data + destp : destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +static asm void INITi_CpuClear32( register u32 data, register void *destp, register u32 size ) +{ + add r12, r1, r2 // r12: destEndp = destp + size +@20: + cmp r1, r12 // while (destp < destEndp) + stmltia r1!, {r0} // *((vu32 *)(destp++)) = data + blt @20 + bx lr +} + +/*---------------------------------------------------------------------------* + Name: INITi_DoAutoload + Description: NɉāAeI[g[hubŇŒf[^̓WJ + yѕϐ 0 NAsB4M bytes z PSRAM + ɔzuI[g[hubN̓WJ́An[hEFA TWL + ꍇɂsBI[g[hf[^ƃI[g[h悪ꕔ + dȂꍇ̂ŁAWJsB + Arguments: ȂB + Returns: ȂB + *---------------------------------------------------------------------------*/ +/* + * < iKI[g[h > + * 0x02000000 Static ZOgyшiڃ[hoCi(KvɉČ㔼k)zuĂB + * kĂꍇ́A܂ 0x02000000 Ɍ㏑‚‰𓀂B + * NITRO ƋL”\ ITCM ɔzuׂoCif[^ 0x01ff8000 Ƀ[hB + * NITRO ƋL”\ DTCM ɔzuׂoCif[^ 0x02fe0000 Ƀ[hB + * 0x02400000 ɓiڃ[hoCi(KvɉđSĈk)zuĂB + * 0x04000 oCg̓J[h ROM ēǂݏos‚Ȃ̂ŁA0x02f80000 - 0x02f84000 ɑޔB + * kĂꍇ́A܂ 0x02400000 Ɍ㏑‚‰𓀂B + * TWL ł삵Ȃ WRAM ɔzuׂoCif[^ꂼwAhXɃ[hB + * TWL ł삵ȂCɔzuׂoCif[^ORs[邱ƂŃ[hB + * ́ANITRO ƋL”\ȃCɔzuf[^ 0x02400000 zȂ͂ł邽߁A + * zuׂAhX 0x02400000 菬AhXɂȂ͂łׁB + * ܂AI[g[h񃊃Xg̎̂Cւ̃I[g[hubN .bss ZNṼNẢߒ + * j󂳂”\邪AÃI[g[h̍Ō̒iKȂ̂ŁAj󂳂ĂȂB + */ +static asm void +INITi_DoAutoload(void) +{ +@000: + stmdb sp!, {lr} + /* NITRO pubN̉ */ + ldr r1, =_start_ModuleParams + ldr r0, [r1, #20] // r0 = bottom of compressed data + bl MIi_UncompressBackward + +@010: + /* NITRO pubNI[g[h */ + ldr r1, =_start_ModuleParams + ldr r12, [r1] // r12 = SDK_AUTOLOAD_LIST + ldr r0, [r1, #4] // r0 = SDK_AUTOLOAD_LIST_END + ldr r1, [r1, #8] // r1 = SDK_AUTOLOAD_START +@011: cmp r12, r0 + bge @020 + /* ŒZNV[h */ + stmdb sp!, {r0} + ldr r2, [r12], #4 // r2 = start address of destination range + stmdb sp!, {r2} + ldr r3, [r12], #4 // r3 = size of fixed section + add r3, r3, r2 // r3 = end address of destination range of fixed section +@012: cmp r2, r3 + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt @012 + /* .bss ZNV 0 NA */ + mov r0, #0 // r0 = number to fill .bss section + ldr r3, [r12], #4 // r3 = size of .bss section + add r3, r3, r2 // r3 = end address of destination range of .bss section +@013: cmp r2, r3 + strlt r0, [r2], #4 + blt @013 + /* LbV𒲐 */ + ldmia sp!, {r2} // r2 = start address of destination range + mov r0, #HW_ITCM_IMAGE + cmp r2, r0 + addge r0, r0, #HW_ITCM_SIZE + cmpge r0, r2 + bgt @015 // If I-TCM autoload block, skip cache control logic. + ldr r0, =SDK_AUTOLOAD_DTCM_START + cmp r2, r0 + addge r0, r0, #HW_DTCM_SIZE + cmpge r0, r2 + bgt @015 // If D-TCM autoload block, skip cache control logic. + bic r2, r2, #HW_CACHE_LINE_SIZE - 1 // RoundDown32 +@014: cmp r2, r3 + bge @015 + mcr p15, 0, r2, c7, c14, 1 // Store and Invalidate D-Cache + mcr p15, 0, r2, c7, c5, 1 // Invalidate I-Cache + add r2, r2, #HW_CACHE_LINE_SIZE + b @014 +@015: ldmia sp!, {r0} + b @011 + +@020: + /* TWL n[hEFAœ삵Ă邩ǂ𒲍 */ + ldr r1, =REG_CLK_ADDR + ldrh r0, [r1] + tst r0, #REG_SCFG_CLK_WRAMHCLK_MASK + beq @030 + + /* TWL pubN݂̑mF */ + ldr r1, =HW_TWL_ROM_HEADER_BUF + 0x1cc /* ARM9 pg풓W[ ROM TCY */ + ldr r0, [r1] + cmp r0, #0 + beq @030 + + /* ēǂݏos•ޔ */ + bl INITi_ShelterLtdBinary + + /* TWL pubN̉ */ + ldr r1, =_start_LtdModuleParams + ldr r0, [r1, #12] + bl MIi_UncompressBackward + + /* TWL pubNI[g[h */ + ldr r1, =_start_LtdModuleParams + ldr r12, [r1] // r12 = SDK_LTDAUTOLOAD_LIST + ldr r0, [r1, #4] // r0 = SDK_LTDAUTOLOAD_LIST_END + ldr r1, [r1, #8] // r1 = SDK_LTDAUTOLOAD_START +@021: cmp r12, r0 + bge @030 + /* ŒZNV[h */ + stmdb sp!, {r0} + ldr r2, [r12], #4 // r2 = start address of destination range + stmdb sp!, {r2} + ldr r3, [r12], #4 // r3 = size of fixed section + add r3, r3, r2 // r3 = end address of destination range of fixed section +@022: cmp r2, r3 + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt @022 + /* .bss ZNV 0 NA */ + mov r0, #0 // r0 = number to fill .bss section + ldr r3, [r12], #4 // r3 = size of .bss section + add r3, r3, r2 // r3 = end address of destination range of .bss section +@023: cmp r2, r3 + strlt r0, [r2], #4 + blt @023 + /* LbV𒲐 */ + ldmia sp!, {r2} // r2 = start address of destination range + mov r0, #HW_ITCM_IMAGE + cmp r2, r0 + addge r0, r0, #HW_ITCM_SIZE + cmpge r0, r2 + bgt @025 // If I-TCM autoload block, skip cache control logic. + ldr r0, =SDK_AUTOLOAD_DTCM_START + cmp r2, r0 + addge r0, r0, #HW_DTCM_SIZE + cmpge r0, r2 + bgt @025 // If D-TCM autoload block, skip cache control logic. + bic r2, r2, #HW_CACHE_LINE_SIZE - 1 // RoundDown32 +@024: cmp r2, r3 + bge @025 + mcr p15, 0, r2, c7, c14, 1 // Store and Invalidate D-Cache + mcr p15, 0, r2, c7, c5, 1 // Invalidate I-Cache + add r2, r2, #HW_CACHE_LINE_SIZE + b @024 +@025: ldmia sp!, {r0} + b @021 + +@030: /* Cgobt@ɂȂ̂҂ */ + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 + + /* I[g[hR[obN֐Ăяo */ + ldr r0, =_start_ModuleParams + ldr r1, =_start_LtdModuleParams + ldmia sp!, {lr} + b _start_AutoloadDoneCallback +} + +/*---------------------------------------------------------------------------* + Name: INITi_ShelterLtdBinary + Description: TWL p̃I[g[hoCif[^̓AJ[h ROM + ēǂݏołȂ̈̃f[^ޔGAɑޔB + ēǂݏołȂ̈̃f[^ ARM7 p ARM9 p̊g풓 + W[̂Q‚ɕÔ\̂ŁA璷ł͂邪 + ̐擪 0x4000 ꂼޔB + Arguments: ȂB + Returns: ȂB + *---------------------------------------------------------------------------*/ +static asm void +INITi_ShelterLtdBinary(void) +{ + /* ARM7 pCԕی샊[WUANZX”\ɕύX */ + mrc p15, 0, r0, c5, c0, 3 + mrc p15, 0, r1, c5, c0, 2 + stmdb sp!, {r0, r1} + bic r0, r0, #(0xf << 8) + orr r0, r0, #(0x1 << 8) + bic r1, r1, #(0xf << 8) + orr r1, r1, #(0x1 << 8) + mcr p15, 0, r0, c5, c0, 3 + mcr p15, 0, r1, c5, c0, 2 + + /* ޔEAhX𒲍 */ + ldr r1, =HW_TWL_ROM_HEADER_BUF + 0x1c8 /* ARM9 pg풓W[ RAM AhX */ + ldr r1, [r1] + ldr r3, =HW_TWL_ROM_HEADER_BUF + 0x038 /* ARM7 p풓W[ RAM AhX */ + ldr r3, [r3] + sub r3, r3, #0x4000 /* ēǂݏos—̈TCY */ /* ARM7 pޔGA */ + sub r2, r3, #0x4000 /* ēǂݏos—̈TCY */ /* ARM9 pޔGA */ + + /* Rs[ */ +@loop: ldr r0, [r1], #4 + str r0, [r2], #4 + cmp r2, r3 + blt @loop + + /* ARM7 pCԕی샊[Wݒɖ߂ */ + ldmia sp!, {r0, r1} + mcr p15, 0, r0, c5, c0, 3 + mcr p15, 0, r1, c5, c0, 2 + bx lr +} + +/*---------------------------------------------------------------------------* + Name: MIi_UncompressBackward + Description: Uncompress special archive for module compression. + Arguments: bottom = Bottom adrs of packed archive + 1 + bottom[-8..-6] = offset for top of compressed data + inp_top = bottom - bottom[-8..-6] + bottom[-5] = offset for bottom of compressed data + inp = bottom - bottom[-5] + bottom[-4..-1] = offset for bottom of original data + outp = bottom + bottom[-4..-1] + typedef struct + { + u32 bufferTop:24; + u32 compressBottom:8; + u32 originalBottom; + } CompFooter; + Returns: None. + *---------------------------------------------------------------------------*/ +asm void +MIi_UncompressBackward(register void* bottom) +{ +#define data r0 +#define inp_top r1 +#define outp r2 +#define inp r3 +#define outp_save r4 +#define flag r5 +#define count8 r6 +#define index r7 +#define len r12 + + cmp bottom, #0 + beq @exit + stmfd sp!, {r4-r7} + ldmdb bottom, {r1-r2} + add outp, bottom, outp + sub inp, bottom, inp_top, LSR #24 + bic inp_top, inp_top, #0xff000000 + sub inp_top, bottom, inp_top + mov outp_save, outp +@loop: + cmp inp, inp_top // exit if inp==inp_top + ble @end_loop + ldrb flag, [inp, #-1]! // r4 = compress_flag = *--inp + mov count8, #8 +@loop8: + subs count8, count8, #1 + blt @loop + tst flag, #0x80 + bne @blockcopy +@bytecopy: + ldrb data, [inp, #-1]! + strb data, [outp, #-1]! // Copy 1 byte + b @joinhere +@blockcopy: + ldrb len, [inp, #-1]! + ldrb index, [inp, #-1]! + orr index, index, len, LSL #8 + bic index, index, #0xf000 + add index, index, #0x0002 + add len, len, #0x0020 +@patterncopy: + ldrb data, [outp, index] + strb data, [outp, #-1]! + subs len, len, #0x0010 + bge @patterncopy + +@joinhere: + cmp inp, inp_top + mov flag, flag, LSL #1 + bgt @loop8 +@end_loop: + + // DC_FlushRange & IC_InvalidateRange + mov r0, #0 + bic inp, inp_top, #HW_CACHE_LINE_SIZE - 1 +@cacheflush: + mcr p15, 0, r0, c7, c10, 4 // wait writebuffer empty + mcr p15, 0, inp, c7, c5, 1 // ICache + mcr p15, 0, inp, c7, c14, 1 // DCache + add inp, inp, #HW_CACHE_LINE_SIZE + cmp inp, outp_save + blt @cacheflush + + ldmfd sp!, {r4-r7} +@exit bx lr +} + +/*---------------------------------------------------------------------------* + Name: _start_AutoloadDoneCallback + Description: I[g[hR[obNB + Arguments: argv - I[g[hp[^ێĂzB + argv[0] = SDK_AUTOLOAD_LIST + argv[1] = SDK_AUTOLOAD_LIST_END + argv[2] = SDK_AUTOLOAD_START + argv[3] = SDK_STATIC_BSS_START + argv[4] = SDK_STATIC_BSS_END + Returns: ȂB + *---------------------------------------------------------------------------*/ +SDK_WEAK_SYMBOL asm void +_start_AutoloadDoneCallback(void* argv[]) +{ + bx lr +} + +/*---------------------------------------------------------------------------* + Name: INITi_InitCoprocessor + Description: VXeRvZbTB + ɁAI-TCM y D-TCM gp”\ȏԂɂB + Arguments: ȂB + Returns: ȂB + *---------------------------------------------------------------------------*/ +static asm void +INITi_InitCoprocessor(void) +{ + /* RvZbT̏Ԏ擾 */ + mrc p15, 0, r0, c1, c0, 0 + + tst r0, #HW_C1_PROTECT_UNIT_ENABLE + beq @010 + tst r0, #HW_C1_DCACHE_ENABLE + beq @003 + + /* D-Cache eɃCgobN */ + mov r1, #0 +@001: mov r2, #0 +@002: orr r3, r1, r2 + mcr p15, 0, r3, c7, c10, 2 + add r2, r2, #HW_CACHE_LINE_SIZE + cmp r2, #HW_DCACHE_SIZE / 4 + blt @002 + adds r1, r1, #1 << HW_C7_CACHE_SET_NO_SHIFT + bne @001 + +@003: /* Cgobt@ɂȂ̂҂ */ + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 + +@010: /* RvZbT̏Ԃ */ + ldr r1, = HW_C1_ITCM_LOAD_MODE \ + | HW_C1_DTCM_LOAD_MODE \ + | HW_C1_ITCM_ENABLE \ + | HW_C1_DTCM_ENABLE \ + | HW_C1_LD_INTERWORK_DISABLE \ + | HW_C1_ICACHE_ENABLE \ + | HW_C1_DCACHE_ENABLE \ + | HW_C1_PROTECT_UNIT_ENABLE + bic r0, r0, r1 + ldr r1, = HW_C1_SB1_BITSET \ + | HW_C1_EXCEPT_VEC_UPPER + orr r0, r0, r1 + mcr p15, 0, r0, c1, c0, 0 + + /* I-TCM ̃TCYݒ */ + mov r1, #HW_C9_TCMR_32MB + mcr p15, 0, r1, c9, c1, 1 + /* D-TCM ̃TCYyї̈x[XAhXݒ */ + ldr r1, =SDK_AUTOLOAD_DTCM_START + orr r1, r1, #HW_C9_TCMR_16KB + mcr p15, 0, r1, c9, c1, 0 + + /* I-TCM / D-TCM gpݒ */ + mov r1, #HW_C1_ITCM_ENABLE | HW_C1_DTCM_ENABLE + orr r0, r0, r1 + mcr p15, 0, r0, c1, c0, 0 + + bx lr +} + +/*---------------------------------------------------------------------------* + Name: INITi_InitRegion + Description: [WݒsB + Arguments: ȂB + Returns: ȂB + *---------------------------------------------------------------------------*/ +/* When hardware is TWL +; Region G: BACK_GROUND: Base = 0x0, Size = 4GB, I:NC NB / D:NC NB, I:NA / D:NA +; Region 0: IO_VRAM: Base = 0x04000000, Size = 64MB, I:NC NB / D:NC NB, I:RW / D:RW +; Region 1: MAINMEM_WRAM: Base = 0x02000000, Size = 32MB, I:Cach Buf / D:Cach Buf, I:RW / D:RW +; Region 2: ARM7_RESERVE: Base = 0x02f80000, Size = 512KB, I:NC NB / D:NC NB, I:NA / D:NA +; Region 3: EX_MAINMEM: Base = 0x0d000000, Size = 16MB, I:Cach Buf / D:Cach Buf, I:RW / D:RW +; Region 4: DTCM: Base = 0x02fe0000, Size = 16KB, I:NC NB / D:NC NB, I:NA / D:RW +; Region 5: ITCM: Base = 0x01000000, Size = 16MB, I:NC NB / D:NC NB, I:RW / D:RW +; Region 6: BIOS: Base = 0xffff0000, Size = 32KB, I:Cach NB / D:Cach NB, I:RO / D:RO +; Region 7: SHARED_WORK: Base = 0x02ffc000, Size = 16KB, I:NC NB / D:NC NB, I:NA / D:RW +*/ +/* When hardware is NITRO +; Region G: BACK_GROUND: Base = 0x0, Size = 4GB, I:NC NB / D:NC NB, I:NA / D:NA +; Region 0: IO_VRAM: Base = 0x04000000, Size = 64MB, I:NC NB / D:NC NB, I:RW / D:RW +; Region 1: MAIN_MEM: Base = 0x02000000, Size = 8MB*, I:Cach Buf / D:Cach Buf, I:RW / D:RW +; (* When hardware is not debugger, size will be reduced to 4MB in OS_InitArena() ) +; Region 2: ARM7_RESERVE: Base = 0x027e0000, Size = 128KB, I:NC NB / D:NC NB, I:NA / D:NA +; (* When hardware is not debugger, base will be moved to 0x023e0000 in OS_InitArena() ) +; Region 3: CARTRIDGE: Base = 0x08000000, Size = 128MB, I:NC NB / D:NC NB, I:NA / D:RW +; Region 4: DTCM: Base = 0x02fe0000, Size = 16KB, I:NC NB / D:NC NB, I:NA / D:RW +; Region 5: ITCM: Base = 0x01000000, Size = 16MB, I:NC NB / D:NC NB, I:RW / D:RW +; Region 6: BIOS: Base = 0xffff0000, Size = 32KB, I:Cach NB / D:Cach NB, I:RO / D:RO +; Region 7: SHARED_WORK: Base = 0x02fff000, Size = 4KB, I:NC NB / D:NC NB, I:NA / D:RW +*/ + +static asm void +INITi_InitRegion(void) +{ +#define SET_PROTECTION_A(id, adr, siz) ldr r0, =(adr|HW_C6_PR_##siz|HW_C6_PR_ENABLE) +#define SET_PROTECTION_B(id, adr, siz) mcr p15, 0, r0, c6, id, 0 +#define REGION_BIT(a, b, c, d, e, f, g, h) (((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | ((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7)) +#define REGION_ACC(a, b, c, d, e, f, g, h) (((a) << 0) | ((b) << 4) | ((c) << 8) | ((d) << 12) | ((e) << 16) | ((f) << 20) | ((g) << 24) | ((h) << 28)) +#define NA 0 +#define RW 1 +#define RO 5 + + /* (0) I/O WX^y VRAM */ + SET_PROTECTION_A(c0, HW_IOREG, 64MB) + SET_PROTECTION_B(c0, HW_IOREG, 64MB) + + /* (4) D-TCM */ + ldr r0, =SDK_AUTOLOAD_DTCM_START + orr r0, r0, #HW_C6_PR_16KB | HW_C6_PR_ENABLE + SET_PROTECTION_B(c4, SDK_AUTOLOAD_DTCM_START, 16KB) + + /* (5) I-TCM */ + SET_PROTECTION_A(c5, HW_ITCM_IMAGE, 16MB) + SET_PROTECTION_B(c5, HW_ITCM_IMAGE, 16MB) + + /* (6) VXeR[ ROM */ + SET_PROTECTION_A(c6, HW_BIOS, 32KB) + SET_PROTECTION_B(c6, HW_BIOS, 32KB) + + /* TWL n[hEFAœ삵Ă邩ǂ𒲍 */ + ldr r1, =REG_CLK_ADDR + ldrh r0, [r1] + tst r0, #REG_SCFG_CLK_WRAMHCLK_MASK + beq @002 + +@001: /* n[hEFA TWL ̏ꍇ */ + /* (1) Cy WRAM */ + SET_PROTECTION_A(c1, HW_TWL_MAIN_MEM_MAIN, 32MB) + SET_PROTECTION_B(c1, HW_TWL_MAIN_MEM_MAIN, 32MB) + + /* (2) ARM7 pC */ + SET_PROTECTION_A(c2, HW_TWL_MAIN_MEM_SUB, 512KB) + SET_PROTECTION_B(c2, HW_TWL_MAIN_MEM_SUB, 512KB) + + /* (3) gC */ + SET_PROTECTION_A(c3, HW_TWL_MAIN_MEM_EX, 16MB) + SET_PROTECTION_B(c3, HW_TWL_MAIN_MEM_EX, 16MB) + + /* (7) ARM9/ARM7 LC */ + SET_PROTECTION_A(c7, HW_TWL_MAIN_MEM_SHARED, 16KB) + SET_PROTECTION_B(c7, HW_TWL_MAIN_MEM_SHARED, 16KB) + + /* ߃LbV */ + mov r0, #REGION_BIT(0, 1, 0, 1, 0, 0, 1, 0) + mcr p15, 0, r0, c2, c0, 1 + + /* f[^LbV */ +// mov r0, #REGION_BIT(0, 1, 0, 1, 0, 0, 1, 0) + mov r0, #REGION_BIT(0, 1, 1, 1, 0, 0, 1, 0) + mcr p15, 0, r0, c2, c0, 0 + + /* Cgobt@ */ +// mov r0, #REGION_BIT(0, 1, 0, 1, 0, 0, 0, 0) + mov r0, #REGION_BIT(0, 1, 1, 1, 0, 0, 0, 0) + mcr p15, 0, r0, c3, c0, 0 + + /* ߃ANZX */ + ldr r0, =REGION_ACC(RW, RW, NA, RW, NA, RW, RO, NA) + mcr p15, 0, r0, c5, c0, 3 + + /* f[^ANZX */ +// ldr r0, =REGION_ACC(RW, RW, NA, RW, RW, RW, RO, RW) + ldr r0, =REGION_ACC(RW, RW, RW, RW, RW, RW, RO, RW) + mcr p15, 0, r0, c5, c0, 2 +// b @003 + +@002: /* n[hEFA NITRO ̏ꍇ */ +#if 0 + /* (1) C */ + SET_PROTECTION_A(c1, HW_MAIN_MEM_MAIN, 8MB) + SET_PROTECTION_B(c1, HW_MAIN_MEM_MAIN, 8MB) + /* Size will be arranged in OS_InitArena(). */ + + /* (2) ARM7 pC */ + SET_PROTECTION_A(c2, (HW_MAIN_MEM_EX_END - HW_MAIN_MEM_SHARED_SIZE - HW_MAIN_MEM_SUB_SIZE), 128KB) + SET_PROTECTION_B(c2, (HW_MAIN_MEM_EX_END - HW_MAIN_MEM_SHARED_SIZE - HW_MAIN_MEM_SUB_SIZE), 128KB) + /* Base address will be moved in OS_InitArena(). */ + + /* (3) J[gbW */ + SET_PROTECTION_A(c3, HW_CTRDG_ROM, 128MB) + SET_PROTECTION_B(c3, HW_CTRDG_ROM, 128MB) + + /* (7) ARM9/ARM7 LC */ + SET_PROTECTION_A(c7, HW_MAIN_MEM_SHARED, 4KB) + SET_PROTECTION_B(c7, HW_MAIN_MEM_SHARED, 4KB) + + /* ߃LbV */ + mov r0, #REGION_BIT(0, 1, 0, 0, 0, 0, 1, 0) + mcr p15, 0, r0, c2, c0, 1 + + /* f[^LbV */ + mov r0, #REGION_BIT(0, 1, 0, 0, 0, 0, 1, 0) + mcr p15, 0, r0, c2, c0, 0 + + /* Cgobt@ */ + mov r0, #REGION_BIT(0, 1, 0, 0, 0, 0, 0, 0) + mcr p15, 0, r0, c3, c0, 0 + + /* ߃ANZX */ + ldr r0, =REGION_ACC(RW, RW, NA, NA, NA, RW, RO, NA) + mcr p15, 0, r0, c5, c0, 3 + + /* f[^ANZX */ + ldr r0, =REGION_ACC(RW, RW, NA, RW, RW, RW, RO, RW) + mcr p15, 0, r0, c5, c0, 2 +#endif +@003: /* veNVjbgyуLbVgpݒ */ + mrc p15, 0, r0, c1, c0, 0 + ldr r1, = HW_C1_ICACHE_ENABLE \ + | HW_C1_DCACHE_ENABLE \ + | HW_C1_CACHE_ROUND_ROBIN \ + | HW_C1_PROTECT_UNIT_ENABLE + orr r0, r0, r1 + mcr p15, 0, r0, c1, c0, 0 + + /* LbV̓ej */ + mov r1, #0 + mcr p15, 0, r1, c7, c6, 0 + mcr p15, 0, r1, c7, c5, 0 + + bx lr +} + + +/*---------------------------------------------------------------------------* + Name: TwlStartUp + + Description: hook for user start up + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +SDK_WEAK_SYMBOL void TwlStartUp(void) +{ +} + +/*---------------------------------------------------------------------------* + Name: OSi_ReferSymbol + + Description: used by SDK_REFER_SYMBOL macro to avoid dead-strip. + + Arguments: symbol unused + + Returns: None. + *---------------------------------------------------------------------------*/ +void OSi_ReferSymbol(void *symbol) +{ +#pragma unused(symbol) +} diff --git a/build/libraries/init/Makefile b/build/libraries/init/Makefile new file mode 100644 index 0000000..ce0d6f5 --- /dev/null +++ b/build/libraries/init/Makefile @@ -0,0 +1,32 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - libraries - init +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM9 \ + ARM7 \ + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/mi/ARM9/Makefile b/build/libraries/mi/ARM9/Makefile new file mode 100644 index 0000000..e8461f1 --- /dev/null +++ b/build/libraries/mi/ARM9/Makefile @@ -0,0 +1,60 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries - mi +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = +SUBMAKES = + + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= TRUE + +SRCDIR = . ../common + +SRCS = \ + mi_init_mainMemory.c \ + mi_loader.c \ + mi_exDma.c \ + +TARGET_LIB = libmi$(FIRM_LIBSUFFIX).a + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + +ifdef NITRO_CALLTRACE +CCFLAGS += -DOS_PROFILE_AVAILABLE -DOS_PROFILE_CALL_TRACE +endif + +ifdef NITRO_FUNCTIONCOST +CCFLAGS += -DOS_PROFILE_AVAILABLE -DOS_PROFILE_FUNCTION_COST +endif + +ifdef NITRO_TCM_APPLY +CCFLAGS += -DSDK_TCM_APPLY +endif + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/libraries/mi/ARM9/mi_init_mainMemory.c b/build/libraries/mi/ARM9/mi_init_mainMemory.c new file mode 100644 index 0000000..87e1d39 --- /dev/null +++ b/build/libraries/mi/ARM9/mi_init_mainMemory.c @@ -0,0 +1,160 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - mi + File: mi_init_mainMemory.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include + +void MIi_InitMainMemCRCore( void ); + +/*---------------------------------------------------------------------------* + Name: MIi_IsMainMemoryInitialized + + Description: + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL MIi_IsMainMemoryInitialized( void ) +{ + return (BOOL)((reg_MI_EXMEMCNT & REG_MI_EXMEMCNT_CE2_MASK) >> REG_MI_EXMEMCNT_CE2_SHIFT); +} + +/*---------------------------------------------------------------------------* + Name: MIi_WaitMainMemoryInitialize + + Description: + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_WaitMainMemoryInitialize( void ) +{ + while( MIi_IsMainMemoryInitialized() == FALSE ) + { + } +} + + +/*---------------------------------------------------------------------------* + Name: MIi_InitMainMemCR + + Description: change mainmem into the burst mode + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +#include + +asm void MIi_InitMainMemCR( BOOL setCR ) +{ + mov r12, lr + + mov r2, r0 + + mov r0, #0x8000 // low period 0.97ms + bl OS_SpinWaitCpuCycles + + ldr r3, =REG_EXMEMCNT_ADDR + mov r1, #REG_MI_EXMEMCNT_CE2_MASK + ldrh r0, [r3] + tst r0, r1 + bxne r12 + + strh r1, [r3] + + mov r0, #0x8000 // high period 0.97ms + bl OS_SpinWaitCpuCycles + + cmp r2, #FALSE + beq @10 + + // C[hin[hZbgj + // 񓯊[hiCLKŒjŃR}hsĂv + ldr r3, =HW_WRAM_AREA - 2 + bl MIi_InitMainMemCRCore +#ifdef TWL_PLATFORM_TS + ldr r3, =HW_MAIN_MEM_HI_EX_END - 2 + bl MIi_InitMainMemCRCore +#endif // TWL_PLATFORM_TS + +@10: + ldr r3, =REG_EXMEMCNT_ADDR + mov r1, #REG_MI_EXMEMCNT_IFM_MASK | REG_MI_EXMEMCNT_CE2_MASK + strh r1, [r3] + + bx r12 +} + +asm void MIi_InitMainMemCRCore( void ) +{ +// stmfd sp!, { lr } + +#ifdef TWL_PLATFORM_BB + mov r2, lr + ldr r0, =MMEM_DCR0_BURST_MODE | MMEM_DCR0_BURST_CONTINUOUS \ + | MMEM_DCR0_PARTIAL_REFRESH_NONE | MMEM_DCR0_SB1 + ldr r1, =MMEM_DCR1_1ST_R4_W3 | MMEM_DCR1_BURST_WRITE | MMEM_DCR1_BURST_LINER \ + | MMEM_DCR1_CLOCK_TRIGGER_UP | MMEM_DCR1_SB1 + ldrh lr, [r3] + strh lr, [r3] + strh lr, [r3] + mov lr, r2 + ldr r2, =HW_MAIN_MEM | MMEM_DCR2_CLOCK_TRIGGER_UP \ + | MMEM_DCR2_BURST_MODE | MMEM_DCR2_BURST_CONTINUOUS \ + | MMEM_DCR2_1ST_R4_W3 | MMEM_DCR2_BURST_WRITE | MMEM_DCR2_BURST_LINER \ + | MMEM_DCR2_PARTIAL_REFRESH_NONE | MMEM_DCR2_SB1 + strh r0, [r3] + strh r1, [r3] + ldrh r3, [r2] +#else // TWL_PLATFORM_TS + mov r2, lr + ldr r0, =MMEM_TCR0 + ldr r1, =MMEM_TCR1 + ldrh lr, [r3] + strh lr, [r3] + strh lr, [r3] + mov lr, r2 + ldr r2, =MMEM_TCR2 + strh r0, [r3] + strh r1, [r3] + strh r2, [r3] +#endif // TWL_PLATFORM_TS + +// ldmfd sp!, { lr } + bx lr +} + +asm void MIi_GetMainMemCR( MIMmemCR* dest ) +{ +#ifdef TWL_PLATFORM_TS + ldr r3, =HW_WRAM_AREA - 2 + ldr r1, =MMEM_TCR0_R + ldrh r2, [r3] + strh r2, [r3] + strh r2, [r3] + strh r1, [r3] + ldrh r1, [r3] + ldrh r2, [r3] + strh r2, [r0, #4] + strh r1, [r0, #2] + ldr r1, =MMEM_TCR0_R + strh r1, [r0, #0] +#endif // TWL_PLATFORM_TS + + bx lr +} \ No newline at end of file diff --git a/build/libraries/mi/ARM9/mi_loader.c b/build/libraries/mi/ARM9/mi_loader.c new file mode 100644 index 0000000..803976c --- /dev/null +++ b/build/libraries/mi/ARM9/mi_loader.c @@ -0,0 +1,509 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - mi + File: mi_loader.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include + +/* + PROFILE_ENABLE `Ƃx̃ptH[}X`FbNł܂B + p邽߂ɂ́Amain.cǂɁAu32 profile[256]; u32 pf_cnt; + `Kv܂B +*/ +//#define PROFILE_ENABLE + +#ifdef SDK_FINALROM // FINALROMŖ +#undef PROFILE_ENABLE +#endif + +#ifdef PROFILE_ENABLE +#define PROFILE_PXI_SEND 0x10000000 +#define PROFILE_PXI_RECV 0x20000000 +#define PROFILE_SHA1 0xa0000000 +#define PROFILE_RSA 0xb0000000 +extern u32 profile[]; +extern u32 pf_cnt; +#endif + + +#define PXI_FIFO_TAG_DATA PXI_FIFO_TAG_USER_0 + +static ROM_Header* const rh = (ROM_Header*)HW_TWL_ROM_HEADER_BUF; + +#define HEADER_SIZE 0x1000 +#define AUTH_SIZE 0xe00 +#define RSA_BLOCK_SIZE 128 + +#define HASH_UNIT 0x1000 // TODO: optimizing to maximize cache efficiency + +static const u8 s_digestDefaultKey[ SVC_SHA1_BLOCK_SIZE ] = { + 0x21, 0x06, 0xc0, 0xde, + 0xba, 0x98, 0xce, 0x3f, + 0xa6, 0x92, 0xe3, 0x9d, + 0x46, 0xf2, 0xed, 0x01, + + 0x76, 0xe3, 0xcc, 0x08, + 0x56, 0x23, 0x63, 0xfa, + 0xca, 0xd4, 0xec, 0xdf, + 0x9a, 0x62, 0x78, 0x34, + + 0x8f, 0x6d, 0x63, 0x3c, + 0xfe, 0x22, 0xca, 0x92, + 0x20, 0x88, 0x97, 0x23, + 0xd2, 0xcf, 0xae, 0xc2, + + 0x32, 0x67, 0x8d, 0xfe, + 0xca, 0x83, 0x64, 0x98, + 0xac, 0xfd, 0x3e, 0x37, + 0x87, 0x46, 0x58, 0x24, +}; + +/*---------------------------------------------------------------------------* + Name: CheckRomCertificate + + Description: check the certification in the ROM + + ROMwb_ɕtꂽؖ̃`FbNs܂B + makerom.TWL̃R[hɈˑ܂B + + Arguments: pool pointer to the SVCSignHeapContext + pCert pointer to the certification + pCAPubKey pointer to the public key for the certification + gameCode initial code + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +static BOOL CheckRomCertificate( SVCSignHeapContext* pool, const RomCertificate *pCert, const void* pCAPubKey, u32 gameCode ) +{ + u8 digest[DIGEST_SIZE_SHA1]; + u8 md[DIGEST_SIZE_SHA1]; + int i; + BOOL result = TRUE; + + // ؖwb_̃}WbNio[`FbN + if( pCert->header.magicNumber != TWL_ROM_CERT_MAGIC_NUMBER || + // ؖwb_ROMwb_̃Q[R[hv`FbN + pCert->header.gameCode != gameCode ) + { + result = FALSE; + } + // ؖ`FbN + SVC_DecryptSign( pool, &digest, pCert->sign, pCAPubKey ); + + // _CWFXǧvZ + SVC_CalcSHA1( md, pCert, ROM_CERT_SIGN_OFFSET ); + + // r + for (i = 0; i < DIGEST_SIZE_SHA1; i++) + { + if ( md[i] != digest[i] ) + { + result = FALSE; + } + } + + return result; +} + +/*---------------------------------------------------------------------------* + Name: MIi_LoadBuffer + + Description: receive data from ARM7 and store(move) via WRAM[B] + + LoadBufferJjYŁAt@C̓eARM7󂯎܂B + SVCSHA1Contextw肵ĂꍇARs[̂‚łSHA1 + vZs܂B + + [LoadBufferJjY] + WRAM[B]𗘗pāAARM7,ARM9Ԃ̃f[^]s܂B + WRAM[B]̊eXbgoPc[œn܂B + 1Xbg̃f[^܂͑Sf[^i[ꂽƂAARM7 + FIRM_PXI_ID_LOAD_PIRIODM܂B + ARM9͎Mɂ̃Xbg̎gpARM9ɕύXăf[^ + oAɃNA(ZLeB)Agp + ARM7ɖ߂܂B + + [gp] + WRAM[B]bNAԂƂARM7ɓ|ĂƁB + + [ӓ_] + offsetsizeARM7ʒm܂Bʂ̌oHœĂB + SRLt@Cǂݍޏꍇ́A݂ROMwb_QƂłΏ\łB + (ROMwb_͌mĂ͂) + + ⑫: + ł́A郉CuARM7/ARM9ŕ킹邱Ƃ + OɂĂ邪AėpIɂɂ(ƗCuȂ)A + MŃXbg𔼕‚ƂAꂼɎMPXIR[obN + XbhpӂAMAPIf[^WRAMɊi[A + destsizeʒmƂ`OKł͂ȂH + (ŊԎԂ) + + Arguments: dest destination address for received data + size size to load + ctx context for SHA1 if execute SVC_SHA1Update + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +static BOOL MIi_LoadBuffer(u8* dest, u32 size, SVCSHA1Context *ctx) +{ + u8* base = (u8*)HW_FIRM_LOAD_BUFFER_BASE; + static int count = 0; + + while (size > 0) + { + u8* src = base + count * HW_FIRM_LOAD_BUFFER_UNIT_SIZE; + u32 unit = size < HW_FIRM_LOAD_BUFFER_UNIT_SIZE ? size : HW_FIRM_LOAD_BUFFER_UNIT_SIZE; + //OS_TPrintf("%s: src=%X, unit=%X\n", __func__, src, unit); + if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_PIRIOD ) + { + return FALSE; + } +#ifdef PROFILE_ENABLE + // x2...: after PXI + profile[pf_cnt++] = PROFILE_PXI_RECV | FIRM_PXI_ID_LOAD_PIRIOD; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + MIi_SetWramBankMaster_B(count, MI_WRAM_ARM9); + if (ctx) + { + int done; + for (done = 0; done < unit; done += HASH_UNIT) + { + u8* s = src + done; + u8* d = dest + done; + u32 u = unit < done + HASH_UNIT ? unit - done : HASH_UNIT; + MI_CpuCopyFast( s, d, u ); + SVC_SHA1Update( ctx, s, u ); + } + } + else + { + MI_CpuCopyFast( src, dest, unit ); + } + MI_CpuClearFast( src, unit ); + DC_FlushRange( src, unit ); +#ifdef PROFILE_ENABLE + // x2...: after copy & clear + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + MIi_SetWramBankMaster_B(count, MI_WRAM_ARM7); + count = (count + 1) % HW_FIRM_LOAD_BUFFER_UNIT_NUMS; + size -= unit; + dest += unit; + } + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: MI_LoadHeader + + Description: load header + + SRLROMwb_ARM7󂯎AF؂܂B + MOɁAARM7 FIRM_PXI_ID_LOAD_HEADER M܂B + MAF؂ʂȂARM7 FIRM_PXI_ID_AUTH_HEADER 𑗐M + ܂BȑOɁAC̏̈ʒuROMwb_i[ + ĂȂ΂Ȃ܂B + āAseedf[^16oCgM܂B + makerom.TWL܂IPL̎dlɈˑ܂B + + Arguments: pool pointer to the pool info for SVCSignHeapContext + rsa_key key address + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +BOOL MI_LoadHeader( SVCSignHeapContext* pool, const void* rsa_key ) +{ + SVCSHA1Context ctx; + u8 md[DIGEST_SIZE_SHA1]; + SignatureData sd; + int i; + BOOL result = TRUE; + + SVC_SHA1Init(&ctx); + +#ifdef PROFILE_ENABLE + pf_cnt = 0x10; +#endif + // load header (hash target) + if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_HEADER || +#ifdef PROFILE_ENABLE + // 10: after PXI + ((profile[pf_cnt++] = PROFILE_PXI_RECV | FIRM_PXI_ID_LOAD_HEADER), FALSE) || + ((profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick())), FALSE) || +#endif + !MIi_LoadBuffer( (u8*)rh, AUTH_SIZE, &ctx ) ) + { + return FALSE; + } + SVC_SHA1GetHash(&ctx, md); +#ifdef PROFILE_ENABLE + // 1x: after HMAC + profile[pf_cnt++] = PROFILE_SHA1; // checkpoint + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + // load header (remain) + if ( !MIi_LoadBuffer( (u8*)rh + AUTH_SIZE, HEADER_SIZE - AUTH_SIZE, NULL ) ) + { + return FALSE; + } + + // Recؖ + if ( CheckRomCertificate( pool, &rh->certificate, rsa_key, *(u32*)rh->s.game_code ) ) + { + rsa_key = rh->certificate.pubKeyMod; // wb_p̌̎o + } + else + { + // Ƃ肠Recؖp̌̂܂܎gƉ + } + + // wb_`FbN + SVC_DecryptSign( pool, &sd, rh->signature, rsa_key ); + for (i = 0; i < DIGEST_SIZE_SHA1; i++) + { + if ( md[i] != sd.digest[i] ) + { + result = FALSE; + } + } +#ifdef PROFILE_ENABLE + // 1x: after RSA, before PXI + profile[pf_cnt++] = PROFILE_RSA; // checkpoint + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); + profile[pf_cnt++] = (u32)PROFILE_PXI_SEND | FIRM_PXI_ID_AUTH_HEADER; // checkpoint +#endif + if ( result ) + { + PXI_NotifyID( FIRM_PXI_ID_AUTH_HEADER ); + PXI_SendDataByFifo( PXI_FIFO_TAG_DATA, sd.aes_key_seed, AES_BLOCK_SIZE ); + // DS݊wb_Rs[ + MI_CpuCopyFast( rh, (void*)HW_ROM_HEADER_BUF, HW_ROM_HEADER_BUF_END-HW_ROM_HEADER_BUF ); + } + MI_CpuClear8(&sd, sizeof(sd)); + MI_CpuClear8(&md, sizeof(md)); + + return result; +} + +/*---------------------------------------------------------------------------* + Name: MIi_GetTransferSize + + Description: get size to transfer once + + xɎMTCYԂ܂B + + ]͈͂AES̈܂ꍇ́AE܂ł̃TCY ( + ȃTCY) Ԃ܂B + makerom.TWL܂IPL̎gpɈˑ܂B + + Arguments: offset offset of region from head of ROM_Header + size size of region + + Returns: size to transfer once + *---------------------------------------------------------------------------*/ +static u32 MIi_GetTransferSize( u32 offset, u32 size ) +{ + u32 aes_offset = rh->s.aes_target_rom_offset; + u32 aes_end = aes_offset + rh->s.aes_target_size; + u32 end = offset + size; + if ( rh->s.enable_aes ) + { + if ( offset >= aes_offset && offset < aes_end ) + { + if ( end > aes_end ) + { + size = aes_end - offset; + } + } + else + { + if ( offset < aes_offset && offset + size > aes_offset ) + { + size = aes_offset - offset; + } + } + } + return size; +} + +/*---------------------------------------------------------------------------* + Name: MIi_LoadModule + + Description: receive module from ARM7 and store(move) via WRAM[B] + + MIi_LoadBuffeȑAPIłB + + AESE܂ꍇ́A2LoadBufferɕ܂B + + łɃnbVlĂāA傤SHA1̌vZ͈͑Ŝ + ǂݍޏꍇɕ֗łB + + Arguments: dest destination address for received data + offset offset from head of ROM_Header + size size to load + digest digest to compare + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +static /*inline*/ BOOL MIi_LoadModule(void* dest, u32 offset, u32 size, const u8 digest[DIGEST_SIZE_SHA1]) +{ + SVCHMACSHA1Context ctx; + u8 md[DIGEST_SIZE_SHA1]; + int i; + BOOL result = TRUE; + + SVC_HMACSHA1Init(&ctx, s_digestDefaultKey, SVC_SHA1_BLOCK_SIZE ); + while ( size > 0 ) + { + u32 unit = MIi_GetTransferSize( offset, size ); + if ( !MIi_LoadBuffer( dest, unit, &ctx.sha1_ctx ) ) // UpdateSHA1Ɠ + { + return FALSE; + } + dest = (u8*)dest + unit; + offset += unit; + size -= unit; + } + SVC_HMACSHA1GetHash(&ctx, md); +#ifdef PROFILE_ENABLE + // 3x: after SHA1 + profile[pf_cnt++] = PROFILE_SHA1; // checkpoint + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + for (i = 0; i < DIGEST_SIZE_SHA1; i++) + { + if (md[i] != digest[i]) + { + result = FALSE; + } + } + MI_CpuClear8(md, DIGEST_SIZE_SHA1); + return result; +} + +/*---------------------------------------------------------------------------* + Name: MI_LoadStatic + + Description: load static binary + + ARM9/ARM7StaticLTD StaticM܂B + MOɁAARM7FIRM_PXI_ID_LOAD_*_STATICM܂B + MAF؂ʂȂARM7FIRM_PXI_ID_AUTH_*_STATIC𑗐M + ܂BTCY0̏ꍇ́Ãp[gPXIʐMs܂B + + APIĂяoOɁAC̏̈ʒuROMwb_ + i[ĂKv܂B + + Arguments: None + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +BOOL MI_LoadStatic( void ) +{ + // load static + if ( PXI_RecvID() != FIRM_PXI_ID_LOAD_STATIC ) + { + return FALSE; + } +#ifdef PROFILE_ENABLE + // 30: after PXI + pf_cnt = 0x30; + profile[pf_cnt++] = PROFILE_PXI_RECV | FIRM_PXI_ID_LOAD_STATIC; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + // load ARM9 static region + if ( rh->s.main_size > 0 ) + { +#ifdef PROFILE_ENABLE + // 31: before PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + if ( !MIi_LoadModule(rh->s.main_ram_address, rh->s.main_rom_offset, rh->s.main_size, rh->s.main_static_digest) ) + { + return FALSE; + } + } + + // load ARM7 static region + if ( rh->s.sub_size > 0 ) + { +#ifdef PROFILE_ENABLE + // 50: before PXI + pf_cnt = 0x50; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + if ( !MIi_LoadModule( rh->s.sub_ram_address, rh->s.sub_rom_offset, rh->s.sub_size, rh->s.sub_static_digest ) ) + { + return FALSE; + } + } + + // load ARM9 extended static region + if ( rh->s.main_ltd_size > 0 ) + { +#ifdef PROFILE_ENABLE + // 70: before PXI + pf_cnt = 0x70; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + if ( !MIi_LoadModule( rh->s.main_ltd_ram_address, rh->s.main_ltd_rom_offset, rh->s.main_ltd_size, rh->s.main_ltd_static_digest ) ) + { + return FALSE; + } + } + // load ARM7 extended static region + if ( rh->s.sub_ltd_size > 0 ) + { +#ifdef PROFILE_ENABLE + // 90: before PXI + pf_cnt = 0x90; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + if ( !MIi_LoadModule( rh->s.sub_ltd_ram_address, rh->s.sub_ltd_rom_offset, rh->s.sub_ltd_size, rh->s.sub_ltd_static_digest ) ) + { + return FALSE; + } + } +#ifdef PROFILE_ENABLE + // 9x: before PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); + profile[pf_cnt++] = (u32)PROFILE_PXI_SEND | FIRM_PXI_ID_AUTH_STATIC; // checkpoint +#endif + PXI_NotifyID( FIRM_PXI_ID_AUTH_STATIC ); + return TRUE; +} + +/*---------------------------------------------------------------------------* + Name: MI_Boot + + Description: boot + + ROMwb_̏ɁAOSi_BootĂяołB + + APIĂяoOɁAC̏̈ʒuROMwb_ + i[ĂKv܂B + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void MI_Boot( void ) +{ + OSi_Boot( rh->s.main_entry_address, (MIHeader_WramRegs*)rh->s.main_wram_config_data ); +} diff --git a/build/libraries/mi/Makefile b/build/libraries/mi/Makefile new file mode 100644 index 0000000..54d99b0 --- /dev/null +++ b/build/libraries/mi/Makefile @@ -0,0 +1,31 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - libraries - mi +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM9 + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/mi/common/mi_exDma.c b/build/libraries/mi/common/mi_exDma.c new file mode 100644 index 0000000..5fab0b0 --- /dev/null +++ b/build/libraries/mi/common/mi_exDma.c @@ -0,0 +1,286 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - mi + File: mi_init_mainMemory.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +static u16 intervalTable[] = +{ + 1, 1, 1, 1, +}; + +static u32 prescaleTable[] = +{ + MI_NDMA_INTERVAL_PS_1, + MI_NDMA_INTERVAL_PS_1, + MI_NDMA_INTERVAL_PS_1, + MI_NDMA_INTERVAL_PS_1, +}; + +//================================================================================ +// memory oparation using DMA (sync) +//================================================================================ + +/*---------------------------------------------------------------------------* + Name: MIi_ExDmaSendAsync + + Description: send data with DMA + async version + + Arguments: dmaNo : DMA channel No. + dest : destination address + src : source address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_ExDmaSendAsync( u32 dmaNo, const void *src, void *dest, u32 size ) +{ + u32 idx = dmaNo - MI_EXDMA_CH_MIN; + + { + u32 blockSize = MI_NDMA_BWORD_8; + u32 interval = intervalTable[idx]; + u32 prescale = prescaleTable[idx]; + + MIi_ExDmaSendAsyncCore( dmaNo, src, dest, size, size, + blockSize, interval, prescale, + MI_NDMA_CONTINUOUS_OFF, MI_NDMA_SRC_RELOAD_DISABLE, MI_NDMA_DEST_RELOAD_DISABLE, + MI_NDMA_IMM_MODE_ON ); + } +} + +/*---------------------------------------------------------------------------* + Name: MIi_ExDmaRecvAsync + + Description: receive data with DMA + async version + + Arguments: dmaNo : DMA channel No. + dest : destination address + src : source address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_ExDmaRecvAsync( u32 dmaNo, const void *src, void *dest, u32 size ) +{ + u32 idx = dmaNo - MI_EXDMA_CH_MIN; + + { + u32 blockSize = MI_NDMA_BWORD_8; + u32 interval = intervalTable[idx]; + u32 prescale = prescaleTable[idx]; + + MIi_ExDmaRecvAsyncCore( dmaNo, src, dest, size, size, + blockSize, interval, prescale, + MI_NDMA_CONTINUOUS_OFF, MI_NDMA_SRC_RELOAD_DISABLE, MI_NDMA_DEST_RELOAD_DISABLE, + MI_NDMA_IMM_MODE_ON ); + } +} + +//----------------- internel functions ------------------- + +/*---------------------------------------------------------------------------* + Name: MIi_ExDmaSendAsyncCore + + Description: send data with DMA + async version + + Arguments: dmaNo : DMA channel No. + dest : destination address + src : source address + size : size (byte) + blockSize : block size + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_ExDmaSendAsyncCore( u32 dmaNo, const void *src, void *dest, u32 size, u32 oneShotSize, + u32 blockSize, u32 interval, u32 prescale, + u32 continuous, u32 srcRld, u32 destRld, + u32 timing ) +{ + MIi_WaitExDma( dmaNo ); + + MIi_SetExDmaParams( dmaNo, src, dest, size, oneShotSize, + blockSize, interval, prescale, + continuous, srcRld, destRld, + timing, + 0, MI_NDMA_SRC_INC, MI_NDMA_DEST_FIX ); +} + +/*---------------------------------------------------------------------------* + Name: MIi_ExDmaRecvAsyncCore + + Description: receive data with DMA + async version + + Arguments: dmaNo : DMA channel No. + dest : destination address + src : source address + size : size (byte) + blockSize : block size + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_ExDmaRecvAsyncCore( u32 dmaNo, const void *src, void *dest, u32 size, u32 oneShotSize, + u32 blockSize, u32 interval, u32 prescale, + u32 continuous, u32 srcRld, u32 destRld, + u32 timing ) +{ + MIi_WaitExDma( dmaNo ); + + MIi_SetExDmaParams( dmaNo, src, dest, size, oneShotSize, + blockSize, interval, prescale, + continuous, srcRld, destRld, + timing, + 0, MI_NDMA_SRC_FIX, MI_NDMA_DEST_INC ); +} + +/*---------------------------------------------------------------------------* + Name: MIi_SetExDmaParams + + Description: set DMA + + Arguments: dmaNo : DMA channel No. + dest : destination address + src : source address + size : size (byte) + blockSize : block size + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_SetExDmaParams( u32 dmaNo, const void *src, void *dest, u32 size, u32 oneShotSize, + u32 blockSize, u32 interval, u32 prescale, + u32 continuous, u32 srcRld, u32 destRld, + u32 timing, + u32 fillData, u32 srcDir, u32 destDir ) +{ + u32 idx = dmaNo - MI_EXDMA_CH_MIN; + + if ( idx < MI_EXDMA_CH_NUM ) + { + OSIntrMode enabled = OS_DisableInterrupts(); + + MIExDmaChanRegs *reg = &((MIExDmaChanRegs*)REG_NDMA0SAD_ADDR)[idx]; + + reg->src = src; + reg->dest = dest; + reg->fillData = fillData; + reg->totalCount = size / 4; + reg->wordCount = oneShotSize / 4; + reg->blockInterval = (interval << REG_MI_NDMA0BCNT_ICNT_SHIFT) | prescale; + reg->ctrl = blockSize + | srcDir | destDir + | srcRld | destRld + | continuous + | timing + | MI_NDMA_ENABLE | MI_NDMA_IF_ENABLE; + + (void)OS_RestoreInterrupts(enabled); + } +} + +//================================================================================ +// DMA WAIT/STOP +//================================================================================ +/*---------------------------------------------------------------------------* + Name: MIi_IsExDmaBusy + + Description: check whether extended DMA is busy or not + + Arguments: dmaNo : DMA channel No. + + Returns: TRUE if extended DMA is busy, FALSE if not + *---------------------------------------------------------------------------*/ +BOOL MIi_IsExDmaBusy( u32 dmaNo ) +{ + u32 idx = dmaNo - MI_EXDMA_CH_MIN; + + if ( idx < MI_EXDMA_CH_NUM ) + { + MIExDmaChanRegs *reg = &((MIExDmaChanRegs*)REG_NDMA0SAD_ADDR)[idx]; + + return (BOOL)((reg->ctrl & REG_MI_NDMA0CNT_E_MASK) >> REG_MI_NDMA0CNT_E_SHIFT); + } + + return FALSE; +} + +/*---------------------------------------------------------------------------* + Name: MIi_WaitExDma + + Description: wait while extended DMA is busy + + Arguments: dmaNo : DMA channel No. + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_WaitExDma( u32 dmaNo ) +{ + u32 idx = dmaNo - MI_EXDMA_CH_MIN; + + if ( idx < MI_EXDMA_CH_NUM ) + { + MIExDmaChanRegs *reg = &((MIExDmaChanRegs*)REG_NDMA0SAD_ADDR)[idx]; + + while (reg->ctrl & REG_MI_NDMA0CNT_E_MASK) + { + } + } +} + +/*---------------------------------------------------------------------------* + Name: MIi_StopDma + + Description: stop extended DMA + + Arguments: dmaNo : DMA channel No. + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_StopExDma( u32 dmaNo ) +{ + MIi_StopExDmaAsync( dmaNo ); + MIi_WaitExDma( dmaNo ); +} + +/*---------------------------------------------------------------------------* + Name: MIi_StopDmaAsync + + Description: stop extended DMA + async version + + Arguments: dmaNo : DMA channel No. + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_StopExDmaAsync( u32 dmaNo ) +{ + OSIntrMode enabled = OS_DisableInterrupts(); + + u32 idx = dmaNo - MI_EXDMA_CH_MIN; + + if ( idx < MI_EXDMA_CH_NUM ) + { + MIExDmaChanRegs *reg = &((MIExDmaChanRegs*)REG_NDMA0SAD_ADDR)[idx]; + + reg->ctrl &= ~MI_NDMA_ENABLE; + } + + (void)OS_RestoreInterrupts(enabled); +} + diff --git a/build/libraries/os/ARM7/Makefile b/build/libraries/os/ARM7/Makefile new file mode 100644 index 0000000..8ebb450 --- /dev/null +++ b/build/libraries/os/ARM7/Makefile @@ -0,0 +1,62 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries_sp - os +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = +#SUBMAKES = Makefile.CALLTRACE \ +# Makefile.FUNCTIONCOST + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= TRUE + +# Codegen for sub processer +FIRM_PROC = ARM7 + +SRCDIR = ../common . + +SRCS = \ + os_init_firm.c \ + os_boot.c \ + +TARGET_LIB = libos_sp$(FIRM_LIBSUFFIX).a + + +#---------------------------------------------------------------------------- + +# DEBUGŃrh̏ꍇARELEASEłŃrh +# DEBUGł̃Cu𑕂܂B + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/os/ARM9/Makefile b/build/libraries/os/ARM9/Makefile new file mode 100644 index 0000000..2e55190 --- /dev/null +++ b/build/libraries/os/ARM9/Makefile @@ -0,0 +1,60 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries - os +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = +SUBMAKES = + + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= TRUE + +SRCDIR = ../common . + +SRCS = \ + os_init_firm.c \ + os_boot.c \ + os_cache_tag.c \ + +TARGET_LIB = libos$(FIRM_LIBSUFFIX).a + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + +ifdef NITRO_CALLTRACE +CCFLAGS += -DOS_PROFILE_AVAILABLE -DOS_PROFILE_CALL_TRACE +endif + +ifdef NITRO_FUNCTIONCOST +CCFLAGS += -DOS_PROFILE_AVAILABLE -DOS_PROFILE_FUNCTION_COST +endif + +ifdef NITRO_TCM_APPLY +CCFLAGS += -DSDK_TCM_APPLY +endif + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/libraries/os/ARM9/os_cache_tag.c b/build/libraries/os/ARM9/os_cache_tag.c new file mode 100644 index 0000000..cb16308 --- /dev/null +++ b/build/libraries/os/ARM9/os_cache_tag.c @@ -0,0 +1,269 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - OS + File: os_cache_tag.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include + + +//=========================================================================== +// DATA CACHE (for specified range) +//=========================================================================== +/*---------------------------------------------------------------------------* + Name: DC_ClearTagAll + + Description: clear tag in data cache + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +void DC_ClearTagAll( void ) +{ + DC_FillTagAll( 0 ); +} + +/*---------------------------------------------------------------------------* + Name: DC_FillTagAll + + Description: clear tag in data cache + + Arguments: data : fill data + + Returns: None. + *---------------------------------------------------------------------------*/ +asm void DC_FillTagAll( u32 data ) +{ + mov r12, #0 +@1: + mov r2, #0 +@2: + orr r3, r2, r12 + mcr p15, 3, r3, c15, c0, 0 // set index + mcr p15, 3, r0, c15, c2, 0 // clear tag + add r2, r2, #HW_CACHE_LINE_SIZE + cmp r2, #HW_DCACHE_SIZE/4 + blt @2 + + add r12, r12, #1< diff --git a/build/libraries/os/Makefile b/build/libraries/os/Makefile new file mode 100644 index 0000000..a61613f --- /dev/null +++ b/build/libraries/os/Makefile @@ -0,0 +1,32 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries - os +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM9 \ + ARM7 \ + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/os/common/os_boot.c b/build/libraries/os/common/os_boot.c new file mode 100644 index 0000000..103efb1 --- /dev/null +++ b/build/libraries/os/common/os_boot.c @@ -0,0 +1,219 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - OS + File: os_boot.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include +#include +#ifdef SDK_ARM9 +#include +#else +#include +#endif + +#if 0 + ۑ: + OSi_BootCorẽRs[挈 + + 낢NA (ITCM,DTCM,STACK,TEXT,RODATA,DATAȂ (OSi_BootCore͎c)) + Ȃ̂ŁAOSi_BootCorẽ͎vOłɉ󂳂ꂻȂƂg +#endif + +void OSi_BootCore( OSEntryPoint p, MIHeader_WramRegs* w ); + +/*---------------------------------------------------------------------------* + Name: OSi_Boot + + Description: boot firm + + Arguments: entry : entry point + w : wram settings + + Returns: None + *---------------------------------------------------------------------------*/ +void OSi_Boot( void* entry, MIHeader_WramRegs* w ) +{ + OSEntryPoint p = (OSEntryPoint)entry; + void (*OSBootCore)( OSEntryPoint p, MIHeader_WramRegs* w ); + + (void)OS_DisableInterrupts(); + OSi_Finalize(); + +#ifdef SDK_ARM9 + OSBootCore = (void*)HW_ITCM; +#else // SDK_ARM7 + OSBootCore = (void*)(HW_PRV_WRAM_SVC_STACK - 0x200); +#endif // SDK_ARM7 + + MI_CpuCopyFast( OSi_BootCore, OSBootCore, 0x200 ); + + OSBootCore(p, w); +} + +/*---------------------------------------------------------------------------* + Name: OSi_Finalize + + Description: finalize + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void OSi_Finalize(void) +{ + (void)OS_DisableInterrupts(); + (void)OS_DisableIrq(); + reg_OS_IE = 0; + reg_OS_IF = 0xffffffff; +#ifdef SDK_ARM7 + reg_OS_IE2 = 0; + reg_OS_IF2 = 0xffff; + // set init check flag by bootrom + SVC_CpuClear( REG_OS_PAUSE_CHK_MASK, (void*)REG_PAUSE_ADDR, sizeof(u16), 16 ); +#else // SDK_ARM9 + // set init check flag + reg_OS_PAUSE = REG_OS_PAUSE_CHK_MASK; + *(u64*)HW_INIT_LOCK_BUF = 0; + + DC_Disable(); + DC_FlushAll(); + DC_WaitWriteBufferEmpty(); + IC_Disable(); + IC_InvalidateAll(); + + // clear cache + IC_ClearTagAll(); + IC_ClearInstructionAll(); + DC_ClearTagAll(); + DC_ClearDataAll(); + + OS_DisableProtectionUnit(); +#endif // SDK_ARM9 +} + +extern void SDK_STATIC_DATA_START(void); // static data start address +extern void SDK_STATIC_BSS_END(void); // static bss end address + +/*---------------------------------------------------------------------------* + Name: OSi_ClearWorkArea + + Description: clear work area + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +#include +asm void OSi_ClearWorkArea( void ) +{ + mov r11, lr + + // clear stack with r4-r9 + mov r0, #0 + ldr r1, =SDK_STATIC_DATA_START + ldr r2, =SDK_STATIC_BSS_END + sub r2, r2, r1 + bl MIi_CpuClearFast + + bx r11 +} + +asm void OSi_BootCore( OSEntryPoint p, MIHeader_WramRegs* w ) +{ + mov r11, r0 + mov r10, r1 + +#ifdef SDK_ARM9 + + // wait for request of wram map + ldr r3, =REG_SUBPINTF_ADDR + mov r2, #REG_PXI_SUBPINTF_A7STATUS_MASK +@0: + ldr r0, [r3] + and r0, r0, r2 + cmp r0, r2 + bne @0 + + // r10- => r9-r2 + ldr r9, =REG_MBK1_ADDR + add r2, r9, #32 +@1: + ldr r3, [r10], #4 + str r3, [r9], #4 + cmp r9, r2 + blt @1 + + // notify wram map + ldr r3, =REG_SUBPINTF_ADDR + mov r0, #REG_PXI_SUBPINTF_A9STATUS_MASK + str r0, [r3] + // wait for finalizing pxi + ldr r3, =REG_SUBPINTF_ADDR +@2: + ldr r0, [r3] + and r0, r0, #REG_PXI_SUBPINTF_A7STATUS_MASK + cmp r0, #0 + bne @2 + // finalize pxi + mov r0, #0 + str r0, [r3] + +#else // ARM7 + + // request wram map + ldr r3, =REG_MAINPINTF_ADDR + mov r0, #REG_PXI_MAINPINTF_A7STATUS_MASK + str r0, [r3] + // wait for wram map + mov r2, #REG_PXI_MAINPINTF_A9STATUS_MASK +@0: + ldr r0, [r3] + and r0, r0, r2 + cmp r0, r2 + bne @0 + // finalize pxi + mov r0, #0 + str r0, [r3] + + // r10- => r9-r2 + add r10, r10, #32 + ldr r9, =REG_MBK6_ADDR + add r2, r9, #15 +@1: + ldr r3, [r10], #4 + str r3, [r9], #4 + cmp r9, r2 + blt @1 + +#endif + + // clear stack with r4-r9 + mov r0, #0 +#if 0 + ldr r1, =HW_FIRM_STACK + ldr r2, =HW_FIRM_STACK_SIZE + bl MIi_CpuClearFast +#endif + + mov lr, r11 + + // clear registers +#if 0 + ldr sp, =HW_FIRM_STACK + ldmia sp, {r0-r12,sp} +#endif + + bx lr +} diff --git a/build/libraries/os/common/os_init_firm.c b/build/libraries/os/common/os_init_firm.c new file mode 100644 index 0000000..7359313 --- /dev/null +++ b/build/libraries/os/common/os_init_firm.c @@ -0,0 +1,148 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - OS + File: os_init_firm.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include + +/*---------------------------------------------------------------------------* + Name: OS_InitNOR + + Description: initialize sdk os for firm + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +#pragma profile off +void OS_InitFIRM(void) +{ +#ifdef SDK_ARM9 + //---- system shared area check +// SDK_ASSERT((u32)&(OS_GetSystemWork()->command_area) == HW_CMD_AREA); + + //---------------------------------------------------------------- + // for ARM9 + +#ifdef SDK_ENABLE_ARM7_PRINT + // Init PrintServer for ARM7 (if specified) +// OS_InitPrintServer(); +#endif + + //---- Init interProcessor I/F + // Sync with ARM7 to enable OS_GetConsoleType() + // PXI_Init() must be called before OS_InitArenaEx() + //PXI_Init(); + PXI_InitFifoFIRM(); + + //---- Init Arena (arenas except SUBPRIV-WRAM) + OS_InitArena(); + + //---- Init Spinlock + OS_InitLock(); + + //---- Init Arena (extended main) + OS_InitArenaEx(); + + //---- Init IRQ Table + OS_InitIrqTable(); + + //---- Init IRQ Stack checker + OS_SetIrqStackChecker(); + + //---- Init Exception System +// OS_InitException(); + + //---- Init MI (Wram bank and DMA0 arranged) + MI_Init(); + + //---- Init VCountAlarm + OS_InitVAlarm(); + + //---- Init VRAM exclusive System + OSi_InitVramExclusive(); + + //---- Init Thread System +#ifndef SDK_NO_THREAD + OS_InitThread(); +#endif + //---- Init Reset System +#ifndef SDK_SMALL_BUILD +// OS_InitReset(); +#endif + + //---- Init Cartridge +#ifndef SDK_TEG +// CTRDG_Init(); +#endif + + //---- Init Card +#ifndef SDK_SMALL_BUILD +// CARD_Init(); +#endif + + //---- Init Power Manager +#ifndef SDK_TEG +// PM_Init(); +#endif + + //---- adjust VCOUNT +// OSi_WaitVCount0(); + +#else // SDK_ARM9 + //---------------------------------------------------------------- + // for ARM7 + + //---- Init interProcessor I/F + //PXI_Init(); + PXI_InitFifoFIRM(); + + //---- Init Arena (SUBPRIV-WRAM arena) + OS_InitArena(); + + //---- Init Spinlock + OS_InitLock(); + + //---- Init IRQ Table + OS_InitIrqTable(); + +#define SDK_EXCEPTION_BUG +#ifndef SDK_EXCEPTION_BUG + //---- Init Exception System + OS_InitException(); +#endif + + //---- Init Tick + OS_InitTick(); + + //---- Init Alarm System + OS_InitAlarm(); + + //---- Init Thread System + OS_InitThread(); + + //---- Init Reset System +#ifndef SDK_SMALL_BUILD +// OS_InitReset(); +#endif + + //---- Init Cartridge +#ifndef SDK_TEG +// CTRDG_Init(); +#endif + +#endif // SDK_ARM9 +} + +#pragma profile reset diff --git a/build/libraries/pm/ARM7/Makefile b/build/libraries/pm/ARM7/Makefile new file mode 100644 index 0000000..124e3af --- /dev/null +++ b/build/libraries/pm/ARM7/Makefile @@ -0,0 +1,62 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries - pm +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = +SUBMAKES = + + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= TRUE + +# Codegen for sub processer +FIRM_PROC = ARM7 + +INCDIR = $(TWLSDK_ROOT)/build/libraries/spi/ARM7/pm/include \ + +SRCDIR = . + +SRCS = \ + pm_init.c \ + pm_pmic_ex.c \ + +TARGET_LIB = libpm_sp$(FIRM_LIBSUFFIX).a + +#---------------------------------------------------------------------------- + +# DEBUGŃrh̏ꍇARELEASEłŃrh +# DEBUGł̃Cu𑕂܂B + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/libraries/pm/ARM7/pm_init.c b/build/libraries/pm/ARM7/pm_init.c new file mode 100644 index 0000000..00cb2f1 --- /dev/null +++ b/build/libraries/pm/ARM7/pm_init.c @@ -0,0 +1,88 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - pm + File: pm_init.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include + +static BOOL doneBackLight = FALSE; + +/*---------------------------------------------------------------------------* + Name: PM_InitFIRM + + Description: set default parameters + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void PM_InitFIRM( void ) +{ + // LED + PMi_ResetFlags( REG_PMIC_LED_CTL_ADDR, PMIC_LED_CTL_AUTO_BLINK | PMIC_LED_CTL_BLINK_BY_SLEEP ); + PMi_SetParams( REG_PMIC_LVL4_BRT_ADDR, + PMIC_LED_1_BRT_LEVEL_4_OFF | PMIC_LED_2_BRT_LEVEL_4_OFF, + PMIC_LVL4_BRT_LED_1_MASK | PMIC_LVL4_BRT_LED_2_MASK + ); + PMi_SetParams( REG_PMIC_LVL3_BRT_ADDR, + PMIC_LED_1_BRT_LEVEL_3_100 | PMIC_LED_2_BRT_LEVEL_3_OFF, + PMIC_LVL3_BRT_LED_1_MASK | PMIC_LVL3_BRT_LED_2_MASK + ); + PMi_SetParams( REG_PMIC_LVL2_BRT_ADDR, + PMIC_LED_1_BRT_LEVEL_2_OFF | PMIC_LED_1_BRT_LEVEL_2_100, + PMIC_LVL2_BRT_LED_1_MASK | PMIC_LVL2_BRT_LED_2_MASK + ); + PMi_SetParams( REG_PMIC_LVL1_BRT_ADDR, + PMIC_LED_1_BRT_LEVEL_1_100 | PMIC_LED_2_BRT_LEVEL_1_100, + PMIC_LVL1_BRT_LED_1_MASK | PMIC_LVL1_BRT_LED_2_MASK + ); + + // LCD ON + PMi_SetFlags( REG_PMIC_CTL2_ADDR, PMIC_CTL2_VDD50 ); + + // back light + PMi_SetParams( REG_PMIC_BL_BRT_A_ADDR, PMIC_BACKLIGHT_BRIGHT_MAX, PMIC_BL_BRT_A_MASK ); // TODO: less brightness + PMi_SetParams( REG_PMIC_BL_BRT_B_ADDR, PMIC_BACKLIGHT_BRIGHT_MAX, PMIC_BL_BRT_B_MASK ); // TODO: less brightness +} + +/*---------------------------------------------------------------------------* + Name: PM_BackLightOn + + Description: power B/L on if not set yet + + Arguments: force TRUE: wait until valid condition + FALSE not set unless valid condition + + Returns: None + *---------------------------------------------------------------------------*/ +void PM_BackLightOn( BOOL force ) +{ + if ( doneBackLight ) + { + return; // have already set + } + if ( force ) + { + while ( (reg_GX_DISPSTAT & REG_GX_DISPSTAT_INI_MASK) == FALSE ) + { + } + } + if ( reg_GX_DISPSTAT & REG_GX_DISPSTAT_INI_MASK ) + { + PMi_SetFlags( REG_PMIC_CTL2_ADDR, PMIC_CTL2_BACK_LIGHT_1 | PMIC_CTL2_BACK_LIGHT_2 ); + doneBackLight = TRUE; + } +} diff --git a/build/libraries/pm/ARM7/pm_pmic_ex.c b/build/libraries/pm/ARM7/pm_pmic_ex.c new file mode 100644 index 0000000..5932fa0 --- /dev/null +++ b/build/libraries/pm/ARM7/pm_pmic_ex.c @@ -0,0 +1,72 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - pm + File: pm_pmic_ex.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +#include + +//================================================================================ +// PMIC BIT CONTROL +//================================================================================ +/*---------------------------------------------------------------------------* + Name: PMi_SetParams + + Description: set control bit to device register + + Arguments: reg : device register + setBits : bits to set + maskBits : bits to mask + + Returns: None + *---------------------------------------------------------------------------*/ +void PMi_SetParams( u8 reg, u8 setBits, u8 maskBits ) +{ + u8 tmp; + tmp = PMi_GetRegister( reg ); + tmp &= ~maskBits; + setBits &= maskBits; + tmp |= setBits; + PMi_SetRegister( reg, tmp ); +} + +/*---------------------------------------------------------------------------* + Name: PMi_SetFlags + + Description: set control bit to device register + + Arguments: reg : device register + setBits : bits to set + + Returns: None + *---------------------------------------------------------------------------*/ +void PMi_SetFlags( u8 reg, u8 setBits ) +{ + PMi_SetParams( reg, setBits, setBits ); +} + +/*---------------------------------------------------------------------------* + Name: PMi_ResetFlags + + Description: clear control bit to device register + + Arguments: reg : device register + clrBits : bits to set + + Returns: None + *---------------------------------------------------------------------------*/ +void PMi_ResetFlags( u8 reg, u8 clrBits ) +{ + PMi_SetParams( reg, 0, clrBits ); +} + diff --git a/build/libraries/pm/Makefile b/build/libraries/pm/Makefile new file mode 100644 index 0000000..4d2df08 --- /dev/null +++ b/build/libraries/pm/Makefile @@ -0,0 +1,31 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - libraries - pm +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM7 + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/pxi/ARM7/Makefile b/build/libraries/pxi/ARM7/Makefile new file mode 100644 index 0000000..72fd9f6 --- /dev/null +++ b/build/libraries/pxi/ARM7/Makefile @@ -0,0 +1,61 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries_sp - pxi +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = +#SUBMAKES = Makefile.CALLTRACE \ +# Makefile.FUNCTIONCOST + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= TRUE + +# Codegen for sub processer +FIRM_PROC = ARM7 + +SRCDIR = ../common . + +SRCS = \ + pxi_misc.c \ + +TARGET_LIB = libpxi_sp$(FIRM_LIBSUFFIX).a + + +#---------------------------------------------------------------------------- + +# DEBUGŃrh̏ꍇARELEASEłŃrh +# DEBUGł̃Cu𑕂܂B + +ifdef NITRO_DEBUG +NITRO_BUILD_TYPE = RELEASE +endif + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/pxi/ARM9/Makefile b/build/libraries/pxi/ARM9/Makefile new file mode 100644 index 0000000..52fe444 --- /dev/null +++ b/build/libraries/pxi/ARM9/Makefile @@ -0,0 +1,58 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries - pxi +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = +SUBMAKES = + + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +FIRM_CODEGEN_ALL ?= TRUE + +SRCDIR = ../common . + +SRCS = \ + pxi_misc.c \ + +TARGET_LIB = libpxi$(FIRM_LIBSUFFIX).a + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(FIRM_INSTALL_LIBDIR) + +ifdef NITRO_CALLTRACE +CCFLAGS += -DOS_PROFILE_AVAILABLE -DOS_PROFILE_CALL_TRACE +endif + +ifdef NITRO_FUNCTIONCOST +CCFLAGS += -DOS_PROFILE_AVAILABLE -DOS_PROFILE_FUNCTION_COST +endif + +ifdef NITRO_TCM_APPLY +CCFLAGS += -DSDK_TCM_APPLY +endif + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/libraries/pxi/Makefile b/build/libraries/pxi/Makefile new file mode 100644 index 0000000..8410a70 --- /dev/null +++ b/build/libraries/pxi/Makefile @@ -0,0 +1,32 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - libraries - pxi +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM9 \ + ARM7 \ + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries/pxi/common/pxi_misc.c b/build/libraries/pxi/common/pxi_misc.c new file mode 100644 index 0000000..7804e4b --- /dev/null +++ b/build/libraries/pxi/common/pxi_misc.c @@ -0,0 +1,352 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - library - pxi + File: pxi_misc.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +#include +#include + +static u16 FifoCtrlInit = 0; + +/*********** function prototypes ******************/ +static inline PXIFifoStatus PXIi_GetFromFifo(u32 *data_buf); +static inline PXIFifoStatus PXIi_SetToFifo(u32 data); + + +/*---------------------------------------------------------------------------* + Name: PXI_InitFifoFIRM + + Description: initialize FIFO system for firm + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void PXI_InitFifoFIRM(void) +{ + OSIntrMode enabled; + + enabled = OS_DisableInterrupts(); + + if (!FifoCtrlInit) + { + FifoCtrlInit = TRUE; + + reg_PXI_FIFO_CNT = + (REG_PXI_FIFO_CNT_SEND_CL_MASK | + REG_PXI_FIFO_CNT_E_MASK | REG_PXI_FIFO_CNT_ERR_MASK); + +#ifdef SDK_ARM9 + PXI_SendIDByIntf( FIRM_PXI_ID_INIT_ARM9 ); + PXI_WaitIDByIntf( FIRM_PXI_ID_INIT_ARM7 ); +#else // SDK_ARM7 + PXI_SendIDByIntf( FIRM_PXI_ID_INIT_ARM7 ); + PXI_WaitIDByIntf( FIRM_PXI_ID_INIT_ARM9 ); +#endif // SDK_ARM7 + } + (void)OS_RestoreInterrupts(enabled); +} + + +/*---------------------------------------------------------------------------* + Name: PXI_NotifyID + + Description: Send 4bit id to other processor + + Arguments: id notifying id + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_NotifyID( u32 id ) +{ + PXI_SendIDByFifo( PXI_FIFO_TAG_SYSTEM, id ); +} + +/*---------------------------------------------------------------------------* + Name: PXI_WaitID + + Description: Wait 4bit id from the other processor + + Arguments: id waiting id + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_WaitID( u32 id ) +{ + PXI_WaitIDByFifo( PXI_FIFO_TAG_SYSTEM, id ); +} + +/*---------------------------------------------------------------------------* + Name: PXI_RecvID + + Description: Receive 4bit id from the other processor + + Arguments: None + + Returns: id + *---------------------------------------------------------------------------*/ +u8 PXI_RecvID( void ) +{ + u8 id; + + while (PXI_RecvIDByFifo(PXI_FIFO_TAG_SYSTEM, &id) != PXI_FIFO_SUCCESS) + { + } + + return id; +} + +/*---------------------------------------------------------------------------* + Name: PXI_SendIDByIntf + + Description: Send 4bit id to the other processor + + Arguments: id sending id + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_SendIDByIntf( u32 id ) +{ + reg_PXI_INTF = (u16)(id << REG_PXI_INTF_SEND_SHIFT); +} + +/*---------------------------------------------------------------------------* + Name: PXI_RecvIDByIntf + + Description: Receive 4bit id from the other processor + + Arguments: None + + Returns: received id + *---------------------------------------------------------------------------*/ +u32 PXI_RecvIDByIntf( void ) +{ + return (u32)((reg_PXI_INTF & REG_PXI_INTF_RECV_MASK) >> REG_PXI_INTF_RECV_SHIFT); +} + +/*---------------------------------------------------------------------------* + Name: PXI_WaitIDByIntf + + Description: Wait 4bit id from the other processor + + Arguments: id waiting id + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_WaitIDByIntf( u32 id ) +{ + while (PXI_RecvIDByIntf() != id) + { + } +} + +/*---------------------------------------------------------------------------* + Name: PXI_SendIDByFifo + + Description: Send 32bit-word to another CPU via FIFO + + Arguments: + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_SendIDByFifo(PXIFifoTag tag, u32 id) +{ + static PXIFifoMessage fifomsg; + + fifomsg.e.tag = tag; + fifomsg.e.data = id; + + while ( PXIi_SetToFifo(fifomsg.raw) != PXI_FIFO_SUCCESS ) + { + } +} + +/*---------------------------------------------------------------------------* + Name: PXI_RecvIDByFifo + + Description: Recv 32bit-word from another CPU via FIFO + + Arguments: + + Returns: if error occured, returns minus value + *---------------------------------------------------------------------------*/ +PXIFifoStatus PXI_RecvIDByFifo(PXIFifoTag tag, void* buf) +{ + static PXIFifoMessage fifomsg; + u8* p = buf; + + while ( PXIi_GetFromFifo(&fifomsg.raw) != PXI_FIFO_SUCCESS ) + { + } + + if (fifomsg.e.tag != tag) + { + return PXI_FIFO_FAIL_RECV_ERR; + } + + *p = (u8)fifomsg.e.data; + + return PXI_FIFO_SUCCESS; +} + +/*---------------------------------------------------------------------------* + Name: PXI_WaitIDByFifo + + Description: Wait 32bit-word from another CPU via FIFO + + Arguments: id waiting id + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_WaitIDByFifo(PXIFifoTag tag, u32 id) +{ + u8 buf = (u8)id; + + do + { + while (PXI_RecvIDByFifo(tag, &buf) != PXI_FIFO_SUCCESS) + { + } + } + while ( buf != id ); +} + +/*---------------------------------------------------------------------------* + Name: PXI_SendDataByFifo + + Description: Send data to another CPU via FIFO + + Arguments: + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_SendDataByFifo(PXIFifoTag tag, void* buf, int size) +{ + static PXIFifoMessage fifomsg; + u32* p = buf; + int len = size/4; + int i; + + fifomsg.e.tag = tag; + fifomsg.e.data = len; + + while ( PXIi_SetToFifo(fifomsg.raw) != PXI_FIFO_SUCCESS ) + { + } + + for ( i=0; i max_size/4) + { + return PXI_FIFO_FAIL_SEND_ERR; + } + + for ( i=0; i9UPLKl-oJ0Z1jw4VCIv;^!KtoB#akvL>c2^Pp z35fzBG$YNv_3X@g{Jipb0GR1+IRVB1hE&05#GylEU9=@pu$&N$+hdJQzMjk$WwC8} ztKly)Anz{54HkI79h&d&@Z!9=UX*E?>!;}~?)K`*sbjyQ?98mgvz8y`lHUto4wHD)Q5jGM z>I@wC%dyn|tN#AK9;8>wfHLr}7%+o$mQMLdp|-XjPHL^C&Z#2eS9#oraNRvu}g=#PM-K?h~vR~h&OVTo># literal 0 HcmV?d00001 diff --git a/build/libraries_sysmenu/Makefile b/build/libraries_sysmenu/Makefile new file mode 100644 index 0000000..2843115 --- /dev/null +++ b/build/libraries_sysmenu/Makefile @@ -0,0 +1,32 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +TARGET_FIRM = SYSTEMMENU + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +SUBDIRS = sysmenu mb_loader acsign + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries_sysmenu/acsign/ARM9/Makefile b/build/libraries_sysmenu/acsign/ARM9/Makefile new file mode 100644 index 0000000..f921383 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/Makefile @@ -0,0 +1,57 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- + +SUBDIRS = + + +#---------------------------------------------------------------------------- +TARGET_FIRM = SYSTEMMENU +TARGET_PLATFORM = TWL +TWL_ARCHGEN = LIMITED +TWL_PROC = ARM9 + +INCDIR = include \ + $(TWLSDK_ROOT)/build/libraries/mb/common/include + +SRCS = acsign.c acmemory.c acsign_util.c + +TARGET_LIB = libacsign$(TWL_LIBSUFFIX).a + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(SYSMENU_INSTALL_LIBDIR) + +CCFLAGS += -DSMALL_CODE_SIZE \ + -DSTANDALONE \ + -DOPT_32_BIT \ + -DNO_SPLIT \ + -DNO_FP_API \ + -DNO_R_DIAG \ + -DNO_STDIO_H \ + -DNO_STDLIB_H + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/libraries_sysmenu/acsign/ARM9/include/acmemory.h b/build/libraries_sysmenu/acsign/ARM9/include/acmemory.h new file mode 100644 index 0000000..8247764 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/include/acmemory.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: acmemory.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef _ACMEMORY_H_ +#define _ACMEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// +void ACMemory_Clear( ); +void* ACMemory_Alloc( u32 size ); +void ACMemory_Free( void* adrs ); +void* ACMemory_Memset( void* adrs, u32 val, u32 cnt ); +void* ACMemory_Memcpy( void* dst, void* src, u32 cnt ); + +#ifdef __cplusplus +} +#endif + +#endif //_ACMEMORY_H_ diff --git a/build/libraries_sysmenu/acsign/ARM9/include/bn.h b/build/libraries_sysmenu/acsign/ARM9/include/bn.h new file mode 100644 index 0000000..ed99275 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/include/bn.h @@ -0,0 +1,1136 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#ifndef HEADER_COMMON_BN_H +#define HEADER_COMMON_BN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef FLAT_INC +#include "r_types.h" +#else +#include "../include/r_types.h" +#endif + +#if !defined(CCONV) +#define CCONV +#endif + +#ifndef PRE_CCONV +#define PRE_CCONV +#endif + +/* convert from the new to the old option names */ +#if defined(OPT_BN_LLONG) +#define BN_LLONG /* comment to make sure Configure leaves this alone */ +#endif + +#if defined(OPT_BN_MUL_LATENCY) +#define BN_MUL_LATENCY +#endif + +/* by default we have the following switched on - unless we have an option + * that switched them off for a specific platform + */ +#ifdef OPT_NO_COMBA +#define OPT_NO_BN_MUL_COMBA +#define OPT_NO_BN_SQR_COMBA +#endif + +#ifdef OPT_NO_REC +#define OPT_NO_BN_RECURSION_MUL +#define OPT_NO_BN_RECURSION_SQR +#endif + +#ifndef OPT_NO_BN_MUL_COMBA +#define BN_MUL_COMBA +#endif +#ifndef OPT_NO_BN_SQR_COMBA +#define BN_SQR_COMBA +#endif +#ifndef OPT_NO_BN_RECURSION_MUL +#define BN_RECURSION_MUL +#endif +#ifndef OPT_NO_BN_RECURSION_SQR +#define BN_RECURSION_SQR +#endif +#ifndef OPT_NO_BN_RECURSION_MONT +#undef BN_RECURSION_MONT /* DO NOT TURN THIS ON, IT IS BROKEN */ +#endif + +#if (!defined(OPT_NO_BN_MUL_COMBA) && !defined(OPT_NO_BN_SQR_COMBA)) +#if OPT_MONT_REDUCE_COMBA /* TEMP UNTIL C IS IMPLEMENTED-DEF'd ON PLATFORMS W/ ASM */ +#define BN_REDUCE_COMBA +#endif +#endif + +#define RECP_MUL_MOD +#define MONT_MUL_MOD + +#ifndef OPT_NO_BN_SURRENDER +#define BN_SURRENDER +#else +#undef BN_SURRENDER +#endif + +#ifdef SMALL_CODE_SIZE +#undef BN_MUL_COMBA /* stop modification */ +#undef BN_SQR_COMBA /* stop modification */ +#undef BN_REDUCE_COMBA /* stop modification */ +#undef BN_RECURSION_MUL /* stop modification */ +#undef BN_RECURSION_SQR /* stop modification */ +#undef BN_RECURSION_MONT /* stop modification */ +#endif + + + +/* This next option uses the C libraries (2 word)/(1 word) function. + * If it is not defined, I use my C version (which is slower). + * The reason for this flag is that when the particular C compiler + * library routine is used, and the library is linked with a different + * compiler, the library is missing. This mostly happens when the + * library is built with gcc and then linked using nornal cc. This would + * be a common occurance because gcc normally produces code that is + * 2 times faster than system compilers for the big number stuff. + * For machines with only one compiler (or shared libraries), this should + * be on. Again this in only really a problem on machines + * using "long long's", are 32bit, and are not using my assember code. */ +#if defined(MSDOS) || defined(WINDOWS) || defined(linux) +#define BN_DIV2W +#endif + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debuging the bignum libraries */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#undef SIXTY_BIT +#undef THIRTY_TWO_BIT +#undef THIRTY_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#undef TEST_EIGHT_BIT + +#if defined(OPT_64_BIT_LONG) +#define SIXTY_FOUR_BIT_LONG +#endif +#if defined(OPT_64_BIT) +#define SIXTY_FOUR_BIT +#endif +#if defined(OPT_60_BIT) +#define SIXTY_BIT +#endif +#if defined(OPT_32_BIT) +#define THIRTY_TWO_BIT +#endif +#if defined(OPT_32_BIT_INT) +#define THIRTY_TWO_BIT +#endif +#if defined(OPT_30_BIT) +#define THIRTY_BIT +#endif +#if defined(OPT_16_BIT) +#define SIXTEEN_BIT +#endif +#if defined(OPT_8_BIT) +#define EIGHT_BIT +#endif +#if defined(OPT_8_BIT_TEST) +#define TEST_EIGHT_BIT +#endif + +/* This define is used for those few functions that 'break' when + * things are compiled for 8 bit words. Basically the size of an + * integer. + */ +#define BN_ILONG BN_ULONG + +/* assuming long is 64bit - this is the DEC Alpha + * unsigned long long is only 64 bits, don't define + * BN_LLONG for the DEC Alpha */ +#ifdef SIXTY_FOUR_BIT_LONG +#undef BN_LLONG +#define BN_ULLONG unsigned long long +#define BN_ULONG unsigned long +#define BN_LONG long +#define BN_BITS 128 +#define BN_BYTES 8 +#define BN_BITS2 64 +#define BN_BITS4 32 +#define BN_MASK (0xffffffffffffffffffffffffffffffffLL) +#define BN_MASK2 (0xffffffffffffffffL) +#define BN_MASK2l (0xffffffffL) +#define BN_MASK2lh (0xffffffffL) +#define BN_MASK2h (0xffffffff00000000L) +#define BN_MASK2h1 (0xffffffff80000000L) +#define BN_TBIT (0x8000000000000000L) +#define BN_DEC_CONV (10000000000000000000UL) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%019lu" +#define BN_DEC_NUM 19 +#define BN_HEX_FMT "%016lX" +#endif + +/* This is where the long long data type is 64 bits, but long is 32. + * For machines where there are 64bit registers, this is the mode to use. + * IRIX, on R4000 and above should use this mode, along with the relevent + * assember code. Do NOT define BN_LLONG. + */ +#ifdef SIXTY_FOUR_BIT +#undef BN_LLONG /* Protect against config */ +/* #define BN_ULLONG unsigned long long */ +#ifdef WIN64 +#define BN_ULONG unsigned _int64 +#define BN_LONG _int64 +#else +#define BN_ULONG unsigned long long +#define BN_LONG long long +#endif +#define BN_BITS 128 +#define BN_BYTES 8 +#define BN_BITS2 64 +#define BN_BITS4 32 +#define BN_MASK2 (0xffffffffffffffffLL) +#define BN_MASK2l (0xffffffffL) +#define BN_MASK2lh (0xffffffffL) +#define BN_MASK2h (0xffffffff00000000LL) +#define BN_MASK2h1 (0xffffffff80000000LL) +#define BN_TBIT (0x8000000000000000LL) +#define BN_DEC_CONV (10000000000000000000ULL) +#ifdef WIN64 +#define BN_DEC_FMT1 "%I64u" +#define BN_DEC_FMT2 "%019I64u" +#define BN_DEC_NUM 19 +#define BN_HEX_FMT "%016I64X" +#else +#define BN_DEC_FMT1 "%llu" +#define BN_DEC_FMT2 "%019llu" +#define BN_DEC_NUM 19 +#define BN_HEX_FMT "%016llX" +#endif +#endif + +#ifdef SIXTY_BIT +#undef SIXTY_FOUR_BIT +#undef BN_LLONG /* Protect against config */ +/* #define BN_ULLONG unsigned long long */ +#define BN_ULONG unsigned long long +#define BN_LONG long long +#define BN_BITS 120 +#define BN_BITS2 60 +#define BN_BITS4 30 +#define BN_MASK2 (0x0fffffffffffffffLL) +#define BN_MASK2l ( 0x3fffffffL) +#define BN_MASK2lh ( 0x3fffffffL) +#define BN_MASK2h (0x0fffffffc0000000LL) +#define BN_MASK2h1 (0x0fffffffe0000000LL) +#define BN_TBIT (0x0800000000000000LL) +#define BN_DEC_CONV (100000000000000000LL) +#define BN_DEC_FMT1 "%9u" +#define BN_DEC_FMT2 "%017llu" +#define BN_DEC_NUM 17 +#define BN_HEX_FMT "%016llX" +#endif + +#ifdef THIRTY_TWO_BIT +#ifdef WIN32 +#if defined(__BORLANDC__) +#define BN_ULLONG unsigned __int64 +#else /* !__BORLANDC__ */ +#if defined(__MINGW32__) || defined(__DJGPP__) +#define BN_ULLONG unsigned long long +#else +#define BN_ULLONG unsigned _int64 +#endif /* __MINGW32__ || __DJGPP__ */ +#endif /* __BORLANDC__ */ +#else /* !WIN32 */ +#define BN_ULLONG unsigned long long +#endif /* WIN32 */ +#ifdef OPT_32_BIT_INT +#define BN_ULONG unsigned int +#define BN_LONG int +#else +#define BN_ULONG unsigned long +#define BN_LONG long +#endif +#define BN_BITS 64 +#define BN_BYTES 4 +#define BN_BITS2 32 +#define BN_BITS4 16 +/* This is needed because the Watcom compiler pre-processor + * under QNX tries to parses the 'LL' part even though it is + * never used. + */ +#ifdef BN_LLONG +#ifndef WIN32 +#define BN_MASK (0xffffffffffffffffLL) +#else +#define BN_MASK (0xffffffffffffffffL) +#endif +#endif +#define BN_MASK2 (0xffffffffL) +#define BN_MASK2l (0xffff) +#define BN_MASK2lh (0xffff) +#define BN_MASK2h1 (0xffff8000L) +#define BN_MASK2h (0xffff0000L) +#define BN_TBIT (0x80000000L) +#define BN_DEC_CONV (1000000000L) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%09lu" +#define BN_DEC_NUM 9 +#define BN_HEX_FMT "%08lX" +#endif + +#ifdef THIRTY_BIT +#ifdef WIN32 +#if defined(__MINGW32__) || defined(__DJGPP__) +#define BN_ULLONG unsigned long long +#else /* ! (__MINGW32__ || __DJGPP__) */ +#define BN_ULLONG unsigned _int64 +#endif /* __MINGW32__ || __DJGPP__ */ +#else /* !WIN32 */ +#define BN_ULLONG unsigned long long +#endif /* WIN32 */ +#define BN_ULONG unsigned long +#define BN_LONG long +#define BN_BITS 60 +#define BN_BITS2 30 +#define BN_BITS4 15 +/* This is needed because the Watcom compiler pre-processor + * under QNX tries to parses the 'LL' part even though it is + * never used. + */ +#ifdef BN_LLONG +#ifndef WIN32 +#define BN_MASK (0x0fffffffffffffffLL) +#else +#define BN_MASK (0x0fffffffffffffffL) +#endif +#endif +#define BN_MASK2 (0x3fffffffL) +#define BN_MASK2l (0x7fff) +#define BN_MASK2lh (0x7fff) +#define BN_MASK2h1 (0x3fffc000L) +#define BN_MASK2h (0x3fff8000L) +#define BN_TBIT (0x20000000L) +#define BN_DEC_CONV (1000000000L) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%09lu" +#define BN_DEC_NUM 9 +#define BN_HEX_FMT "%08lX" +#endif + +#ifdef SIXTEEN_BIT +#ifndef BN_DIV2W +#define BN_DIV2W +#endif +#define BN_ULLONG unsigned long +#define BN_ULONG unsigned short +#define BN_LONG short +#define BN_BITS 32 +#define BN_BYTES 2 +#define BN_BITS2 16 +#define BN_BITS4 8 +#define BN_MASK (0xffffffff) +#define BN_MASK2 (0xffff) +#define BN_MASK2l (0xff) +#define BN_MASK2lh (0xff) +#define BN_MASK2h1 (0xff80) +#define BN_MASK2h (0xff00) +#define BN_TBIT (0x8000) +#define BN_DEC_CONV (10000) +#define BN_DEC_FMT1 "%u" +#define BN_DEC_FMT2 "%04u" +#define BN_DEC_NUM 4 +#define BN_HEX_FMT "%04X" +#endif + +#ifdef TEST_EIGHT_BIT +#define EIGHT_BIT /* comment to stop editing */ +#endif + +#ifdef EIGHT_BIT +#undef BN_ILONG +#define BN_ILONG unsigned int +#ifndef BN_DIV2W +#define BN_DIV2W +#endif +#ifdef TEST_EIGHT_BIT +#define BN_ULLONG unsigned int +#define BN_ULONG unsigned int +#define BN_LONG int +#else +#define BN_ULLONG unsigned short +#define BN_ULONG unsigned char +#define BN_LONG char +#endif +#define BN_BITS 16 +#define BN_BYTES 1 +#define BN_BITS2 8 +#define BN_BITS4 4 +#define BN_MASK (0xffff) +#define BN_MASK2 (0xff) +#define BN_MASK2lh (0xf) +#define BN_MASK2l (0xf) +#define BN_MASK2h1 (0xf8) +#define BN_MASK2h (0xf0) +#define BN_TBIT (0x80) +#define BN_DEC_CONV (100) +#define BN_DEC_FMT1 "%u" +#define BN_DEC_FMT2 "%02u" +#define BN_DEC_NUM 2 +#define BN_HEX_FMT "%02X" +#endif + +#ifdef BIGNUM +#undef BIGNUM +#endif + +#define BN_FLG_MALLOCED 0x01 +#define BN_FLG_STATIC_DATA 0x02 +#define BN_FLG_FREE 0x8000 /* used for debuging */ +#define BN_CTX_FLG_ABORT 0x4000 /* used for aborting RSA operations*/ +#define BN_set_flags(b,n) ((b)->flags|=(n)) +#define BN_get_flags(b,n) ((b)->flags&(n)) +#define BN_CTX_set_flags(b,n) ((b)->flags|=(n)) +#define BN_CTX_get_flags(b,n) ((b)->flags&(n)) + +#ifndef HEADER_COMMON_BN_H_TYPEDEF_DEF +#define HEADER_COMMON_BN_H_TYPEDEF_DEF +typedef struct bignum_st BIGNUM; +typedef struct bignum_ctx BN_CTX; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct bn_recp_ctx_st BN_RECP_CTX; +typedef struct bn_prime_ctx_st BN_PRIME_CTX; +typedef struct bn_blind_ctx_st BN_BLIND_CTX; +typedef struct bn_blind_meth_st BN_BLIND_METH; +#endif + +typedef struct bn_mod_exp_meth_st BN_ME_METH; +typedef struct bn_mod_exp_ctx_st BN_ME_CTX; + + +/* The data array d must always have an extra 'valid' word in location + * bn->d[bn->max]. It must be ok for reading. This is needed if + * BN_MUL_LATENCY is defined. + */ +struct bignum_st + { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int max; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; + }; + +/* Used for temp variables */ +#define BN_CTX_NUM 12 +struct bignum_ctx + { + int tos; + BIGNUM bn[BN_CTX_NUM+1]; + int flags; + R_SURRENDER *surrender; + }; + +#if defined(WIN64) || defined(__ia64__) || defined(CPU_IA64) +#define BN_USHORT unsigned int +#else +#define BN_USHORT unsigned short +#endif + +/* Used for prime number generation */ +struct bn_prime_ctx_st + { + BN_USHORT *primes; + BN_USHORT *mods; + int num_primes; + int prime_checks; + R_SURRENDER *surrender; + R_RANDOM *random; + int flags; + }; + +struct bn_blind_ctx_st + { + int init; + BN_BLIND_METH *meth; + BIGNUM B; + BIGNUM Bi; + BIGNUM mod; + }; + +struct bn_blind_meth_st + { + void (*init) (BN_BLIND_CTX *); + void (*ctx_free)(BN_BLIND_CTX *); + int (*set) (BN_BLIND_CTX *,R_RANDOM *,BIGNUM *,BIGNUM *, BN_ME_CTX *,BN_CTX *); + int (*convert) (BN_BLIND_CTX *,BIGNUM *,BN_CTX *); + int (*invert) (BN_BLIND_CTX *,BIGNUM *,BN_CTX *); + int (*update) (BN_BLIND_CTX *,BN_CTX *); + int (*copy) (BN_BLIND_CTX *,BN_BLIND_CTX *); + }; + +/* Used for montgomery multiplication */ +struct bn_mont_ctx_st + { + int use_word; /* 0 for word form, 1 for long form */ + int ri; /* number of bits in R */ + int riw; /* number of words in R */ + BIGNUM RR; /* used to convert to montgomery form */ + BIGNUM N; /* The modulus */ + BIGNUM Ni; /* The inverse of N */ + BN_ULONG n0; /* word form of inverse, normally only one of + * Ni or n0 is defined */ + int flags; + }; + +/* Used by the recursive exponentiation implementations */ +typedef struct bn_mod_exp_rec_meth_st + { +#ifndef NOPROTO + void (PRE_CCONV CCONV *mul)(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); + void (PRE_CCONV CCONV *sqr)(BN_ULONG *r, BN_ULONG *a); + void (PRE_CCONV CCONV *low_mul)(); +#else + void (PRE_CCONV CCONV *mul)(); + void (PRE_CCONV CCONV *sqr)(); + void (PRE_CCONV CCONV *low_mul)(); +#endif + } BN_MOD_EXP_REC_METH; + +/* If this flag is set, if there is a custom method for a modulus + * two times larger, use it. This is mostly mean for use on the + * itanium where a 512*512 routine is 10 times faster than the C + * code version, so we need to detect that we can turn of CRT + * for RSA if there is an native IA64 512*512 present. + */ +#define BN_ME_FLG_FAST_ASM 0x0001 + +struct bn_mod_exp_meth_st + { + int num; /* Word size we target */ + char *name; /* Identify the method */ +#ifndef NOPROTO + int (*useit)(const BN_ME_METH *meth); + /* If 'power' is null, reuse the old one */ + int (*mod_exp)(BN_ME_CTX *mctx,BIGNUM *r,BIGNUM *a,BIGNUM *p, + BN_CTX *ctx); + /* Create the BN_ME_CTX */ + int (*init_ctx)(const BN_ME_METH *meth,BN_ME_CTX **mctx); + /* Get rid of it */ + int (*free_ctx)(BN_ME_CTX *mctx); + /* Assign the modulus */ + int (*set)(BN_ME_CTX *mctx,BIGNUM *n,int cmd,int flags,BN_CTX *ctx); +#else + int (*useit)(); + int (*mod_exp)(); + int (*init_ctx)(); + int (*free_ctx)(); + int (*set)(); +#endif + int argi; + char *argp; /* 'Extra stuff' */ + }; + +#define BN_ME_METH_TABLE_MAX 32 +/* Used in BN_library_init */ +#define BN_INIT_LAST 0x00 +#define BN_INIT_BN_ME_METH 0x01 + +#define BN_BNME_F_DEFAULT 0x01 +/* Used only when loading, kept as bits internally, normally loaded as + * words */ +#define BN_BNME_F_BITS 0x02 +typedef struct bn_me_meth_info_st + { +#ifndef NOPROTO + const BN_ME_METH *(*meth)(void); +#else + const BN_ME_METH *(*meth)(); +#endif + int min; + int max; + int flags; + } BN_ME_METH_INFO; + +#define BN_ME_SET_MOD 0x01 +#define BN_ME_SET_BASE 0x02 +#define BN_ME_SET_EXP 0x03 +#define BN_ME_SET_FLG_NO_LOOKUP 0x01 /* Passed to BN_ME_CTX_set() */ + +#define BN_FLG_CACHE 0x10 /* Cache values */ +#define BN_ME_FLG_BASE 0x40 /* base has been cached */ +#define BN_ME_FLG_EXP 0x80 /* power has been cached */ +/* When one of these structures is setup, it is intended that the + * base or power, if not null, will be used for the current calculation. + * If the base and/or power are cached, they will only be used if the input + * value is null. + * For RSA, the power would normally be set. + * For DH, the base and power would be set. The initial value generated + * would be the public key, which is exchanged. The phase2 part would + * change the base but not the power. + * For DSA signing, a fixed base is used, but a random power. + * For DSA verification, there are two bases and two powers, + * a^p%m * b^q%m + * One way to implement this is to use a special function to + * generate a composite power value, and or a special base form. + * The other option is to have a special function to generate + * the 'base' array. The problem is that we are exponentiating with + * a 3 value power value, instead of the normal two. It should be possible + * to use the standard a^b%m function. + */ +struct bn_mod_exp_ctx_st + { + const BN_ME_METH *meth; + char *callback; + char *cb_arg; + int flags; + /* Evil hack for storage of data values, it should really be here + * other than the first value */ + char *modulus; /* eg BN_MONT_CTX */ + char *power; /* eg power representation */ + char *base; /* eg base representation */ + char *arg; + }; + +/* Used for reciprocal division/mod functions + * It cannot be shared between threads + */ +struct bn_recp_ctx_st + { + BIGNUM N; /* the divisor */ + BIGNUM Nr; /* the reciprocal */ + int num_bits; + int shift; + int flags; + }; + +typedef struct bn_rec_st + { + int depth; + int n; +#ifndef NOPROTO + void (PRE_CCONV CCONV *mul)(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); + void (PRE_CCONV CCONV *sqr)(BN_ULONG *r, BN_ULONG *a); + void (PRE_CCONV CCONV *low_mul)(); +#else + void (PRE_CCONV CCONV *mul)(); + void (PRE_CCONV CCONV *sqr)(); + void (PRE_CCONV CCONV *low_mul)(); +#endif + } BN_REC; + +#define BN_to_montgomery(r,a,mont,ctx) BN_mod_mul_montgomery(\ + r,a,&((mont)->RR),(mont),ctx) + +#define BN_prime_checks (5) + +#define BN_num_bytes(a) ((BN_num_bits(a)+7)/8) +#define BN_length(a) ((a)->top * BN_BYTES) +#define BN_is_word(a,w) (((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) +#define BN_is_zero(a) (((a)->top == 0) || BN_is_word(a,0)) +#define BN_is_one(a) (BN_is_word((a),1)) +#define BN_is_odd(a) (((a)->top > 0) && ((a)->d[0] & 1)) +#define BN_one(a) (BN_set_word((a),(BN_ULONG)1)) +#define BN_zero(a) (BN_set_word((a),(BN_ULONG)0)) + +/*#define BN_ascii2bn(a) BN_hex2bn(a) */ +/*#define BN_bn2ascii(a) BN_bn2hex(a) */ + +#define bn_expand(n,b) ((((((b+BN_BITS2-1))/BN_BITS2)) <= (n)->max)?\ + (n):bn_expand2((n),(b)/BN_BITS2+1)) +#define bn_wexpand(n,b) (((b) <= (n)->max)?(n):bn_expand2((n),(b))) + +#ifdef SMALL_CODE_SIZE +void bn_zexpand(BIGNUM *a,int n); +void bn_fix_top(BIGNUM *a); +#else +#define bn_zexpand(a,n) \ + if ((a)->top < n) \ + { \ + int i; \ + bn_wexpand((a),n); \ + if ((a)->d!=NULL) \ + { \ + for (i=(a)->top; id[i]=0; \ + } \ + } + +#define bn_fix_top(a) \ + { \ + BN_ULONG *ftl; \ + if ((a)->top > 0) \ + { \ + for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \ + if (*(ftl--)) break; \ + } \ + } +#endif + +#define BN_MONT_CTX_set(a,b,c) BN_MONT_CTX_set_word((a),(b),(c)) + +#ifndef NOPROTO + + +const BN_ME_METH *BN_ME_METH_word(void); +const BN_ME_METH *BN_ME_METH_full(void); + +#if (defined(BN_MUL_COMBA) || defined(BN_SQR_COMBA)) + +/* word4 - used for 64bit multiprime*/ +const BN_ME_METH *BN_ME_METH_word4(void); +const BN_ME_METH *BN_ME_METH_rec4_word8(void); +const BN_ME_METH *BN_ME_METH_rec4_word16(void); +const BN_ME_METH *BN_ME_METH_rec4_word32(void); +const BN_ME_METH *BN_ME_METH_rec4_word64(void); +const BN_ME_METH *BN_ME_METH_rec4_word128(void); + +/* word6 - used for 64bit multiprime*/ +const BN_ME_METH *BN_ME_METH_word6(void); +const BN_ME_METH *BN_ME_METH_rec6_word12(void); +const BN_ME_METH *BN_ME_METH_rec6_word24(void); +const BN_ME_METH *BN_ME_METH_rec6_word48(void); +const BN_ME_METH *BN_ME_METH_rec6_word96(void); + +const BN_ME_METH *BN_ME_METH_word8(void); +const BN_ME_METH *BN_ME_METH_rec8_word16(void); +const BN_ME_METH *BN_ME_METH_rec8_word32(void); +const BN_ME_METH *BN_ME_METH_rec8_word64(void); +const BN_ME_METH *BN_ME_METH_rec8_word128(void); +const BN_ME_METH *BN_ME_METH_rec8_word256(void); + +const BN_ME_METH *BN_ME_METH_word11(void); +const BN_ME_METH *BN_ME_METH_rec11_word22(void); +const BN_ME_METH *BN_ME_METH_rec11_word44(void); +const BN_ME_METH *BN_ME_METH_rec11_word88(void); + +const BN_ME_METH *BN_ME_METH_word16(void); +const BN_ME_METH *BN_ME_METH_rec16_word32(void); +const BN_ME_METH *BN_ME_METH_rec16_word64(void); +const BN_ME_METH *BN_ME_METH_rec16_word128(void); +const BN_ME_METH *BN_ME_METH_rec16_word256(void); + +#endif + +#ifdef CPU_IA64 +const BN_ME_METH *BN_ME_METH_ia64_384(void); +const BN_ME_METH *BN_ME_METH_ia64_512(void); +const BN_ME_METH *BN_ME_METH_ia64_1024(void); +#endif + +#if (defined(CPU_SPARC_V8PLUS) || defined (CPU_SPARC_V9)) +const BN_ME_METH *BN_ME_METH_usparc(void); +const BN_ME_METH *BN_ME_METH_usparc_352(void); +const BN_ME_METH *BN_ME_METH_usparc_512(void); +#endif + +#if 1 || defined(CPU_X86) +const BN_ME_METH *BN_ME_METH_pentium4_29(void); +const BN_ME_METH *BN_ME_METH_pentium4_28(void); +#endif + +/* NCipher Nfast hardware accelerator method prototype */ +const BN_ME_METH *BN_ME_METH_nfast(void); + + +BIGNUM *BN_value_one(void); +const char * BN_options(void); +BN_CTX *BN_CTX_new(void); +void BN_CTX_init(BN_CTX *c); +void BN_CTX_free(BN_CTX *c); +#ifndef NO_BN_RAND +int BN_rand(BIGNUM *rnd, R_RANDOM *rand, int bits, int top,int bottom); +#endif +int BN_num_bits(BIGNUM *a); +int BN_num_bits_word(BN_ILONG); +BIGNUM *BN_new(void); +void BN_init(BIGNUM *); +void BN_clear_free(BIGNUM *a); +BIGNUM *BN_copy(BIGNUM *a, BIGNUM *b); +BIGNUM *BN_bin2bn(unsigned char *s,int len,BIGNUM *ret); +int BN_bn2bin(BIGNUM *a, unsigned char *to); +BIGNUM *BN_mpi2bn(unsigned char *s,int len,BIGNUM *ret); +int BN_bn2mpi(BIGNUM *a, unsigned char *to); +int BN_sub(BIGNUM *r, BIGNUM *a, BIGNUM *b); +int BN_usub(BIGNUM *r, BIGNUM *a, BIGNUM *b); +int BN_uadd(BIGNUM *r, BIGNUM *a, BIGNUM *b); +int BN_add(BIGNUM *r, BIGNUM *a, BIGNUM *b); +int BN_mod(BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx); +int BN_div(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx); +int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b,BN_CTX *ctx); +int BN_sqr(BIGNUM *r, BIGNUM *a,BN_CTX *ctx); +BN_ULONG BN_mod_word(BIGNUM *a, BN_ULONG w); +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w); +int BN_mul_word(BIGNUM *a, BN_ULONG w); +int BN_add_word(BIGNUM *a, BN_ULONG w); +int BN_sub_word(BIGNUM *a, BN_ULONG w); +int BN_set_word(BIGNUM *a, BN_ULONG w); +BN_ULONG BN_get_word(BIGNUM *a); +int BN_cmp(BIGNUM *a, BIGNUM *b); +void BN_free(BIGNUM *a); +int BN_is_bit_set(BIGNUM *a, int n); +int BN_lshift(BIGNUM *r, BIGNUM *a, int n); +int BN_lshift1(BIGNUM *r, BIGNUM *a); +int BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p,BN_CTX *ctx); +int BN_mod_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx); +int BN_mod_exp_mont(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx, + BN_MONT_CTX *m_ctx); +int BN_mod_exp2_mont(BIGNUM *r, BIGNUM *a1, BIGNUM *p1,BIGNUM *a2, + BIGNUM *p2,BIGNUM *m,BN_CTX *ctx,BN_MONT_CTX *m_ctx); +int BN_mod_exp_simple(BIGNUM *r, BIGNUM *a, BIGNUM *p, + BIGNUM *m,BN_CTX *ctx); +int BN_mask_bits(BIGNUM *a,int n); +int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, BIGNUM *m, + BN_CTX *ctx); +#if !defined(WIN16) && !defined(NO_FP_API) +int BN_print_fp(FILE *fp, BIGNUM *a); +#endif +#ifdef HEADER_COMMON_BIO_H +int BN_print(BIO *fp, BIGNUM *a); +#else +/* int BN_print(char *fp, BIGNUM *a); */ +#endif +int BN_reciprocal(BIGNUM *r, BIGNUM *m, int len, BN_CTX *ctx); +int BN_rshift(BIGNUM *r, BIGNUM *a, int n); +int BN_rshift1(BIGNUM *r, BIGNUM *a); +void BN_clear(BIGNUM *a); +BIGNUM *bn_expand2(BIGNUM *b, int bits); +BIGNUM *BN_dup(BIGNUM *a); +int BN_ucmp(BIGNUM *a, BIGNUM *b); +int BN_set_bit(BIGNUM *a, int n); +int BN_clear_bit(BIGNUM *a, int n); +char * BN_bn2hex(BIGNUM *a); +char * BN_bn2dec(BIGNUM *a); +int BN_hex2bn(BIGNUM **a,char *str); +int BN_dec2bn(BIGNUM **a,char *str); +int BN_gcd(BIGNUM *r,BIGNUM *in_a,BIGNUM *in_b,BN_CTX *ctx); +BIGNUM *BN_mod_inverse(BIGNUM *ret,BIGNUM *a, BIGNUM *n,BN_CTX *ctx); +/* Return R, where it is R*(1< +#include +#include "r_error.h" +#include "err.h" +#include +#else //NITRO +#include "r_error.h" +#ifndef NULL +#define NULL 0 +#endif +#endif + +#ifndef STANDALONE +#include "r_com.h" +#else +#if 0 //RSA +#define NO_STDLIB_MAPPING +#define Malloc(a) malloc(a) +#define Free(a) free(a) +#define Memset(a,b,c) memset(a,b,c) +#define Memcpy(a,b,c) memcpy(a,b,c) +#else // Nitro +#define NO_STDLIB_MAPPING +#include "acmemory.h" +#define Malloc(a) ACMemory_Alloc(a) +#define Free(a) ACMemory_Free(a) +#define Memset(a,b,c) ACMemory_Memset(a,b,c) +#define Memcpy(a,b,c) ACMemory_Memcpy(a,b,c) +#endif +#endif + +/* TEMP FIX */ +#undef BNerr +#define BNerr(a,b) +#include "bn.h" + +#define BN_EXP_TABLE_SIZE 16 + +/* see the bn_limit_ fields which are the start of a runtime + * tunable set of values to match these fixed compile-time constants + */ +/* Pentium pro 16,16,16,32,64 */ +/* Alpha 16,16,16,16.64 */ +/* StrongARM */ +#define BN_MULL_SIZE_NORMAL (16) /* 32 */ +#define BN_MUL_RECURSIVE_SIZE_NORMAL (16) /* 32 */ /* less than */ +#define BN_SQR_RECURSIVE_SIZE_NORMAL (16) /* 32 */ +#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */ +#define BN_MONT_CTX_SET_SIZE_WORD (64) /* 32 */ + +/************************************************************* + * Using the long long type + */ +#define Lw(t) (((BN_ULONG)(t))&BN_MASK2) +#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2) + +/* These are used for internal error checking and are not normally used */ +#ifdef BN_DEBUG +#define bn_check_top(a) \ + { if ( ((a)->top < 0) || \ + ((a)->top > (a)->max) || \ + (((a)->top == 0) && (a)->neg) || \ + (((a)->top == 1) && (a->d[0] == 0))) \ + { char *nullp=NULL; *nullp='z'; } } +#define bn_check_num(a) if ((a) < 0) { char *nullp=NULL; *nullp='z'; } +#define bn_assert(a) if (!(a)) { char *nullp=NULL; *nullp='z'; } +#define bn_set_used_check(l,size,num) bn_su_check(l,size,num) +#ifdef BN_DEBUG2 +#define bn_do_used_check(fp,str,l,size,num) bn_du_check(fp,str,l,size,num) +#else +#define bn_do_used_check(fp,str,l,size,num) +#endif +#else +#define bn_assert(a) +#define bn_check_top(a) +#define bn_check_num(a) +#define bn_set_used_check(l,size,num) +#define bn_do_used_check(fp,str,l,size,num) +#endif + + +/*********************************************** +* IA64 32 bit build SWIZZLE code +* This essentially casts our points which are +* 32bits under abi32 to 64bit unsigned long +* longs and then grabs the top two bits of the +* pointer and places it in the 2nd and 3rd bits +* of the unsigned long long. +**********************************************/ +#ifdef HPUX_IA64_32 +#define SWIZLLE(VALUE) ((((unsigned long long)(VALUE) & 0xc0000000LL) <<31)\ +|((unsigned long long)(VALUE))) +#else +#define SWIZZLE(VALUE) (VALUE) +#endif + +#define bn_neg_words(a,n) \ + { \ + int iii; \ + \ + for (iii=0; iiimax=(r)->top,BN_set_flags((r),BN_FLG_STATIC_DATA)) +#else +#define bn_set_max(r) +#endif + +/* These macros are used to 'take' a section of a bignum for read only use */ +#define bn_set_low(r,a,n) \ + { \ + (r)->top=((a)->top > (n))?(n):(a)->top; \ + (r)->d=(a)->d; \ + (r)->neg=(a)->neg; \ + (r)->flags|=BN_FLG_STATIC_DATA; \ + bn_set_max(r); \ + } + +#define bn_set_high(r,a,n) \ + { \ + if ((a)->top > (n)) \ + { \ + (r)->top=(a)->top-n; \ + (r)->d= &((a)->d[n]); \ + } \ + else \ + (r)->top=0; \ + (r)->neg=(a)->neg; \ + (r)->flags|=BN_FLG_STATIC_DATA; \ + bn_set_max(r); \ + } + +/* #define bn_expand(n,b) ((((b)/BN_BITS2) <= (n)->max)?(n):bn_expand2((n),(b))) */ + +#ifdef BN_LLONG +#define mul_add(r,a,w,c) { \ + BN_ULLONG t; \ + t=(BN_ULLONG)w * (a) + (r) + (c); \ + (r)= Lw(t); \ + (c)= Hw(t); \ + } + +#define mul(r,a,w,c) { \ + BN_ULLONG t; \ + t=(BN_ULLONG)w * (a) + (c); \ + (r)= Lw(t); \ + (c)= Hw(t); \ + } + +#else +/************************************************************* + * No long long type + */ + +#define LBITS(a) ((a)&BN_MASK2l) +#define HBITS(a) (((a)>>BN_BITS4)&BN_MASK2lh) +#define L2HBITS(a) ((BN_ULONG)((a)&BN_MASK2lh)<>(BN_BITS4-1); \ + m =((m&BN_MASK2l)<<(BN_BITS4+1))&BN_MASK2; \ + l=(l+m)&BN_MASK2; if (l < m) h++; \ + (lo)=l; \ + (ho)=h; \ + } + +#if 0 +#define mul_add(r,a,bl,bh,b_hl,c) { \ + BN_ULONG l,h; \ + BN_ULONG lt,mt; \ + \ + h= (a); \ + l=LBITS(h); \ + h=HBITS(h); \ + mt=bl*l; \ + lt=mt+c+(r); \ + c=bh*h; \ + mt+=c+(l-h)*b_hl; \ + mt+=(lt>>BN_BITS4); \ + (r)=(lt&BN_MASK2l)|((mt&BN_MASK2l)<>BN_BITS4); \ + } +#else /* Normal version */ +#define mul_add(r,a,bl,bh,b_hl,c) { \ + BN_ULONG l,h; \ + \ + h= (a); \ + l=LBITS(h); \ + h=HBITS(h); \ + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ + l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ + (c)=(r); \ + l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ + (c)=h&BN_MASK2; \ + (r)=l; \ + } +#endif + +#define mul(r,a,bl,bh,c) { \ + BN_ULONG l,h; \ + \ + h= (a); \ + l=LBITS(h); \ + h=HBITS(h); \ + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ + l+=(c); if ((l&BN_MASK2) < (c)) h++; \ + (c)=h&BN_MASK2; \ + (r)=l&BN_MASK2; \ + } + +#endif + +#ifndef BN_MUL_COMBA +#define bn_mul_comba4(r,a,b) bn_mul_normal(r,a,4,b,4) +#define bn_mul_comba5(r,a,b) bn_mul_normal(r,a,5,b,5) +#define bn_mul_comba6(r,a,b) bn_mul_normal(r,a,6,b,6) +#define bn_mul_comba8(r,a,b) bn_mul_normal(r,a,8,b,8) +#define bn_mul_comba11(r,a,b) bn_mul_normal(r,a,11,b,11) +#define bn_mul_comba12(r,a,b) bn_mul_normal(r,a,12,b,12) +#define bn_mul_comba16(r,a,b) bn_mul_normal(r,a,16,b,16) +#endif +#if 1 +#ifndef BN_SQR_COMBA +#define bn_sqr_comba4(r,a) bn_mul_normal(r,a,4,a,4) +#define bn_sqr_comba5(r,a) bn_mul_normal(r,a,5,a,5) +#define bn_sqr_comba6(r,a) bn_mul_normal(r,a,6,a,6) +#define bn_sqr_comba8(r,a) bn_mul_normal(r,a,8,a,8) +#define bn_sqr_comba11(r,a) bn_mul_normal(r,a,11,a,11) +#define bn_sqr_comba12(r,a) bn_mul_normal(r,a,12,a,12) +#define bn_sqr_comba16(r,a) bn_mul_normal(r,a,16,a,16) +#endif +#else +#ifndef BN_SQR_COMBA +#define bn_sqr_comba4(r,a) bn_mul_comba4(r,a,a) +#define bn_sqr_comba5(r,a) bn_mul_comba5(r,a,a) +#define bn_sqr_comba6(r,a) bn_mul_comba6(r,a,a) +#define bn_sqr_comba8(r,a) bn_mul_comba8(r,a,a) +#define bn_sqr_comba11(r,a) bn_mul_comba11(r,a,a) +#define bn_sqr_comba12(r,a) bn_mul_comba12(r,a,a) +#define bn_sqr_comba16(r,a) bn_mul_comba16(r,a,a) +#endif +#endif +#ifndef BN_REDUCE_COMBA +#define r0_bn_mont_comba4(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba5(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba6(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba8(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba11(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba12(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba16(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#endif + +#ifndef NOPROTO + +BIGNUM *bn_expand2(BIGNUM *b, int bits); + +#ifdef X86_ASM +void bn_add_words(BN_ULONG *r,BN_ULONG *a,int num); +#endif + +#else + +BIGNUM *bn_expand2(); +#ifdef X86_ASM +BN_ULONG bn_add_words(); +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_COMMON_BN_LCL_H */ + +void bn_mul_low_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,BN_ULONG *t); +void bn_mul_high(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,BN_ULONG *l,int n2, BN_ULONG *t); +int BN_gen_exp_string(unsigned char *str, BIGNUM *p, int bits); +void bn_from_montgomery_rec_full(BN_ULONG *rp, BN_ULONG *ap, + BN_ULONG *np, BN_ULONG *nip, BN_ULONG *tmp,BN_REC *rec); + +int bn_mont_ctx_new_word(const BN_ME_METH *meth, BN_ME_CTX **retp); + diff --git a/build/libraries_sysmenu/acsign/ARM9/include/bn_thx.h b/build/libraries_sysmenu/acsign/ARM9/include/bn_thx.h new file mode 100644 index 0000000..451b3e4 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/include/bn_thx.h @@ -0,0 +1,317 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +/***************************************************************************** + * Copyright (c). 2001 RSA Security Inc. All rights reserved. + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + ****************************************************************************/ +/** + * @file bn_thx.h + * @brief header file created for used as interface defines for systems + * containing hetergeneous environments where some bn operations + * will be performed in isolation from the rest of the library + */ +#ifndef HEADER_COMMON_BN_THX_H +#define HEADER_COMMON_BN_THX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* These defines are required on systems so that the mod_exp code + * to be used in isolation from the bn operation with library will work, + * if these are not available, the header files with equivalent functionality + * should be added inside a CPU or Operating system define + */ +#ifndef NO_STDIO_H +#include +#endif + +#ifndef NO_STDLIB_H +#include +#endif + +#ifndef NO_STRING_H +#include +#endif + +/* Interface for ARM/DSP systems, this interface requires only + * the standard defines and includes at the moment + */ +#ifdef CPU_TMS320 +#define THX_RECIPIENT +#define CPU_DSP +#endif + +#ifdef THX_RECIPIENT + +#ifndef restrict +#define restrict +#endif + +#ifndef Malloc +#define Malloc malloc +#endif + +#ifndef Memcpy +#define Memcpy memcpy +#endif + +#ifndef Memmove +#define Memmove memmove +#endif + +#ifndef Memset +#define Memset memset +#endif + +#ifndef Free +#define Free free +#endif + +#endif /* THX_RECIPIENT */ + +#ifndef THX_RECIPIENT /* not the recipient, we must be the caller */ + +#include "bn_lcl.h" + +#endif /* ! THX_RECIPIENT */ + +/* The follow define protected inclusions are excerpts from the + * header file bn.h, this has been done, so that code written for the + * THX systems can be used in isolation from the library + * This code may need to be updated in line with changes to the bn.h + * header file. + */ +#ifndef HEADER_COMMON_BN_H +#define HEADER_COMMON_BN_H + +#if !defined(CCONV) +#define CCONV +#endif + +#ifndef PRE_CCONV +#define PRE_CCONV +#endif + +/* convert from the new to the old option names */ +#if defined(OPT_BN_LLONG) +#define BN_LLONG /* comment to make sure Configure leaves this alone */ +#endif + +#if defined(OPT_32_BIT_INT) || defined(OPT_32_BIT) +#define THIRTY_TWO_BIT +#endif + +#define BN_ILONG BN_ULONG + +#ifdef THIRTY_TWO_BIT +#define BN_ULLONG unsigned long long +#ifdef OPT_32_BIT_INT +#define BN_ULONG unsigned int +#define BN_LONG int +#else +#define BN_ULONG unsigned long +#define BN_LONG long +#endif +#define BN_BITS 64 +#define BN_BYTES 4 +#define BN_BITS2 32 +#define BN_BITS4 16 +/* This is needed because the Watcom compiler pre-processor + * under QNX is perverted and tries to parses the 'LL' + * part even though it is never used. + */ +#ifdef BN_LLONG +#define BN_MASK (0xffffffffffffffffL) +#endif +#define BN_MASK2 (0xffffffffL) +#define BN_MASK2l (0xffff) +#define BN_MASK2lh (0xffff) +#define BN_MASK2h1 (0xffff8000L) +#define BN_MASK2h (0xffff0000L) +#define BN_TBIT (0x80000000L) +#define BN_DEC_CONV (1000000000L) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%09lu" +#define BN_DEC_NUM 9 +#define BN_HEX_FMT "%08lX" +#endif + +#define BN_EXP_TABLE_SIZE 16 + +typedef struct bignum_st BIGNUM; + +struct bignum_st + { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int max; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; + }; + +PRE_CCONV BN_ULONG CCONV bn_mul_add_words(BN_ULONG *rp,BN_ULONG *ap, + int num, BN_ULONG w); +PRE_CCONV BN_ULONG CCONV bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, + int num, BN_ULONG w); +PRE_CCONV void CCONV bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num); +BN_ULONG CCONV bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d); +PRE_CCONV BN_ULONG CCONV bn_add_words(BN_ULONG *rp, BN_ULONG *ap, + BN_ULONG *bp,int num); +PRE_CCONV BN_ULONG CCONV bn_sub_words(BN_ULONG *rp, BN_ULONG *ap, + BN_ULONG *bp,int num); + +#ifndef BN_ME_METH +#define BN_ME_METH void +#endif + +#endif /* ! HEADER_COMMON_BN_H */ + +/* The follow define protected inclusions are excerpts from the + * header file r_error.h, this has been done, so that code written for the + * THX systems can be used in isolation from the library + * This code may need to be updated in line with changes to the r_error.h + * header file. + */ +#ifndef HEADER_COMMON_R_ERROR_H +#define HEADER_COMMON_R_ERROR_H + +/* The FATAL_INTERNAL_ERROR is a flag that is set with the following + * error codes: + * R_ERROR_INVALID_STATE + * R_ERROR_INIT_NOT_CALLED + * R_ERROR_SHOULD_NOT_HAVE_BEEN_CALLED + */ +#define R_ERROR_FATAL_INTERNAL_ERROR 64 + +/* The BAD_PARAMETER is a flag that is set with the following error + * codes: + * R_ERROR_NULL_ARG + * R_ERROR_BUFFER_TOO_SMALL + * R_ERROR_BAD_VALUE + * R_ERROR_BAD_RANGE + * R_ERROR_BAD_FORMAT + * R_ERROR_BAD_TYPE + * R_ERROR_BAD_DATA + * R_ERROR_BAD_LENGTH + */ +#define R_ERROR_BAD_PARAMETER 32 + +/* Base value for all general errors used through all products */ +#define R_ERROR_BASE 10000 + +#define R_ERROR_NONE 0 + +#define R_ERROR_FAILED (R_ERROR_BASE+1) +#define R_ERROR_IO (R_ERROR_BASE+2) +#define R_ERROR_PROTOCOL (R_ERROR_BASE+3) +#define R_ERROR_EOF (R_ERROR_BASE+4) +#define R_ERROR_ALLOC_FAILURE (R_ERROR_BASE+5) +#define R_ERROR_EVAL_RESTRICTION (R_ERROR_BASE+6) +#define R_ERROR_EVAL_EXPIRED (R_ERROR_BASE+7) +#define R_ERROR_NOT_FOUND (R_ERROR_BASE+8) +#define R_ERROR_NOT_AVAILABLE (R_ERROR_BASE+9) +#define R_ERROR_NOT_IMPLEMENTED (R_ERROR_BASE+10) +#define R_ERROR_NOT_SUPPORTED (R_ERROR_BASE+11) +#define R_ERROR_INVALID_STATE \ + ((R_ERROR_BASE+12) | R_ERROR_FATAL_INTERNAL_ERROR) +#define R_ERROR_INIT_NOT_CALLED \ + ((R_ERROR_BASE+13) | R_ERROR_FATAL_INTERNAL_ERROR) +#define R_ERROR_SHOULD_NOT_HAVE_BEEN_CALLED \ + ((R_ERROR_BASE+14) | R_ERROR_FATAL_INTERNAL_ERROR) +#define R_ERROR_METHOD_UNDEFINED \ + ((R_ERROR_BASE+15) | R_ERROR_FATAL_INTERNAL_ERROR) +#define R_ERROR_BUFFER_TOO_SMALL \ + ((R_ERROR_BASE+16) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_NULL_ARG ((R_ERROR_BASE+17) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_VALUE ((R_ERROR_BASE+18) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_RANGE ((R_ERROR_BASE+19) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_FORMAT ((R_ERROR_BASE+20) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_TYPE ((R_ERROR_BASE+21) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_DATA ((R_ERROR_BASE+22) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_LENGTH ((R_ERROR_BASE+23) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_RCOM_LIBRARY_NOT_SUPPORTED (R_ERROR_BASE+24) + +/* Resource Manager base for errors */ +#define R_COM_ERR_LIB_CTX_BASE 10100 + +#endif /* HEADER_COMMON_R_ERROR_H */ + + +const BN_ME_METH *BN_ME_METH_thxc(void); +/** + * @note THX code only needs to store rr, n0, str + * + */ +typedef struct thxc_mont_ctx_st + { + BIGNUM *rr; + unsigned char *str; + unsigned int str_len; + BN_ULONG n0; + } THXC_MONT_CTX; + + +int Rx_thxr_mod_exp_mont( BN_ULONG *result, BN_ULONG *ap, BN_ULONG *np, + BN_ULONG *rrp, BN_ULONG n0, int top, int tmp_len, unsigned char *str); + +int Ri_thxr_mod_exp_mont( BN_ULONG *result, BN_ULONG *ap, BN_ULONG *np, + BN_ULONG *rrp, BN_ULONG *dp, BN_ULONG *aap, BN_ULONG *rp, BN_ULONG *tmp, + BN_ULONG n0, int top, unsigned char *str); + +void Ri_thxr_mul_normal(BN_ULONG *r,BN_ULONG *a,int na,BN_ULONG *b,int nb); +void Ri_thxr_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp); + +void Ri_thxr_from_montgomery_words(BN_ULONG *ret,BN_ULONG *ap,BN_ULONG *np, + int w, BN_ULONG n0); + +BN_ULONG Ri_thxr_from_mont_words(BN_ULONG *ap,BN_ULONG *wap, + BN_ULONG *np, int w, BN_ULONG n0); + +#ifdef CPU_TMS320 + +/* Method and functions required for the ARM/DSP interface */ + +const BN_ME_METH *BN_ME_METH_dspc(void); + +int Rx_dsp_mod_exp_mont( BN_ULONG *result, BN_ULONG *ap, BN_ULONG *np, + BN_ULONG *rrp, BN_ULONG n0, int top, int tmp_len, unsigned char *str); + +int Ri_dsp_mod_exp_mont( BN_ULONG *result, BN_ULONG *ap, BN_ULONG *np, + BN_ULONG *rrp, BN_ULONG *dp, BN_ULONG *aap, BN_ULONG *rp, BN_ULONG *tmp, + BN_ULONG n0, int top, unsigned char *str); + +#endif + +#ifdef __cplusplus +} +#endif +#endif /* HEADER_COMMON_BN_THX_H */ diff --git a/build/libraries_sysmenu/acsign/ARM9/include/md5.h b/build/libraries_sysmenu/acsign/ARM9/include/md5.h new file mode 100644 index 0000000..7a5ca73 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/include/md5.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef _MD5_H_ +#define _MD5_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +typedef struct MD5_CTX MD5_CTX; +typedef struct MD5_CTX MD5Context; + +/* MD5 context. */ +struct MD5_CTX{ + unsigned long state[4]; /* state (ABCD) */ + unsigned long count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} ; + +void MD5Init(MD5_CTX *); +void MD5Update(MD5_CTX *, unsigned char *, unsigned int); +void MD5Final(unsigned char digest[16], MD5_CTX *); + + +#if defined( MD5_TEST ) +int MD5Test( ); +#endif // MD5_TEST + +#ifdef __cplusplus +} +#endif + +#endif // _MD5_H_ diff --git a/build/libraries_sysmenu/acsign/ARM9/include/r_error.h b/build/libraries_sysmenu/acsign/ARM9/include/r_error.h new file mode 100644 index 0000000..16ffb55 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/include/r_error.h @@ -0,0 +1,226 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +/** + * @file r_error.h + * This file contains the error definitions for the toolkit. + */ +#ifndef HEADER_COMMON_R_ERROR_H +#define HEADER_COMMON_R_ERROR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup R_ERROR_IDS Error Identifiers + * This section outlines the error codes returned, enabling identification of + * specific errors. For more information, see the + * Developer's Guide. + * + * @{ + */ +/** + * Indicates that a fatal error has occurred in the operation performed. + * This flag is set with the following error codes:
+ *
    + *
  • #R_ERROR_INVALID_STATE.
  • + *
  • #R_ERROR_INIT_NOT_CALLED.
  • + *
  • #R_ERROR_SHOULD_NOT_HAVE_BEEN_CALLED.
  • + *
+ */ +#define R_ERROR_FATAL_INTERNAL_ERROR 64 + +/** + * Indicates that the specified parameter is incorrect or contains invalid + * information. This flag is set with the following error codes:
+ *
    + *
  • #R_ERROR_NULL_ARG.
  • + *
  • #R_ERROR_BUFFER_TOO_SMALL.
  • + *
  • #R_ERROR_BAD_VALUE.
  • + *
  • #R_ERROR_BAD_RANGE.
  • + *
  • #R_ERROR_BAD_FORMAT.
  • + *
  • #R_ERROR_BAD_TYPE.
  • + *
  • #R_ERROR_BAD_DATA.
  • + *
  • #R_ERROR_BAD_LENGTH.
  • + *
+ */ +#define R_ERROR_BAD_PARAMETER 32 + +/* Indicates the base value for all general errors used through all products */ +#define R_ERROR_BASE 10000 + +/** + * Indicates that no errors were detected in the requested operation. + */ +#define R_ERROR_NONE 0 + +/** + * Indicates that the requested operation failed. + */ +#define R_ERROR_FAILED (R_ERROR_BASE+1) +/** + * Indicates that the requested operation detected an Input/Output error. + */ +#define R_ERROR_IO (R_ERROR_BASE+2) +/** + * Indicates that the requested operation detected a protocol error. + */ +#define R_ERROR_PROTOCOL (R_ERROR_BASE+3) +/** + * Indicates that the requested operation detected an End-of-File (EOF) error. + */ +#define R_ERROR_EOF (R_ERROR_BASE+4) +/** + * Indicates that the requested operation failed in a memory allocation + * operation. + */ +#define R_ERROR_ALLOC_FAILURE (R_ERROR_BASE+5) +/** + * Indicates that the requested operation is restricted in an evaluation + * version of the library. + */ +#define R_ERROR_EVAL_RESTRICTION (R_ERROR_BASE+6) +/** + * Indicates that the evaluation period of the library has expired. + */ +#define R_ERROR_EVAL_EXPIRED (R_ERROR_BASE+7) +/** + * Indicates that the requested operation detected that a pre-requirement was + * not found. + */ +#define R_ERROR_NOT_FOUND (R_ERROR_BASE+8) +/** + * Indicates that the requested operation detected that a pre-requirement was + * unavailable. + */ +#define R_ERROR_NOT_AVAILABLE (R_ERROR_BASE+9) +/** + * Indicates that the requested operation is not implemented in the current + * instantiation of the library. + */ +#define R_ERROR_NOT_IMPLEMENTED (R_ERROR_BASE+10) +/** + * Indicates that the requested operation is not supported in the current + * instantiation of the library. + */ +#define R_ERROR_NOT_SUPPORTED (R_ERROR_BASE+11) +/** + * Indicates that the requested operation entered an invalid state. + */ +#define R_ERROR_INVALID_STATE \ + ((R_ERROR_BASE+12) | R_ERROR_FATAL_INTERNAL_ERROR) +/** + * Indicates that the requested operation detected that an initialization + * operation has not been performed. + */ +#define R_ERROR_INIT_NOT_CALLED \ + ((R_ERROR_BASE+13) | R_ERROR_FATAL_INTERNAL_ERROR) +/** + * Indicates that the requested operation should not have been called. + */ +#define R_ERROR_SHOULD_NOT_HAVE_BEEN_CALLED \ + ((R_ERROR_BASE+14) | R_ERROR_FATAL_INTERNAL_ERROR) +/** + * Indicates that the requested method is not defined. + */ +#define R_ERROR_METHOD_UNDEFINED \ + ((R_ERROR_BASE+15) | R_ERROR_FATAL_INTERNAL_ERROR) +/** + * Indicates that the requested operation detected an inadequately sized + * buffer. + */ +#define R_ERROR_BUFFER_TOO_SMALL \ + ((R_ERROR_BASE+16) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * was passed as NULL. + */ +#define R_ERROR_NULL_ARG ((R_ERROR_BASE+17) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed contained a bad or incorrect value. + */ +#define R_ERROR_BAD_VALUE ((R_ERROR_BASE+18) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed was out of the allowed range. + */ +#define R_ERROR_BAD_RANGE ((R_ERROR_BASE+19) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed used a format that is not supported or incorrect. + */ +#define R_ERROR_BAD_FORMAT ((R_ERROR_BASE+20) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed used a type that is not supported or incorrect. + */ +#define R_ERROR_BAD_TYPE ((R_ERROR_BASE+21) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed contained incorrect or invalid data. + */ +#define R_ERROR_BAD_DATA ((R_ERROR_BASE+22) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed contained an incorrect length value. + */ +#define R_ERROR_BAD_LENGTH ((R_ERROR_BASE+23) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the library instantiation requested is not supported. + */ +#define R_ERROR_RCOM_LIBRARY_NOT_SUPPORTED (R_ERROR_BASE+24) +/** + * Indicates that the request operation was denied. + */ +#define R_ERROR_DENIED (R_ERROR_BASE+25) +/** + * Indicates that authentication is required before the operation + * can succeed. + */ +#define R_ERROR_AUTHENTICATION_REQUIRED (R_ERROR_BASE+26) + +/** + * Indicates that a required module was unable to be loaded. + */ +#define R_ERROR_MODULE_LOAD_FAILED \ + ((R_ERROR_BASE+27)|R_ERROR_FATAL_INTERNAL_ERROR) + +/* Resource Manager base for errors */ +#define R_COM_ERR_LIB_CTX_BASE 10100 + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* HEADER_COMMON_R_ERROR_H */ + + + diff --git a/build/libraries_sysmenu/acsign/ARM9/include/r_stdiag.h b/build/libraries_sysmenu/acsign/ARM9/include/r_stdiag.h new file mode 100644 index 0000000..fbe3d3c --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/include/r_stdiag.h @@ -0,0 +1,98 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +/* + * *************************************************************************** + * + * Purpose: + * + * This file defines an API for performing stack diagnostics. + * + * It provides: + * Peek Stack Usage statistics + * To use it: + * 1. Build the library without "NO_R_DIAG" defined + * 2. Make a call to R_DIAG_set_stack_datum() prior to + * calling the first library function. + * 3. Add calls to the macro R_DIAG_CHECK_STACK where potential + * high stack usage points are. + * 4. Call R_DIAG_get_stack_low_water_mark() at then end of the + * library calls to return the maximum stack usage OR + * 5. Call R_DIAG_print_stack_depth() to display the peek stack + * usage + * + * + * + * History: + * 3-Aug-00 mjs development + * + * ************************************************************************** + */ + + +#ifndef HEADER_COMMON_R_STDIAG_H +#define HEADER_COMMON_R_STDIAG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NO_R_DIAG + +#ifdef NOPROTO +int R_DIAG_set_stack_datum(char *ptr); +int R_DIAG_check_stack(char *ptr, char *file, int line, int hit); +int R_DIAG_get_stack_low_water_mark(int *depth, char **file, int *line, + int *hit); +int R_DIAG_print_stack_depth(BIO *bio); + +#else + +int R_DIAG_set_stack_datum(); +int R_DIAG_check_stack(); +int R_DIAG_get_stack_low_water_mark(); +int R_DIAG_print_stack_depth(); + +#endif + +#define R_DIAG_CHECK_STACK {\ + char r_diag_stack_check_var = 0;\ + static int r_diag_stack_check_cnt = 0;\ +\ + R_DIAG_check_stack(&r_diag_stack_check_var, __FILE__,\ + __LINE__,++r_diag_stack_check_cnt);\ + } +#else +#define R_DIAG_CHECK_STACK +#endif + + +#ifdef __cplusplus +} +#endif +#endif /* HEADER_COMMON_R_STDIAG_H */ + diff --git a/build/libraries_sysmenu/acsign/ARM9/include/r_types.h b/build/libraries_sysmenu/acsign/ARM9/include/r_types.h new file mode 100644 index 0000000..f6514b1 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/include/r_types.h @@ -0,0 +1,257 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +/** + * @file r_types.h + * This file contains the library structure and type definitions. + */ +#ifndef HEADER_COMMON_R_TYPES_H +#define HEADER_COMMON_R_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup DATA_MNG_FLAGS Data Management Flags + * This section lists the data management flags. + * @{ + */ + +/** + * @} + */ + +/* This gets set if the flags field if the we need to 'free' the + * R_RANDOM when we call R_rand_free(). If it is not set, the + * rand_ctrl will only be called to clean things up. + */ +#define R_RANDOM_FLG_MALLOCED 0x01 + +/* portable form of a random callback function */ +/** + * @typedef R_RANDOM + * The random object type. + */ +typedef struct r_random_st R_RANDOM; +/** + * This structure is used by the random object type. + */ +struct r_random_st +{ + /** + * A method function for generation of random data. + * + * @see R_rand_bytes(). + */ + int (*rand_bytes)(R_RANDOM *ctx,unsigned char *bytes,int len); + /** + * A method function for seeding of the random generator. + * @see R_rand_seed(). + */ + int (*rand_seed)(R_RANDOM *ctx,unsigned char *bytes,int len); + /** + * A method function for control of the random generator used by + * other functions as a single interface. + * + * @see R_rand_entropy_count(), R_rand_set_entropy_func(), + * R_rand_get_entropy_func(), R_rand_load_file(), R_rand_write_file() + * and R_rand_file_name(). + */ + int (*rand_ctrl)(R_RANDOM *ctx,int op,char *arg); + /** + * The data used by the random implementation. + */ + char *arg; + /** + * A method flag for used for keeping the state of the #R_RANDOM. + */ + int flags; /* normally set to zero */ +}; +/** + * @typedef R_SURRENDER + * The surrender function and argument. + */ +typedef struct r_surrender_st R_SURRENDER; +/** + * This structure provides a status update of a time intensive operation. It + * also allows you to abort the operation if required. + */ +struct r_surrender_st +{ + /* Return 0 to continue, non-zero to 'cancel' function */ + /** + * The surrender function pointer used as a generic method of + * passing user-defined callback or information collection functions. + */ + int (*callback)(R_SURRENDER *ctx,int function,int num); + /** + * The argument data used by the callback operation. + */ + char *arg; +}; + +typedef struct r_fixed_point_number_st R_FIXED_POINT_NUMBER; +struct r_fixed_point_number_st +{ + unsigned long hi; + unsigned long lo; +}; + +/** + * @typedef R_INDEXED_INFO + * This structure details the index containing information for get and set + * functions. + */ +typedef struct r_indexed_info_st R_INDEXED_INFO; +/** This structure details the index containing information for get and set + * functions. + */ +struct r_indexed_info_st +{ + /** The index into the list of the item to work with. */ + int index; + /** The data of the item in the list. */ + void *data; + /** The length of the data. */ + unsigned int len; + /** The data value as an integer. */ + int value; +}; + +/** + * @typedef R_ID_INFO + * The information to work with requires a second identity value to find it. + */ +typedef struct r_id_info_st R_ID_INFO; +/** The information to get or set requires a second information identifier. + * This type is used when calling set_info and get_info to get a number of + * information items in one call. + */ +struct r_id_info_st +{ + /** The information identifier. */ + int info_id; + /** The information data associated with the identifier. */ + void *value; +}; + +/** @defgroup R_FLAG_COPY_IDS Copy Flag Identifiers + * + * This section provides information on the copy mode. When data is passed + * to/from the library you can specify whether or not the copy should be done + * by value, by reference or by direct assignment. + * @ingroup DATA_MNG_FLAGS + * @{ + */ + +/** + * The copy flag. When data is passed to/from the library you can specify + * whether or not the copy should be done by value, by reference or + * by direct assignment. + */ +typedef int R_FLAG_COPY; + +/* + * action flag app lib + * obj_get BY_VAL F X + * BY_REF X F [app will not free "obj" until it is + * BY_ASSIGN F X finished with the returned reference] + * obj_set BY_VAL F X + * BY_REF F X [app will not free passed reference + * BY_ASSIGN X F until after it has freed "obj"] + * + * BY_REF makes the lifetime of the two objects linked and it is up to + * the application to manage the objects in a manner that preserves this + * relationship. + */ + +/** + * Indicates to copy by value. A complete clone of the object is made. + * The lifecycles of the two objects are independent. + */ +#define R_FLAG_COPY_BY_VALUE 0x0000 + +/** + * Indicates to copy by reference. A reference to the object is made. + * The lifecycles of objects sharing references are linked. + */ +#define R_FLAG_COPY_BY_REFERENCE 0x0001 + +/** + * Indicates to copy by assignment. The object is assigned to the required + * party. The caller does not keep a reference to the passed object. + */ +#define R_FLAG_COPY_BY_ASSIGN 0x0002 + +/** + * Indicates to copy using the default flag settings. + */ +#define R_FLAG_COPY_DEFAULT R_FLAG_COPY_BY_VALUE + +/** + * @} + */ + +/** @defgroup R_FLAG_SHARE_IDS Shared Flag Identifiers + * + * This section provides information on the shared flags available. + * @ingroup DATA_MNG_FLAGS + * @{ + */ + +/** + * The constructor flag. Indicates whether or not it is permissible to share + * the internal state between objects. + */ +typedef int R_FLAG_SHARE; + +/** + * Indicates to share nothing. The states of the two objects are completely + * separate. + */ +#define R_FLAG_SHARE_NONE 0x0000 + +/** + * Indicates to share data. Constructed objects may reference the state of + * the object from which it was constructed. The lifecycles of the two objects + * are linked. + */ +#define R_FLAG_SHARE_DATA 0x0001 + +/** Indicates the share default in which nothing is shared. */ +#define R_FLAG_SHARE_DEFAULT R_FLAG_SHARE_NONE + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/build/libraries_sysmenu/acsign/ARM9/include/sha.h b/build/libraries_sysmenu/acsign/ARM9/include/sha.h new file mode 100644 index 0000000..e1543a7 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/include/sha.h @@ -0,0 +1,105 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#ifndef HEADER_COMMON_SHA_H +#define HEADER_COMMON_SHA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(CCONV) +#define CCONV +#endif + +#ifndef PRE_CCONV +#define PRE_CCONV +#endif + +#define SHA_CBLOCK 64 +#define SHA_LBLOCK 16 +#define SHA_BLOCK 16 +#define SHA_LAST_BLOCK 56 +#define SHA_LENGTH_BLOCK 8 +#define SHA_DIGEST_LENGTH 20 + +/* the default is to use unsigned long */ +#if !defined(OPT_SHA_INT) && !defined(OPT_SHA_LONG) +#define OPT_SHA_LONG +#endif + +#ifdef OPT_SHA_LONG +#define SHA_LONG unsigned long +#endif + +#ifdef OPT_SHA_INT +#define SHA_LONG unsigned int +#endif + +typedef struct sha_ctx_st SHA_CTX; + +struct sha_ctx_st + { + SHA_LONG h0,h1,h2,h3,h4; + SHA_LONG Nl,Nh; + SHA_LONG data[SHA_LBLOCK]; + int num; + void (PRE_CCONV CCONV *sha_block)(SHA_CTX *c, const unsigned char *W, + int num); + }; + +#ifndef NOPROTO +int SHA1_Setup(SHA_CTX *c, void (PRE_CCONV CCONV *sha_block)(SHA_CTX *c, + const unsigned char *W, int num)); +void SHA_Init(SHA_CTX *c); +void SHA_Update(SHA_CTX *c, const unsigned char *data, unsigned long len); +void SHA_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA(const unsigned char *d, unsigned long n,unsigned char *md); +void SHA_Transform(SHA_CTX *c, const unsigned char *data); +void SHA1_Init(SHA_CTX *c); +void SHA1_Update(SHA_CTX *c, const unsigned char *data, unsigned long len); +void SHA1_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA1(const unsigned char *d, unsigned long n,unsigned char *md); +void SHA1_Transform(SHA_CTX *c, const unsigned char *data); +#else +void SHA_Init(); +void SHA_Update(); +void SHA_Final(); +unsigned char *SHA(); +void SHA_Transform(); +void SHA1_Init(); +void SHA1_Update(); +void SHA1_Final(); +unsigned char *SHA1(); +void SHA1_Transform(); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_COMMON_SHA_H */ diff --git a/build/libraries_sysmenu/acsign/ARM9/include/sha1.h b/build/libraries_sysmenu/acsign/ARM9/include/sha1.h new file mode 100644 index 0000000..692f2e9 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/include/sha1.h @@ -0,0 +1,90 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * sha1.h + * + * Description: + * This is the header file for code which implements the Secure + * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published + * April 17, 1995. + * + * Many of the variable names in this code, especially the + * single character names, were used because those were the names + * used in the publication. + * + * Please read the file sha1.c for more information. + * + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _SHA_enum_ +#define _SHA_enum_ +enum +{ + shaSuccess = 0, + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError /* called Input after Result */ +}; +#endif + +/* + * This structure will hold context information for the SHA-1 + * hashing operation + */ +typedef struct SHA1Context +{ + unsigned long Intermediate_Hash[20/4]; /* Message Digest */ + + unsigned long Length_Low; /* Message length in bits */ + unsigned long Length_High; /* Message length in bits */ + + int Message_Block_Index; /* Index into message block array */ + unsigned char Message_Block[64]; /* 512-bit message blocks */ + + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corrupted? */ +} SHA1Context; + +/* + * Function Prototypes + */ + +int SHA1Reset( SHA1Context *); +int SHA1Input( SHA1Context *, + const unsigned char *, + unsigned int); +int SHA1Result( SHA1Context *, + unsigned char Message_Digest[20]); + +#if defined( SHA1_TEST ) +int SHA1Test( ); +#endif // SHA1_TEST + + +#ifdef __cplusplus +} +#endif + +#endif // _SHA1_H_ diff --git a/build/libraries_sysmenu/acsign/ARM9/include/sha_locl.h b/build/libraries_sysmenu/acsign/ARM9/include/sha_locl.h new file mode 100644 index 0000000..10553ab --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/include/sha_locl.h @@ -0,0 +1,290 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#ifndef HEADER_COMMON_SHA_LOCL_H +#define HEADER_COMMON_SHA_LOCL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STANDALONE +#include "r_com.h" +#else +#if 0 //RSA +#include +#include +#include +#define Memcpy memcpy +#define Memset memset +#define Strcpy strcpy +#else //NITRO +#include "acmemory.h" +#define Malloc(a) ACMemory_Alloc(a) +#define Free(a) ACMemory_Free(a) +#define Memset(a,b,c) ACMemory_Memset(a,b,c) +#define Memcpy(a,b,c) ACMemory_Memcpy(a,b,c) +#endif +#endif + +#ifdef undef +/* one or the other must be defined */ +#ifndef SHA_1 /* FIPE 180-1 */ +#define SHA_0 /* FIPS 180 */ +#endif +#endif + +#define ULONG unsigned long +#define UCHAR unsigned char +#define UINT unsigned int + +#ifdef NOCONST +#define const +#endif + +#undef c2nl +#define c2nl(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) )) + +#undef p_c2nl +#define p_c2nl(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + case 3: l|=((unsigned long)(*((c)++))); \ + } \ + } + +#undef c2nl_p +/* NOTE the pointer is not incremented at the end of this */ +#define c2nl_p(c,l,n) { \ + l=0; \ + (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<< 8; \ + case 2: l|=((unsigned long)(*(--(c))))<<16; \ + case 1: l|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +#undef p_c2nl_p +#define p_c2nl_p(c,l,sc,len) { \ + switch (sc) \ + { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + } \ + } + +#undef nl2c +#define nl2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#undef c2l +#define c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24)) + +#undef p_c2l +#define p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++))); \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + case 3: l|=((unsigned long)(*((c)++)))<<24; \ + } \ + } + +#undef c2l_p +/* NOTE the pointer is not incremented at the end of this */ +#define c2l_p(c,l,n) { \ + l=0; \ + (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<<16; \ + case 2: l|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l|=((unsigned long)(*(--(c)))); \ + } \ + } + +#undef p_c2l_p +#define p_c2l_p(c,l,sc,len) { \ + switch (sc) \ + { \ + case 0: l =((unsigned long)(*((c)++))); \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +#ifdef OPT_SHA_B_ENDIAN +#define B_ENDIAN +#endif +#ifdef OPT_SHA_L_ENDIAN +#define L_ENDIAN +#endif + +#undef ROTATE +#if defined(WIN32) +#define ROTATE(a,n) _lrotl(a,n) +#else +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + +/* byte order reversal */ +#if defined(WIN32) +/* 5 instructions with rotate instruction, else 9 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + (a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \ + } +#else +/* 6 instructions with rotate instruction, else 8 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \ + (a)=ROTATE(l,16L); \ + } +#endif + +/* F() below can be + * simplified to the code in F_00_19. + * #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) + * another tweak to be made + * in F_40_59, (x&a)|(y&a) -> (x|y)&a + */ +#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) +#define F_40_59(b,c,d) (((b) & (c)) | (((b)|(c)) & (d))) +#define F_60_79(b,c,d) F_20_39(b,c,d) + +#ifdef SHA_0 +#undef Xupdate +#define Xupdate(a,i,ia,ib,ic,id) X[(i)&0x0f]=(a)=\ + (ia[(i)&0x0f]^ib[((i)+2)&0x0f]^ic[((i)+8)&0x0f]^id[((i)+13)&0x0f]); +#endif +#ifdef SHA_1 +#undef Xupdate +#define Xupdate(a,i,ia,ib,ic,id) (a)=\ + (ia[(i)&0x0f]^ib[((i)+2)&0x0f]^ic[((i)+8)&0x0f]^id[((i)+13)&0x0f]);\ + X[(i)&0x0f]=(a)=ROTATE((a),1); +#endif + +#define BODY_00_15(i,a,b,c,d,e,f,xa) \ + (f)=xa[i]+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_60_79(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)=X[(i)&0x0f]+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \ + (b)=ROTATE((b),30); + +/* + * The CodeWarrior compiler has a problem correctly expanding things like + * + * (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); + * + * so we separate this to 3 explicit adds, just for PalmOS. + */ +#ifndef UNDER_PALMOS + +#define BODY_16_19(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,i,xa,xb,xc,xd); \ + (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_20_31(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,i,xa,xb,xc,xd); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_32_39(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_40_59(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#else /* UNDER_PALMOS */ + +#define BODY_16_19(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,i,xa,xb,xc,xd); \ + (f)+=(e); \ + (f)+=K_00_19; \ + (f)+=ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_20_31(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,i,xa,xb,xc,xd); \ + (f)+=(e); \ + (f)+=K_20_39; \ + (f)+=ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_32_39(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)+=(e); \ + (f)+=K_20_39; \ + (f)+=ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_40_59(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)+=(e); \ + (f)+=K_40_59; \ + (f)+=ROTATE((a),5)+F_40_59((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#endif /* UNDER_PALMOS */ + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_COMMON_SHA_LOCL_H */ diff --git a/build/libraries_sysmenu/acsign/ARM9/src/acmemory.c b/build/libraries_sysmenu/acsign/ARM9/src/acmemory.c new file mode 100644 index 0000000..a6785f0 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/acmemory.c @@ -0,0 +1,306 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +// +// BNn֐p̃֘Au +// +#include +#include "acmemory.h" + +/* + head tail + | | | | + +--------+---------+----....----+---------+--------+ + |block |check |buffer |check |block | + +--------+---------+----....----+---------+--------+ + |4byte |4byte |Upper4(size)|4byte |4byte | + <------------------ 4 * n -------------------> + + block = n = (4 * 4 + Upper4(size)) / 4 + check = 0x0F5555F0Fgp^0x0FAAAAF0Fgp +*/ + +unsigned long aACMemoryPoolA[ 16 ]; +unsigned long aACMemoryPool[ 1024 * 32 / sizeof (unsigned long) ]; // 32K +unsigned long aACMemoryPoolB[ 16 ]; + +#define ACMEMORYPOOL_HEAD (aACMemoryPool) +#define ACMEMORYPOOL_TAIL (aACMemoryPool + sizeof aACMemoryPool / sizeof (unsigned long)) +#define ACMEMORYPOOL_SIZE ((unsigned long)ACMEMORYPOOL_TAIL - (unsigned long)ACMEMORYPOOL_HEAD) + +#define ACMEMORY_CHECK_BASE 0xF000000F +#define ACMEMORY_CHECK_FREE (0x00555500 | ACMEMORY_CHECK_BASE) +#define ACMEMORY_CHECK_USED (0x00AAAA00 | ACMEMORY_CHECK_BASE) + +#define ACMemory_Lower4( _size ) (((_size) ) & 0xFFFFFFFC) +#define ACMemory_Upper4( _size ) (((_size) + 3) & 0xFFFFFFFC) + +#define pACMemory_FromHeadToBody( _head ) ((unsigned long*)(((volatile unsigned long*)(_head)) + 2)) +#define pACMemory_FromBodyToHead( _body ) ((unsigned long*)(((volatile unsigned long*)(_body)) - 2)) +#define pACMemory_FromHeadToTail( _head ) ((unsigned long*)(((volatile unsigned long*)(_head)) + nACMemory_HeadBlock( _head ))) +#define pACMemory_FromTailToHead( _tail ) ((unsigned long*)(((volatile unsigned long*)(_tail)) - nACMemory_TailBlock( _tail ))) +#define nACMemory_HeadBlock( _head ) (((volatile unsigned long*)(_head))[+0]) +#define nACMemory_HeadCheck( _head ) (((volatile unsigned long*)(_head))[+1]) +#define nACMemory_TailBlock( _tail ) (((volatile unsigned long*)(_tail))[-1]) +#define nACMemory_TailCheck( _tail ) (((volatile unsigned long*)(_tail))[-2]) + +//#define USE_OSALLOC +//#define USE_ACMEMORY_DEBUGDUMP +//#define USE_ACMEMORY_DEBUGFILL + +// +#if defined( USE_ACMEMORY_DEBUGDUMP ) +static +void acMemory_DebugDump( ) +{ + unsigned long* ptr = ACMEMORYPOOL_HEAD; + + // + OS_Printf( "----ACMemory_Dump [0x%.8x - 0x%.8x : 0x%.8x ]----\n", ACMEMORYPOOL_HEAD, ACMEMORYPOOL_TAIL, ACMEMORYPOOL_SIZE ); + + for ( ; (unsigned long)ptr < (unsigned long)ACMEMORYPOOL_TAIL; ) + { + OS_Printf( " [0x%.8x - 0x%.8x] (0x%.8x) <%c> ", + ptr, + pACMemory_FromHeadToTail( ptr ), + nACMemory_HeadBlock( ptr ), + nACMemory_HeadCheck( ptr ) == ACMEMORY_CHECK_USED ? '*' : '-' ); + + //OS_Printf( "0x%.8x 0x%.8x", nACMemory_HeadBlock( ptr ), nACMemory_HeadCheck( ptr ) ); + + //OS_Printf( " .... " ); + + ptr += nACMemory_HeadBlock( ptr ); + + //OS_Printf( "0x%.8x 0x%.8x", nACMemory_TailCheck( ptr ), nACMemory_TailBlock( ptr ) ); + + OS_Printf( "\n" ); + OS_PrintServer(); + } + ptr = 0; +} + +#define ACMemory_DebugDump( ) acMemory_DebugDump( ) + +#else + +#define ACMemory_DebugDump( ) + +#endif //USE_ACMEMORY_DEBUGDUMP + +// +#if defined( USE_ACMEMORY_DEBUGFILL ) +static +void acMemory_DebugFill( void* ptr, int cnt, int val ) +{ + (void)ACMemory_Memset( ptr, val, cnt ); +} + +#define ACMemory_DebugFill( _ptr, _cnt, _val ) acMemory_DebugFill( _ptr, _cnt, _val ) + +#else + +#define ACMemory_DebugFill( _ptr, _cnt, _val ) + +#endif //USE_ACMEMORY_DEBUGFILL + +// +void ACMemory_Clear( ) +{ + unsigned long* head = ACMEMORYPOOL_HEAD; + unsigned long* tail = ACMEMORYPOOL_TAIL; + unsigned long block; + unsigned long check; + + + block = ACMEMORYPOOL_SIZE / 4; + check = ACMEMORY_CHECK_FREE; + + nACMemory_HeadBlock( head ) = block; + nACMemory_HeadCheck( head ) = check; + nACMemory_TailBlock( tail ) = block; + nACMemory_TailCheck( tail ) = check; + + ACMemory_DebugFill( pACMemory_FromHeadToBody( head ), (block - 4) * 4, 0xFF ); + ACMemory_DebugDump( ); +} + +// +void* ACMemory_Alloc( u32 size ) +{ + #if defined( USE_OSALLOC ) + OSIntrMode nOSIntrMode; + void* alloc = NULL; + + nOSIntrMode = OS_DisableInterrupts( ); + alloc = OS_Alloc( size ); + (void)OS_RestoreInterrupts( nOSIntrMode ); + return alloc; + + #else + + unsigned long* head = ACMEMORYPOOL_HEAD; + unsigned long* tail = ACMEMORYPOOL_TAIL; + unsigned long block, oldblock, newblock; + unsigned long check, oldcheck, newcheck; + + if ( !size ) return 0; + + // + if ( size < 16 ) size = 16; + block = 4 + ACMemory_Upper4( size ) / 4; + check = ACMEMORY_CHECK_USED; + + // + for ( ; ; ) + { + if ( (unsigned long)head >= (unsigned long)tail ) + { + head = 0; + break; + } + + newblock = nACMemory_HeadBlock( head ); + newcheck = nACMemory_HeadCheck( head ); + if ( newcheck == check ) + { + head += newblock; + continue ; + } + if ( newblock < block + 4 + 4 ) + { + head += newblock; + continue ; + } + + break; + } + + if ( !head ) return 0; + + // + oldblock = nACMemory_HeadBlock( head ); + oldcheck = nACMemory_HeadCheck( head ); + + nACMemory_HeadBlock( head ) = block; + nACMemory_HeadCheck( head ) = check; + + tail = pACMemory_FromHeadToTail( head ); + nACMemory_TailBlock( tail ) = block; + nACMemory_TailCheck( tail ) = check; + + if ( (unsigned long)tail < (unsigned long)ACMEMORYPOOL_TAIL ) + { + nACMemory_HeadBlock( tail ) = oldblock - block; + nACMemory_HeadCheck( tail ) = oldcheck; + tail = pACMemory_FromHeadToTail( tail ); + nACMemory_TailBlock( tail ) = oldblock - block; + nACMemory_TailCheck( tail ) = oldcheck; + } + + // + (void)ACMemory_Memset( pACMemory_FromHeadToBody( head ), 0x00, (block - 4) * 4 ); + + ACMemory_DebugFill( pACMemory_FromHeadToBody( head ), (block - 4) * 4, 0x00 ); + ACMemory_DebugDump( ); + + return (void*)pACMemory_FromHeadToBody( head ); + #endif +} + +// +void ACMemory_Free( void* adrs ) +{ + #if defined( USE_OSALLOC ) + OSIntrMode nOSIntrMode; + + nOSIntrMode = OS_DisableInterrupts( ); + OS_Free( adrs ); + (void)OS_RestoreInterrupts( nOSIntrMode ); + #else + + unsigned long* work; + unsigned long* head; + unsigned long* tail; + unsigned long block; + unsigned long check; + + + if ( !adrs ) return ; + + // + head = pACMemory_FromBodyToHead( adrs ); + tail = pACMemory_FromHeadToTail( head ); + block = nACMemory_HeadBlock( head ); + check = ACMEMORY_CHECK_FREE; + + // + if ( nACMemory_HeadBlock( head ) != nACMemory_TailBlock( tail ) ) + return ; + if ( nACMemory_HeadCheck( head ) != nACMemory_TailCheck( tail ) ) + return ; + + + // + if ( (unsigned long)head != (unsigned long)ACMEMORYPOOL_HEAD ) + { + work = pACMemory_FromTailToHead( head ); + if ( nACMemory_HeadCheck( work ) == check ) + { + block += nACMemory_HeadBlock( work ); + head = work; + } + } + // + if ( (unsigned long)tail != (unsigned long)ACMEMORYPOOL_TAIL ) + { + work = pACMemory_FromHeadToTail( tail ); + if ( nACMemory_TailCheck( work ) == check ) + { + block += nACMemory_TailBlock( work ); + tail = work; + } + } + + // + nACMemory_HeadBlock( head ) = nACMemory_TailBlock( tail ) = block; + nACMemory_HeadCheck( head ) = nACMemory_TailCheck( tail ) = check; + + ACMemory_DebugFill( pACMemory_FromHeadToBody( head ), (block - 4) * 4, 0xFF ); + ACMemory_DebugDump( ); + + #endif +} + + +// +void* ACMemory_Memset( void* adrs, u32 val, u32 cnt ) +{ + if ( !adrs ) return 0; + MI_CpuFill8( (void*)adrs, (u8)val, (u32)cnt ); + return adrs; +} + +// +void* ACMemory_Memcpy( void* dst, void* src, u32 cnt ) +{ + if ( !dst || !src ) return 0; + MI_CpuCopy8( (const void*)src, (void*)dst, (u32)cnt ); + return dst; +} + + diff --git a/build/libraries_sysmenu/acsign/ARM9/src/acsign.c b/build/libraries_sysmenu/acsign/ARM9/src/acsign.c new file mode 100644 index 0000000..f5dc67d --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/acsign.c @@ -0,0 +1,453 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "acmemory.h" + +// SHA1 +#include "sha.h" +#include "sha1dgst.c" + +#define _DLENGTH_ (160/8) +#define _BLENGTH_ (512/8) + +#define HASHContext SHA_CTX + +#define HASHReset( _context ) (void)SHA1_Init( _context ) +#define HASHSetSource( _context, _ptr, _len ) (void)SHA1_Update( _context, _ptr, _len ) +#define HASHGetDigest( _context, _ptr ) (void)SHA1_Final( _ptr, _context ) + +// BN +#include "bn.h" + +#include "bn_lib.c" +#include "bn_asm.c" +#include "bn_comba.c" +#include "bn_lsh.c" +#include "bn_rsh.c" +#include "bn_word.c" +#include "bn_add.c" +#include "bn_mul.c" +#include "bn_div.c" +#include "bn_exp.c" +#include "bn_sqr.c" +#include "bn_fm_w.c" +#include "bn_gcd.c" +#include "bn_ex_str.c" +#include "bn_ms_w.c" +//#include "bn_me.c" +#include "bn_rec.c" +#include "bn_mont.c" +#include "bn_recp.c" +#include "bn_wdiv.c" +#include "bn_r_exp.c" +#include "bn_m_exp.c" + + +#if !defined( RSA_ENC_DEC ) + +#define BER_NULL 5 +#define BER_OBJECT 6 +#define BER_SEQUENCE 16 +#define BER_OCTET_STRING 4 +#define BER_CONSTRUCTED 0x20 + + +// +// rsa_padding_check_pkcs1_type_1֐ +// +static +int decode_padding( unsigned char* pdst_adrs, unsigned int* pdst_size, + unsigned char* psrc_adrs, unsigned int nsrc_size, + int length ) +{ + unsigned char* p; + unsigned char* q; + unsigned char* pe; + int i; + + if (nsrc_size >= length ) + return 0; + + /* The leading 0 was removed by the bignum->bin conversion */ + if (nsrc_size < 10) + return 0; + + p = psrc_adrs; + pe = &(psrc_adrs[nsrc_size]); + /* if (p[0] != 0) goto err; */ + if ( p[0] != 1 ) + return 0; + p++; + + for ( i = 0; i < 8; i++ ) + { + if ( *(p++) != 0xFF ) + return 0; + } + for ( ; p != pe; p++ ) + { + if ( *p != 0xFF ) + break; + } + if ( p == pe ) + return 0; + + if ( *(p++) != 0 ) + return 0; + + *pdst_size = (unsigned int)((int)pe - (int)p); + q = pdst_adrs; + while ( p != pe ) + *(q++)= *(p++); + + return 1; +} + +// +// +// +static +int pk_skip( unsigned char **datap, unsigned int *dlenp, + unsigned char type, unsigned int *lenp) +{ + unsigned char *data = *datap; + unsigned int dlen = *dlenp; + unsigned int len = 0; + unsigned char l; + + if (*(data++) != type) + return 0; + + if (dlen < 1) + return 0; + dlen--; + + if ( (*data & 0x80) != 0 ) + { + l = (unsigned char)( *data & 0x7F ); + if (dlen < (unsigned int)l + 1) + return 0; + dlen -= l; + if (lenp != NULL) + { + data++; + do + { + len <<= 7; + len += (*data & 0x7f); + l--; + } + while (l > 0); + } + else + { + data += l; + } + } + else + { + len = *data; + data++; + if (dlen < 1) + return 0; + dlen--; + } + + *datap = data; + *dlenp = dlen; + if (lenp != NULL) + { + *lenp = len; + } + + return 1; +} + +// +// PK_decode_sighash֐ +// +static +int decode_sighash( unsigned char* data, unsigned int dlen, + unsigned char** ppdgst_adrs, unsigned int* pdgst_size, + unsigned char** pphash_adrs, unsigned int* phash_size ) +{ + #if 0 + /* 01 */ OB_cmpu(BER_SEQUENCE, 0, 0), + /* 02 */ OB_down(0, 1), + /* 03 */ OB_cmpu(BER_SEQUENCE, 0, 0), + /* 04 */ OB_down(0, 1), + /* 05 */ OB_cmpu(BER_OBJECT, 0, 0), + /* 06 */ OB_call(OB_F_SET, PK_TYPE_SIG, PK_SIG_DIGEST_OID), + + /* go up a level - we got all we need out of the + * sequence that contains the parameters + * - we could OB_next(0,1) and check that we have BER_NULL + * as then next item but there is no real need to do that + */ + + /* 07 */ OB_up(0, 1), + /* 08 */ OB_next(0, 1), + /* 09 */ OB_cmpu(BER_OCTET_STRING, 0, 0), + /* 10 */ OB_call(OB_F_SET, PK_TYPE_SIG, PK_SIG_HASH), + + /* 11 */ OB_exit(0), + /* 12 */ OB_FINISH, + #endif + + unsigned int len; + + if ( !pk_skip(&data, &dlen, (BER_SEQUENCE|BER_CONSTRUCTED), NULL) ) + return 0; + + if ( !pk_skip(&data, &dlen, (BER_SEQUENCE|BER_CONSTRUCTED), NULL) ) + return 0; + + if ( !pk_skip(&data, &dlen, (BER_OBJECT), &len) ) + return 0; + + /* + if (digest != NULL) + { + digest->adrs = data; + digest->size = len; + } + */ + if ( ppdgst_adrs ) *ppdgst_adrs = data; + if ( pdgst_size ) *pdgst_size = len; + + data += len; + if (dlen < len) + return 0; + dlen -= len; + + if ( !pk_skip(&data, &dlen, BER_NULL, &len) ) + return 0; + data += len; + if (dlen < len) + return 0; + dlen -= len; + + if ( !pk_skip(&data, &dlen, (BER_OCTET_STRING), &len) ) + return 0; + + /* + if (hash != NULL) + { + hash->adrs = data; + hash->size = len; + } + */ + if ( pphash_adrs ) *pphash_adrs = data; + if ( phash_size ) *phash_size = len; + + return 1; +} + +#endif + + + + +// +#define SGN_LEN 128 +#define MOD_LEN 128 +#define EXP_LEN 3 + +int ACSign_Decrypto( + void* buffer, // o͗̈ + void* sgn_ptr, // f[^ւ̃|C^ + void* key_ptr // L[ւ̃|C^ + ) +{ + BN_CTX* ctx; + BIGNUM src, dst, exp, mod; + void* exp_ptr; + void* mod_ptr; + int nTmp, nWrk; + unsigned char* pAdrs = 0; + unsigned int nSize = 0; + unsigned long nDummyExp = 0x00010001; // 65537Œ + unsigned long aBufferA[ 256 / sizeof (unsigned long) ]; + unsigned long aBufferB[ 256 / sizeof (unsigned long) ]; + + + if ( !buffer ) return 0; + if ( !sgn_ptr ) return 0; + if ( !key_ptr ) return 0; + + // + ACMemory_Clear( ); + + // + exp_ptr = &nDummyExp; + mod_ptr = key_ptr; + + (void)ACMemory_Memset( aBufferA, 0, sizeof aBufferA ); + (void)ACMemory_Memset( aBufferB, 0, sizeof aBufferB ); + + ctx=BN_CTX_new(); + + BN_init( &src ); + BN_init( &dst ); + BN_init( &exp ); + BN_init( &mod ); + + (void)BN_bin2bn( sgn_ptr, SGN_LEN, &src ); + (void)BN_bin2bn( exp_ptr, EXP_LEN, &exp ); + (void)BN_bin2bn( mod_ptr, MOD_LEN, &mod ); + + nTmp = BN_mod_exp( &dst, &src, &exp, &mod, ctx ); + + nTmp = BN_bn2bin( &dst, (unsigned char*)aBufferA ); + + BN_free( &src ); + BN_free( &dst ); + BN_free( &exp ); + BN_free( &mod ); + + if (ctx != NULL) + BN_CTX_free(ctx); + + #if defined( RSA_ENC_DEC ) + + pAdrs = (unsigned char*)aBufferA + 4; //_~[SoCg͓ǂݔ΂ + nSize = nTmp; + + (void)ACMemory_Memcpy( buffer, pAdrs, _DLENGTH_ * 4 ); + + #else + + if ( !decode_padding( (unsigned char*)aBufferB, (unsigned int*)&nWrk, (unsigned char*)aBufferA, (unsigned int )nTmp, SGN_LEN ) ) + return 0; + if ( !decode_sighash( (unsigned char*)aBufferB, (unsigned int)nWrk, NULL, NULL, (unsigned char**)&pAdrs, (unsigned int*)&nSize ) ) + return 0; + if ( nSize != _DLENGTH_ ) + return 0; + + (void)ACMemory_Memcpy( buffer, pAdrs, _DLENGTH_ * 1 ); + + #endif + + return 1; +} + + +// +#define ROMH_SIZE 0x0160 +int ACSign_Digest( + void* buffer, // o͗̈ + void* romh_ptr, // f[^ւ̃|C^ + void* mbin_ptr, // f[^ւ̃|C^ + int mbin_len, // f[^̒ + void* sbin_ptr, // f[^ւ̃|C^ + int sbin_len, // f[^̒ + u32 serial_num // VAio[ + ) +{ + #if defined( RSA_ENC_DEC ) + HASHContext context; + + + if ( !buffer ) return 0; + if ( !romh_ptr ) return 0; + if ( !mbin_ptr || !mbin_len ) return 0; + if ( !sbin_ptr || !sbin_len ) return 0; + + + HASHReset( &context ); + HASHSetSource( &context, romh_ptr, ROMH_SIZE ); + HASHGetDigest( &context, (unsigned char*)buffer + _DLENGTH_ * 0 ); + + HASHReset( &context ); + HASHSetSource( &context, mbin_ptr, mbin_len ); + HASHGetDigest( &context, (unsigned char*)buffer + _DLENGTH_ * 1 ); + + HASHReset( &context ); + HASHSetSource( &context, sbin_ptr, sbin_len ); + HASHGetDigest( &context, (unsigned char*)buffer + _DLENGTH_ * 2 ); + + HASHReset( &context ); + HASHSetSource( &context, buffer, _DLENGTH_ * 3 ); + HASHGetDigest( &context, (unsigned char*)buffer + _DLENGTH_ * 3 ); + + #else + + HASHContext context; + unsigned char aBuffer[ (_DLENGTH_ * 3 + sizeof (unsigned long)) ]; + + if ( !buffer ) return 0; + if ( !romh_ptr ) return 0; + if ( !mbin_ptr || !mbin_len ) return 0; + if ( !sbin_ptr || !sbin_len ) return 0; + + HASHReset( &context ); + HASHSetSource( &context, romh_ptr, ROMH_SIZE ); + HASHGetDigest( &context, (unsigned char*)aBuffer + _DLENGTH_ * 0 ); + + HASHReset( &context ); + HASHSetSource( &context, mbin_ptr, mbin_len ); + HASHGetDigest( &context, (unsigned char*)aBuffer + _DLENGTH_ * 1 ); + + HASHReset( &context ); + HASHSetSource( &context, sbin_ptr, sbin_len ); + HASHGetDigest( &context, (unsigned char*)aBuffer + _DLENGTH_ * 2 ); + + // VAԍ ͂OŒ + aBuffer[ (_DLENGTH_ * 3) + 0 ] = (unsigned char)((serial_num >> 0) & 0xFF); + aBuffer[ (_DLENGTH_ * 3) + 1 ] = (unsigned char)((serial_num >> 8) & 0xFF); + aBuffer[ (_DLENGTH_ * 3) + 2 ] = (unsigned char)((serial_num >> 16) & 0xFF); + aBuffer[ (_DLENGTH_ * 3) + 3 ] = (unsigned char)((serial_num >> 24) & 0xFF); + + HASHReset( &context ); + HASHSetSource( &context, (unsigned char*)aBuffer, _DLENGTH_ * 3 + sizeof (unsigned long) ); + HASHGetDigest( &context, (unsigned char*)buffer ); + #endif + return 1; +} + + +// +int ACSign_Compare( + void* decrypto, // ACSign_Decryptȍo + void* digest // ACSign_Digest̏o + ) +{ + unsigned char* ptrA = (unsigned char*)decrypto; + unsigned char* ptrB = (unsigned char*)digest; + int loop; + int test = 1; + + if ( !decrypto ) return 0; + if ( !digest ) return 0; + + #if defined( RSA_ENC_DEC ) + for ( loop = 0; loop < _DLENGTH_ * 4; loop++ ) + #else + for ( loop = 0; loop < _DLENGTH_ * 1; loop++ ) + #endif + { + if ( *ptrA++ != *ptrB++ ) + { + test = 0; + break; + } + } + return test; +} + + diff --git a/build/libraries_sysmenu/acsign/ARM9/src/acsign_util.c b/build/libraries_sysmenu/acsign/ARM9/src/acsign_util.c new file mode 100644 index 0000000..ccda052 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/acsign_util.c @@ -0,0 +1,111 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include + +#define AUTH_KEY_BUFFER_LEN 128 +#define MB_AUTH_SIGN_SIZE (128) /* digital sign size */ + + +typedef struct MbAuthCode +{ + char magic_code[2]; // }WbNio[ + u16 version; // o[W + u8 sign[MB_AUTH_SIGN_SIZE]; // + u32 serial_number; // VAԍ +} MbAuthCode; // 16byte + + + +static u8 key_buffer[AUTH_KEY_BUFFER_LEN] = { + 0x9E,0xC1,0xCC,0xC0,0x4A,0x6B,0xD0,0xA0,0x6D,0x62,0xED,0x5F,0x15,0x67,0x87,0x12, + 0xE6,0xF4,0x77,0x1F,0xD8,0x5C,0x81,0xCE,0x0C,0xD0,0x22,0x31,0xF5,0x89,0x08,0xF5, + 0xBE,0x04,0xCB,0xC1,0x4F,0x63,0xD9,0x5A,0x98,0xFF,0xEB,0x36,0x0F,0x9C,0x5D,0xAD, + 0x15,0xB9,0x99,0xFB,0xC6,0x86,0x2C,0x0A,0x0C,0xFC,0xE6,0x86,0x03,0x60,0xD4,0x87, + 0x28,0xD5,0x66,0x42,0x9C,0xF7,0x04,0x14,0x4E,0x6F,0x73,0x20,0xC3,0x3E,0x3F,0xF5, + 0x82,0x2E,0x78,0x18,0xD6,0xCD,0xD5,0xC2,0xDC,0xAA,0x1D,0x34,0x91,0xEC,0x99,0xC9, + 0xF7,0xBF,0xBF,0xA0,0x0E,0x1E,0xF0,0x25,0xF8,0x66,0x17,0x54,0x34,0x28,0x2D,0x28, + 0xA3,0xAE,0xF0,0xA9,0xFA,0x3A,0x70,0x56,0xD2,0x34,0xA9,0xC5,0x9E,0x5D,0xF5,0xE1 +}; + + +int ACSignDecrpto(void *output_buffer, MBDownloadFileInfo *download_file_info_buf) +{ + return ACSign_Decrypto(output_buffer, + ((MbAuthCode *)(download_file_info_buf->auth_code))->sign, + key_buffer); +} + + +int ACSignDigest(void *input_buffer, MBDownloadFileInfo *download_file_info_buf) +{ + int ret_code; + u8 digest_output_buffer[AUTH_BUFFER_LEN]; + + ret_code = ACSign_Digest((void *)digest_output_buffer, // o͗̈ 20 Bytes + (void *)(download_file_info_buf->seg[0].recv_addr), + (void *)(download_file_info_buf->seg[1].recv_addr), + (int)(download_file_info_buf->seg[1].size), + (void *)(download_file_info_buf->seg[2].recv_addr), + (int)(download_file_info_buf->seg[2].size), + ((MbAuthCode *)(download_file_info_buf)->auth_code)->serial_number // serial_number + ); + if( ret_code == 0 ) + { + return ret_code; // failure + } + + return ACSign_Compare( + input_buffer, // ACSign_Decryptȍo + (void*)digest_output_buffer // ACSign_Digest̏o + ); +} + +#if 0 +void* doAlloc( int size ) +{ + OSIntrMode nOSIntrMode; + void* alloc = NULL; + + nOSIntrMode = OS_DisableInterrupts( ); + alloc = OS_Alloc( size ); + (void)OS_RestoreInterrupts( nOSIntrMode ); + return alloc; +} + +void doFree( void* adrs ) +{ + OSIntrMode nOSIntrMode; + + nOSIntrMode = OS_DisableInterrupts( ); + OS_Free( adrs ); + (void)OS_RestoreInterrupts( nOSIntrMode ); +} + +void* doMemset( void* adrs, int val, int cnt ) +{ + return memset( adrs, val, cnt ); +} + +void* doMemcpy( void* dst, void* src, int cnt ) +{ + return memcpy( dst, src, cnt ); +} + +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_add.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_add.c new file mode 100644 index 0000000..7b36c8b --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_add.c @@ -0,0 +1,320 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +/** + * @file bn_add.c + * @brief BIGNUM addition and subtraction functions + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_ADD +#define SPLIT_BN_UADD +#define SPLIT_BN_USUB +#define SPLIT_BN_SUB +#endif /* NO_SPLIT */ + +#ifdef SPLIT_BN_ADD +/* r can == a or b */ +int BN_add(r, a, b) +BIGNUM *r; +BIGNUM *a; +BIGNUM *b; + { + BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + /* a + b a+b + * a + -b a-b + * -a + b b-a + * -a + -b -(a+b) + */ + if (a->neg ^ b->neg) + { + /* only one is negative */ + if (a->neg) + { tmp=a; a=b; b=tmp; } + + /* we are now a - b */ + + if (BN_ucmp(a,b) < 0) + { + if (!BN_usub(r,b,a)) return(0); + r->neg=1; + } + else + { + if (!BN_usub(r,a,b)) return(0); + r->neg=0; + } + return(1); + } + + if (a->neg) /* both are neg */ + r->neg=1; + else + r->neg=0; + + if (!BN_uadd(r,a,b)) return(0); + return(1); + } +#endif + +#ifdef SPLIT_BN_UADD +/* unsigned add of b to a, r must be large enough */ +int BN_uadd(r,a,b) +BIGNUM *r; +BIGNUM *a; +BIGNUM *b; + { + register int i; + int max,min; + BN_ULONG *ap,*bp,*rp,carry,t1; + BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + if (a->top < b->top) + { tmp=a; a=b; b=tmp; } + max=a->top; + min=b->top; + + if (bn_wexpand(r,max+1) == NULL) + return(0); + + r->top=max; + + + ap=a->d; + bp=b->d; + rp=r->d; + carry=0; + + carry=bn_add_words(rp,ap,bp,min); + rp+=min; + ap+=min; + bp+=min; + i=min; + + if (carry) + { + while (i < max) + { + i++; + t1= *(ap++); + if ((*(rp++)=(t1+1)&BN_MASK2) >= t1) + { + carry=0; + break; + } + } + if ((i >= max) && carry) + { + *(rp++)=1; + r->top++; + } + } + if (rp != ap) + { + for (; ib from a + * @param r result of subtraction + * @param a pointer to a BIGNUM + * @param b pointer to a BIGNUM + * @pre a must be larger than b + * @return 1 on success, 0 on failure + * @todo On next IRIX port check the validity of IRIX_CC_BUG. + */ +#ifdef SPLIT_BN_USUB +int BN_usub(r, a, b) +BIGNUM *r; +BIGNUM *a; +BIGNUM *b; + { + int max,min; + register BN_ULONG t1,t2,*ap,*bp,*rp; + int i,carry; +#if defined(IRIX_CC_BUG) && !defined(LINT) + int dummy; +#endif + + bn_check_top(a); + bn_check_top(b); + + /* + * check for pre-condition violation + */ + if (a->top < b->top) + { +#ifndef NO_ERR + BNerr(BN_F_BN_USUB,BN_R_ARG2_LT_ARG3); +#endif + return(0); + } + + max=a->top; + min=b->top; + if (bn_wexpand(r,max) == NULL) return(0); + + ap=a->d; + bp=b->d; + rp=r->d; + + /* + * perform the subtraction and see if we + * have a (final) carry + */ + carry=0; + for (i=0; i t2) break; + } + } + + if (rp != ap) + { +#ifdef BN_LIBRARY_SMALL + Memcpy(rp,ap,sizeof(*rp)*(max-i)); +#else /* BN_LIBRARY_SMALL */ + for (;;) + { + if (i++ >= max) break; + rp[0]=ap[0]; + if (i++ >= max) break; + rp[1]=ap[1]; + if (i++ >= max) break; + rp[2]=ap[2]; + if (i++ >= max) break; + rp[3]=ap[3]; + rp+=4; + ap+=4; + } +#endif /* BN_LIBRARY_SMALL */ + } + + r->top=max; + bn_fix_top(r); + return(1); + } +#endif + +#ifdef SPLIT_BN_SUB +int BN_sub(r, a, b) +BIGNUM *r; +BIGNUM *a; +BIGNUM *b; + { + int max; + int add=0,neg=0; + BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + /* a - b a-b + * a - -b a+b + * -a - b -(a+b) + * -a - -b b-a + */ + if (a->neg) + { + if (b->neg) + { tmp=a; a=b; b=tmp; } + else + { add=1; neg=1; } + } + else + { + if (b->neg) { add=1; neg=0; } + } + + if (add) + { + if (!BN_uadd(r,a,b)) return(0); + r->neg=neg; + return(1); + } + + /* We are actually doing a - b */ + + max=(a->top > b->top)?a->top:b->top; + if (bn_wexpand(r,max) == NULL) return(0); + if (BN_ucmp(a,b) < 0) + { + if (!BN_usub(r,b,a)) return(0); + r->neg=1; + } + else + { + if (!BN_usub(r,a,b)) return(0); + r->neg=0; + } + return(1); + } +#endif + +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_asm.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_asm.c new file mode 100644 index 0000000..64efa61 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_asm.c @@ -0,0 +1,525 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#ifndef OPT_BN_ASM + +#define BN_MUL_ADD_WORDS + +#ifndef BN_MUL_WORDS +#define BN_MUL_WORDS +#endif + +#ifndef BN_SQR_WORDS +#define BN_SQR_WORDS +#endif + +#ifndef BN_ADD_WORDS +#define BN_ADD_WORDS +#endif + +#ifndef BN_SUB_WORDS +#define BN_SUB_WORDS +#endif + +#endif + + +#include "bn_lcl.h" + +#ifdef BN_LLONG + +/* + * bn_mul_add_words + * + * for(i=0;i=0; i--) + fprintf(stderr,BN_HEX_FMT,ap[i]); + fprintf(stderr,"*"); + fprintf(stderr,BN_HEX_FMT,w); + fprintf(stderr,"+"); + for (i=num-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,rp[i]); +#endif + + for (;;) + { + mul_add(rp[0],ap[0],w,c1); + if (--num == 0) break; + mul_add(rp[1],ap[1],w,c1); + if (--num == 0) break; + mul_add(rp[2],ap[2],w,c1); + if (--num == 0) break; + mul_add(rp[3],ap[3],w,c1); + if (--num == 0) break; + ap+=4; + rp+=4; + } + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + fprintf(stderr,"-"); + fprintf(stderr,BN_HEX_FMT,c1); + for (i=nn-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,rp[i]); + fprintf(stderr,"\n"); + } +#endif + return(c1); + } +#endif + +#ifdef BN_MUL_WORDS +BN_ULONG bn_mul_words(rp,ap,num,w) +BN_ULONG *rp,*ap; +int num; +BN_ULONG w; + { + BN_ULONG c1=0; + + bn_check_num(num); + if (num <= 0) return(c1); + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + { + int i,nn=num; + + for (i=num-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,ap[i]); + fprintf(stderr,"*"); + fprintf(stderr,BN_HEX_FMT,w); +#endif + + for (;;) + { + mul(rp[0],ap[0],w,c1); + if (--num == 0) break; + mul(rp[1],ap[1],w,c1); + if (--num == 0) break; + mul(rp[2],ap[2],w,c1); + if (--num == 0) break; + mul(rp[3],ap[3],w,c1); + if (--num == 0) break; + ap+=4; + rp+=4; + } + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + fprintf(stderr,"-"); + fprintf(stderr,BN_HEX_FMT,c1); + for (i=nn-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,rp[i]); + fprintf(stderr,"\n"); + } +#endif + return(c1); + } +#endif + +#ifdef BN_SQR_WORDS +void bn_sqr_words(r,a,n) +BN_ULONG *r,*a; +int n; + { + bn_check_num(n); + if (n <= 0) return; + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + { + int i,nn=n; + + for (i=n-1; i>=0; i--) + { + fprintf(stderr,BN_HEX_FMT,a[i]); + if (i != 0) + fprintf(stderr,"^2*2^%X+",i*2*BN_BITS2); + else + fprintf(stderr,"^2"); + } +#endif + + for (;;) + { + BN_ULLONG t; + + t=(BN_ULLONG)(a[0])*(a[0]); + r[0]=Lw(t); r[1]=Hw(t); + if (--n == 0) break; + + t=(BN_ULLONG)(a[1])*(a[1]); + r[2]=Lw(t); r[3]=Hw(t); + if (--n == 0) break; + + t=(BN_ULLONG)(a[2])*(a[2]); + r[4]=Lw(t); r[5]=Hw(t); + if (--n == 0) break; + + t=(BN_ULLONG)(a[3])*(a[3]); + r[6]=Lw(t); r[7]=Hw(t); + if (--n == 0) break; + + a+=4; + r+=8; + } +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + + fprintf(stderr,"-"); + for (i=nn+nn-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,r[i]); + fprintf(stderr,"\n"); + } +#endif + } +#endif + +#else + +#ifdef BN_MUL_ADD_WORDS + +BN_ULONG bn_mul_add_words(rp,ap,num,w) +BN_ULONG *rp,*ap; +int num; +BN_ULONG w; + { + BN_ULONG c=0; + BN_ULONG bl,bh,b_hl; + + bn_check_num(num); + if (num <= 0) return((BN_ULONG)0); + + bl=LBITS(w); + bh=HBITS(w); + b_hl=bh-bl; +/* +{ int i,nnum=num; +BN_ULONG *rrp=rp; +for (i=num-1; i>=0; i--) printf("%02X",rp[i]); +printf("+"); +for (i=num-1; i>=0; i--) printf("%02X",ap[i]); +printf("*%02X - ",w); +*/ + for (;;) + { + mul_add(rp[0],ap[0],bl,bh,b_hl,c); + if (--num == 0) break; + mul_add(rp[1],ap[1],bl,bh,b_hl,c); + if (--num == 0) break; + mul_add(rp[2],ap[2],bl,bh,b_hl,c); + if (--num == 0) break; + mul_add(rp[3],ap[3],bl,bh,b_hl,c); + if (--num == 0) break; + ap+=4; + rp+=4; + } + +/* +printf("%02X",c); +for (i=nnum-1; i>=0; i--) printf("%02X",rrp[i]); +printf("\n"); +} +*/ + return(c); + } + +#endif + +#ifdef BN_MUL_WORDS +BN_ULONG bn_mul_words(rp,ap,num,w) +BN_ULONG *rp,*ap; +int num; +BN_ULONG w; + { + BN_ULONG carry=0; + BN_ULONG bl,bh; + + bn_check_num(num); + if (num <= 0) return((BN_ULONG)0); + + bl=LBITS(w); + bh=HBITS(w); + + for (;;) + { + mul(rp[0],ap[0],bl,bh,carry); + if (--num == 0) break; + mul(rp[1],ap[1],bl,bh,carry); + if (--num == 0) break; + mul(rp[2],ap[2],bl,bh,carry); + if (--num == 0) break; + mul(rp[3],ap[3],bl,bh,carry); + if (--num == 0) break; + ap+=4; + rp+=4; + } + return(carry); + } +#endif + +#ifdef BN_SQR_WORDS +void bn_sqr_words(r,a,n) +BN_ULONG *r,*a; +int n; + { + bn_check_num(n); + if (n <= 0) return; + for (;;) + { + sqr64(r[0],r[1],a[0]); + if (--n == 0) break; + + sqr64(r[2],r[3],a[1]); + if (--n == 0) break; + + sqr64(r[4],r[5],a[2]); + if (--n == 0) break; + + sqr64(r[6],r[7],a[3]); + if (--n == 0) break; + + a+=4; + r+=8; + } + } +#endif + +#endif + +#ifdef BN_ADD_WORDS +#ifdef BN_LLONG +BN_ULONG bn_add_words(r,a,b,n) +BN_ULONG *r,*a,*b; +int n; + { + BN_ULLONG ll=0; + + bn_check_num(n); + if (n <= 0) return((BN_ULONG)0); + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + { + int i,nn=n; + + for (i=n-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,a[i]); + fprintf(stderr,"+"); + for (i=n-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,b[i]); +#endif + + for (;;) + { + ll+=(BN_ULLONG)a[0]+b[0]; + r[0]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + ll+=(BN_ULLONG)a[1]+b[1]; + r[1]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + ll+=(BN_ULLONG)a[2]+b[2]; + r[2]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + ll+=(BN_ULLONG)a[3]+b[3]; + r[3]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + a+=4; + b+=4; + r+=4; + } +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + fprintf(stderr,"-"); + fprintf(stderr,BN_HEX_FMT,(BN_ULONG)ll); + for (i=nn-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,r[i]); + fprintf(stderr,"\n"); + } +#endif + return((BN_ULONG)ll); + } +#else +BN_ULONG bn_add_words(r,a,b,n) +BN_ULONG *r,*a,*b; +int n; + { + BN_ULONG c,l,t; + + bn_check_num(n); + if (n <= 0) return((BN_ULONG)0); + + c=0; + for (;;) + { + t=a[0]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[0])&BN_MASK2; + c+=(l < t); + r[0]=l; + if (--n <= 0) break; + + t=a[1]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[1])&BN_MASK2; + c+=(l < t); + r[1]=l; + if (--n <= 0) break; + + t=a[2]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[2])&BN_MASK2; + c+=(l < t); + r[2]=l; + if (--n <= 0) break; + + t=a[3]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[3])&BN_MASK2; + c+=(l < t); + r[3]=l; + if (--n <= 0) break; + + a+=4; + b+=4; + r+=4; + } + + return((BN_ULONG)c); + } +#endif +#endif + +#ifdef BN_SUB_WORDS +BN_ULONG bn_sub_words(r,a,b,n) +BN_ULONG *r,*a,*b; +int n; + { + BN_ULONG c,t1,t2; + + bn_check_num(n); + if (n <= 0) return((BN_ULONG)0); + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + { + int i,nn=n; + + for (i=n-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,a[i]); + fprintf(stderr,"-"); + for (i=n-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,b[i]); +#endif + + c=0; + for (;;) + { + t1=a[0]; t2=b[0]; + r[0]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + t1=a[1]; t2=b[1]; + r[1]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + t1=a[2]; t2=b[2]; + r[2]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + t1=a[3]; t2=b[3]; + r[3]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + a+=4; + b+=4; + r+=4; + } + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + fprintf(stderr,"- "); + if (c) fprintf(stderr,"-"); + for (i=nn-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,r[i]); + fprintf(stderr,"\n"); + } +#endif + return(c); + } +#endif + diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_comba.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_comba.c new file mode 100644 index 0000000..462c8f4 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_comba.c @@ -0,0 +1,450 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_MUL_COMBA8 +#define SPLIT_BN_MUL_COMBA4 +#define SPLIT_BN_SQR_COMBA8 +#define SPLIT_BN_SQR_COMBA4 +#endif /* NO_SPLIT */ + +#ifndef OPT_BN_ASM +/* #if 1 */ + +#ifdef BN_LLONG +#define mul_add_c(a,b,c0,c1,c2) \ + t=(BN_ULLONG)a*b; \ + t1=(BN_ULONG)Lw(t); \ + t2=(BN_ULONG)Hw(t); \ + c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define mul_add_c2(a,b,c0,c1,c2) \ + t=(BN_ULLONG)a*b; \ + tt=(t+t)&BN_MASK; \ + if (tt < t) c2++; \ + t1=(BN_ULONG)Lw(tt); \ + t2=(BN_ULONG)Hw(tt); \ + c0=(c0+t1)&BN_MASK2; \ + if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c(a,i,c0,c1,c2) \ + t=(BN_ULLONG)a[i]*a[i]; \ + t1=(BN_ULONG)Lw(t); \ + t2=(BN_ULONG)Hw(t); \ + c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c2(a,i,j,c0,c1,c2) \ + mul_add_c2((a)[i],(a)[j],c0,c1,c2) +#else +#define mul_add_c(a,b,c0,c1,c2) \ + t1=LBITS(a); t2=HBITS(a); \ + bl=LBITS(b); bh=HBITS(b); \ + mul64(t1,t2,bl,bh); \ + c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define mul_add_c2(a,b,c0,c1,c2) \ + t1=LBITS(a); t2=HBITS(a); \ + bl=LBITS(b); bh=HBITS(b); \ + mul64(t1,t2,bl,bh); \ + if (t2 & BN_TBIT) c2++; \ + t2=(t2+t2)&BN_MASK2; \ + if (t1 & BN_TBIT) t2++; \ + t1=(t1+t1)&BN_MASK2; \ + c0=(c0+t1)&BN_MASK2; \ + if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c(a,i,c0,c1,c2) \ + sqr64(t1,t2,(a)[i]); \ + c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c2(a,i,j,c0,c1,c2) \ + mul_add_c2((a)[i],(a)[j],c0,c1,c2) +#endif + +#if defined(BN_MUL_COMBA) + +#ifdef SPLIT_BN_MUL_COMBA8 +#undef bn_mul_comba8 +void bn_mul_comba8(r,a,b) +BN_ULONG *r,*a,*b; + { +#ifdef BN_LLONG + BN_ULLONG t; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + mul_add_c(a[0],b[0],c1,c2,c3); + r[0]=c1; + c1=0; + mul_add_c(a[0],b[1],c2,c3,c1); + mul_add_c(a[1],b[0],c2,c3,c1); + r[1]=c2; + c2=0; + mul_add_c(a[2],b[0],c3,c1,c2); + mul_add_c(a[1],b[1],c3,c1,c2); + mul_add_c(a[0],b[2],c3,c1,c2); + r[2]=c3; + c3=0; + mul_add_c(a[0],b[3],c1,c2,c3); + mul_add_c(a[1],b[2],c1,c2,c3); + mul_add_c(a[2],b[1],c1,c2,c3); + mul_add_c(a[3],b[0],c1,c2,c3); + r[3]=c1; + c1=0; + mul_add_c(a[4],b[0],c2,c3,c1); + mul_add_c(a[3],b[1],c2,c3,c1); + mul_add_c(a[2],b[2],c2,c3,c1); + mul_add_c(a[1],b[3],c2,c3,c1); + mul_add_c(a[0],b[4],c2,c3,c1); + r[4]=c2; + c2=0; + mul_add_c(a[0],b[5],c3,c1,c2); + mul_add_c(a[1],b[4],c3,c1,c2); + mul_add_c(a[2],b[3],c3,c1,c2); + mul_add_c(a[3],b[2],c3,c1,c2); + mul_add_c(a[4],b[1],c3,c1,c2); + mul_add_c(a[5],b[0],c3,c1,c2); + r[5]=c3; + c3=0; + mul_add_c(a[6],b[0],c1,c2,c3); + mul_add_c(a[5],b[1],c1,c2,c3); + mul_add_c(a[4],b[2],c1,c2,c3); + mul_add_c(a[3],b[3],c1,c2,c3); + mul_add_c(a[2],b[4],c1,c2,c3); + mul_add_c(a[1],b[5],c1,c2,c3); + mul_add_c(a[0],b[6],c1,c2,c3); + r[6]=c1; + c1=0; + mul_add_c(a[0],b[7],c2,c3,c1); + mul_add_c(a[1],b[6],c2,c3,c1); + mul_add_c(a[2],b[5],c2,c3,c1); + mul_add_c(a[3],b[4],c2,c3,c1); + mul_add_c(a[4],b[3],c2,c3,c1); + mul_add_c(a[5],b[2],c2,c3,c1); + mul_add_c(a[6],b[1],c2,c3,c1); + mul_add_c(a[7],b[0],c2,c3,c1); + r[7]=c2; + c2=0; + mul_add_c(a[7],b[1],c3,c1,c2); + mul_add_c(a[6],b[2],c3,c1,c2); + mul_add_c(a[5],b[3],c3,c1,c2); + mul_add_c(a[4],b[4],c3,c1,c2); + mul_add_c(a[3],b[5],c3,c1,c2); + mul_add_c(a[2],b[6],c3,c1,c2); + mul_add_c(a[1],b[7],c3,c1,c2); + r[8]=c3; + c3=0; + mul_add_c(a[2],b[7],c1,c2,c3); + mul_add_c(a[3],b[6],c1,c2,c3); + mul_add_c(a[4],b[5],c1,c2,c3); + mul_add_c(a[5],b[4],c1,c2,c3); + mul_add_c(a[6],b[3],c1,c2,c3); + mul_add_c(a[7],b[2],c1,c2,c3); + r[9]=c1; + c1=0; + mul_add_c(a[7],b[3],c2,c3,c1); + mul_add_c(a[6],b[4],c2,c3,c1); + mul_add_c(a[5],b[5],c2,c3,c1); + mul_add_c(a[4],b[6],c2,c3,c1); + mul_add_c(a[3],b[7],c2,c3,c1); + r[10]=c2; + c2=0; + mul_add_c(a[4],b[7],c3,c1,c2); + mul_add_c(a[5],b[6],c3,c1,c2); + mul_add_c(a[6],b[5],c3,c1,c2); + mul_add_c(a[7],b[4],c3,c1,c2); + r[11]=c3; + c3=0; + mul_add_c(a[7],b[5],c1,c2,c3); + mul_add_c(a[6],b[6],c1,c2,c3); + mul_add_c(a[5],b[7],c1,c2,c3); + r[12]=c1; + c1=0; + mul_add_c(a[6],b[7],c2,c3,c1); + mul_add_c(a[7],b[6],c2,c3,c1); + r[13]=c2; + c2=0; + mul_add_c(a[7],b[7],c3,c1,c2); + r[14]=c3; + r[15]=c1; + } +#endif + +#ifdef SPLIT_BN_MUL_COMBA4 +#undef bn_mul_comba4 +void bn_mul_comba4(r,a,b) +BN_ULONG *r,*a,*b; + { +#ifdef BN_LLONG + BN_ULLONG t; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + mul_add_c(a[0],b[0],c1,c2,c3); + r[0]=c1; + c1=0; + mul_add_c(a[0],b[1],c2,c3,c1); + mul_add_c(a[1],b[0],c2,c3,c1); + r[1]=c2; + c2=0; + mul_add_c(a[2],b[0],c3,c1,c2); + mul_add_c(a[1],b[1],c3,c1,c2); + mul_add_c(a[0],b[2],c3,c1,c2); + r[2]=c3; + c3=0; + mul_add_c(a[0],b[3],c1,c2,c3); + mul_add_c(a[1],b[2],c1,c2,c3); + mul_add_c(a[2],b[1],c1,c2,c3); + mul_add_c(a[3],b[0],c1,c2,c3); + r[3]=c1; + c1=0; + mul_add_c(a[3],b[1],c2,c3,c1); + mul_add_c(a[2],b[2],c2,c3,c1); + mul_add_c(a[1],b[3],c2,c3,c1); + r[4]=c2; + c2=0; + mul_add_c(a[2],b[3],c3,c1,c2); + mul_add_c(a[3],b[2],c3,c1,c2); + r[5]=c3; + c3=0; + mul_add_c(a[3],b[3],c1,c2,c3); + r[6]=c1; + r[7]=c2; + } +#endif + +#else + +#ifdef SPLIT_BN_MUL_COMBA4 +#undef bn_mul_comba4 +void bn_mul_comba4(r,a,b) +BN_ULONG *r,*a,*b; + { + r[4]=bn_mul_words( &(r[0]),a,4,b[0]); + r[5]=bn_mul_add_words(&(r[1]),a,4,b[1]); + r[6]=bn_mul_add_words(&(r[2]),a,4,b[2]); + r[7]=bn_mul_add_words(&(r[3]),a,4,b[3]); + } +#endif + +#ifdef SPLIT_BN_MUL_COMBA8 +#undef bn_mul_comba8 +void bn_mul_comba8(r,a,b) +BN_ULONG *r,*a,*b; + { + r[ 8]=bn_mul_words( &(r[0]),a,8,b[0]); + r[ 9]=bn_mul_add_words(&(r[1]),a,8,b[1]); + r[10]=bn_mul_add_words(&(r[2]),a,8,b[2]); + r[11]=bn_mul_add_words(&(r[3]),a,8,b[3]); + r[12]=bn_mul_add_words(&(r[4]),a,8,b[4]); + r[13]=bn_mul_add_words(&(r[5]),a,8,b[5]); + r[14]=bn_mul_add_words(&(r[6]),a,8,b[6]); + r[15]=bn_mul_add_words(&(r[7]),a,8,b[7]); + } +#endif + +#endif /* BN_MUL_COMBA */ + +#ifdef BN_SQR_COMBA + +#ifdef SPLIT_BN_SQR_COMBA8 +#undef bn_sqr_comba8 +void bn_sqr_comba8(r,a) +BN_ULONG *r,*a; + { +#ifdef BN_LLONG + BN_ULLONG t,tt; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + sqr_add_c(a,0,c1,c2,c3); + r[0]=c1; + c1=0; + sqr_add_c2(a,1,0,c2,c3,c1); + r[1]=c2; + c2=0; + sqr_add_c(a,1,c3,c1,c2); + sqr_add_c2(a,2,0,c3,c1,c2); + r[2]=c3; + c3=0; + sqr_add_c2(a,3,0,c1,c2,c3); + sqr_add_c2(a,2,1,c1,c2,c3); + r[3]=c1; + c1=0; + sqr_add_c(a,2,c2,c3,c1); + sqr_add_c2(a,3,1,c2,c3,c1); + sqr_add_c2(a,4,0,c2,c3,c1); + r[4]=c2; + c2=0; + sqr_add_c2(a,5,0,c3,c1,c2); + sqr_add_c2(a,4,1,c3,c1,c2); + sqr_add_c2(a,3,2,c3,c1,c2); + r[5]=c3; + c3=0; + sqr_add_c(a,3,c1,c2,c3); + sqr_add_c2(a,4,2,c1,c2,c3); + sqr_add_c2(a,5,1,c1,c2,c3); + sqr_add_c2(a,6,0,c1,c2,c3); + r[6]=c1; + c1=0; + sqr_add_c2(a,7,0,c2,c3,c1); + sqr_add_c2(a,6,1,c2,c3,c1); + sqr_add_c2(a,5,2,c2,c3,c1); + sqr_add_c2(a,4,3,c2,c3,c1); + r[7]=c2; + c2=0; + sqr_add_c(a,4,c3,c1,c2); + sqr_add_c2(a,5,3,c3,c1,c2); + sqr_add_c2(a,6,2,c3,c1,c2); + sqr_add_c2(a,7,1,c3,c1,c2); + r[8]=c3; + c3=0; + sqr_add_c2(a,7,2,c1,c2,c3); + sqr_add_c2(a,6,3,c1,c2,c3); + sqr_add_c2(a,5,4,c1,c2,c3); + r[9]=c1; + c1=0; + sqr_add_c(a,5,c2,c3,c1); + sqr_add_c2(a,6,4,c2,c3,c1); + sqr_add_c2(a,7,3,c2,c3,c1); + r[10]=c2; + c2=0; + sqr_add_c2(a,7,4,c3,c1,c2); + sqr_add_c2(a,6,5,c3,c1,c2); + r[11]=c3; + c3=0; + sqr_add_c(a,6,c1,c2,c3); + sqr_add_c2(a,7,5,c1,c2,c3); + r[12]=c1; + c1=0; + sqr_add_c2(a,7,6,c2,c3,c1); + r[13]=c2; + c2=0; + sqr_add_c(a,7,c3,c1,c2); + r[14]=c3; + r[15]=c1; + } +#endif + +#ifdef SPLIT_BN_SQR_COMBA4 +#undef bn_sqr_comba4 +void bn_sqr_comba4(r,a) +BN_ULONG *r,*a; + { +#ifdef BN_LLONG + BN_ULLONG t,tt; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + sqr_add_c(a,0,c1,c2,c3); + r[0]=c1; + c1=0; + sqr_add_c2(a,1,0,c2,c3,c1); + r[1]=c2; + c2=0; + sqr_add_c(a,1,c3,c1,c2); + sqr_add_c2(a,2,0,c3,c1,c2); + r[2]=c3; + c3=0; + sqr_add_c2(a,3,0,c1,c2,c3); + sqr_add_c2(a,2,1,c1,c2,c3); + r[3]=c1; + c1=0; + sqr_add_c(a,2,c2,c3,c1); + sqr_add_c2(a,3,1,c2,c3,c1); + r[4]=c2; + c2=0; + sqr_add_c2(a,3,2,c3,c1,c2); + r[5]=c3; + c3=0; + sqr_add_c(a,3,c1,c2,c3); + r[6]=c1; + r[7]=c2; + } +#endif +#else + +#ifdef SPLIT_BN_SQR_COMBA4 +/* hmm... is it faster just to do a multiply? */ +#undef bn_sqr_comba4 +void bn_sqr_comba4(r,a) +BN_ULONG *r,*a; + { + BN_ULONG t[8]; + bn_sqr_normal(r,a,4,t); + } +#endif + +#ifdef SPLIT_BN_SQR_COMBA8 +#undef bn_sqr_comba8 +void bn_sqr_comba8(r,a) +BN_ULONG *r,*a; + { + BN_ULONG t[16]; + bn_sqr_normal(r,a,8,t); + } +#endif + +#endif + +#endif /* OPT_BN_ASM */ + +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_div.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_div.c new file mode 100644 index 0000000..7036d19 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_div.c @@ -0,0 +1,381 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +/** + * @file bn_div.c + * @brief Division and modulus functions + */ +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_DIV +#define SPLIT_BN_MOD +#endif /* NO_SPLIT */ + +#ifdef SPLIT_BN_DIV +/* The old slow way */ +#ifdef OLD_BN_DIVISION +int BN_div(dv, rem, m, d,ctx) +BIGNUM *dv; +BIGNUM *rem; +BIGNUM *m; +BIGNUM *d; +BN_CTX *ctx; + { + int i,nm,nd; + BIGNUM *D; + + bn_check_top(m); + bn_check_top(d); + if (BN_is_zero(d)) + { +#ifndef NO_ERR + BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO); +#endif + return(0); + } + + if (BN_ucmp(m,d) < 0) + { + if (rem != NULL) + { if (BN_copy(rem,m) == NULL) return(0); } + if (dv != NULL) BN_zero(dv); + return(1); + } + + D= &(ctx->bn[ctx->tos]); + if (dv == NULL) dv= &(ctx->bn[ctx->tos+1]); + if (rem == NULL) rem= &(ctx->bn[ctx->tos+2]); + + nd=BN_num_bits(d); + nm=BN_num_bits(m); + if (BN_copy(D,d) == NULL) return(0); + if (BN_copy(rem,m) == NULL) return(0); + + /* The next 2 are needed so we can do a dv->d[0]|=1 later + * since BN_lshift1 will only work once there is a value + */ + BN_zero(dv); + bn_wexpand(dv,1); + dv->top=1; + + if (!BN_lshift(D,D,nm-nd)) return(0); + for (i=nm-nd; i>=0; i--) + { + if (!BN_lshift1(dv,dv)) return(0); + if (BN_ucmp(rem,D) >= 0) + { + dv->d[0]|=1; + if (!BN_usub(rem,rem,D)) return(0); + } +/* CAN IMPROVE (and have now :=) */ + if (!BN_rshift1(D,D)) return(0); + } + rem->neg=BN_is_zero(rem)?0:m->neg; + dv->neg=m->neg^d->neg; + return(1); + } + +#else +/** + * Performs Big number division + * + * @param dv [In] division + * @param rm [Out] remainder + * @param num [In] number + * @param divisor [In] divisor + * @param ctx [In] Temporary data storage + * + * @todo add more comments to this function + */ +int BN_div(BIGNUM *dv, BIGNUM *rm, BIGNUM *num, BIGNUM *divisor, BN_CTX *ctx) + { + int norm_shift,i,j,loop; + BIGNUM *tmp,wnum,*snum,*sdiv,*res; + BN_ULONG *resp,*wnump; + BN_ULONG d0,d1; + int num_n,div_n; + + bn_check_top(num); + bn_check_top(divisor); + + if (BN_is_zero(divisor)) + { +#ifndef NO_ERR + BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO); +#endif + return(0); + } + + if (BN_ucmp(num,divisor) < 0) + { + if (rm != NULL) + { if (BN_copy(rm,num) == NULL) return(0); } + if (dv != NULL) (void)BN_zero(dv); + return(1); + } + + tmp= &(ctx->bn[ctx->tos]); + tmp->neg=0; + snum= &(ctx->bn[ctx->tos+1]); + sdiv= &(ctx->bn[ctx->tos+2]); + if (dv == NULL) + res= &(ctx->bn[ctx->tos+3]); + else res=dv; + + /* First we normalise the numbers */ + norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2); + if (!BN_lshift(sdiv,divisor,norm_shift)) return(0); + sdiv->neg=0; + norm_shift+=BN_BITS2; + if (!BN_lshift(snum,num,norm_shift)) return(0); + snum->neg=0; + div_n=sdiv->top; + num_n=snum->top; + loop=num_n-div_n; + + /* Lets setup a 'window' into snum + * This is the part that corresponds to the current + * 'area' being divided */ + BN_init(&wnum); + wnum.d= &(snum->d[loop]); + wnum.top= div_n; + wnum.max= snum->max+1; /* a bit of a lie */ + + /* Get the top 2 words of sdiv */ + /* i=sdiv->top; */ + d0=sdiv->d[div_n-1]; + d1=(div_n == 1)?0:sdiv->d[div_n-2]; + + /* pointer to the 'top' of snum */ + wnump= &(snum->d[num_n-1]); + + /* Setup to 'res' */ + if (!bn_wexpand(res,(loop+1))) goto err; + res->neg= (num->neg^divisor->neg); + res->top=loop; + resp= &(res->d[loop-1]); + + /* space for temp */ + if (!bn_wexpand(tmp,(div_n+1))) goto err; + + if (BN_ucmp(&wnum,sdiv) >= 0) + { + if (!BN_usub(&wnum,&wnum,sdiv)) goto err; + *resp=1; + res->d[res->top-1]=1; + } + else + res->top--; + resp--; + + for (i=0; i>BN_BITS2) || + (t2 <= ((BN_ULLONG)(rem< t1l) t3h++; + t3h=(t1h-t3h)&BN_MASK2; + + /*if ((t3>>BN_BITS2) || + (t2 <= ((t3<d,sdiv->d,div_n,q); + tmp->d[div_n]=l0; + for (j=div_n+1; j>0; j--) + if (tmp->d[j-1]) break; + tmp->top=j; + + j=wnum.top; +#ifdef BN_DEBUG + /* Sometimes this is 0 now (wnum.top is not). + * We need to look at this some time, I am quite + * sure it has no affect. + */ + bn_fix_top(&wnum); +#endif + (void)BN_sub(&wnum,&wnum,tmp); + + snum->top=snum->top+wnum.top-j; + + if (wnum.neg) + { + q--; + j=wnum.top; + (void)BN_add(&wnum,&wnum,sdiv); + snum->top+=wnum.top-j; + } + *(resp--)=q; + wnump--; + } + bn_fix_top(snum); + if (rm != NULL) + { + i=num->neg; /* just in case num == rm */ + if (BN_rshift(rm,snum,norm_shift) == 0) + return(0); + rm->neg=i; + } + return(1); +err: + return(0); + } +#endif +#endif + +#ifdef SPLIT_BN_MOD +/** + * Calculate the remainder where rem = m mod d + * + * @param rem [Out] Modulus result + * @param m [In] Base value + * @param d [In] Divisor + * @param ctx [In] BN_CTX for data space + * + * @pre variables are initialised and valid + * @post rem contained modulus + * + * @retval 1 success + * @retval 0 failure + * + * @note when BN_LIBRARY_SMALL define uses following algorithm + * otherwise calls through to BN_div + * + * @note m < d rem = m + * (length m = length of d) and (m > d) , rem = m - d + * alg otherwise + * let rem = m + * loop while rem > d + * let dv = shift left d, n bits to = length rem + * if dv > rem + * let dv = shift left d, n - 1 bits ( = length rem - 1) + * end if + * let rem = rem - dv; + * end loop + * + * @relates BN_div + */ +int BN_mod(BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx) +{ +#ifdef BN_LIBRARY_SMALL + int nm,nd; + BIGNUM *dv, *dv2; + + /* if m < d , mod = m */ + if (BN_ucmp(m,d) < 0) + return((BN_copy(rem,m) == NULL)?0:1); + + dv= &(ctx->bn[ctx->tos]); + dv2 = &(ctx->bn[ctx->tos+1]); + + nm=BN_num_bits(m); + nd=BN_num_bits(d); + + /* if bits m = bits d and m >= d (from above) + * rem = m - d + */ + if(nm == nd) + { + BN_usub(rem, m, d); + goto end; + } + + if (BN_copy(rem, m) == NULL) + { + return 0; + } + + /* while the rem > d */ + while(BN_ucmp(rem,d) > 0) + { + nm=BN_num_bits(rem); + if(!BN_lshift(dv2,d,nm-nd)) + { + return(0); + } + + if(BN_ucmp(dv2, rem) >0) + { + if(!BN_lshift(dv2,d,nm-nd-1)) + { + return(0); + } + } + + BN_usub(rem,rem,dv2); + } +end: + return(1); +#else + return(BN_div(NULL,rem,m,d,ctx)); +#endif +} +#endif + +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_ex_str.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_ex_str.c new file mode 100644 index 0000000..02e31d1 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_ex_str.c @@ -0,0 +1,453 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +#include "bn_lcl.h" + +const static unsigned char p2 []={0,8,1,1,1,1,1,0,0,0}; +const static unsigned char p4 []={0,8,1,1,1,4,1,0,0,0}; +const static unsigned char p16[]={0,8,1,1,1,16,1,0,0,0}; + +/* The following defines allow for redefinition of the window size + * of the exponent string at compile time, this affects the size + * of temporary data required in montgomery operations. + * Larger window sizes have more memory and are slightly faster + */ +#ifndef MAX_WIN_SIZE +#define MAX_WIN_SIZE 5 +#endif + +#if (MAX_WIN_SIZE == 6) +#define MAX_NUM_SIZE 16 +#endif + +#if (MAX_WIN_SIZE == 5) +#define MAX_NUM_SIZE 16 +#endif + +#if (MAX_WIN_SIZE == 4) +#define MAX_NUM_SIZE 8 +#endif + +#if (MAX_WIN_SIZE == 3) +#define MAX_NUM_SIZE 4 +#endif + +#ifndef MAX_NUM_SIZE +#define MAX_NUM_SIZE 16 +#endif + +/* This table is used to calculate how far to shift a window to find + * the next 1 bit within the window, for a given window size + * Comment next to each value represents window size, value of the window + * and the number of shifts to find the next 1 bit. + * where the value of the window is 0, the shift is the size of the window + * and thus may not necessary yield a 1 bit, but refreshes the window + */ +const static unsigned char shift[64]= + {6, /* window 6, bits 000000, shift 6 */ + 0, /* 6, bits 000001, shift 0 */ + 1, /* 6, bits 000010, shift 1 */ + 0, /* 6, bits 000011, shift 0 */ + 2, /* 6, bits 000100, shift 2 */ + 0, /* 6, bits 000101, shift 0 */ + 1, /* 6, bits 000110, shift 1 */ + 0, /* 6, bits 000111, shift 0 */ + 3, /* 6, bits 001000, shift 3 */ + 0, /* 6, bits 001001, shift 0 */ + 1, /* 6, bits 001010, shift 1 */ + 0, /* 6, bits 001011, shift 0 */ + 2, /* 6, bits 001100, shift 2 */ + 0, /* 6, bits 001101, shift 0 */ + 1, /* 6, bits 001110, shift 1 */ + 0, /* 6, bits 001111, shift 0 */ + 4, /* 6, bits 010000, shift 4 */ + 0, /* 6, bits 010001, shift 0 */ + 1, /* 6, bits 010010, shift 1 */ + 0, /* 6, bits 010011, shift 0 */ + 2, /* 6, bits 010100, shift 2 */ + 0, /* 6, bits 010101, shift 0 */ + 1, /* 6, bits 010110, shift 1 */ + 0, /* 6, bits 010111, shift 0 */ + 3, /* 6, bits 011000, shift 3 */ + 0, /* 6, bits 011001, shift 0 */ + 1, /* 6, bits 011010, shift 1 */ + 0, /* 6, bits 011011, shift 0 */ + 2, /* 6, bits 011100, shift 2 */ + 0, /* 6, bits 011101, shift 0 */ + 1, /* 6, bits 011110, shift 1 */ + 0, /* 6, bits 011111, shift 0 */ + 5, /* 6, bits 100000, shift 5 */ + /* also window 5, bits 00000, shift 5 */ + 0, /* 5 ,bits 00001, shift 0 */ + 1, /* 5 ,bits 00010, shift 1 */ + 0, /* 5 ,bits 00011, shift 0 */ + 2, /* 5 ,bits 00100, shift 2 */ + 0, /* 5 ,bits 00101, shift 0 */ + 1, /* 5 ,bits 00110, shift 1 */ + 0, /* 5 ,bits 00111, shift 0 */ + 3, /* 5 ,bits 01000, shift 3 */ + 0, /* 5 ,bits 01001, shift 0 */ + 1, /* 5 ,bits 01010, shift 1 */ + 0, /* 5 ,bits 01011, shift 0 */ + 2, /* 5 ,bits 01100, shift 2 */ + 0, /* 5 ,bits 01101, shift 0 */ + 1, /* 5 ,bits 01110, shift 1 */ + 0, /* 5 ,bits 01111, shift 0 */ + 4, /* 5 ,bits 10000, shift 1 */ + /* also window 4, bits 0000, shift 4 */ + 0, /* 4 ,bits 0001, shift 0 */ + 1, /* 4 ,bits 0010, shift 1 */ + 0, /* 4 ,bits 0011, shift 0 */ + 2, /* 4 ,bits 0100, shift 2 */ + 0, /* 4 ,bits 0101, shift 0 */ + 1, /* 4 ,bits 0110, shift 1 */ + 0, /* 4 ,bits 0111, shift 0 */ + 3, /* 4 ,bits 1000, shift 3 */ + /* also window 3, bits 000, shift 3 */ + 0, /* 3 ,bits 001, shift 0 */ + 1, /* 3 ,bits 010, shift 1 */ + 0, /* 3 ,bits 011, shift 0 */ + 2, /* 3 ,bits 100, shift 2 */ + 0, /* 3 ,bits 101, shift 0 */ + 1, /* 3 ,bits 110, shift 1 */ + 0 /* 3 ,bits 111, shift 0 */ + }; + +/* This table defines the starting point in the shift table for + * a particular window size + */ +const static unsigned char *shift_val[7]= + { + &(shift[63]), /* window 0 - unused */ + &(shift[62]), /* window 1 */ + &(shift[60]), /* window 2 - unused */ + &(shift[56]), /* window 3 */ + &(shift[48]), /* window 4 */ + &(shift[32]), /* window 5 */ + &(shift[ 0]), /* window 6 - unused */ + }; + +/** + * Calculates a Montgomery exponent string. + * + * For a supplied exponent p, generate an exponent string strp, which + * defines in pairs the number of multiplies and square operations + * required by a particular bit pattern, commonly used exponents + * 3, 11 and F4 have predefined constant string values, the rest + * are calculated into a cast unsigned char * array via the data + * pointer of a BIGNUM taken from the BN_CTX stack of BIGNUMs + * + * @param p [In] Exponent + * @param strp [Out] Exponent string result + * @param flags [In] Unused + * @param ctx [In] Temporary data storage + * + * @pre p, and ctx are initialised and valid + * @post strp points to required exponent string + * + * @notes String length value in strp[2] is invalid for strings + * greater than length 255 + * string terminates with pattern, 0, 0 this should be + * used in accurately determining the length of a returned + * string strp. + * + * @note strings with value sqr = 255, mul = 0, sqr value should be + * treated as value 256, and added to the next sqr value, this + * is used by exponent strings where more then 256 contiguous + * zero bits are in the exponent bit representation. + * + * @note code contains conditional compilation of code dependent on + * the OS int/long sizes + */ +int BN_gen_exp_bits(p,strp,flags,ctx) +BIGNUM *p; +unsigned char **strp; +int flags; +BN_CTX *ctx; + { + int bits,i,j,window,num; + unsigned char *str=NULL; + BIGNUM *tmp; + + flags=flags; + bits=p->top*BN_BITS2; + tmp=&(ctx->bn[ctx->tos]); + if (p->top == 0) + return(0); + +#if (BN_BITS2 > 17) + if (p->top == 1) +#else + if (bits <= 32) +#endif + { +#if (BN_BITS2 > 17) + if ((p->top == 1) && (p->d[0] == 0x10001)) + str=(unsigned char *)p16; +#endif +#if (16 >= BN_BITS2) && (BN_BITS > 8) + if ( (p->top == 2) && + (p->d[0] == 0x0001) && + (p->d[1] == 0x0001)) + str=(unsigned char *)p16; +#endif +#if (8 >= BN_BITS) + if ( (p->top == 3) && + (p->d[0] == 0x01) && + (p->d[1] == 0x00) && + (p->d[2] == 0x01)) + str=(unsigned char *)p16; +#endif + else if ((p->d[0] == 0x11) && (p->top == 1)) + str=(unsigned char *)p4; + else if ((p->d[0] == 0x3) && (p->top == 1)) + str=(unsigned char *)p2; + window=1; + num=1; + i=BN_BITS2; + } + else if (bits >= 256) + { + window=MAX_WIN_SIZE; /* max size of window */ + num=MAX_NUM_SIZE; + i=(BN_BITS2+(MAX_WIN_SIZE -1))/MAX_WIN_SIZE; + } + else if (bits >= 128) + { + window=4; + num=8; + i=(BN_BITS2+3)/4; + } + else /* 128 to 33 */ + { + window=3; + num=4; + i=(BN_BITS2+2)/3; + } + + /* Number of tmp words */ + j=(p->top*i*2+BN_BYTES-1+4)/BN_BYTES; + + if (str == NULL) + { + if (!bn_wexpand(tmp,j)) + return(0); + str=(unsigned char *)tmp->d; + i=BN_gen_exp_string(&(str[4]),p,window); + i+=2; + str[0]=(unsigned char)((i>>8)&0xff); + str[1]=(unsigned char)((i )&0xff); + str[2]=(unsigned char)window; + str[3]=(unsigned char)num; + } + else + { + i=8; + } + *strp=str; + return(i+2); + } + + +/** + * Generates the Montgomery exponent string. + * + * This function is used to generate an 'exponent string' + * which is an array of bytes that encode how to perform the steps in + * the a^p%m operation. + * + * @param str [Out] Containing the generated string + * @param p [In] Exponent to generate the string for + * @param bits [In] Size of the window for shifting the values of the BIGNUM + * + * @pre p is initialised and value BIGNUM, bits is not 0 + * @post str points to generated exponent string + * + * @note str is cast assigned the data of a BIGNUM allocated and + * expanded from the BN_CTX of the calling function BN_gen_exp_bits + * it does not need to be de-allocated + * + * @note string consisted of unsigned char pairs and 4 byte init + * pairs are sqr count and multiply, where strings are greater + * than 256 bit, length in position str[2] is invalid + * + * @note strings with value sqr = 255, mul = 0, sqr value should be + * treated as value 256, and added to the next sqr value, this + * is used by exponent strings where more then 256 contiguous + * zero bits are in the exponent bit representation. + * + */ +int BN_gen_exp_string(str,p,bits) +unsigned char *str; +BIGNUM *p; +int bits; + { + unsigned char *sp; + unsigned int mask; + const unsigned char *shift; + BN_ULONG w,wh,wl,*d; + unsigned int i,mul,sqr,t,s,ss; + int top; + + if (bits > 6) bits=6; + shift= shift_val[bits]; + + /* This is the mask for the bits we wish to operate on */ + mask=(unsigned int)( (1<top*BN_BITS2+bits-1)/bits)*2+2]); + *sp-- = 0; + *sp-- = 0; + top=p->top; /* Total words we will shift in */ + d=p->d; + w=wl= *d++; + if (top <= 1) + wh=0; + else + wh= *d++; + sqr=0; + i=0; + + for (;;) + { + /* t will contain how far we need to shift to set a 1 + * in the bottom bit. */ + for (;;) + { + t=w&mask; /* retrieve our window */ + s=shift[t]; /* get the shift value for the window */ + if (s == 0) break; /* no shift write out the vals */ + sqr+=s; /* add the shifted zero count to sqr */ + ss+=s; /* ss is total shift for wl */ + if (ss >= BN_BITS2) /* we have shifted > word len */ + { + if (top <= 1) break; /* no more to do */ + top--; /* dec the count */ + + wl=wh; /* copy the next word */ + /* load the word after or 0 if no more */ + wh=(top <= 1)?0:(*d++); + /* adjust our shift by len of word */ + ss-=BN_BITS2; + } + /* reset our window word w */ + if (ss == 0) + w=wl; + else + w=(wl>>ss)|(wh<<(BN_BITS2-ss)); + } + + /* At this point we have the 0th bit set */ + mul=t; + if (t == 0) break; /* we have reached the end of p */ + /* write out sqr/mul pair */ + *sp-- = (unsigned char)(sqr & 0xff); + *sp-- = (unsigned char)(mul & 0xff); + if(sqr >= 256) /* check whether sqr exceeds max uchar */ + { + /* output the expanded list of to allow for this + * and numbers will require to be added together + * at interpret time + */ + while(sqr >= 256) + { + *sp-- = 255; + *sp-- = 0; /* mul is never zero normally */ + sqr-= 256; + } + } + sqr=(unsigned int)bits; /* set sqr to be the window size */ + + ss+=bits; /* ss is total shift for wl */ + if (ss >= BN_BITS2) /* adjust window words w,wl, wh again */ + { + if (top <= 1) break; + top--; + + wl=wh; + wh=(top <= 1)?0:(*(d++)); + ss-=BN_BITS2; + } + + if (ss == 0) + w=wl; + else + w=(wl>>ss)|(wh<<(BN_BITS2-ss)); + } + sp++; + i=2; + /* reverse the string from the top of the exponent string + * and copy to the bottom, allocated exponent string is 2 * max length + * expected for exponent string + */ + while (sp[0] != 0 || sp[1] != 0) + { + str[0]=sp[0]; + str[1]=sp[1]; + str+=2; + sp+=2; + i+=2; + } + str[0]=0; + str[1]=0; + + return( (int)i ); + } + +#ifdef MAIN +main() + { + BIGNUM p; + unsigned char buf[512],*pp; + int i; + + BN_init(&p); + BN_rand(&p,33,1,0); +#ifndef NO_FP_API + BN_print_fp(stdout,&p); fprintf(stdout,"\n"); +#endif + + BN_rand(&p,512,1,1); +#ifndef NO_FP_API + BN_print_fp(stdout,&p); fprintf(stdout,"\n"); +#endif + for (i=0; i<10000; i++) + BN_gen_exp_string(buf,&p,5); + +#if 0 + BN_gen_exp_string(buf,&p,3); + + pp=buf; + for (;;) + { + printf("mul %d sqr %d\n",pp[0],pp[1]); + if (pp[1] == 0) break; + pp+=2; + } +#endif + } +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_exp.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_exp.c new file mode 100644 index 0000000..723b62f --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_exp.c @@ -0,0 +1,172 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_MOD_EXP_ORIG +#define SPLIT_BN_MOD_EXP +#endif /* NO_SPLIT */ + +#define TABLE_SIZE 16 + +#ifdef SPLIT_BN_MOD_EXP_ORIG +#if 0 +/* this one works - simple but works */ +int BN_mod_exp_orig(r,a,p,m,ctx) +BIGNUM *r,*a,*p,*m; +BN_CTX *ctx; + { + int i,bits,ret=0; + BIGNUM *v,*tmp; + + v= &(ctx->bn[ctx->tos++]); + tmp= &(ctx->bn[ctx->tos++]); + + if (BN_copy(v,a) == NULL) goto err; + bits=BN_num_bits(p); + + if (BN_is_odd(p)) + { if (BN_copy(r,a) == NULL) goto err; } + else { if (!BN_one(r)) goto err; } + + for (i=1; itos-=2; + return(ret); + } + +#endif + +/* this one works - simple but works */ +int BN_exp(r,a,p,ctx) +BIGNUM *r,*a,*p; +BN_CTX *ctx; + { + int i,bits,ret=0,tos; + BIGNUM *v,*rr; + + bn_check_top(a); + bn_check_top(p); + + tos=ctx->tos; + v= &(ctx->bn[ctx->tos++]); + if ((r == a) || (r == p)) + rr= &(ctx->bn[ctx->tos++]); + else + rr=r; + + if (BN_copy(v,a) == NULL) goto err; + bits=BN_num_bits(p); + + if (BN_is_odd(p)) + { if (BN_copy(rr,a) == NULL) goto err; } + else { if (!BN_one(rr)) goto err; } + + for (i=1; itos=tos; + if (r != rr) (void)BN_copy(r,rr); + return(ret); + } +#endif + +#ifdef SPLIT_BN_MOD_EXP +/** + * Perform mod exp on BIGNUM + * @param r Pointer to return value BIGNUM + * @param a Pointer to data value BIGNUM + * @param p Pointer to Public exponent BIGNUM + * @param m Pointer to modulus BIGNUM + * @param ctx Pointer to BN_CTX + * @return 0 success + * @pre BIGNUMs a, p, m and BN_CTX ctx exist and are valid + * @post BIGNUM r points to evaluated mod_exp + * @note BN_mod_exp_mont is only available if library compiled + * with define BN_MONT_MUL, and will only be used to compute + * mod_exp operation where the modulus m is odd. + * BN_mod_exp_recp is only available if library is compiled + * with define RECP_MUL_MOD. + * BN_mod_exp_simple is the default method, not available if + * library is compiled with define RECP_MUL_MOD. + * if BN_mod_exp_mont is available, which ever of BN_mod_exp_simple + * or BN_mod_exp_recp is available will only be used for even + * modulus m values. + * @relates BN_mod_exp_mont + * @relates BN_mod_exp_recp + * @relates BN_mod_exp_simple + */ +int BN_mod_exp(r,a,p,m,ctx) +BIGNUM *r; +BIGNUM *a; +BIGNUM *p; +BIGNUM *m; +BN_CTX *ctx; + { + int ret; + + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + +#ifdef MONT_MUL_MOD + + if (BN_is_odd(m)) + { ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL); } + else +#endif +#ifdef RECP_MUL_MOD + { ret=BN_mod_exp_recp(r,a,p,m,ctx); } +#else + { ret=BN_mod_exp_simple(r,a,p,m,ctx); } +#endif + + return(ret); + } +#endif + +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_fm_w.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_fm_w.c new file mode 100644 index 0000000..54c67ab --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_fm_w.c @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +#include "bn_lcl.h" + +/* rp has w words, the top w words are 0 */ +void bn_from_montgomery_words(ret,a,np,w,n0) +BN_ULONG *ret; +BN_ULONG *a; +BN_ULONG *np; +int w; +BN_ULONG n0; + { + BN_ULONG v0,v1,*ap,*wap; + int i; + + v1=0; + + ap=a; + wap= &(a[w]); + /* Consider putting this loop in ASM */ + for (i=0; i0; i--) + if (ap[i] != np[i]) break; + } + v1=(ap[i] >= np[i]); + } + if (v1) + (void)bn_sub_words(ret,ap,np,w); + else + { +#if 0 /* Alpha does not like Memcpy */ + Memcpy(ret,ap,sizeof(BN_ULONG)*w); +#else + for (i=0; ibn[ctx->tos]); + b= &(ctx->bn[ctx->tos+1]); + + if (BN_copy(a,in_a) == NULL) goto err; + if (BN_copy(b,in_b) == NULL) goto err; + + if (BN_cmp(a,b) < 0) { t=a; a=b; b=t; } + t=bn_euclid(a,b); + if (t == NULL) goto err; + + if (BN_copy(r,t) == NULL) goto err; + ret=1; +err: + return(ret); + } + +BIGNUM *bn_euclid(a,b) +BIGNUM *a,*b; + { + BIGNUM *t; + int shifts=0; + + bn_check_top(a); + bn_check_top(b); + + for (;;) + { + if (BN_is_zero(b)) + break; + + if (BN_is_odd(a)) + { + if (BN_is_odd(b)) + { + if (!BN_sub(a,a,b)) goto err; + if (!BN_rshift1(a,a)) goto err; + if (BN_cmp(a,b) < 0) + { t=a; a=b; b=t; } + } + else /* a odd - b even */ + { + if (!BN_rshift1(b,b)) goto err; + if (BN_cmp(a,b) < 0) + { t=a; a=b; b=t; } + } + } + else /* a is even */ + { + if (BN_is_odd(b)) + { + if (!BN_rshift1(a,a)) goto err; + if (BN_cmp(a,b) < 0) + { t=a; a=b; b=t; } + } + else /* a even - b even */ + { + if (!BN_rshift1(a,a)) goto err; + if (!BN_rshift1(b,b)) goto err; + shifts++; + } + } + } + if (shifts) + { + if (!BN_lshift(a,a,shifts)) goto err; + } + return(a); +err: + return(NULL); + } +#endif + +#ifdef SPLIT_BN_MOD_INVERSE +/* solves ax == 1 (mod n) */ +BIGNUM *BN_mod_inverse(in, a, n, ctx) +BIGNUM *in; +BIGNUM *a; +BIGNUM *n; +BN_CTX *ctx; + { + BIGNUM *A,*B,*X,*Y,*M,*D,*R; + BIGNUM *T,*ret=NULL; + int sign; + + bn_check_top(a); + bn_check_top(n); + + A= &(ctx->bn[ctx->tos]); + B= &(ctx->bn[ctx->tos+1]); + X= &(ctx->bn[ctx->tos+2]); + D= &(ctx->bn[ctx->tos+3]); + M= &(ctx->bn[ctx->tos+4]); + Y= &(ctx->bn[ctx->tos+5]); + ctx->tos+=6; + if (in == NULL) + R=BN_new(); + else + R=in; + if (R == NULL) goto err; + + (void)BN_zero(X); + (void)BN_one(Y); + if (BN_copy(A,a) == NULL) goto err; + if (BN_copy(B,n) == NULL) goto err; + sign=1; + + while (!BN_is_zero(B)) + { + if (!BN_div(D,M,A,B,ctx)) goto err; + T=A; + A=B; + B=M; + /* T has a struct, M does not */ + + if (!BN_mul(T,D,X,ctx)) goto err; + if (!BN_add(T,T,Y)) goto err; + M=Y; + Y=X; + X=T; + sign= -sign; + } + if (sign < 0) + { + if (!BN_sub(Y,n,Y)) goto err; + } + + if (BN_is_one(A)) + { if (!BN_mod(R,Y,n,ctx)) goto err; } + else + { +#ifndef NO_ERR + BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE); +#endif + goto err; + } + ret=R; +err: + if ((ret == NULL) && (in == NULL)) BN_free(R); + ctx->tos-=6; + return(ret); + } +#endif + +#ifdef SPLIT_BN_MOD_INVERSE_WORD +/* solves 1 == (ret*(1<l + * @param l [In] a word (size of word depends on machine) + * @returns number of bits in parameter l + */ +#ifdef SPLIT_BN_NUM_BITS_WORD +int BN_num_bits_word(l) +BN_ILONG l; + { + int i; + + /* + * This table represents the number of bits required to + * represent a "number", where "number" is indexed from + * 0 into the table. So: + * number 0 = # bits req'd to represent 0 = bits[0] = 0 + * number 1 = # bits req'd to represent 1 = bits[1] = 1 + * number 2 = # bits req'd to represent 2 = bits[2] = 2 + * number 3 = # bits req'd to represent 3 = bits[3] = 2 + * number 4 = # bits req'd to represent 4 = bits[4] = 3 + * etc. + * + * The small code size table exists to save some space, + * but requires (at most) an extra shift, an extra AND, + * and an extra add. + */ +#ifdef SMALL_CODE_SIZE + const static char bits[16]={ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 + }; +#else + const static char bits[256]={ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + }; +#endif + +#if defined(SIXTY_FOUR_BIT_LONG) + if (l & 0xffffffff00000000L) + { + if (l & 0xffff000000000000L) + { + if (l & 0xff00000000000000L) + i=56; + else i=48; + } + else + { + if (l & 0x0000ff0000000000L) + i=40; + else i=32; + } + } + else +#else +#ifdef SIXTY_FOUR_BIT + if (l & 0xffffffff00000000LL) + { + if (l & 0xffff000000000000LL) + { + if (l & 0xff00000000000000LL) + i=56; + else i=48; + } + else + { + if (l & 0x0000ff0000000000LL) + i=40; + else i=32; + } + } + else +#endif +#endif + { +#if defined(THIRTY_BIT) || defined(THIRTY_ONE_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) + if (l & 0xffff0000L) + { + if (l & 0xff000000L) + i=24; + else i=16; + } + else +#endif + { + if (l & 0xff00L) + i=8; + else + i=0; + } + } +#ifndef SMALL_CODE_SIZE + return(i+bits[l>>i]); +#else + l>>=i; + if (l & 0xf0) + return(bits[l>>4]+i+4); + else + return(bits[l]+i); +#endif + } +#endif + +#ifdef SPLIT_BN_NUM_BITS +int BN_num_bits(a) +BIGNUM *a; + { + BN_ULONG l; + int i; + + bn_check_top(a); + + if (a->top == 0) return(0); + l=a->d[a->top-1]; + i=(a->top-1)*BN_BITS2; +#ifdef BN_DEBUG + if (l == 0) + { +#if !defined(NO_FP_API) && !defined(WIN16) + fprintf(stderr,"BAD TOP VALUE\n"); +#endif + abort(); /* BN_DEBUG */ + /* TODO: need to understand what sort of error can + * be reported for this error + */ + return(0); + } +#endif + return(i+BN_num_bits_word(l)); + } +#endif + +/** + * Clears and free a BIGNUM + * + * @param a [In] BIGNUM to clear then free + */ +#ifdef SPLIT_BN_CLEAR_FREE +void BN_clear_free(BIGNUM *a) +{ + if (a == NULL) + { + return; + } + + BN_clear(a); + BN_free(a); +} +#endif + +#ifdef SPLIT_BN_FREE +/** + * Frees a BIGNUM + * + * @param a [In] BIGNUM to free + */ +void BN_free(a) +BIGNUM *a; + { + if (a == NULL) return; + if ((a->d != NULL) && !(BN_get_flags(a,BN_FLG_STATIC_DATA))) + Free(a->d); + a->flags|=BN_FLG_FREE; /* REMOVE? */ + if (a->flags & BN_FLG_MALLOCED) + Free(a); + } +#endif + +#ifdef SPLIT_BN_INIT + +#ifdef SMALL_CODE_SIZE +/** + * Zero expands a bignum + * + * @param a [In] BIGNUM to expand + * @param n [In] number of bits to expand to + * + * @pre a is a valid BIGNUM. + */ +void bn_zexpand(a,n) +BIGNUM *a; +int n; + { + if ((a)->top < n) + { + int i; + bn_wexpand((a),n); + if (a->d!=NULL) + { + for (i=(a)->top; id[i]=0; + } + } + } + +/** + * Fixes the top value in the BIGNUM to be the count of BN_ULONGs with data. + * + * @param a [In] BIGNUM to free + * + * @pre a is a valid BIGNUM. + */ +void bn_fix_top(a) +BIGNUM *a; + { + BN_ULONG *ftl; + if ((a)->top > 0) + { + for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) + if (*(ftl--)) break; + } + } +#endif + +/** + * Initializes a BIGNUM + * + * @param a [In] BIGNUM reference + * + * @pre a is a valid BIGNUM. + */ +void BN_init(a) +BIGNUM *a; + { + (void)Memset(a,0,sizeof(BIGNUM)); + } +#endif + +#ifdef SPLIT_BN_NEW +/** + * Allocates a BIGNUM + * + * @return pointer to allocated BIGNUM + */ +BIGNUM *BN_new() + { + BIGNUM *ret; + + if ((ret=(BIGNUM *)Malloc(sizeof(BIGNUM))) == NULL) + { +#ifndef NO_ERR + BNerr(BN_F_BN_NEW,ERR_R_MALLOC_FAILURE); +#endif + return(NULL); + } + ret->flags=BN_FLG_MALLOCED; + ret->top=0; + ret->neg=0; + ret->max=0; + ret->d=NULL; + return(ret); + } +#endif + +#ifdef SPLIT_BN_CTX_NEW +/** + * Allocates a BIGNUM context + * + * @return pointer to allocated BIGNUM context + */ +BN_CTX *BN_CTX_new() + { + BN_CTX *ret; + + ret=(BN_CTX *)Malloc(sizeof(BN_CTX)); + if (ret == NULL) + { +#ifndef NO_ERR + BNerr(BN_F_BN_CTX_NEW,ERR_R_MALLOC_FAILURE); +#endif + return(NULL); + } + + BN_CTX_init(ret); + ret->flags=BN_FLG_MALLOCED; + return(ret); + } +#endif + +#ifdef SPLIT_CTX_INIT +/** + * Initializes a BIGNUM context + * + * @param a [In] BIGNUM context reference + * + * @pre a is a valid BIGNUM context. + */ +void BN_CTX_init(ctx) +BN_CTX *ctx; + { + (void)Memset(ctx,0,sizeof(BN_CTX)); + ctx->tos=0; + ctx->flags=0; + } +#endif + +#ifdef SPLIT_BN_CTX_FREE +/** + * Frees a BIGNUM context + * + * @param a [In] BIGNUM context reference + * + * @pre a is a valid BIGNUM context. + */ +void BN_CTX_free(c) +BN_CTX *c; + { + int i; + + for (i=0; ibn[i])); + if (c->flags & BN_FLG_MALLOCED) + Free(c); + } +#endif + +#ifdef SPLIT_BN_EXPAND2 +BIGNUM *bn_expand2(b, words) +BIGNUM *b; +int words; + { + BN_ULONG *A,*B,*a; + + R_DIAG_CHECK_STACK; + + bn_check_top(b); + + if (words > b->max) + { + bn_check_top(b); + if (BN_get_flags(b,BN_FLG_STATIC_DATA)) + { +#ifndef NO_ERR + BNerr(BN_F_BN_EXPAND2,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); +#endif + return(NULL); + } + a=A=(BN_ULONG *)Malloc(sizeof(BN_ULONG)*(words+1)); + if (A == NULL) + { +#ifndef NO_ERR + BNerr(BN_F_BN_EXPAND2,ERR_R_MALLOC_FAILURE); +#endif + return(NULL); + } + /* during development this is a nice way of making sure + * that we are not relying on the top byte being 0 or + * other such things + */ +#ifdef BN_DEBUG + (void)Memset(A,0x5c,sizeof(BN_ULONG)*(words+1)); +#endif + + B=b->d; + if (B != NULL) + { +#ifndef SMALL_CODE_SIZE + int i; + + /* for (i=b->top&(~7); i>0; i-=8) */ + /* The above line can induce a SunC compiler bug */ + for (i=(b->top>>3); i>0; i--) + { + BN_ULONG T0,T1,T2,T3; + + T0=B[0]; + T1=B[1]; + T2=B[2]; + T3=B[3]; + A[0]=T0; + A[1]=T1; + A[2]=T2; + A[3]=T3; + T0=B[4]; + T1=B[5]; + T2=B[6]; + T3=B[7]; + A[4]=T0; + A[5]=T1; + A[6]=T2; + A[7]=T3; + A+=8; + B+=8; + } + switch (b->top&7) + { + case 7: + A[6]=B[6]; + case 6: + A[5]=B[5]; + case 5: + A[4]=B[4]; + case 4: + A[3]=B[3]; + case 3: + A[2]=B[2]; + case 2: + A[1]=B[1]; + case 1: + A[0]=B[0]; + case 0: + /* I need the 'case 0' entry for utrix cc. + * If the optimiser is turned on, it does the + * switch table by doing + * a=top&7 + * a--; + * goto jump_table[a]; + * If top is 0, this makes us jump to 0xffffffc + * which is rather bad. + * eric 23-Apr-1998 + */ + ; + } +#if 0 /* Not needed */ + B= &(b->d[b->top]); + j=b->max-8; + for (i=b->top; itop); +#endif + Free(b->d); + } + + b->d=a; + b->max=words; + } + return(b); + } +#endif + +#ifdef SPLIT_BN_DUP +/** + * Duplicates a BIGNUM + * + * @param a [In] BIGNUM reference + * + * @returns pointer to duplicate BIGNUM of a + */ +BIGNUM *BN_dup(a) +BIGNUM *a; + { + BIGNUM *r; + BIGNUM *ret; + + bn_check_top(a); + + r=BN_new(); + if (r == NULL) return(NULL); + ret = (BIGNUM *)BN_copy(r,a); + if (ret == NULL) + { + BN_free(r); + } + return(ret); + } +#endif + +#ifdef SPLIT_BN_COPY +/** + * Copies a BIGNUM to an existing BIGNUM + * + * @param a [In] To BIGNUM reference + * @param b [Out] From BIGNUM reference + * + * @pre Both a and b are valid BIGNUMs + * + * @returns pointer to duplicate BIGNUM of a + */ +BIGNUM *BN_copy(a, b) +BIGNUM *a; +BIGNUM *b; + { +#ifndef SMALL_CODE_SIZE + int i; + BN_ULONG *A,*B; +#endif + + bn_check_top(b); + + if (a == b) return(a); + if (bn_wexpand(a,b->top) == NULL) return(NULL); +#ifndef SMALL_CODE_SIZE + A=a->d; + B=b->d; + +/* for (i=b->top&~0x07; i>0; i-=8) */ +/* The above version of this loop has been removed. It appeared + to generate a compiler bug in SunC 4.x and 5.x. I do not believe + that the code was to blame. Compiling with -fast was the problem + since this would loop unroll the loop below another 3 times. + The compiler would generate generate + andcc %o0,-8,%o1 # load ~0x07 + ld [%i2],%o3 # load *B + ble .L77000125 # exit loop unless 8 or more + ld [%i1],%o2 # load *A + sub %o1,-7,%o0 # + sdivcc %o0,8,%o0 # when do we clear %y? + bvs,a .L900001510 + sethi %hi(0x80000000),%o0 +.L900001510: + cmp %o0,3 + bl .L77000114 # one loop + ld [%o2],%o0 + # three loop code + + The loop would then be unrolled 3 times. The problem I believe + I was seeing was that the sdivcc operates is %y:%o0 / 8. + %y is not being cleared, and so occasionally this would + cause problems. The replacement code sequence stops + the compiler generating the sdiv instruction. + */ + for (i=(b->top>>3); i>0; i--) + { + BN_ULONG T0,T1,T2,T3; + T0=B[0]; + T1=B[1]; + T2=B[2]; + T3=B[3]; + A[0]=T0; + A[1]=T1; + A[2]=T2; + A[3]=T3; + T0=B[4]; + T1=B[5]; + T2=B[6]; + T3=B[7]; + A[4]=T0; + A[5]=T1; + A[6]=T2; + A[7]=T3; + A+=8; + B+=8; + } + switch (b->top&0x07) + { + case 7: + A[6]=B[6]; + case 6: + A[5]=B[5]; + case 5: + A[4]=B[4]; + case 4: + A[3]=B[3]; + case 3: + A[2]=B[2]; + case 2: + A[1]=B[1]; + case 1: + A[0]=B[0]; + case 0: + /* I need the 'case 0' entry for utrix cc. + * If the optimiser is turned on, it does the + * switch table by doing + * a=top&7 + * a--; + * goto jump_table[a]; + * If top is 0, this makes us jump to 0xffffffc which is + * rather bad. + * eric 23-Apr-1998 + */ + ; + } +#else + (void)Memcpy(a->d,b->d,sizeof(b->d[0])*b->top); +#endif + +/* (void)Memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top));*/ + a->top=b->top; + if ((a->top == 0) && (a->d != NULL)) + a->d[0]=0; + a->neg=b->neg; + return(a); + } +#endif + +#ifdef SPLIT_BN_CLEAR +/** + * Clears a BIGNUM + * + * @param a [In] BIGNUM to clear + * + * @pre a is valid + */ +void BN_clear(a) +BIGNUM *a; + { + if (a->d != NULL) + (void)Memset(a->d,0,a->max*sizeof(a->d[0])); + a->top=0; + a->neg=0; + } +#endif + +#ifdef SPLIT_BN_GET_WORD +BN_ULONG BN_get_word(a) +BIGNUM *a; + { + int i,n; + BN_ULONG ret=0; + + n=BN_num_bytes(a); + if (n > ((int) sizeof(BN_ULONG))) + return(BN_MASK2); + for (i=a->top-1; i>=0; i--) + { +#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */ + ret<<=BN_BITS4; /* stops the compiler complaining */ + ret<<=BN_BITS4; +#else + ret=0; +#endif + ret|=a->d[i]; + } + return(ret); + } +#endif + +#ifdef SPLIT_BN_SET_WORD +/** + * Set the BIGNUM to the supplied BN_ULONG value. + * + * @param a [In/Out] BIGNUM to be updated + * @param w [In] Value to be set in a + * + * @notes Function will expand a to be an + * array of 8 BN_ULONGs in size. + * @todo Review behaviour of expansion without checking + * of size first. + */ +int BN_set_word(a,w) +BIGNUM *a; +BN_ULONG w; + { + int i,n; + + if (bn_expand(a,(int)(sizeof(BN_ULONG)*8)) == NULL) return(0); + +#ifdef BN_BYTES + /* This is used when a BN_ULONG is greater in size + * than the BN_BYTES of the array, eg BN_ULONG 64 bits + * and actual a->d array of 32 bits. + */ + n=sizeof(BN_ULONG)/BN_BYTES; +#else + n=1; +#endif + a->neg=0; + a->top=0; + a->d[0]=(BN_ULONG)w&BN_MASK2; + if (a->d[0] != 0) a->top=1; + for (i=1; i>=BN_BITS2 so compilers don't complain + * on builds where sizeof(long) == BN_TYPES */ +#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */ + w>>=BN_BITS4; + w>>=BN_BITS4; +#else + w=0; +#endif + a->d[i]=(BN_ULONG)w&BN_MASK2; + if (a->d[i] != 0) a->top=i+1; + } + return(1); + } +#endif + +#ifdef BN_BYTES +#ifdef SPLIT_BN_BIN2BN +/* ignore negative */ +BIGNUM *BN_bin2bn(s, len, ret) +unsigned char *s; +int len; +BIGNUM *ret; + { + int i,m; + int n; + BN_ULONG l; + + if (ret == NULL) ret=BN_new(); + if (ret == NULL) return(NULL); + l=0; + n=len; + if (n == 0) + { + ret->top=0; + return(ret); + } + if (bn_expand(ret,(int)(n+2)*8) == NULL) + return(NULL); + i=((n-1)/BN_BYTES)+1; + m=((n-1)%(BN_BYTES)); + ret->top=i; + while (n-- > 0) + { + l=(l<<8L)| *(s++); + if (m-- == 0) + { + ret->d[--i]=l; + l=0; + m=BN_BYTES-1; + } + } + /* need to call this due to clear byte at top if avoiding + * having the top bit set (-ve number) */ + bn_fix_top(ret); + return(ret); + } +#endif + +#ifdef SPLIT_BN_BN2BIN +/* ignore negative */ +int BN_bn2bin(a, to) +BIGNUM *a; +unsigned char *to; + { + int n,i; + BN_ULONG l; + + bn_check_top(a); + + n=i=BN_num_bytes(a); + while (i-- > 0) + { + l=a->d[i/BN_BYTES]; + *(to++)=(unsigned char)((l>>(8*(i%BN_BYTES)))&0xff); + } + return(n); + } +#endif +#else +#ifdef SPLIT_BN_BIN2BN +/* ignore negative */ +BIGNUM *BN_bin2bn(s, len, ret) +unsigned char *s; +int len; +BIGNUM *ret; + { + int i,w,r,b,j,v; + int n; + BN_ULONG l; + + if (ret == NULL) ret=BN_new(); + if (ret == NULL) return(NULL); + while (len > 0) + { + if (*s != 0) break; + s++; + len--; + } + n=len*8; + if (bn_expand(ret,n) == NULL) + return(NULL); + for (i=0; imax; i++) + ret->d[i]=0; + j=0; + for (i=len-1; i>=0; i--) + { + v=((int)s[i])&0xff; + w=j/BN_BITS2; + b=j%BN_BITS2; + r=BN_BITS2-b; + j+=8; + if (r >= 8) + { + ret->d[w]|=(((BN_ULONG)v)<d[w] =(ret->d[w]|(((BN_ULONG)v)<d[w+1]=(ret->d[w+1]|(((BN_ULONG)v)>>r)); + } + } + + ret->top=((n-1)/BN_BITS2)+1; + bn_fix_top(ret); + return(ret); + } +#endif + +#ifdef SPLIT_BN_BN2BIN +int BN_bn2bin(a, to) +BIGNUM *a; +unsigned char *to; + { + int num,i,bi,w,b,r,max; + BN_ULONG l,*lp; + + bn_check_top(a); + + num=bi=BN_num_bytes(a); + lp=a->d; + for (i=0; i= 8) + to[bi]=(lp[w]>>b)&0xff; + else + { + to[bi]=(lp[w]>>b); + if (w+1 < a->top) + to[bi]|=lp[w+1]<top-b->top; + if (i != 0) return(i); + ap=a->d; + bp=b->d; + for (i=a->top-1; i>=0; i--) + { + t1= ap[i]; + t2= bp[i]; + if (t1 != t2) + return(t1 > t2?1:-1); + } + return(0); + } +#endif + +#ifdef SPLIT_BN_CMP +int BN_cmp(a, b) +BIGNUM *a; +BIGNUM *b; + { + int i; + int gt,lt; + BN_ULONG t1,t2; + + if ((a == NULL) || (b == NULL)) + { + if (a != NULL) + return(-1); + else if (b != NULL) + return(1); + else + return(0); + } + + bn_check_top(a); + bn_check_top(b); + + if (a->neg != b->neg) + { + if (a->neg) + return(-1); + else return(1); + } + if (a->neg == 0) + { gt=1; lt= -1; } + else { gt= -1; lt=1; } + + if (a->top > b->top) return(gt); + if (a->top < b->top) return(lt); + for (i=a->top-1; i>=0; i--) + { + t1=a->d[i]; + t2=b->d[i]; + if (t1 > t2) return(gt); + if (t1 < t2) return(lt); + } + return(0); + } +#endif + +#ifdef SPLIT_BN_SET_BIT +int BN_set_bit(a, n) +BIGNUM *a; +int n; + { + int i,j,k; + + bn_check_top(a); + + i=n/BN_BITS2; + j=n%BN_BITS2; + if (a->top <= i) + { + if (bn_wexpand(a,i+1) == NULL) return(0); + for(k=a->top; kd[k]=0; + a->top=i+1; + } + + a->d[i]|=(((BN_ULONG)1)<top <= i) return(0); + + a->d[i]&=(~(((BN_ULONG)1)<top <= i) return(0); + return((a->d[i]&(((BN_ULONG)1)<= a->top) return(0); + if (b == 0) + a->top=w; + else + { + a->top=w+1; + a->d[w]&= ~(((BN_ULONG)BN_MASK2)< bb)?1:-1); + for (i=n-2; i>=0; i--) + { + aa=a[i]; + bb=b[i]; + if (aa != bb) return((aa > bb)?1:-1); + } + return(0); + } +#endif +#endif + diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_lsh.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_lsh.c new file mode 100644 index 0000000..21508b1 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_lsh.c @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_LSHIFT1 +#define SPLIT_BN_LSHIFT +#endif /* NO_SPLIT */ + +#ifdef SPLIT_BN_LSHIFT1 +#ifdef SMALL_CODE_SIZE + +int BN_lshift1(r, a) +BIGNUM *r,*a; + { + return(BN_lshift(r, a, 1)); + } + +#else + +int BN_lshift1(r, a) +BIGNUM *r; +BIGNUM *a; + { + register BN_ULONG *ap,*rp,t,c; + int i; + + bn_check_top(a); + + if (r != a) + { + if (bn_wexpand(r,a->top+1) == NULL) return(0); + r->neg=a->neg; + r->top=a->top; + } + else + { + if (bn_wexpand(r,a->top+1) == NULL) return(0); + } + ap=a->d; + rp=r->d; + c=0; + for (i=0; itop; i++) + { + t= *(ap++); + *(rp++)=((t<<1L)|c)&BN_MASK2; + c=(t & BN_TBIT)?1:0; + } + if (c) + { + *rp=1; + r->top++; + } + return(1); + } +#endif +#endif + +#ifdef SPLIT_BN_LSHIFT +int BN_lshift(r, a, n) +BIGNUM *r; +BIGNUM *a; +int n; + { + int i,nw,lb,rb; + BN_ULONG *t,*f; + BN_ULONG l; + + bn_check_top(a); + +#ifndef SMALL_CODE_SIZE + if (n == 1) return(BN_lshift1(r,a)); +#endif + if (bn_wexpand(r,a->top+(n/BN_BITS2)+1) == NULL) return(0); + r->neg=a->neg; + nw=n/BN_BITS2; + lb=n%BN_BITS2; + rb=BN_BITS2-lb; + f=a->d; + t=r->d; + t[a->top+nw]=0; + if (lb == 0) + for (i=a->top-1; i>=0; i--) + t[nw+i]=f[i]; + else + for (i=a->top-1; i>=0; i--) + { + l=f[i]; + t[nw+i+1]|=(l>>rb)&BN_MASK2; + t[nw+i]=(l<top=a->top+nw+1; + bn_fix_top(r); + return(1); + } +#endif + +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_m_exp.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_m_exp.c new file mode 100644 index 0000000..480bb59 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_m_exp.c @@ -0,0 +1,299 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#if 0 //RSA +#include +#endif +#include "bn_lcl.h" + +/* #ifdef MONT_MUL_MOD */ +/** + * Generic form of Montgomery Exponentiation, can be called directly + * out side of a BN_ME_METH + * + * @param rr_in BIGNUM pointer for result + * @param a_in BIGNUM pointer for base + * @param p BIGNUM pointer to the exponent + * @param m BIGNUM pointer to the modulus + * @param ctx BN_CTX pointer for temp values are argument storage + * @param in_mont BN_MONT_CTX pointer to structure of montgomery values + * + * @pre arguments are all initialised and not NULL or zero + * @post rr_in contains evaluated result + * + * @note + */ +int BN_mod_exp_mont(rr_in,a_in,p,m,ctx,in_mont) +BIGNUM *rr_in; +BIGNUM *a_in; +BIGNUM *p; +BIGNUM *m; +BN_CTX *ctx; +BN_MONT_CTX *in_mont; + { + int i,j,k,ret=0,tos,top; + int mul,sqr,num; + BIGNUM *d,*aa,*r,*a,*t; + BN_ULONG *vall[BN_EXP_TABLE_SIZE],*dp,*rp,n0,*rr,*tmp,*np; + BN_MONT_CTX *mont=NULL; + unsigned char *str=NULL; +#ifdef BN_SURRENDER + R_SURRENDER *surrender=NULL; + int count=0; +#endif + + bn_check_top(a_in); + bn_check_top(p); + bn_check_top(m); + + if (!(m->d[0] & 1)) + { +#ifndef NO_ERR + BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS); +#endif + return(0); + } + + tos=ctx->tos; + + if (BN_is_zero(a_in)) + { (void)BN_zero(rr_in); return(1); } + if (BN_is_zero(p)) + { (void)BN_one(rr_in); return(1); } + if (BN_is_one(p)) + { (void)BN_copy(rr_in,a_in); return(1); } + + /* If this is not done, things will break in the montgomery + * part */ + +#if 1 + if (in_mont != NULL) + mont=in_mont; + else +#endif + { + if ((mont=BN_MONT_CTX_new()) == NULL) goto err; + if (!BN_MONT_CTX_set(mont,m,ctx)) goto err; + } + +#ifdef BN_SURRENDER + surrender=ctx->surrender; +#endif + + if (!BN_gen_exp_bits(p,&str,0,ctx)) goto err; + /* Remember this function uses another element from the passed ctx */ + ctx->tos++; + num=str[3]; + i=(BN_BITS+str[2]-1)/str[2]; + str+=4; + + + top=mont->N.top; + if ((a_in->top == top) && (a_in->d[top-1] < m->d[top-1])) + { + a=a_in; + } + else if (a_in->top < top) + { + a= &(ctx->bn[ctx->tos++]); + a->top=a_in->top; + bn_zexpand(a,top); + for (j=0; jtop; j++) + a->d[j]=a_in->d[j]; + } + else /* if (a_in->top > i) */ + { + a= &(ctx->bn[ctx->tos++]); + if (!BN_mod(a,a_in,m,ctx)) goto err; + bn_zexpand(a,top); + } + + /* At this point a is the size of the modulus and is 0 padded + * out to its size if needed. + */ + + /* Number of tmp words */ + k=num*top; + j=k+(p->top*i*2+BN_BYTES-1+4)/BN_BYTES; + + aa=&(ctx->bn[ctx->tos++]); + d= &(ctx->bn[ctx->tos++]); + r= &(ctx->bn[ctx->tos++]); + t= &(ctx->bn[ctx->tos++]); + + if (bn_wexpand(rr_in,top) == NULL) goto err; + if (bn_wexpand(d,top*4) == NULL) goto err; /* *2? */ + if (bn_wexpand(r,top*2) == NULL) goto err; + if (bn_wexpand(aa,j) == NULL) goto err; + if (bn_wexpand(t,top*2) == NULL) goto err; + dp=d->d; + rp=r->d; + tmp=t->d; + rr=mont->RR.d; + + n0=mont->n0; + np=mont->N.d; + + vall[0]=aa->d; + + bn_mul_normal(tmp,a->d,top,rr,top); + bn_from_montgomery_words(vall[0],tmp,np,top,n0); + + if (num > 1) + { + bn_sqr_normal(tmp,vall[0],top,dp); + bn_from_montgomery_words(dp,tmp,np,top,n0); + + for (i=1; i>1],sizeof(BN_ULONG)*top); + while (sqr != 0) + { +#ifdef BN_SURRENDER + /* + * Check this at the start of the loop rather than the + * end so we avoid as many of the bn operations as possible + */ + if (surrender != NULL) + { + if (surrender->callback(surrender,0xff, count++) != 0) + { + goto err; + } + } +#endif /* BN_SURRENDER */ + + /* + * check the abort flag at the start of the loop so we avoid + * as many of the bn operations as possible + */ + if (BN_CTX_get_flags(ctx, BN_CTX_FLG_ABORT)) + { + goto err; + } + + for (i=0; i>1],top); + bn_from_montgomery_words(rp,tmp,np,top,n0); + } + else + { + bn_mul_normal(tmp,rp,top,a->d,top); + bn_from_montgomery_words(rr_in->d,tmp,np,top,n0); + goto end; + } + } + + /* if (mul != 1) */ + { + for (i=top; id,rp,np,top,n0); + } +end: /* Use this to avoid an if */ + + /* + * Even if the operation has completed successfully, if the + * abort flag is set we want to abort so that anything + * calling this function will know not to continue. + */ + if (BN_CTX_get_flags(ctx, BN_CTX_FLG_ABORT)) + { + goto err; + } + + rr_in->top=top; + bn_fix_top(rr_in); + ret=1; +err: +#ifdef BN_SURRENDER + /* + * Even if the operation completed successfully we want to abort + * if the abort flag has been is set, so that subsequent operations + * do not continue. Allow the caller change to return value and + * cause the function to fail. + */ + if (surrender != NULL) + { + if (surrender->callback(surrender, 0xff, -1) != 0) + { + ret = 0; + } + } +#endif + if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); + ctx->tos=tos; + return(ret); + } +/* #endif */ + diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_me.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_me.c new file mode 100644 index 0000000..fae0749 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_me.c @@ -0,0 +1,267 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +/** + * @file bn_me.c + * @brief BN method functions and utilities + */ +#include "bn_lcl.h" +#include "bn_thx.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_MOD_EXP_METH_DEFAULT +#define SPLIT_BN_MONT_CTX_USEIT +#define SPLIT_BN_ME_CTX_NAME +#define SPLIT_BN_ME_CTX_NEW +#define SPLIT_BN_ME_CTX_FREE +#define SPLIT_BN_ME_CTX_SET +#define SPLIT_BN_ME_CTX_MOD_EXP +#endif /* NO_SPLIT */ + +#ifndef NOPROTO +BN_ME_METH *bn_mod_exp_meth_default(int fallback); +#else +BN_ME_METH *bn_mod_exp_meth_default(); +#endif + +#ifdef SPLIT_BN_MOD_EXP_METH_DEFAULT + +/** + * Returns the default mod_exp method, choose first available in the + * method table or a hardwired default + * + * @param fallback [In] Flag for choice of method + * - 0 use the first value in the method table + * - 1 use the all encompassing default method + * + * @pre BN_default_init() has been run setting up library + * + * @post + * + * @internal uses global table bnme[] and counter me_num + * + * @internal only read the BN_ME_METH_INFO table no need for locking + * + * @relates BN_library_init + * @relates BN_default_init + * @relates BN_ME_CTX_new + * @relates BN_ME_CTX_free + * + */ +BN_ME_METH *bn_mod_exp_meth_default(int fallback) +{ + const BN_ME_METH *tmp; + +#ifndef BN_LIBRARY_SMALL + BN_ME_METH_INFO *meth_info; + + if(!fallback && ((meth_info = BN_bnme_get_info(0)) != NULL)) + { + tmp = meth_info->meth(); + } + else +#endif + { + /* set in bn.h or override bn_thx.h */ + tmp = BN_ME_METH_DEFAULT(); + } + return((BN_ME_METH *)tmp); +} +#endif + +#ifdef SPLIT_BN_MONT_CTX_USEIT + +#ifndef NOPROTO +int bn_mont_ctx_useit(int argi); +#else +int bn_mont_ctx_useit(); +#endif + +/** + * Montgomery method default useit function + * + * @param argi [In] reserved for future use + * + * @return 0 success + */ +int bn_mont_ctx_useit(int argi) + { + return(0); + } +#endif + +#ifdef SPLIT_BN_ME_CTX_NAME +/** + * Retrieve the BN method name string + * + * @param ctx [In] Method + * + * @pre ctx is valid and not NULL + * + * @return string pointer + */ +char *BN_ME_CTX_name(BN_ME_CTX *ctx) + { + return(ctx->meth->name); + } +#endif + +#ifdef SPLIT_BN_ME_CTX_NEW +/** + * Allocate a new BN_ME_CTX structure and assign method + * + * @param meth [In] Method to assign + * @param in [Out] Result BN_ME_CTX + * + * @note if meth is NULL system method default is used + * + * @retval pointer to BN_ME_CTX success + * @retval NULL failure + */ +BN_ME_CTX *BN_ME_CTX_new(BN_ME_METH *meth, BN_ME_CTX **in) + { + int i; + BN_ME_CTX *ret; + + if (in == NULL) + in= &ret; + + if (meth == NULL) + meth=bn_mod_exp_meth_default(0); + i=meth->init_ctx(meth,in); + if (i) + return(NULL); + else + return(*in); + } +#endif + +#ifdef SPLIT_BN_ME_CTX_FREE +/** + * Free context method + * + * @param mctx [In] Context object to be deallocated + * + * @note it is the callers responsibility to set mctx to NULL after free + * + * @pre mctx is not NULL and is valide BN_ME_CTX + */ +void BN_ME_CTX_free(BN_ME_CTX *mctx) + { + mctx->meth->free_ctx(mctx); + } +#endif + +#ifdef SPLIT_BN_ME_CTX_SET +/** + * Set value to BN_ME_CTX by identifier + * + * @param mctx [In] Method context object + * @param b [In] Big number + * @param cmd [In] Command identifier + * @param flags [In] Mask operation directives + * @param ctx [In] BN data store + * + * @note cmd values: + * @li BN_ME_SET_MOD will cause a method lookup is method not set + * + * @note passes control to set method in mctx + * + * @return result of mctx method set operation + */ +int BN_ME_CTX_set(BN_ME_CTX *mctx, BIGNUM *b, int cmd, int flags, BN_CTX *ctx) + { +#ifndef BN_LIBRARY_SMALL +#ifndef NOPROTO + const BN_ME_METH *(*meth)(void); +#else + const BN_ME_METH *(*meth)(); +#endif +#endif /* BN_LIBRARY_SMALL */ + + /* If we are loading the modulus, and we do not have the + * no_lookup flag (without a null method) + */ + if ((cmd == BN_ME_SET_MOD) && + ((mctx->meth != NULL) && !(flags & BN_ME_SET_FLG_NO_LOOKUP))) + { +#ifndef BN_LIBRARY_SMALL + meth=(const BN_ME_METH*(*)(void)) + BN_bnme_get(BN_num_bits(b),BN_BNME_F_BITS); + if (meth != NULL) + mctx->meth=meth(); + else +#endif + mctx->meth=bn_mod_exp_meth_default(1); + } + return(mctx->meth->set(mctx,b,cmd,flags,ctx)); + } +#endif + +#ifdef SPLIT_BN_ME_CTX_MOD_EXP +/** + * Call method mod_exp operation + * + * @param mctx [In] Method context object + * @param ret [Out] Result + * @param a [In] Base value + * @param p [In] Exponent + * @param m [In] Modulus + * @param ctx [In] Data storage + * + * @pre a must be expandable + * + * @return 0 success + */ +int BN_ME_CTX_mod_exp(BN_ME_CTX *mctx, BIGNUM *ret, BIGNUM *a, BIGNUM *p, + BIGNUM *m, BN_CTX *ctx) + { + int wtop; + + /* Before we call the method, make sure we are not doing 0^p, + * and p is not 0 or 1 */ + if (BN_is_zero(a)) + { BN_zero(ret); return(0); } + if (p != NULL) + { + if (BN_is_zero(p)) + { BN_one(ret); return(0); } + else if (BN_is_one(p)) + { BN_copy(ret,a); return(0); } + } + + /* wtop is the size 'a' needs to be for the method */ + wtop=mctx->meth->num; + bn_zexpand(a,wtop); + + return(mctx->meth->mod_exp(mctx,ret,a,p,ctx)); + } +#endif + +#endif + diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_mont.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_mont.c new file mode 100644 index 0000000..d6a45de --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_mont.c @@ -0,0 +1,247 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#undef BN_DEBUG +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_MOD_MUL_MONTGOMERY +#define SPLIT_BN_FROM_MONTGOMERY +#define SPLIT_BN_MONT_CTX_NEW +#define SPLIT_BN_MONT_CTX_INIT +#define SPLIT_BN_MONT_CTX_FREE +#define SPLIT_BN_MONT_CTX_COPY +#endif /* NO_SPLIT */ + +/* #define DEBUG */ + +#ifdef SPLIT_BN_MOD_MUL_MONTGOMERY +/* We multiply a by b, generating a number 2n words long. + * This is then reduced by the montogmery number, which is + * n words. */ +int BN_mod_mul_montgomery(r,a,b,mont,ctx) +BIGNUM *r,*a,*b; +BN_MONT_CTX *mont; +BN_CTX *ctx; + { + BIGNUM *tmp,*tmp2; + int ret=0,w; + int i; + + bn_check_top(a); + bn_check_top(b); + + w=mont->riw; + + tmp= &(ctx->bn[ctx->tos++]); + tmp2= &(ctx->bn[ctx->tos++]); + bn_check_top(tmp); + bn_check_top(tmp2); + if (bn_wexpand(tmp,w+w) == NULL) goto err; + if (bn_wexpand(r,w+w) == NULL) goto err; + + if (a == b) + { + if (bn_wexpand(tmp2,w+w) == NULL) goto err; +#ifdef BN_SQR_COMBA + if ((a->top == 8) && (a->top == b->top)) + bn_sqr_comba8(tmp->d,a->d); + else +#endif + { + bn_sqr_normal(tmp->d,a->d,a->top,tmp2->d); + } + } + else + { +#ifdef BN_MUL_COMBA + if (a->top == 8) + bn_mul_comba8(tmp->d,a->d,b->d); + else +#endif + { + bn_mul_normal(tmp->d,a->d,a->top,b->d,b->top); + } + } + + i=a->top+b->top; + while (i<(w+w)) + { + tmp->d[i]=0; + i++; + } + tmp->top=w+w; + tmp->neg=0; + + /* reduce from aRR to aR */ + /* tmp->d is 2w words */ +#if 0 + bn_fix_top(tmp); + BN_from_montgomery_words(r,tmp,mont,ctx); +#else + bn_from_montgomery_words(r->d,tmp->d,mont->N.d,w,mont->n0); +#endif + r->top=w; + r->neg=0; + bn_fix_top(r); + + ret=1; +err: + ctx->tos-=2; + return(ret); + } +#endif + +#ifdef SPLIT_BN_FROM_MONTGOMERY +int BN_from_montgomery(ret,a,mont,ctx) +BIGNUM *ret; +BIGNUM *a; +BN_MONT_CTX *mont; +BN_CTX *ctx; + { + BIGNUM *n,*r; + BN_ULONG *np,*rp,n0,v0,v1,*nrp; + int al,nl,max,i; + int retn=0; + + bn_check_top(a); + + r= &(ctx->bn[ctx->tos]); + + if (!BN_copy(r,a)) goto err1; + n= &(mont->N); + + /* mont->riw is the size of mont->N in bits/words */ + al=mont->riw; + + nl=n->top; + if ((al == 0) || (nl == 0)) { r->top=0; return(1); } + + max=(nl+al+1); /* allow for overflow (no?) XXX */ + if (bn_wexpand(r,max) == NULL) goto err1; + if (bn_wexpand(ret,max) == NULL) goto err1; + + r->neg=a->neg^n->neg; + np=n->d; + rp=r->d; + nrp= &(r->d[nl]); + + /* clear the top words of T */ + for (i=r->top; id[i]=0; + + r->top=max; + n0=mont->n0; + + v1=0; + for (i=0; iriw will be a multiple of the word size */ + (void)BN_rshift(ret,r,mont->riw*BN_BITS2); + + if (BN_ucmp(ret, &(mont->N)) >= 0) + { + (void)BN_usub(ret,ret,&(mont->N)); /* XXX */ + } + retn=1; + +err1: + return(retn); + } +#endif + +#ifdef SPLIT_BN_MONT_CTX_NEW +BN_MONT_CTX *BN_MONT_CTX_new() + { + BN_MONT_CTX *ret; + + if ((ret=(BN_MONT_CTX *)Malloc(sizeof(BN_MONT_CTX))) == NULL) + return(NULL); + + BN_MONT_CTX_init(ret); + ret->flags=BN_FLG_MALLOCED; + return(ret); + } +#endif + +#ifdef SPLIT_BN_MONT_CTX_INIT +void BN_MONT_CTX_init(ctx) +BN_MONT_CTX *ctx; + { + ctx->use_word=0; + ctx->riw=0; + BN_init(&(ctx->RR)); + BN_init(&(ctx->N)); + BN_init(&(ctx->Ni)); + ctx->flags=0; + } +#endif + +#ifdef SPLIT_BN_MONT_CTX_FREE +void BN_MONT_CTX_free(mont) +BN_MONT_CTX *mont; + { + BN_free(&(mont->RR)); + BN_free(&(mont->N)); + BN_free(&(mont->Ni)); + if (mont->flags & BN_FLG_MALLOCED) + Free(mont); + } +#endif + +#ifdef SPLIT_BN_MONT_CTX_COPY +BN_MONT_CTX *BN_MONT_CTX_copy(to, from) +BN_MONT_CTX *to, *from; + { + if (to == from) return(to); + + (void)BN_copy(&(to->RR),&(from->RR)); + (void)BN_copy(&(to->N),&(from->N)); + (void)BN_copy(&(to->Ni),&(from->Ni)); + bn_zexpand(&(to->RR),from->riw); + bn_zexpand(&(to->Ni),from->riw); + to->use_word=from->use_word; + to->riw=from->riw; + to->n0=from->n0; + return(to); + } +#endif + +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_ms_w.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_ms_w.c new file mode 100644 index 0000000..86a6510 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_ms_w.c @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +int BN_MONT_CTX_set_word(mont,mod,ctx) +BN_MONT_CTX *mont; +BIGNUM *mod; +BN_CTX *ctx; + { + BIGNUM Ri,*R; +#if 1 + BN_ULONG tmod,rr; +#else + BN_ULONG buf[2]; + BIGNUM tmod; +#endif + + + bn_check_top(mod); + if (mod->top == 0) return(0); + + R= &(mont->RR); /* grab RR as a temp */ + if (BN_copy(&(mont->N),mod) == NULL) /* Set N */ + return(0); + + BN_init(&Ri); + + mont->use_word=1; + +/* EAY is this number of words to shift, or the number to shift to end up + * with a '1' in the next word? + * for 8 bit words, is 0x01ab == 1 or 2 + */ + mont->riw=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2; + if (!BN_zero(R)) return(0); + + /* We are now setting a number which is larger than our current + * one after we do the shift + */ + if (!BN_set_bit(R,BN_BITS2)) + goto err; + +#if 0 + tmod.d=buf; + tmod.top=1; + tmod.max=mod->max; + tmod.neg=mod->neg; + buf[0]=mod->d[0]&BN_MASK2; + buf[1]=0; + + if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL) + goto err; +#else + tmod=mod->d[0]; + rr=BN_mod_inverse_word(tmod); + if (!BN_set_word(&Ri,rr)) + goto err; +#endif + + /* R*Ri */ + if (!BN_lshift(&Ri,&Ri,BN_BITS2)) + goto err; + + if (!BN_is_zero(&Ri)) + (void)BN_sub_word(&Ri,1); + else + { + /* This is not common..., 1 in BN_MASK2, + * It happens when buf[0] was == 1. So for 8 bit, + * this is 1/256, 16bit, 1 in 2^16 etc. + */ + if (!BN_set_word(&Ri,BN_MASK2)) + goto err; + } +#if 0 + BN_div(&Ri,NULL,&Ri,&tmod,ctx); + //BN_div_word(&Ri,tmod); + mont->n0=Ri.d[0]; +#else +#if 0 + { + BN_ULONG h,l; + + h=l=0; + if (Ri.top >= 2) h=Ri.d[1]; + if (Ri.top >= 1) l=Ri.d[0]; + mont->n0=bn_div_words(h,l,tmod); + } +#endif + mont->n0=bn_div_words( + (Ri.top >= 2)?Ri.d[1]:0, + (Ri.top >= 1)?Ri.d[0]:0, + tmod); +#endif + /* mod->top=z; */ + + /* setup RR for conversions */ + (void)BN_zero(&(mont->RR)); + if (!BN_set_bit(&(mont->RR),mont->riw*2*BN_BITS2)) + goto err; + (void)BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx); + bn_zexpand(&(mont->RR),mont->riw); +#if 0 + bn_zexpand(&(mont->Ni),mont->riw); /*This is not used? */ +#endif + +err: + BN_free(&Ri); + return(1); + } + + diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_mul.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_mul.c new file mode 100644 index 0000000..76e83e7 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_mul.c @@ -0,0 +1,795 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_MUL_RECURSIVE +#define SPLIT_BN_MUL_PART_RECURSIVE +#define SPLIT_BN_MUL_LOW_RECURSIVE +#define SPLIT_BN_MUL_HIGH +#define SPLIT_BN_MUL +#define SPLIT_BN_MUL_NORMAL +#define SPLIT_BN_MUL_LOW_NORMAL +#endif /* NO_SPLIT */ + +#ifdef SMALL_CODE_SIZE +#undef BN_RECURSION_MUL +#endif + +#ifdef BN_RECURSION_MUL +#if 0 /* Replaced by bn_mul_rec_words() */ +/* r is 2*n2 words in size, + * a and b are both n2 words in size. + * n2 must be a power of 2. + * We multiply and return the result. + * t must be 2*n2 words in size + * We calulate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +#ifdef SPLIT_BN_MUL_RECURSIVE +void bn_mul_recursive(r,a,b,n2,t) +BN_ULONG *r,*a,*b; +int n2; +BN_ULONG *t; + { + int n=n2/2,c1,c2; + unsigned int neg,zero; + BN_ULONG ln,lo,*p; + +#ifdef BN_COUNT +printf(" bn_mul_recursive %d * %d\n",n2,n2); +#endif +#ifdef BN_MUL_COMBA +/* if (n2 == 4) + { + bn_mul_comba4(r,a,b); + return; + } + else */ if (n2 == 8) + { + bn_mul_comba8(r,a,b); + return; + } +#endif + if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) + { + /* This should not happen */ + bn_mul_normal(r,a,n2,b,n2); + return; + } + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1=bn_cmp_words(a,&(a[n]),n); + c2=bn_cmp_words(&(b[n]),b,n); + zero=neg=0; + switch (c1*3+c2) + { + case -4: + bn_sub_words(t, &(a[n]),a, n); /* - */ + bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */ + break; + case -3: + zero=1; + break; + case -2: + bn_sub_words(t, &(a[n]),a, n); /* - */ + bn_sub_words(&(t[n]),&(b[n]),b, n); /* + */ + neg=1; + break; + case -1: + case 0: + case 1: + zero=1; + break; + case 2: + bn_sub_words(t, a, &(a[n]),n); /* + */ + bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */ + neg=1; + break; + case 3: + zero=1; + break; + case 4: + bn_sub_words(t, a, &(a[n]),n); + bn_sub_words(&(t[n]),&(b[n]),b, n); + break; + } + +#ifdef BN_MUL_COMBA + if (n == 4) + { + if (!zero) + bn_mul_comba4(&(t[n2]),t,&(t[n])); + else + Memset(&(t[n2]),0,8*sizeof(BN_ULONG)); + + bn_mul_comba4(r,a,b); + bn_mul_comba4(&(r[n2]),&(a[n]),&(b[n])); + } + else if (n == 8) + { + if (!zero) + bn_mul_comba8(&(t[n2]),t,&(t[n])); + else + Memset(&(t[n2]),0,16*sizeof(BN_ULONG)); + + bn_mul_comba8(r,a,b); + bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n])); + } + else +#endif + { + p= &(t[n2*2]); + if (!zero) + bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p); + else + Memset(&(t[n2]),0,n2*sizeof(BN_ULONG)); + bn_mul_recursive(r,a,b,n,p); + bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,p); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1=(int)bn_add_words(t,r,&(r[n2]),n2); + + if (neg) /* if t[32] is negative */ + { + c1-=(int)bn_sub_words(&(t[n2]),t,&(t[n2]),n2); + } + else + { + /* Might have a carry */ + c1+=(int)bn_add_words(&(t[n2]),&(t[n2]),t,n2); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1+=(int)bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2); + if (c1) + { + p= &(r[n+n2]); + lo= *p; + ln=(lo+c1)&BN_MASK2; + *p=ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) + { + do { + p++; + lo= *p; + ln=(lo+1)&BN_MASK2; + *p=ln; + } while (ln == 0); + } + } + } +#endif +#endif + +#if 0 +#ifdef SPLIT_BN_MUL_PART_RECURSIVE +/* n+tn is the word length + * t must be n*4 is size, as does r */ +void bn_mul_part_recursive(r,a,b,tn,n,t) +BN_ULONG *r,*a,*b; +int tn,n; +BN_ULONG *t; + { + int i,j,n2=n*2; + int c1; + BN_ULONG ln,lo,*p; + +#ifdef BN_COUNT +printf(" bn_mul_part_recursive %d * %d\n",tn+n,tn+n); +#endif + if (n < 8) + { + i=tn+n; + bn_mul_normal(r,a,i,b,i); + return; + } + + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + bn_sub_words(t, a, &(a[n]),n); /* + */ + bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */ + +#ifdef BN_MUL_COMBA +/* if (n == 4) + { + bn_mul_comba4(&(t[n2]),t,&(t[n])); + bn_mul_comba4(r,a,b); + bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn); + Memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2)); + } + else */ if (n == 8) + { + bn_mul_comba8(&(t[n2]),t,&(t[n])); + bn_mul_comba8(r,a,b); + bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn); + Memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2)); + } + else +#endif + { + p= &(t[n2*2]); + bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p); + bn_mul_recursive(r,a,b,n,p); + i=n/2; + /* If there is only a bottom half to the number, + * just do it */ + j=tn-i; + if (j == 0) + { + bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),i,p); + Memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2)); + } + else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */ + { + bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]), + j,i,p); + Memset(&(r[n2+tn*2]),0, + sizeof(BN_ULONG)*(n2-tn*2)); + } + else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */ + { + Memset(&(r[n2]),0,sizeof(BN_ULONG)*n2); + if (tn < BN_MUL_RECURSIVE_SIZE_NORMAL) + { + bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn); + } + else + { + for (;;) + { + i/=2; + if (i < tn) + { + bn_mul_part_recursive(&(r[n2]), + &(a[n]),&(b[n]), + tn-i,i,p); + break; + } + else if (i == tn) + { + bn_mul_recursive(&(r[n2]), + &(a[n]),&(b[n]), + i,p); + break; + } + } + } + } + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1=(int)bn_add_words(t,r,&(r[n2]),n2); + c1-=(int)bn_sub_words(&(t[n2]),t,&(t[n2]),n2); + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1+=(int)bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2); + if (c1) + { + p= &(r[n+n2]); + lo= *p; + ln=(lo+c1)&BN_MASK2; + *p=ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) + { + do { + p++; + lo= *p; + ln=(lo+1)&BN_MASK2; + *p=ln; + } while (ln == 0); + } + } + } +#endif +#endif + +#if 0 +#ifdef SPLIT_BN_MUL_LOW_RECURSIVE +/* a and b must be the same size, which is n2. + * r must be n2 words and t must be n2*2 + */ +void bn_mul_low_recursive(r,a,b,n2,t) +BN_ULONG *r,*a,*b; +int n2; +BN_ULONG *t; + { + int n=n2/2; + +#ifdef BN_COUNT +printf(" bn_mul_low_recursive %d * %d\n",n2,n2); +#endif + + bn_mul_recursive(r,a,b,n,&(t[0])); + if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) + { + bn_mul_low_recursive(&(t[0]),&(a[0]),&(b[n]),n,&(t[n2])); + bn_add_words(&(r[n]),&(r[n]),&(t[0]),n); + bn_mul_low_recursive(&(t[0]),&(a[n]),&(b[0]),n,&(t[n2])); + bn_add_words(&(r[n]),&(r[n]),&(t[0]),n); + } + else + { + bn_mul_low_normal(&(t[0]),&(a[0]),&(b[n]),n); + bn_mul_low_normal(&(t[n]),&(a[n]),&(b[0]),n); + bn_add_words(&(r[n]),&(r[n]),&(t[0]),n); + bn_add_words(&(r[n]),&(r[n]),&(t[n]),n); + } + } +#endif +#endif + +#ifdef SPLIT_BN_MUL_HIGH +#if 0 +/* a and b must be the same size, which is n2. + * r must be n2 words and t must be n2*2 + * l is the low words of the output. + * t must be n2*3 + */ +void bn_mul_high(r,a,b,l,n2,t) +BN_ULONG *r,*a,*b,*l; +int n2; +BN_ULONG *t; + { + int i,n; + int c1,c2; + int neg,oneg,zero; + BN_ULONG ll,lc,*lp,*mp; + +#ifdef BN_COUNT +printf(" bn_mul_high %d * %d\n",n2,n2); +#endif + n=n2/2; + + /* Calculate (al-ah)*(bh-bl) */ + neg=zero=0; + c1=bn_cmp_words(&(a[0]),&(a[n]),n); + c2=bn_cmp_words(&(b[n]),&(b[0]),n); + switch (c1*3+c2) + { + case -4: + bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n); + bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n); + break; + case -3: + zero=1; + break; + case -2: + bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n); + bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n); + neg=1; + break; + case -1: + case 0: + case 1: + zero=1; + break; + case 2: + bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n); + bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n); + neg=1; + break; + case 3: + zero=1; + break; + case 4: + bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n); + bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n); + break; + } + + oneg=neg; + /* t[10] = (a[0]-a[1])*(b[1]-b[0]) */ + /* r[10] = (a[1]*b[1]) */ +#ifdef BN_MUL_COMBA + if (n == 8) + { + bn_mul_comba8(&(t[0]),&(r[0]),&(r[n])); + bn_mul_comba8(r,&(a[n]),&(b[n])); + } + else +#endif + { +#ifdef BN_MUL_RECURSION + bn_mul_recursive(&(t[0]),&(r[0]),&(r[n]),n,&(t[n2])); + bn_mul_recursive(r,&(a[n]),&(b[n]),n,&(t[n2])); +#else + bn_mul_normal(&(t[0]),&(r[0]),n,&(r[n]),n); + bn_mul_normal(r,&(a[n]),n,&(b[n]),n); +#endif + } + + /* s0 == low(al*bl) + * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl) + * We know s0 and s1 so the only unknown is high(al*bl) + * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl)) + * high(al*bl) == s1 - (r[0]+l[0]+t[0]) + */ + if (l != NULL) + { + lp= &(t[n2+n]); + c1=(int)bn_add_words(lp,&(r[0]),&(l[0]),n); + } + else + { + c1=0; + lp= &(r[0]); + } + + if (neg) + neg=(int)bn_sub_words(&(t[n2]),lp,&(t[0]),n); + else + { + bn_add_words(&(t[n2]),lp,&(t[0]),n); + neg=0; + } + + if (l != NULL) + { + bn_sub_words(&(t[n2+n]),&(l[n]),&(t[n2]),n); + } + else + { + lp= &(t[n2+n]); + mp= &(t[n2]); + for (i=0; i 0) + { + lc=c1; + do { + ll=(r[i]+lc)&BN_MASK2; + r[i++]=ll; + lc=(lc > ll); + } while (lc); + } + else + { + lc= -c1; + do { + ll=r[i]; + r[i++]=(ll-lc)&BN_MASK2; + lc=(lc > ll); + } while (lc); + } + } + if (c2 != 0) /* Add starting at r[1] */ + { + i=n; + if (c2 > 0) + { + lc=c2; + do { + ll=(r[i]+lc)&BN_MASK2; + r[i++]=ll; + lc=(lc > ll); + } while (lc); + } + else + { + lc= -c2; + do { + ll=r[i]; + r[i++]=(ll-lc)&BN_MASK2; + lc=(lc > ll); + } while (lc); + } + } + } +#endif +#endif +#endif + +#ifdef SPLIT_BN_MUL +int BN_mul(r,a,b,ctx) +BIGNUM *r,*a,*b; +BN_CTX *ctx; + { + int top,al,bl,neg; + BIGNUM *rr; +#ifdef BN_RECURSION_MUL + BIGNUM *t; + int i,j,k,l; +#endif + +#ifdef BN_COUNT +printf("BN_mul %d * %d\n",a->top,b->top); +#endif + + bn_check_top(a); + bn_check_top(b); + bn_check_top(r); + + al=a->top; + bl=b->top; + + if ((al == 0) || (bl == 0)) + { + (void)BN_zero(r); + return(1); + } + top=al+bl; + neg=a->neg^b->neg; + + if ((r == a) || (r == b)) + rr= &(ctx->bn[ctx->tos+1]); + else + rr=r; + + if (bn_wexpand(rr,top) == NULL) return(0); + rr->top=top; + +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION_MUL) + if (al == bl) + { +# ifdef BN_MUL_COMBA +/* if (al == 4) + { + bn_mul_comba4(rr->d,a->d,b->d); + goto end; + } + else */ if (al == 8) + { + bn_mul_comba8(rr->d,a->d,b->d); + goto end; + } + else +# endif +#ifdef BN_RECURSION_MUL + if (al < BN_MULL_SIZE_NORMAL) +#endif + { + bn_mul_normal(rr->d,a->d,al,b->d,bl); + goto end; + } +# ifdef BN_RECURSION_MUL + goto symetric; +# endif + } +#endif +#ifdef BN_RECURSION_MUL + else if ((al < BN_MULL_SIZE_NORMAL) || (bl < BN_MULL_SIZE_NORMAL)) + { + bn_mul_normal(rr->d,a->d,al,b->d,bl); + goto end; + } + else + { + i=(al-bl); + if ((i == 1) && !BN_get_flags(b,BN_FLG_STATIC_DATA)) + { + bn_wexpand(b,al); + b->d[bl]=0; + bl++; + goto symetric; + } + else if ((i == -1) && !BN_get_flags(a,BN_FLG_STATIC_DATA)) + { + bn_wexpand(a,bl); + a->d[al]=0; + al++; + goto symetric; + } + } +#endif + +#ifdef BN_RECURSION_MUL +normal_mul: +#endif + bn_mul_normal(rr->d,a->d,al,b->d,bl); + +#ifdef BN_RECURSION_MUL + if (0) + { +symetric: + /* symetric and > 4 */ + /* 16 or larger */ + l=BN_num_bits_word((BN_ULONG)al); + j=1<<(l-1); + k=j+j; + t= &(ctx->bn[ctx->tos]); + if (al == j) /* exact multiple */ + { + BN_REC rec; + rec.depth=l-5; + rec.n=j; + rec.mul=bn_mul_comba8; + rec.sqr=bn_sqr_comba8; + if (bn_wexpand(t,k+k) == NULL) + return(0); + if (bn_wexpand(rr,k) == NULL) + return(0); + bn_mul_rec_words(rr->d,a->d,b->d,t->d,&rec); + } + else + goto normal_mul; +#if 0 + { + bn_zexpand(a,k); + bn_zexpand(b,k); + bn_wexpand(t,k); + bn_wexpand(rr,k); + bn_mul_part_recursive(rr->d,a->d,b->d,al-j,j,t->d); + } +#endif + } +#endif +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION_MUL) +end: +#endif + + r->neg=neg; + bn_fix_top(rr); + if (r != rr) (void)BN_copy(r,rr); + return(1); + } +#endif + + +#ifdef SPLIT_BN_MUL_NORMAL +void bn_mul_normal(r,a,na,b,nb) +BN_ULONG *r,*a; +int na; +BN_ULONG *b; +int nb; + { + BN_ULONG *rr; + +#ifdef BN_COUNT +printf(" bn_mul_normal %d * %d\n",na,nb); +#endif + /* asymetric and >= 4 */ +#if 0 + if ((na == nb) && (na == 8)) + { + bn_mul_normal(r,a,na,b,nb); + return; + } +#endif + + if (na < nb) + { + int itmp; + BN_ULONG *ltmp; + + itmp=na; na=nb; nb=itmp; + ltmp=a; a=b; b=ltmp; + + } + rr= &(r[na]); + rr[0]=bn_mul_words(r,a,na,b[0]); + + for (;;) + { + if (--nb <= 0) return; + rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]); + if (--nb <= 0) return; + rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]); + if (--nb <= 0) return; + rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]); + if (--nb <= 0) return; + rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]); + rr+=4; + r+=4; + b+=4; + } + } +#endif + +#ifdef SPLIT_BN_MUL_LOW_NORMAL +void bn_mul_low_normal(r,a,b,n) +BN_ULONG *r,*a,*b; +int n; + { +#ifdef BN_COUNT +printf(" bn_mul_low_normal %d * %d\n",n,n); +#endif + (void)bn_mul_words(r,a,n,b[0]); + + for (;;) + { + if (--n <= 0) return; + (void)bn_mul_add_words(&(r[1]),a,n,b[1]); + if (--n <= 0) return; + (void)bn_mul_add_words(&(r[2]),a,n,b[2]); + if (--n <= 0) return; + (void)bn_mul_add_words(&(r[3]),a,n,b[3]); + if (--n <= 0) return; + (void)bn_mul_add_words(&(r[4]),a,n,b[4]); + r+=4; + b+=4; + } + } +#endif +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_r_exp.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_r_exp.c new file mode 100644 index 0000000..ef056ef --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_r_exp.c @@ -0,0 +1,150 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +/* #ifdef RECP_MUL_MOD */ +int BN_mod_exp_recp(r,a,p,m,ctx) +BIGNUM *r; +BIGNUM *a; +BIGNUM *p; +BIGNUM *m; +BN_CTX *ctx; + { + int i,j,bits,ret=0,wstart,wend,window,wvalue; + int start=1,ts=0; + BIGNUM *aa; + BIGNUM val[BN_EXP_TABLE_SIZE]; + BN_RECP_CTX recp; + + bits=BN_num_bits(p); + + if (BN_is_zero(a)) + { (void)BN_zero(r); return(1); } + if (BN_is_zero(p)) + { (void)BN_one(r); return(1); } + if (BN_is_one(p)) + { (void)BN_copy(r,a); return(1); } + + BN_RECP_CTX_init(&recp); + if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err; + + BN_init(&(val[0])); + ts=1; + + aa= &(ctx->bn[ctx->tos++]); + + if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */ + if (!BN_mod_mul_reciprocal(aa,&(val[0]),&(val[0]),&recp,ctx)) + goto err; /* 2 */ + + if (bits <= 17) /* This is probably 3 or 0x10001, so just do singles */ + window=1; + else if (bits >= 256) + window=5; /* max size of window */ + else if (bits >= 128) + window=4; + else + window=3; + + j=1<<(window-1); + for (i=1; i>1]),&recp,ctx)) + goto err; + + /* move the 'window' down further */ + wstart-=wend+1; + wvalue=0; + start=0; + if (wstart < 0) break; + } + ret=1; +err: + ctx->tos--; + for (i=0; in; + int n2=n/2; + int neg=0; + BN_ULONG c1; + + + if (rec->depth == 0) + { + /* t needs to have space for 4*n words + * The multiply needs to be a n2*n2 -> n + */ +#ifndef NOPROTO + void (PRE_CCONV CCONV *rmul)(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); +#else + void (PRE_CCONV CCONV *rmul)(); +#endif + rmul=rec->mul; + +#ifdef _EXTRA_ARG_ + /* THIS IS WRONG - there is no extra int arg on the end */ + rmul(&(r[0]),&(a[0]),&(b[0]),n2); + rmul(&(r[n]),&(a[n2]),&(b[n2]),n2); +#else + rmul(&(r[0]),&(a[0]),&(b[0])); + rmul(&(r[n]),&(a[n2]),&(b[n2])); +#endif + + if (bn_sub_words(&(tt[n+0]), &(a[0]),&(a[n2]),n2)) + { + bn_2s_comp(&(tt[n+ 0]),&(tt[n+ 0]),n2); + neg=1; + } + else + neg=0; + if (bn_sub_words(&(tt[n+n2]),&(b[n2]),&(b[0]),n2)) + { + neg^=1; + bn_2s_comp(&(tt[n+n2]),&(tt[n+n2]),n2); + } + +#ifdef _EXTRA_ARG_ + rmul(&(tt[0]),&(tt[n+0]),&(tt[n+n2]),n2); +#else + rmul(&(tt[0]),&(tt[n+0]),&(tt[n+n2])); +#endif + } + else /* Leaf node */ + { + /* t has 4*n words taken per call. + * Since n is half the size per call, we need + * 6*n words for our current level and all sub levels + * The multiply needs to be a n2*n2 -> n + */ + rec->depth--; + rec->n=n2; + bn_mul_rec_words(&(r[0]), &(a[0]), &(b[0]), &(tt[n+n]),rec); + bn_mul_rec_words(&(r[n]), &(a[n2]),&(b[n2]), &(tt[n+n]),rec); + + neg=0; + if (bn_sub_words(&(tt[n+0]), &(a[0]),&(a[n2]),n2)) + { + bn_2s_comp(&(tt[n+ 0]),&(tt[n+ 0]),n2); + neg=1; + } + else + neg=0; + if (bn_sub_words(&(tt[n+n2]),&(b[n2]),&(b[0]),n2)) + { + neg^=1; + bn_2s_comp(&(tt[n+n2]),&(tt[n+n2]),n2); + } + + bn_mul_rec_words(&(tt[0]),&(tt[n]),&(tt[n+n2]),&(tt[n+n]),rec); + rec->n=n; + rec->depth++; + } + + c1=bn_add_words(&(tt[n]),&(r[0]),&(r[n]),n); + + if (neg) + c1-=bn_sub_words(&(tt[0]),&(tt[n]),&(tt[0]),n); + else + c1+=bn_add_words(&(tt[0]),&(tt[n]),&(tt[0]),n); + tt[n]=c1; + c1=bn_add_words(&(r[n2]),&(r[n2]),&(tt[0]),n+1); + if (c1) + { + tt= &(r[n+n2+1]); + do { + } while (++(*(tt++)) == 0); + } + } +#endif + +#ifdef SPLIT_BN_SQR_REC_WORDS +/* tt needs to be 3*n words */ +void bn_sqr_rec_words(r,a,tt,rec) +BN_ULONG *r,*a,*tt; +BN_REC *rec; + { + int n=rec->n; + int n2=n/2; + BN_ULONG c1; + + if (rec->depth == 0) + { + /* t needs to have space for 4*n words + * The multiply needs to be a n2*n2 -> n + */ +#ifndef NOPROTO + void (PRE_CCONV CCONV *rsqr)(BN_ULONG *r, BN_ULONG *a); +#else + void (PRE_CCONV CCONV *rsqr)(); +#endif + + rsqr=rec->sqr; + +#ifdef _EXTRA_ARG_ + /* THIS IS WRONG - there is no extra int arg on the end */ + rsqr(&(r[0]), &(a[0]), n2); + rsqr(&(r[n]), &(a[n2]),n2); +#else + rsqr(&(r[0]), &(a[0])); + rsqr(&(r[n]), &(a[n2])); +#endif + + if (bn_sub_words(&(tt[n+0]), &(a[0]),&(a[n2]),n2)) + bn_2s_comp(&(tt[n+0]),&tt[n+0], n2); + +#ifdef _EXTRA_ARG_ + rsqr(&(tt[0]),&(tt[n]), n2); +#else + rsqr(&(tt[0]),&(tt[n])); +#endif + + } + else /* Leaf node */ + { + /* t has 4*n words taken per call. + * Since n is half the size per call, we need + * 6*n words for our current level and all sub levels + * The multiply needs to be a n2*n2 -> n + */ + rec->depth--; + rec->n=n2; + bn_sqr_rec_words(&(r[0]), &(a[0]), &(tt[n+n]),rec); + bn_sqr_rec_words(&(r[n]), &(a[n2]),&(tt[n+n]),rec); + + if (bn_sub_words(&(tt[n+0]), &(a[0]),&(a[n2]),n2)) + bn_2s_comp(&(tt[n+0]),&tt[n+0], n2); + bn_sqr_rec_words(&(tt[0]),&(tt[n]),&(tt[n+n]),rec); + + rec->n=n; + rec->depth++; + } + + c1=bn_add_words(&(tt[n]),&(r[0]),&(r[n]),n); + c1-=bn_sub_words(&(tt[0]),&(tt[n]),&(tt[0]),n); + + tt[n]=c1; + c1=bn_add_words(&(r[n2]),&(r[n2]),&(tt[0]),n+1); + if (c1) + { + tt= &(r[n+n2+1]); + do { + } while (++(*(tt++)) == 0); + } + } +#endif + +#endif /* !NO_SPLIT || !SPLIT_FILE */ diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_recp.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_recp.c new file mode 100644 index 0000000..6830f59 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_recp.c @@ -0,0 +1,218 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +void BN_RECP_CTX_init(recp) +BN_RECP_CTX *recp; + { + BN_init(&(recp->N)); + BN_init(&(recp->Nr)); + recp->num_bits=0; + recp->flags=0; + } + +BN_RECP_CTX *BN_RECP_CTX_new() + { + BN_RECP_CTX *ret; + + if ((ret=(BN_RECP_CTX *)Malloc(sizeof(BN_RECP_CTX))) == NULL) + return(NULL); + + BN_RECP_CTX_init(ret); + ret->flags=BN_FLG_MALLOCED; + return(ret); + } + +void BN_RECP_CTX_free(recp) +BN_RECP_CTX *recp; + { + BN_free(&(recp->N)); + BN_free(&(recp->Nr)); + if (recp->flags & BN_FLG_MALLOCED) + Free(recp); + } + +int BN_RECP_CTX_set(recp,d,ctx) +BN_RECP_CTX *recp; +BIGNUM *d; +BN_CTX *ctx; + { + (void)BN_copy(&(recp->N),d); + (void)BN_zero(&(recp->Nr)); + recp->num_bits=BN_num_bits(d); + recp->shift=0; + ctx=ctx; /* Stop warning */ + return(1); + } + +int BN_mod_mul_reciprocal(r, x, y, recp, ctx) +BIGNUM *r; +BIGNUM *x; +BIGNUM *y; +BN_RECP_CTX *recp; +BN_CTX *ctx; + { + int ret=0; + BIGNUM *a; + + bn_check_top(x); + bn_check_top(y); + + a= &(ctx->bn[ctx->tos++]); + if (y != NULL) + { + if (x == y) + { if (!BN_sqr(a,x,ctx)) goto err; } + else + { if (!BN_mul(a,x,y,ctx)) goto err; } + } + else + a=x; /* Just do the mod */ + + (void)BN_div_recp(NULL,r,a,recp,ctx); + ret=1; +err: + ctx->tos--; + return(ret); + } + +int BN_div_recp(dv,rem,m,recp,ctx) +BIGNUM *dv; +BIGNUM *rem; +BIGNUM *m; +BN_RECP_CTX *recp; +BN_CTX *ctx; + { + int i,j,tos,ret=0,ex; + BIGNUM *a,*b,*d,*r; + + bn_check_top(m); + + tos=ctx->tos; + a= &(ctx->bn[ctx->tos++]); + b= &(ctx->bn[ctx->tos++]); + if (dv != NULL) + d=dv; + else + d= &(ctx->bn[ctx->tos++]); + if (rem != NULL) + r=rem; + else + r= &(ctx->bn[ctx->tos++]); + + if (BN_ucmp(m,&(recp->N)) < 0) + { + (void)BN_zero(d); + (void)BN_copy(r,m); + ctx->tos=tos; + return(1); + } + + /* We want the remainder + * Given input of ABCDEF / ab + * we need multiply ABCDEF by 3 digests of the reciprocal of ab + * + */ + i=BN_num_bits(m); + + j=recp->num_bits*2; + if (j > i) + { + i=j; + ex=0; + } + else + { + ex=(i-j)/2; + } + + j=i/2; + + if (i != recp->shift) + recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N), + i,ctx); + + if (!BN_rshift(a,m,j-ex)) goto err; + if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err; + if (!BN_rshift(d,b,j+ex)) goto err; + d->neg=0; + if (!BN_mul(b,&(recp->N),d,ctx)) goto err; + if (!BN_usub(r,m,b)) goto err; + r->neg=0; + + j=0; +#if 1 + while (BN_ucmp(r,&(recp->N)) >= 0) + { + if (j++ > 2) + { +#ifndef NO_ERR + BNerr(BN_F_BN_DIV_RECP,BN_R_BAD_RECIPROCAL); +#endif + goto err; + } + if (!BN_usub(r,r,&(recp->N))) goto err; + if (!BN_add_word(d,1)) goto err; + } +#endif + + r->neg=BN_is_zero(r)?0:m->neg; + d->neg=m->neg^recp->N.neg; + ret=1; +err: + ctx->tos=tos; + return(ret); + } + +/* len is the expected size of the result + * We actually calculate with an extra word of precision, so + * we can do faster division if the remainder is not required. + */ +int BN_reciprocal(r,m,len,ctx) +BIGNUM *r; +BIGNUM *m; +int len; +BN_CTX *ctx; + { + int ret= -1; + BIGNUM t; + + bn_check_top(m); + + BN_init(&t); + + (void)BN_zero(&t); + if (!BN_set_bit(&t,len)) goto err; + + if (!BN_div(r,NULL,&t,m,ctx)) goto err; + ret=len; +err: + BN_free(&t); + return(ret); + } + diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_rsh.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_rsh.c new file mode 100644 index 0000000..0f0d5c6 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_rsh.c @@ -0,0 +1,139 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_RSHIFT1 +#define SPLIT_BN_RSHIFT +#endif /* NO_SPLIT */ + +#ifdef SPLIT_BN_RSHIFT1 +#ifdef SMALL_CODE_SIZE +int BN_rshift1(r, a) +BIGNUM *r; +BIGNUM *a; + { + return(BN_rshift(r,a,1)); + } + +#else + +int BN_rshift1(r, a) +BIGNUM *r; +BIGNUM *a; + { + BN_ULONG *ap,*rp,t,c; + int i; + + bn_check_top(a); + + if (BN_is_zero(a)) + { + BN_zero(r); + return(1); + } + if (a != r) + { + if (bn_wexpand(r,a->top) == NULL) return(0); + r->top=a->top; + r->neg=a->neg; + } + ap=a->d; + rp=r->d; + c=0; + for (i=a->top-1; i>=0; i--) + { + t=ap[i]; + rp[i]=((t>>1)&BN_MASK2)|c; + c=(t&1)?BN_TBIT:0; + } + bn_fix_top(r); + return(1); + } +#endif +#endif + +#ifdef SPLIT_BN_RSHIFT +int BN_rshift(r, a, n) +BIGNUM *r; +BIGNUM *a; +int n; + { + int i,j,nw,lb,rb; + BN_ULONG *t,*f; + BN_ULONG l,tmp; + + bn_check_top(a); + +#ifndef SMALL_CODE_SIZE + if (n == 1) return(BN_rshift1(r,a)); +#endif + nw=n/BN_BITS2; + rb=n%BN_BITS2; + lb=BN_BITS2-rb; + if (nw > a->top) + { + (void)BN_zero(r); + return(1); + } + if (r != a) + { + if (bn_wexpand(r,a->top-nw+1+1/*???*/) == NULL) return(0); + r->neg=a->neg; + } + + f= &(a->d[nw]); + t=r->d; + j=a->top-nw; + r->top=j; + + if (rb == 0) + { + for (i=j+1; i > 0; i--) + *(t++)= *(f++); + } + else + { + l= *(f++); + for (i=1; i>rb)&BN_MASK2; + l= *(f++); + *(t++) =(tmp|(l<>rb)&BN_MASK2; + *t=0; + } + bn_fix_top(r); + return(1); + } +#endif + +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_sqr.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_sqr.c new file mode 100644 index 0000000..24b5c4c --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_sqr.c @@ -0,0 +1,289 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#ifdef SMALL_CODE_SIZE +#undef BN_RECURSION_SQR +#endif + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_SQR +#define SPLIT_BN_SQR_NORMAL +#define SPLIT_BN_RECURSION_SQR +#endif /* NO_SPLIT */ + +#ifdef SPLIT_BN_SQR +/* r must not be a */ +int BN_sqr(r, a, ctx) +BIGNUM *r; +BIGNUM *a; +BN_CTX *ctx; + { + int max,al; + BIGNUM *tmp,*rr; + +#ifdef BN_COUNT +printf("BN_sqr %d * %d\n",a->top,a->top); +#endif + bn_check_top(a); + tmp= &(ctx->bn[ctx->tos]); + rr=(a != r)?r: (&ctx->bn[ctx->tos+1]); + + al=a->top; + if (al <= 0) + { + r->top=0; + return(1); + } + + max=(al+al); + if (bn_wexpand(rr,max) == NULL) return(0); + + rr->top=max; + rr->neg=0; + + if (al == 4) + { +#ifndef BN_SQR_COMBA + BN_ULONG t[8]; + bn_sqr_normal(rr->d,a->d,4,t); +#else + bn_sqr_comba4(rr->d,a->d); +#endif + } + else if (al == 8) + { +#ifndef BN_SQR_COMBA + BN_ULONG t[16]; + bn_sqr_normal(rr->d,a->d,8,t); +#else + bn_sqr_comba8(rr->d,a->d); +#endif + } + else + { +#if 1 && defined(BN_RECURSION_SQR) + if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) + { + BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL*2]; + bn_sqr_normal(rr->d,a->d,al,t); + } + else + { + int j,l,k; + + l=BN_num_bits_word((BN_ULONG)al); + j=1<<(l-1); + k=j+j; + if ((al == j) && !BN_get_flags(a,BN_FLG_STATIC_DATA)) + { + BN_REC rec; + if (bn_wexpand(tmp,k*2) == NULL) return(0); + rec.depth=l-5; + rec.n=j; + rec.mul=bn_mul_comba8; + rec.sqr=bn_sqr_comba8; + + bn_sqr_rec_words(rr->d,a->d,tmp->d,&rec); + } + else + { + if (bn_wexpand(tmp,max) == NULL) return(0); + bn_assert(al*2 <= max); + bn_sqr_normal(rr->d,a->d,al,tmp->d); + } + } +#else + if (bn_wexpand(tmp,max) == NULL) return(0); + bn_assert(al*2 <= max); + bn_sqr_normal(rr->d,a->d,al,tmp->d); +#endif +#ifdef BN_DEBUG + tmp->top=0; +#endif + } + + if ((max > 0) && (rr->d[max-1] == 0)) rr->top--; + if (rr != r) (void)BN_copy(r,rr); + return(1); + } +#endif + +#ifdef SPLIT_BN_SQR_NORMAL +/* tmp must have 2*n words */ +void bn_sqr_normal(r, a, n, tmp) +BN_ULONG *r; +BN_ULONG *a; +int n; +BN_ULONG *tmp; + { + int i,j,max; + BN_ULONG *ap,*rp,m; + + max=n*2; + ap=a; + rp=r; + rp[0]=rp[max-1]=0; + rp++; + j=n; + + if (--j > 0) + { + m= (*ap++); + rp[j]=bn_mul_words(rp,ap,j,m); + rp+=2; + } + + for (i=n-2; i>0; i--) + { + j--; + m= *(ap++); + rp[j]=bn_mul_add_words(rp,ap,j,m); + rp+=2; + } + + (void)bn_add_words(r,r,r,max); + + /* There will not be a carry */ + + bn_sqr_words(tmp,a,n); + + (void)bn_add_words(r,r,tmp,max); + } +#endif + +#if 0 /* replaced by bn_sqr_rec_words() AND this has bugs */ +#ifdef SPLIT_BN_RECURSION_SQR +#ifdef BN_RECURSION_SQR +/* r is 2*n words in size, + * a and b are both n words in size. + * n must be a power of 2. + * We multiply and return the result. + * t must be 2*n words in size + * We calulate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +void bn_sqr_recursive(r,a,n2,t) +BN_ULONG *r,*a; +int n2; +BN_ULONG *t; + { + int n=n2/2; + int zero,c1; + BN_ULONG ln,lo,*p; + +#ifdef BN_COUNT +printf(" bn_sqr_recursive %d * %d\n",n2,n2); +#endif + if (n2 == 4) + { +#ifndef BN_SQR_COMBA + bn_sqr_normal(r,a,4,t); +#else + bn_sqr_comba4(r,a); +#endif + return; + } + else if (n2 == 8) + { +#ifndef BN_SQR_COMBA + bn_sqr_normal(r,a,8,t); +#else + bn_sqr_comba8(r,a); +#endif + return; + } + if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) + { + bn_sqr_normal(r,a,n2,t); + return; + } + /* r=(a[0]-a[1])*(a[1]-a[0]) */ + c1=bn_cmp_words(a,&(a[n]),n); + zero=0; + if (c1 > 0) + bn_sub_words(t,a,&(a[n]),n); + else if (c1 < 0) + bn_sub_words(t,&(a[n]),a,n); + else + zero=1; + + /* The result will always be negative unless it is zero */ + p= &(t[n2*2]); + + if (!zero) + bn_sqr_recursive(&(t[n2]),t,n,p); + else + Memset(&(t[n2]),0,n*sizeof(BN_ULONG)); + bn_sqr_recursive(r,a,n,p); + bn_sqr_recursive(&(r[n2]),&(a[n]),n,p); + + /* t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1=(int)(bn_add_words(t,r,&(r[n2]),n2)); + + /* t[32] is negative */ + c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2)); + + /* t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1]) + * r[10] holds (a[0]*a[0]) + * r[32] holds (a[1]*a[1]) + * c1 holds the carry bits + */ + c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2)); + if (c1) + { + p= &(r[n+n2]); + lo= *p; + ln=(lo+c1)&BN_MASK2; + *p=ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) + { + do { + p++; + lo= *p; + ln=(lo+1)&BN_MASK2; + *p=ln; + } while (ln == 0); + } + } + } +#endif +#endif +#endif +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/bn_wdiv.c b/build/libraries_sysmenu/acsign/ARM9/src/bn_wdiv.c new file mode 100644 index 0000000..97c2186 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/bn_wdiv.c @@ -0,0 +1,116 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#ifndef OPT_BN_ASM + +#ifndef BN_DIV_WORDS +#define BN_DIV_WORDS +#endif + +#endif + +#ifdef BN_DIV_WORDS +#if defined(BN_LLONG) +BN_ULONG bn_div_words(h,l,d) +BN_ULONG h,l,d; + { + return((BN_ULONG)(((((BN_ULLONG)h)< ((BN_ULONG)1)<= d) h-=d; + + if (i) + { + d=(d<>(BN_BITS2-i)))&BN_MASK2; + l=(l<>BN_BITS4)&BN_MASK2lh; + dl=(d&BN_MASK2l); + for (;;) + { + if ((h>>BN_BITS4) == dh) + q=BN_MASK2l; + else + q=h/dh; + + for (;;) + { + t=(h-q*dh)&BN_MASK2; + if ((t&BN_MASK2h) || + (((dl*q)&BN_MASK2) <= (( + (t<>BN_BITS4)&BN_MASK2lh))&BN_MASK2))) + break; + q--; + } + th=(q*dh)&BN_MASK2; + tl=(q*dl)&BN_MASK2; + t=(tl>>BN_BITS4); + tl=(tl&BN_MASK2lh)<>BN_BITS4))&BN_MASK2; + l=(l&BN_MASK2l)<top-1; i>=0; i--) + { +#ifndef BN_LLONG + ret=((ret<d[i]>>BN_BITS4)&BN_MASK2l))%w; + ret=((ret<d[i]&BN_MASK2l))%w; +#else + ret=(BN_ULLONG)(((ret<<(BN_ULLONG)BN_BITS2)|a->d[i])% + (BN_ULLONG)w); +#endif + } + return((BN_ULONG)ret); + } +#endif + +#ifdef SPLIT_BN_DIV_WORD +BN_ULONG BN_div_word(a, w) +BIGNUM *a; +BN_ULONG w; + { + BN_ULONG ret; + int i; + + if (a->top == 0) return(0); + ret=0; + w=w&BN_MASK2;//w&=BN_MASK2; + for (i=a->top-1; i>=0; i--) + { + BN_ULONG l,d; + + l=a->d[i]; + d=bn_div_words(ret,l,w); + ret=(l-((d*w)&BN_MASK2))&BN_MASK2; + a->d[i]=d; + } + if ((a->top > 0) && (a->d[a->top-1] == 0)) + a->top--; + return(ret); + } +#endif + +#ifdef SPLIT_BN_ADD_WORD +int BN_add_word(a, w) +BIGNUM *a; +BN_ULONG w; + { + BN_ULONG l; + int i; + + if (w == 0) return(1); + bn_check_top(a); + + w=w&BN_MASK2;//w&=BN_MASK2; + if (a->neg) + { + if(a->top > 1) + { + a->neg=0; + i=BN_sub_word(a,w); + a->neg=1; + return(i); + } + else + { /* a->top == 1, it cannot be 0 */ + l=a->d[0]; + if (l > w) + a->d[0]=l-w; + else if (l < w) + { + a->neg=0; + a->d[0]=w-l; + } + else + { + a->neg=0; + a->top=0; + } + return(1); + } + } + w=w&BN_MASK2;//w&=BN_MASK2; + if (bn_wexpand(a,a->top+1) == NULL) return(0); + a->d[a->top]=0; + i=0; + for (;;) + { + l=(a->d[i]+(BN_ULONG)w)&BN_MASK2; + a->d[i]=l; + if (w > l) + w=1; + else + break; + i++; + } + if (i >= a->top) + a->top++; + return(1); + } +#endif + +#ifdef SPLIT_BN_SUB_WORD +int BN_sub_word(a, w) +BIGNUM *a; +BN_ULONG w; + { + int i; + + bn_check_top(a); + if (w == 0) return(1); + + w=w&BN_MASK2;//w&=BN_MASK2; + if (a->neg) + { + a->neg=0; + i=BN_add_word(a,w); + a->neg=1; + return(i); + } + + w=w&BN_MASK2;//w&=BN_MASK2; + if (a->top <= 1) + { + BN_ULONG l; + + if (a->top == 0) + { + if (bn_wexpand(a,1) == NULL) return(0); + a->d[0]=w; + a->neg = 1; + a->top = 1; + return(1); + } + l=a->d[0]; + if (l == w) + a->top=0; + else if (l > w) + a->d[0]=l-w; + else + { + a->neg=1; + a->d[0]=w-l; + } + return(1); + } + i=0; + for (;;) + { + if (a->d[i] >= w) + { + a->d[i]-=w; + break; + } + else + { + a->d[i]=(a->d[i]-w)&BN_MASK2; + i++; + w=1; + } + } + if ((a->d[i] == 0) && (i == (a->top-1))) + a->top--; + return(1); + } +#endif + +#ifdef SPLIT_BN_MUL_WORD +int BN_mul_word(a,w) +BIGNUM *a; +BN_ULONG w; + { + BN_ULONG ll; + + w=w&BN_MASK2;//w&=BN_MASK2; + if (a->top) + { + ll=bn_mul_words(a->d,a->d,a->top,w); + if (ll) + { + if (bn_wexpand(a,a->top+1) == NULL) return(0); + a->d[a->top++]=ll; + } + } + return(1); + } +#endif + +#endif diff --git a/build/libraries_sysmenu/acsign/ARM9/src/main.c b/build/libraries_sysmenu/acsign/ARM9/src/main.c new file mode 100644 index 0000000..d0d591b --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/main.c @@ -0,0 +1,320 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +#include +#include + +#include "acsign.h" +#include "acmemory.h" + +/*---------------------------------------------------------------------------*/ +unsigned long binarray[ 1024 * 1024 * 2 / sizeof (unsigned long) ]; +unsigned long keyarray[ 1024 / sizeof (unsigned long) ]; +unsigned long sgnarray[ 1024 / sizeof (unsigned long) ]; +unsigned long bufferA[ ACSIGN_BUFFER / sizeof (unsigned long) ]; +unsigned long bufferB[ ACSIGN_BUFFER / sizeof (unsigned long) ]; + + + +/*--------------------------------------------------------------------------*/ +// ROMwb_ +//---------------------------------------------------------------------- +typedef struct { + // + // 0x000 System Reserved + // + char title_name[12]; // Soft title name + u32 game_code; // Game code + + u16 maker_code; // Maker code + u8 machine_code; // Machine code + u8 rom_type; // Rom type + u8 rom_size; // Rom size + + u8 reserved_A[9]; // System Reserved A ( Set ALL 0 ) + u8 soft_version; // Soft version + + u8 comp_arm9_boot_area:1; // Compress arm9 boot area + u8 comp_arm7_boot_area:1; // Compress arm7 boot area + u8 inspectCard:1; // J[htO + u8 disableClearMemoryPad:1; // IPL2pbhNAEfBZ[utO + u8 :0; + + + // + // 0x020 for Static modules (Section:B) + // + // ARM9 + u32 main_rom_offset; // ROM offset + void* main_entry_address; // Entry point + void* main_ram_address; // RAM address + u32 main_size; // Module size + + // ARM7 + u32 sub_rom_offset; // ROM offset + void* sub_entry_address; // Entry point + void* sub_ram_address; // RAM address + u32 sub_size; // Module size + + // + // 0x040 for File Name Table[FNT] (Section:C) + // + u32 fnt_offset; // ROM offset + u32 fnt_size; // Table size + + // + // 0x048 for File Allocation Table[FAT] (Section:E) + // + u32 fat_offset; // ROM offset + u32 fat_size; // Table size + + // + // 0x050 for Overlay Tables[OVT] (Section:D) + // + // ARM9 + u32 main_ovt_offset; // ROM offset + u32 main_ovt_size; // Table size + + // ARM7 + u32 sub_ovt_offset; // ROM offset + u32 sub_ovt_size; // Table size + + // 0x060 for ROM control parameter + u8 reserved_A2[32]; + + // 0x080 - 0x0C0 System Reserved + u8 reserved_B[64]; // System Reserved B (Set 0) + + // 0x0C0 for NINTENDO logo data + u8 nintendo_logo[0x9c]; // NINTENDO logo data + u16 nintendo_logo_crc16; // CRC-16 + + // 0x15E ROM header CRC-16 + u16 header_crc16; // ROM header CRC-16 +} RomHeader; + + +/* V-blank callback */ +static void VBlankIntr(void) +{ + OS_SetIrqCheckFlag(OS_IE_V_BLANK); +} + + + + + +/*---------------------------------------------------------------------------* + Name: InitializeAllocateSystem + + Description: C̃A[iɂăăVXeB + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +static void InitializeAllocateSystem(void) +{ + void* tempLo; + OSHeapHandle hh; + + // OS_Init͌Ă΂ĂƂO + tempLo = OS_InitAlloc( + OS_ARENA_MAIN , + OS_GetMainArenaLo() , + OS_GetMainArenaHi() , + 1 + ); + OS_SetArenaLo( + OS_ARENA_MAIN , + tempLo + ); + hh = OS_CreateHeap( + OS_ARENA_MAIN , + OS_GetMainArenaLo() , + OS_GetMainArenaHi() + ); + if( hh < 0 ) + { + OS_Panic("ARM9: Fail to create heap...\n"); + } + hh = OS_SetCurrentHeap( + OS_ARENA_MAIN , + hh + ); +} + + +// +static +void TestAC(char* iplfile, char* srlfile, char* sgnfile, FSFile* pfile ) +{ + RomHeader* pHeader; + const char* path; + BOOL fresult; + void* srl_ptr = 0; + long srl_len = 0; + void* key_ptr = 0; + long key_len = 0; + void* sgn_ptr = 0; + long sgn_len = 0; + + + if ( !pfile ) return ; + if ( !iplfile ) return ; + if ( !srlfile ) return ; + if ( !sgnfile ) return ; + + path = iplfile; + if ( (fresult = FS_OpenFile(pfile, path)) ) + { + key_len = FS_ReadFile( pfile, keyarray, sizeof keyarray ); + key_ptr = keyarray; + fresult = FS_CloseFile( pfile ); + } + if ( !fresult ) + OS_Printf("file read error! %s\n", path ); + + path = srlfile; + if ( (fresult = FS_OpenFile(pfile, path)) ) + { + srl_len = FS_ReadFile( pfile, binarray, sizeof binarray ); + srl_ptr = binarray; + fresult = FS_CloseFile( pfile ); + } + if ( !fresult ) + OS_Printf("file read error! %s\n", path ); + + path = sgnfile; //"/data/sgn0.bin"; // sgn + if ( (fresult = FS_OpenFile(pfile, path)) ) + { + sgn_len = FS_ReadFile( pfile, sgnarray, sizeof sgnarray ); + sgn_ptr = sgnarray; + fresult = FS_CloseFile( pfile ); + } + if ( !fresult ) + OS_Printf("file read error! %s\n", path ); + + // F + if ( srl_ptr && srl_len && key_ptr && key_len && sgn_ptr && sgn_len ) + { + long nSerial = 0; + pHeader = (RomHeader*)binarray; + + MI_CpuFill8( bufferA, 0, sizeof bufferA ); + MI_CpuFill8( bufferB, 0, sizeof bufferB ); + #if 0 + HMAC/Digtal Signature + >char seg_id[2]; //->"ac"ɌŒ + >u16 version; //-> 1ɌŒ + >u8 auth_code[20]/digital_sign[128] + >long serial_number + >char title_name[12]; // RomHeader.title_name + >u32 game_code; // RomHeader.game_code + >u16 maker_code; // RomHeader.make_code + >u8 machine_code; // RomHeader.machine_code + #endif + ((unsigned char*)&nSerial)[0] = ((unsigned char*)sgn_ptr + 4 + 128)[0]; + ((unsigned char*)&nSerial)[1] = ((unsigned char*)sgn_ptr + 4 + 128)[1]; + ((unsigned char*)&nSerial)[2] = ((unsigned char*)sgn_ptr + 4 + 128)[2]; + ((unsigned char*)&nSerial)[3] = ((unsigned char*)sgn_ptr + 4 + 128)[3]; + + (void)ACSign_Decrypto( bufferA, + (char*)sgn_ptr + 4, // t@C̈Í͂ւ̃ItZbgvX + (char*)key_ptr + 16 ); // PCMOD݂̂̃t@CɑΉ+16sv + + (void)ACSign_Digest( bufferB, + srl_ptr, + (char*)srl_ptr + pHeader->main_rom_offset, + pHeader->main_size, + (char*)srl_ptr + pHeader->sub_rom_offset, + pHeader->sub_size, + nSerial ); + + if ( ACSign_Compare( bufferA, bufferB ) ) + { + OS_Printf( "Authentication_Code test : success! [%12s %12s] \n", srlfile, sgnfile ); + } + else + { + OS_Printf( "Authentication_Code test : failure! [%12s %12s]\n", srlfile, sgnfile ); + } + + } + else + { + OS_Printf( "no test\n" ); + } + + OS_PrintServer(); +} + + +void NitroMain(void) +{ + FSFile file; + + + OS_InitPrintServer(); + OS_Init(); + OS_InitThread(); + InitializeAllocateSystem(); + + OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr); + (void)OS_EnableIrqMask(OS_IE_V_BLANK); + (void)OS_EnableIrqMask(OS_IE_FIFO_RECV); + (void)OS_EnableIrq(); + + if ( sizeof (int ) < sizeof ( long ) ) + OS_Printf( "sizeof (int ) != sizeof ( long )\n" ); + if ( sizeof ( RomHeader ) != 0x0160 ) + OS_Printf( "sizeof ( RomHeader ) != 0x0160\n" ); + + /* initialize file-system */ + FS_Init( (u32)MI_DMA_MAX_NUM ); /* use DMA-3 for FS */ + + /* always preload FS table for faster directory access. */ + { + u32 need_size = FS_GetTableSize(); + void *p_table = OS_Alloc(need_size); + SDK_ASSERT(p_table != NULL); + (void)FS_LoadTable(p_table, need_size); + } + + // t@Cǂݍ + FS_InitFile(&file); + //TestAC( "/data/iplpub.bin", "/data/main.srl", "/data/sgn.bin", &file ); + + TestAC( "/data/iplpub.bin", "/data/main0.srl", "/data/sgn0.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main1.srl", "/data/sgn1.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main2.srl", "/data/sgn2.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main3.srl", "/data/sgn3.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main4.srl", "/data/sgn4.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main5.srl", "/data/sgn5.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main6.srl", "/data/sgn6.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main7.srl", "/data/sgn7.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main0.srl", "/data/sgn7.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main3.srl", "/data/sgn1.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main5.srl", "/data/sgn5.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main1.srl", "/data/sgn0.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main0.srl", "/data/sgn1.bin", &file ); + TestAC( "/data/iplpub.bin", "/data/main0.srl", "/data/sgn0.bin", &file ); + + OS_Terminate(); +} + diff --git a/build/libraries_sysmenu/acsign/ARM9/src/md5.c b/build/libraries_sysmenu/acsign/ARM9/src/md5.c new file mode 100644 index 0000000..9b89e56 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/md5.c @@ -0,0 +1,412 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#include "md5.h" + +/* Constants for MD5Transform routine. */ + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform(unsigned long [4], unsigned char [64]); +static void Encode(unsigned char *, unsigned long *, unsigned int); +static void Decode(unsigned long *, unsigned char *, unsigned int); +static void MD5_memcpy(unsigned char*, unsigned char*, unsigned int); +static void MD5_memset(unsigned char*, int, unsigned int); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (unsigned long)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (unsigned long)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (unsigned long)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (unsigned long)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void MD5Init(context) +MD5_CTX *context; /* context */ +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +void MD5Update(context, input, inputLen) +MD5_CTX *context; /* context */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((unsigned long)inputLen << 3)) < ((unsigned long)inputLen << 3)) + context->count[1]++; + context->count[1] += ((unsigned long)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) { + MD5_memcpy((unsigned char*)&context->buffer[index], (unsigned char*)input, partLen); + MD5Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + MD5_memcpy((unsigned char*)&context->buffer[index], (unsigned char*)&input[i], inputLen-i); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +void MD5Final(digest, context) +unsigned char digest[16]; /* message digest */ +MD5_CTX *context; /* context */ +{ + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. */ + index = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. */ + MD5_memset ((unsigned char*)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + */ +static void MD5Transform (state, block) +unsigned long state[4]; +unsigned char block[64]; +{ + unsigned long a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + MD5_memset ((unsigned char*)x, 0, sizeof (x)); +} + +/* Encodes input (unsigned long) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void Encode(output, input, len) +unsigned char *output; +unsigned long *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j ] = (unsigned char)( input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (unsigned long). Assumes len is + a multiple of 4. + */ +static void Decode(output, input, len) +unsigned long *output; +unsigned char *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((unsigned long)input[j]) | (((unsigned long)input[j+1]) << 8) | + (((unsigned long)input[j+2]) << 16) | (((unsigned long)input[j+3]) << 24); +} + +/* Note: Replace "for loop" with standard memcpy if possible. + */ + +static void MD5_memcpy(output, input, len) +unsigned char* output; +unsigned char* input; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + output[i] = input[i]; +} + +/* Note: Replace "for loop" with standard memset if possible. + */ +static void MD5_memset(output, value, len) +unsigned char* output; +int value; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} + + + + +////////////////////////////////////////////////////////////////////////////// +#if defined( MD5_TEST ) + +#include + +char* samplearray[ 7 ] = +{ + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "1234567890" // x8 +}; + +char* resultarray[ 7 ] = +{ + "\xD4\x1D\x8C\xD9\x8F\x00\xB2\x04\xE9\x80\x09\x98\xEC\xF8\x42\x7E", + "\x0C\xC1\x75\xB9\xC0\xF1\xB6\xA8\x31\xC3\x99\xE2\x69\x77\x26\x61", + "\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72", + "\xF9\x6B\x69\x7D\x7C\xB7\x93\x8D\x52\x5A\x2F\x31\xAA\xF1\x61\xD0", + "\xC3\xFC\xD3\xD7\x61\x92\xE4\x00\x7D\xFB\x49\x6C\xCA\x67\xE1\x3B", + "\xD1\x74\xAB\x98\xD2\x77\xD9\xF5\xA5\x61\x1C\x2C\x9F\x41\x9D\x9F", + "\x57\xED\xF4\xA2\x2B\xE3\xC9\x55\xAC\x49\xDA\x2E\x21\x07\xB6\x7A" +}; + +int repeatarray[ 7 ] = +{ + 1, + 1, + 1, + 1, + 1, + 1, + 8 +}; + +int MD5Test( ) +{ + MD5_CTX context; + unsigned char digest[16]; + int i, j, error; + + error = 0; + for ( j = 0; j < 7; j++ ) + { + MD5Init(&context); + + for ( i = 0; i < repeatarray[j]; i++ ) + { + MD5Update (&context, + (unsigned char*)samplearray[j], + (unsigned int)strlen( samplearray[j]) ); + } + + MD5Final(digest, &context); + + error = memcmp( digest, resultarray[j], 16 ); + + if ( error ) + break; + } + + return error ? 0 : 1; +} + +#endif // MD5_TEST +////////////////////////////////////////////////////////////////////////////// diff --git a/build/libraries_sysmenu/acsign/ARM9/src/sha1.c b/build/libraries_sysmenu/acsign/ARM9/src/sha1.c new file mode 100644 index 0000000..e7f2a65 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/sha1.c @@ -0,0 +1,470 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * sha1.c + * + * Description: + * This file implements the Secure Hashing Algorithm 1 as + * defined in FIPS PUB 180-1 published April 17, 1995. + * + * The SHA-1, produces a 160-bit message digest for a given + * data stream. It should take about 2**n steps to find a + * message with the same digest as a given message and + * 2**(n/2) to find any two messages with the same digest, + * when n is the digest size in bits. Therefore, this + * algorithm can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code + * uses (included via "sha1.h" to define 32 and 8 + * bit unsigned integer types. If your C compiler does not + * support 32 bit unsigned integers, this code is not + * appropriate. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated + * for messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is + * a multiple of the size of an 8-bit character. + * + */ + +#include "sha1.h" + +/* + * Define the SHA1 circular left shift macro + */ +#define SHA1CircularShift(bits,word) \ + (((word) << (bits)) | ((word) >> (32-(bits)))) + +/* Local Function Prototyptes */ +void SHA1PadMessage(SHA1Context *); +void SHA1ProcessMessageBlock(SHA1Context *); + +/* + * SHA1Reset + * + * Description: + * This function will initialize the SHA1Context in preparation + * for computing a new SHA1 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Reset(SHA1Context *context) +{ + if (!context) + { + return shaNull; + } + + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Intermediate_Hash[0] = 0x67452301; + context->Intermediate_Hash[1] = 0xEFCDAB89; + context->Intermediate_Hash[2] = 0x98BADCFE; + context->Intermediate_Hash[3] = 0x10325476; + context->Intermediate_Hash[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; + + return shaSuccess; +} + +/* + * SHA1Result + * + * Description: + * This function will return the 160-bit message digest into the + * Message_Digest array provided by the caller. + * NOTE: The first octet of hash is stored in the 0th element, + * the last octet of hash in the 19th element. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * Message_Digest: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Result( SHA1Context *context, + unsigned char Message_Digest[20]) +{ + int i; + + if (!context || !Message_Digest) + { + return shaNull; + } + + if (context->Corrupted) + { + return context->Corrupted; + } + + if (!context->Computed) + { + SHA1PadMessage(context); + for(i=0; i<64; ++i) + { + /* message may be sensitive, clear it out */ + context->Message_Block[i] = 0; + } + context->Length_Low = 0; /* and clear length */ + context->Length_High = 0; + context->Computed = 1; + + } + + for(i = 0; i < 20; ++i) + { + Message_Digest[i] = (unsigned char) + (context->Intermediate_Hash[i>>2] + >> 8 * ( 3 - ( i & 0x03 ) )); + } + + return shaSuccess; +} + +/* + * SHA1Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update + * message_array: [in] + * An array of characters representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array + * + * Returns: + * sha Error Code. + * + */ +int SHA1Input( SHA1Context *context, + const unsigned char *message_array, + unsigned int length) +{ + if (!length) + { + return shaSuccess; + } + + if (!context || !message_array) + { + return shaNull; + } + + if (context->Computed) + { + context->Corrupted = shaStateError; + + return shaStateError; + } + + if (context->Corrupted) + { + return context->Corrupted; + } + while(length-- && !context->Corrupted) + { + context->Message_Block[context->Message_Block_Index++] = + (unsigned char)(*message_array & 0xFF); + + context->Length_Low += 8; + if (context->Length_Low == 0) + { + context->Length_High++; + if (context->Length_High == 0) + { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) + { + SHA1ProcessMessageBlock(context); + } + + message_array++; + } + + return shaSuccess; +} + +/* + * SHA1ProcessMessageBlock + * + * Description: + * This function will process the next 512 bits of the message + * stored in the Message_Block array. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + * + * Comments: + * + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the publication. + * + * + */ +void SHA1ProcessMessageBlock(SHA1Context *context) +{ + const unsigned long K[] = { /* Constants defined in SHA-1 */ + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + unsigned long temp; /* Temporary word value */ + unsigned long W[80]; /* Word sequence */ + unsigned long A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for(t = 0; t < 16; t++) + { + W[t] = context->Message_Block[t * 4 ] << 24; + W[t] |= context->Message_Block[t * 4 + 1] << 16; + W[t] |= context->Message_Block[t * 4 + 2] << 8; + W[t] |= context->Message_Block[t * 4 + 3]; + } + + for(t = 16; t < 80; t++) + { + W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + + for(t = 0; t < 20; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + + B = A; + A = temp; + } + + for(t = 20; t < 40; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 40; t < 60; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 60; t < 80; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + + context->Message_Block_Index = 0; +} + +/* + * SHA1PadMessage + * + + * Description: + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 + * bits represent the length of the original message. All bits in + * between should be 0. This function will pad the message + * according to those rules by filling the Message_Block array + * accordingly. It will also call the ProcessMessageBlock function + * provided appropriately. When it returns, it can be assumed that + * the message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad + * ProcessMessageBlock: [in] + * The appropriate SHA*ProcessMessageBlock function + * Returns: + * Nothing. + * + */ + +void SHA1PadMessage(SHA1Context *context) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 64) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + + SHA1ProcessMessageBlock(context); + + while(context->Message_Block_Index < 56) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + else + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 56) + { + + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = (unsigned char)(context->Length_High >> 24); + context->Message_Block[57] = (unsigned char)(context->Length_High >> 16); + context->Message_Block[58] = (unsigned char)(context->Length_High >> 8); + context->Message_Block[59] = (unsigned char)(context->Length_High ); + context->Message_Block[60] = (unsigned char)(context->Length_Low >> 24); + context->Message_Block[61] = (unsigned char)(context->Length_Low >> 16); + context->Message_Block[62] = (unsigned char)(context->Length_Low >> 8); + context->Message_Block[63] = (unsigned char)(context->Length_Low ); + + SHA1ProcessMessageBlock(context); +} + + + + +////////////////////////////////////////////////////////////////////////////// +#if defined( SHA1_TEST ) + +#include "string.h" + +char* samplearray[4] = +{ + "abc", + "abcdbcdecdefdefgefghfghighijhi" "jkijkljklmklmnlmnomnopnopq", + "a", + "01234567012345670123456701234567" "01234567012345670123456701234567" +}; + +char* resultarray[ 4 ] = +{ + "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D", + "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1", + "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F", + "\xDE\xA3\x56\xA2\xCD\xDD\x90\xC7\xA7\xEC\xED\xC5\xEB\xB5\x63\x93\x4F\x46\x04\x52" +}; + +long int repeatcount[4] = { 1, 1, 1000000, 10 }; + +int SHA1Test( ) +{ + SHA1Context sha; + unsigned char digest[20]; + int i, j, error; + + error = 0; + for ( j = 0; j < 4; ++j ) + { + if ( !error ) + error = SHA1Reset(&sha); + + for(i = 0; i < repeatcount[j]; ++i) + { + if ( !error ) + error = SHA1Input(&sha, + (const unsigned char *)samplearray[j], + (unsigned int)strlen(samplearray[j])); + } + + if ( !error ) + error = SHA1Result(&sha, digest); + + if ( !error ) + error = memcmp( digest, resultarray[j], 20 ); + + if (error) + break; + } + + return error ? 0 : 1; +} + +#endif // SHA1_TEST +////////////////////////////////////////////////////////////////////////////// + diff --git a/build/libraries_sysmenu/acsign/ARM9/src/sha1dgst.c b/build/libraries_sysmenu/acsign/ARM9/src/sha1dgst.c new file mode 100644 index 0000000..4742b60 --- /dev/null +++ b/build/libraries_sysmenu/acsign/ARM9/src/sha1dgst.c @@ -0,0 +1,786 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +////!!!!#include "r_com.h" + +#ifndef NO_SHA1 +#undef SHA_0 +#define SHA_1 +#include "sha.h" +#include "sha_locl.h" +#ifdef CPU_X86 +#include "r_cpuid.h" +#endif /* NO_SHA1 */ + +const char *SHA1_version="SHA1 part of RCOM 2.3.0 11-Jun-2002"; + +/* Implemented from SHA-1 document - The Secure Hash Algorithm + */ + +#define INIT_DATA_h0 (SHA_LONG)0x67452301L +#define INIT_DATA_h1 (SHA_LONG)0xefcdab89L +#define INIT_DATA_h2 (SHA_LONG)0x98badcfeL +#define INIT_DATA_h3 (SHA_LONG)0x10325476L +#define INIT_DATA_h4 (SHA_LONG)0xc3d2e1f0L + +#define K_00_19 (SHA_LONG)0x5a827999L +#define K_20_39 (SHA_LONG)0x6ed9eba1L +#define K_40_59 (SHA_LONG)0x8f1bbcdcL +#define K_60_79 (SHA_LONG)0xca62c1d6L + +#ifndef CCONV +#define CCONV +#endif + +#ifndef PRE_CCONV +#define PRE_CCONV +#endif + +/* Endian flags are only used for the assembler code */ +#ifndef OPT_SHA1_ASM +#undef L_ENDIAN +#undef B_ENDIAN +#endif + + +#ifdef OPT_SHA1_ASM + +#ifdef CPU_X86 +void CCONV sha1_block_586(SHA_CTX *c,const unsigned char *p, int num); +void CCONV sha1_block_686(SHA_CTX *c,const unsigned char *p, int num); +void CCONV sha1_block_786(SHA_CTX *c,const unsigned char *p, int num); +unsigned long r_cpuid(unsigned long *,char **name); + +#elif OPT_SHA1_ARM +PRE_CCONV void CCONV sha1_arm4_fast(SHA_CTX *c, const unsigned char *p, + int num); +PRE_CCONV void CCONV sha1_arm4_small(SHA_CTX *c, const unsigned char *p, + int num); +#else +void CCONV sha1_block_asm(SHA_CTX *c, const unsigned char *p, int num); +#endif /* CPU_X86 */ + +#else /* OPT_SHA1_ASM */ + +void sha1_block(SHA_CTX *c, SHA_LONG *p, int num); + +#endif /* OPT_SHA1_ASM */ + +#undef M_c2nl +#undef M_p_c2nl +#undef M_c2nl_p +#undef M_p_c2nl_p +#undef M_nl2c + +#if defined(L_ENDIAN) && !defined(OPT_SHA1_ASM) +# define M_c2nl c2l +# define M_p_c2nl p_c2l +# define M_c2nl_p c2l_p +# define M_p_c2nl_p p_c2l_p +# define M_nl2c l2c +#else +# define M_c2nl c2nl +# define M_p_c2nl p_c2nl +# define M_c2nl_p c2nl_p +# define M_p_c2nl_p p_c2nl_p +# define M_nl2c nl2c +#endif /* defined(L_ENDIAN) && !defined(OPT_SHA1_ASM) */ + +int SHA1_Setup(c,sha_block) +SHA_CTX *c; +void (PRE_CCONV CCONV *sha_block)(SHA_CTX *c, const unsigned char *W, int num); + { + c->sha_block=sha_block; + return(0); + } + +void SHA1_Init(c) +SHA_CTX *c; + { + c->h0=INIT_DATA_h0; + c->h1=INIT_DATA_h1; + c->h2=INIT_DATA_h2; + c->h3=INIT_DATA_h3; + c->h4=INIT_DATA_h4; + c->Nl=0; + c->Nh=0; + c->num=0; + +#ifdef OPT_SHA1_ASM +#ifdef CPU_X86 + if (c->sha_block == NULL) + { + unsigned long cpu,attrib; + + /* We should make the methods loadable */ + cpu=r_cpuid(&attrib,NULL); + if (attrib & R_CPU_X86_HAS_PENTIUM_IV) + c->sha_block=sha1_block_786; + else if (attrib & R_CPU_X86_HAS_PENTIUM_PRO) + c->sha_block=sha1_block_686; + else + c->sha_block=sha1_block_586; + } +#else /* CPU_X86 */ + +#ifndef OPT_SHA1_ARM + c->sha_block=sha1_block_asm; +#else /* OPT_SHA1_ARM */ + if (c->sha_block == NULL) + { +#ifdef SMALL_CODE_SIZE + c->sha_block = sha1_arm4_small; +#else /* SMALL_CODE_SIZE */ + c->sha_block = sha1_arm4_fast; +#endif /* SMALL_CODE_SIZE */ + } +#endif /* OPT_SHA1_ARM */ +#endif /* CPU_X86 */ + +#else /* OPT_SHA1_ASM */ + c->sha_block=(void (PRE_CCONV CCONV *)(SHA_CTX *, const unsigned char *, int))sha1_block; +#endif /* OPT_SHA1_ASM */ + } + +#ifdef OPT_SHA1_ASM + +void SHA1_Update(c, data, len) +SHA_CTX *c; +const register unsigned char *data; +unsigned long len; + { + int i; + unsigned int alignment; + unsigned long l; + unsigned char *cp=(unsigned char *)c->data; + + if (len == 0) return; + + l=(c->Nl+(len<<3))&0xffffffffL; + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); + c->Nl=l; + + if (c->num != 0) + { + if (c->num+len >= SHA_CBLOCK) + { + i=SHA_CBLOCK-c->num; + Memcpy(&(cp[c->num]),data,i); + len-=i; + data+=i; + + c->sha_block(c,cp,64); + c->num=0; + /* drop through and do the rest */ + } + else + { + Memcpy(&(cp[c->num]),data,len); + c->num+=(int)len; + return; + } + } + /* we now can process the input data in blocks of SHA_CBLOCK + * chars and save the leftovers to c->data. */ + if (len >= SHA_CBLOCK) + { + i=(int)(len& ~63); + len-=i; + + /* + * Check to see if the input data lies on a word boundary. + * Do this as the ASM relies on input data being word aligned. + */ + alignment = (((unsigned int)data) & (sizeof(unsigned int)-1)) + & 0x03; + if (alignment == 0) + { + c->sha_block(c,data,i); + data+=i; + } + else + { + do { + Memcpy(cp, data, SHA_CBLOCK); + data += SHA_CBLOCK; + c->sha_block(c, cp, SHA_CBLOCK); + i -= SHA_CBLOCK; + } while (i > 0); + } + } + c->num=len; + if (len) + { + Memcpy(cp,data,(int)len); + } + } + +void SHA1_Transform(c,b) +SHA_CTX *c; +const unsigned char *b; + { + c->sha_block(c,b,64); + } + +void SHA1_Final(md, c) +unsigned char *md; +SHA_CTX *c; + { + register int i,j; + register SHA_LONG l; + register SHA_LONG *p; + const static unsigned char end[4]={0x80,0x00,0x00,0x00}; + unsigned char *cp= (unsigned char *)end; + unsigned char *pc; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + j=c->num; + i=j>>2; + +#ifdef PURIFY + /* PURIFY */ + /* we reference uninitialised data but don't keep the result + * which purify complains about ... and we don't want to have + * to come back here to find a non-existant problem later + */ + + /* purify often complains about the following line as an + * Uninitialized Memory Read. While this can be true, the + * following p_c2l macro will reset l when that case is true. + * This is because j&0x03 contains the number of 'valid' bytes + * already in p[i]. If and only if j&0x03 == 0, the UMR will + * occur but this is also the only time p_c2l will do + * l= *(cp++) instead of l|= *(cp++) + */ + if ((j&0x03) == 0) p[i]=0; +#endif + + pc=(unsigned char *)c->data; + pc[j]=0x80; + for (j++; j & 0x03; j++) + pc[j]=0; + i++; + /* i is the next 'undefined word' */ + if (c->num >= SHA_LAST_BLOCK) + { + for (; isha_block(c,(unsigned char *)p,64); + i=0; + } + for (; i<(SHA_LBLOCK-2); i++) + p[i]=0; + + l=c->Nl; + pc[63]=(unsigned char)((l )&0xff); + pc[62]=(unsigned char)((l>> 8)&0xff); + pc[61]=(unsigned char)((l>>16)&0xff); + pc[60]=(unsigned char)((l>>24)&0xff); + l=c->Nh; + pc[59]=(unsigned char)((l )&0xff); + pc[58]=(unsigned char)((l>> 8)&0xff); + pc[57]=(unsigned char)((l>>16)&0xff); + pc[56]=(unsigned char)((l>>24)&0xff); + + c->sha_block(c,(unsigned char *)p,64); + cp=md; + l=c->h0; nl2c(l,cp); + l=c->h1; nl2c(l,cp); + l=c->h2; nl2c(l,cp); + l=c->h3; nl2c(l,cp); + l=c->h4; nl2c(l,cp); + + /* clear stuff, sha1_block_asm may be leaving some stuff on the stack + * but I'm not worried :-) */ + c->num=0; +/* Memset((char *)&c,0,sizeof(c));*/ + } + +#else /* !OPT_SHA1_ASM */ + +void SHA1_Update(c, data, len) +SHA_CTX *c; +const register unsigned char *data; +unsigned long len; + { + register SHA_LONG *p; + int ew,ec,sw,sc; + SHA_LONG l; + + if (len == 0) return; + + l=(c->Nl+(len<<3))&0xffffffffL; + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); + c->Nl=l; + + if (c->num != 0) + { + p=c->data; + sw=c->num>>2; + sc=c->num&0x03; + + if ((c->num+len) >= SHA_CBLOCK) + { + l= p[sw]; + M_p_c2nl(data,l,sc); + p[sw++]=l; + for (; swnum); + + c->sha_block(c,(unsigned char *)p,64); + c->num=0; + /* drop through and do the rest */ + } + else + { + c->num+=(int)len; + if ((sc+len) < 4) /* ugly, add char's to a word */ + { + l= p[sw]; + M_p_c2nl_p(data,l,sc,len); + p[sw]=l; + } + else + { + ew=(c->num>>2); + ec=(c->num&0x03); + l= p[sw]; + M_p_c2nl(data,l,sc); + p[sw++]=l; + for (; sw < ew; sw++) + { M_c2nl(data,l); p[sw]=l; } + if (ec) + { + M_c2nl_p(data,l,ec); + p[sw]=l; + } + } + return; + } + } + /* We can only do the following code for assember, the reason + * being that the sha1_block 'C' version changes the values + * in the 'data' array. The assember code avoids this and + * copies it to a local array. I should be able to do this for + * the C version as well.... + */ +#if defined(B_ENDIAN) || defined(OPT_SHA1_ASM) + if ((((unsigned long)data)%sizeof(SHA_LONG)) == 0) + { + sw=len/SHA_CBLOCK; + if (sw) + { + sw*=SHA_CBLOCK; + c->sha_block(c,(SHA_LONG *)data,sw); + data+=sw; + len-=sw; + } + } +#endif + /* we now can process the input data in blocks of SHA_CBLOCK + * chars and save the leftovers to c->data. */ + p=c->data; + while (len >= SHA_CBLOCK) + { +#if defined(B_ENDIAN) || defined(L_ENDIAN) + if (p != (SHA_LONG *)data) + Memcpy(p,data,SHA_CBLOCK); + data+=SHA_CBLOCK; +# ifdef L_ENDIAN +# ifndef OPT_SHA1_ASM /* Will not happen */ + for (sw=(SHA_LBLOCK/4); sw; sw--) + { + Endian_Reverse32(p[0]); + Endian_Reverse32(p[1]); + Endian_Reverse32(p[2]); + Endian_Reverse32(p[3]); + p+=4; + } + p=c->data; +# endif +# endif +#else + for (sw=(SHA_BLOCK/4); sw; sw--) + { + M_c2nl(data,l); *(p++)=l; + M_c2nl(data,l); *(p++)=l; + M_c2nl(data,l); *(p++)=l; + M_c2nl(data,l); *(p++)=l; + } + p=c->data; +#endif + c->sha_block(c,(unsigned char *)p,64); + len-=SHA_CBLOCK; + } + ec=(int)len; + c->num=ec; + ew=(ec>>2); + ec&=0x03; + + for (sw=0; sw < ew; sw++) + { M_c2nl(data,l); p[sw]=l; } + M_c2nl_p(data,l,ec); + p[sw]=l; + } + +void SHA1_Transform(c,b) +SHA_CTX *c; +const unsigned char *b; + { + SHA_LONG p[16]; +#ifndef B_ENDIAN + SHA_LONG *q; + int i; +#endif + +#if defined(B_ENDIAN) || defined(L_ENDIAN) + Memcpy(p,b,64); +#ifdef L_ENDIAN + q=p; + for (i=(SHA_LBLOCK/4); i; i--) + { + Endian_Reverse32(q[0]); + Endian_Reverse32(q[1]); + Endian_Reverse32(q[2]); + Endian_Reverse32(q[3]); + q+=4; + } +#endif +#else + q=p; + for (i=(SHA_LBLOCK/4); i; i--) + { + SHA_LONG l; + c2nl(b,l); *(q++)=l; + c2nl(b,l); *(q++)=l; + c2nl(b,l); *(q++)=l; + c2nl(b,l); *(q++)=l; + } +#endif + c->sha_block(c,(unsigned char *)p,64); + } + + +void sha1_block(c, W, num) +SHA_CTX *c; +SHA_LONG *W; +int num; + { +#ifndef SMALL_CODE_SIZE + register SHA_LONG A,B,C,D,E,T; + SHA_LONG X[16]; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + BODY_00_15( 0,A,B,C,D,E,T,W); + BODY_00_15( 1,T,A,B,C,D,E,W); + BODY_00_15( 2,E,T,A,B,C,D,W); + BODY_00_15( 3,D,E,T,A,B,C,W); + BODY_00_15( 4,C,D,E,T,A,B,W); + BODY_00_15( 5,B,C,D,E,T,A,W); + BODY_00_15( 6,A,B,C,D,E,T,W); + BODY_00_15( 7,T,A,B,C,D,E,W); + BODY_00_15( 8,E,T,A,B,C,D,W); + BODY_00_15( 9,D,E,T,A,B,C,W); + BODY_00_15(10,C,D,E,T,A,B,W); + BODY_00_15(11,B,C,D,E,T,A,W); + BODY_00_15(12,A,B,C,D,E,T,W); + BODY_00_15(13,T,A,B,C,D,E,W); + BODY_00_15(14,E,T,A,B,C,D,W); + BODY_00_15(15,D,E,T,A,B,C,W); + BODY_16_19(16,C,D,E,T,A,B,W,W,W,W); + BODY_16_19(17,B,C,D,E,T,A,W,W,W,W); + BODY_16_19(18,A,B,C,D,E,T,W,W,W,W); + BODY_16_19(19,T,A,B,C,D,E,W,W,W,X); + + BODY_20_31(20,E,T,A,B,C,D,W,W,W,X); + BODY_20_31(21,D,E,T,A,B,C,W,W,W,X); + BODY_20_31(22,C,D,E,T,A,B,W,W,W,X); + BODY_20_31(23,B,C,D,E,T,A,W,W,W,X); + BODY_20_31(24,A,B,C,D,E,T,W,W,X,X); + BODY_20_31(25,T,A,B,C,D,E,W,W,X,X); + BODY_20_31(26,E,T,A,B,C,D,W,W,X,X); + BODY_20_31(27,D,E,T,A,B,C,W,W,X,X); + BODY_20_31(28,C,D,E,T,A,B,W,W,X,X); + BODY_20_31(29,B,C,D,E,T,A,W,W,X,X); + BODY_20_31(30,A,B,C,D,E,T,W,X,X,X); + BODY_20_31(31,T,A,B,C,D,E,W,X,X,X); + BODY_32_39(32,E,T,A,B,C,D,X); + BODY_32_39(33,D,E,T,A,B,C,X); + BODY_32_39(34,C,D,E,T,A,B,X); + BODY_32_39(35,B,C,D,E,T,A,X); + BODY_32_39(36,A,B,C,D,E,T,X); + BODY_32_39(37,T,A,B,C,D,E,X); + BODY_32_39(38,E,T,A,B,C,D,X); + BODY_32_39(39,D,E,T,A,B,C,X); + + BODY_40_59(40,C,D,E,T,A,B,X); + BODY_40_59(41,B,C,D,E,T,A,X); + BODY_40_59(42,A,B,C,D,E,T,X); + BODY_40_59(43,T,A,B,C,D,E,X); + BODY_40_59(44,E,T,A,B,C,D,X); + BODY_40_59(45,D,E,T,A,B,C,X); + BODY_40_59(46,C,D,E,T,A,B,X); + BODY_40_59(47,B,C,D,E,T,A,X); + BODY_40_59(48,A,B,C,D,E,T,X); + BODY_40_59(49,T,A,B,C,D,E,X); + BODY_40_59(50,E,T,A,B,C,D,X); + BODY_40_59(51,D,E,T,A,B,C,X); + BODY_40_59(52,C,D,E,T,A,B,X); + BODY_40_59(53,B,C,D,E,T,A,X); + BODY_40_59(54,A,B,C,D,E,T,X); + BODY_40_59(55,T,A,B,C,D,E,X); + BODY_40_59(56,E,T,A,B,C,D,X); + BODY_40_59(57,D,E,T,A,B,C,X); + BODY_40_59(58,C,D,E,T,A,B,X); + BODY_40_59(59,B,C,D,E,T,A,X); + + BODY_60_79(60,A,B,C,D,E,T,X); + BODY_60_79(61,T,A,B,C,D,E,X); + BODY_60_79(62,E,T,A,B,C,D,X); + BODY_60_79(63,D,E,T,A,B,C,X); + BODY_60_79(64,C,D,E,T,A,B,X); + BODY_60_79(65,B,C,D,E,T,A,X); + BODY_60_79(66,A,B,C,D,E,T,X); + BODY_60_79(67,T,A,B,C,D,E,X); + BODY_60_79(68,E,T,A,B,C,D,X); + BODY_60_79(69,D,E,T,A,B,C,X); + BODY_60_79(70,C,D,E,T,A,B,X); + BODY_60_79(71,B,C,D,E,T,A,X); + BODY_60_79(72,A,B,C,D,E,T,X); + BODY_60_79(73,T,A,B,C,D,E,X); + BODY_60_79(74,E,T,A,B,C,D,X); + BODY_60_79(75,D,E,T,A,B,C,X); + BODY_60_79(76,C,D,E,T,A,B,X); + BODY_60_79(77,B,C,D,E,T,A,X); + BODY_60_79(78,A,B,C,D,E,T,X); + BODY_60_79(79,T,A,B,C,D,E,X); + + c->h0=(c->h0+E)&0xffffffffL; + c->h1=(c->h1+T)&0xffffffffL; + c->h2=(c->h2+A)&0xffffffffL; + c->h3=(c->h3+B)&0xffffffffL; + c->h4=(c->h4+C)&0xffffffffL; + + num-=64; + if (num <= 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + W+=16; + } +#else /* SMALL_CODE_SIZE */ + SHA_LONG A,B,C,D,E,T; + SHA_LONG X[16]; + SHA_LONG *a1,*a2,*a3; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + int i; + + for (i=0; i<16; i++) + { + BODY_00_15(i,A,B,C,D,E,T,W); + E=D; D=C; C=B; B=A; A=T; + } + + a1=W; + for (i=16; i<20; i++) + { + if (i == 19) a1=X; + BODY_16_19(i,A,B,C,D,E,T,W,W,W,a1); + E=D; D=C; C=B; B=A; A=T; + } + + a1=a2=a3=W; + for (i=20; i<40; i++) + { + if (i == 24) a3=X; + if (i == 30) a2=X; + if (i == 32) a1=X; + BODY_20_31(i,A,B,C,D,E,T,a1,a2,a3,X); + E=D; D=C; C=B; B=A; A=T; + } + + for (i=40; i<60; i++) + { + BODY_40_59(i,A,B,C,D,E,T,X); + E=D; D=C; C=B; B=A; A=T; + } + + for (i=60; i<80; i++) + { + BODY_60_79(i,A,B,C,D,E,T,X); + E=D; D=C; C=B; B=A; A=T; + } + + c->h0=(c->h0+A)&0xffffffffL; + c->h1=(c->h1+B)&0xffffffffL; + c->h2=(c->h2+C)&0xffffffffL; + c->h3=(c->h3+D)&0xffffffffL; + c->h4=(c->h4+E)&0xffffffffL; + + num-=64; + if (num <= 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + W+=16; + } +#endif /* SMALL_CODE_SIZE */ + } + +void SHA1_Final(md, c) +unsigned char *md; +SHA_CTX *c; + { + register int i,j; + register SHA_LONG l; + register SHA_LONG *p; + const static unsigned char end[4]={0x80,0x00,0x00,0x00}; + unsigned char *cp= (unsigned char *)end; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + j=c->num; + i=j>>2; + +#ifdef PURIFY + /* PURIFY */ + /* we reference uninitialised data but don't keep the result + * which purify complains about ... and we don't want to have + * to come back here to find a non-existant problem later + */ + + /* purify often complains about the following line as an + * Uninitialized Memory Read. While this can be true, the + * following p_c2l macro will reset l when that case is true. + * This is because j&0x03 contains the number of 'valid' bytes + * already in p[i]. If and only if j&0x03 == 0, the UMR will + * occur but this is also the only time p_c2l will do + * l= *(cp++) instead of l|= *(cp++) + */ + if ((j&0x03) == 0) p[i]=0; +#endif + + l=p[i]; + M_p_c2nl(cp,l,j&0x03); + p[i]=l; + i++; + /* i is the next 'undefined word' */ + if (c->num >= SHA_LAST_BLOCK) + { + for (; isha_block(c,(unsigned char *)p,64); + i=0; + } + for (; i<(SHA_LBLOCK-2); i++) + p[i]=0; + p[SHA_LBLOCK-2]=c->Nh; + p[SHA_LBLOCK-1]=c->Nl; +#if defined(L_ENDIAN) + Endian_Reverse32(p[SHA_LBLOCK-2]); + Endian_Reverse32(p[SHA_LBLOCK-1]); +#endif + c->sha_block(c,(unsigned char *)p,64); + cp=md; + l=c->h0; nl2c(l,cp); + l=c->h1; nl2c(l,cp); + l=c->h2; nl2c(l,cp); + l=c->h3; nl2c(l,cp); + l=c->h4; nl2c(l,cp); + + /* clear stuff, sha1_block may be leaving some stuff on the stack + * but I'm not worried :-) */ + c->num=0; +/* Memset((char *)&c,0,sizeof(c));*/ + } +#endif + +#if 0 +int pr(ctx) +SHA_CTX *ctx; + { + int i,j; + unsigned char *p=(unsigned char *)(ctx->data); + + fprintf(stderr,"num = %08X%08X\n",ctx->Nh,ctx->Nl); + fprintf(stderr," %08X %08X %08X %08X %08X\n", + ctx->h0,ctx->h1,ctx->h2,ctx->h3,ctx->h4); + fprintf(stderr,"bufnum = %d\n",ctx->num); + fprintf(stderr," "); + for (j=0; j<64; j+=16) + { + for (i=0; i<16; i++) + { +/* + if ((i+j) >= ctx->num) + fprintf(stderr,"--"); + else +*/ + fprintf(stderr,"%02X",p[i+j]); + } + if ((j+16) >=64) + fprintf(stderr,"\n"); + else + fprintf(stderr,"\n "); + } + } + +#endif + +#endif /* NO_SHA1 */ diff --git a/build/libraries_sysmenu/acsign/Makefile b/build/libraries_sysmenu/acsign/Makefile new file mode 100644 index 0000000..665c3ec --- /dev/null +++ b/build/libraries_sysmenu/acsign/Makefile @@ -0,0 +1,31 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-27#$ +# $Rev: 1203 $ +# $Author: yada $ +#---------------------------------------------------------------------------- + +SUBDIRS = ARM9 + +TARGET_FIRM = SYSTEMMENU + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/libraries_sysmenu/mb_loader/ARM7/Makefile b/build/libraries_sysmenu/mb_loader/ARM7/Makefile new file mode 100644 index 0000000..c678ae7 --- /dev/null +++ b/build/libraries_sysmenu/mb_loader/ARM7/Makefile @@ -0,0 +1,53 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-27#$ +# $Rev: 1203 $ +# $Author: yada $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +#---------------------------------------------------------------------------- +TARGET_FIRM = SYSTEMMENU +TARGET_PLATFORM = TWL +TWL_ARCHGEN = LIMITED +TWL_PROC = ARM7 + +#---------------------------------------------------------------------------- + +SRCDIR = ../common/src + +INCDIR = ../common/include \ + $(TWLSDK_ROOT)/build/libraries/mb/common/include + + +SRCS = mb_loader.c + +TARGET_LIB = libmbloader_sp$(TWL_LIBSUFFIX).a + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(SYSMENU_INSTALL_LIBDIR) + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== + diff --git a/build/libraries_sysmenu/mb_loader/ARM9/Makefile b/build/libraries_sysmenu/mb_loader/ARM9/Makefile new file mode 100644 index 0000000..257cddc --- /dev/null +++ b/build/libraries_sysmenu/mb_loader/ARM9/Makefile @@ -0,0 +1,52 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-27#$ +# $Rev: 1203 $ +# $Author: yada $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +#---------------------------------------------------------------------------- +TARGET_FIRM = SYSTEMMENU +TARGET_PLATFORM = TWL +TWL_ARCHGEN = LIMITED +TWL_PROC = ARM9 + +#---------------------------------------------------------------------------- + +SRCDIR = ../common/src + +INCDIR = ../common/include \ + $(TWLSDK_ROOT)/build/libraries/mb/common/include + +SRCS = mb_loader.c + +TARGET_LIB = libmbloader$(TWL_LIBSUFFIX).a + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(SYSMENU_INSTALL_LIBDIR) + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== + diff --git a/build/libraries_sysmenu/mb_loader/Makefile b/build/libraries_sysmenu/mb_loader/Makefile new file mode 100644 index 0000000..6024cf8 --- /dev/null +++ b/build/libraries_sysmenu/mb_loader/Makefile @@ -0,0 +1,30 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-27#$ +# $Rev: 1203 $ +# $Author: yada $ +#---------------------------------------------------------------------------- + +TARGET_FIRM = SYSTEMMENU +SUBDIRS = ARM7 ARM9 + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/libraries_sysmenu/mb_loader/common/src/mb_loader.c b/build/libraries_sysmenu/mb_loader/common/src/mb_loader.c new file mode 100644 index 0000000..5289b5c --- /dev/null +++ b/build/libraries_sysmenu/mb_loader/common/src/mb_loader.c @@ -0,0 +1,312 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: mb_loader.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +#if defined(SDK_ARM7) +#include +#else +#ifdef SDK_SMALL_BUILD +#include "SYSM_work.h" +#endif +#endif + + +#include // twl/mb.hȂB +#include +#include + +// -------------------------------------------------------------------------- + +// Download̃TCY + +#define MB_OVT_MAX_SIZE MB_COMM_BLOCK_SIZE // OVT̍őTCYiBlockTCYőTCYƂj + +/*----------------------------------------------------------------------------*/ +#define MB_TRIGGER_SIGNAL_TO_ARM7 (0x00000001) + +/*----------------------------------------------------------------------------*/ +static void MIm_CpuClear32( register u32 data, register void *destp, register u32 size ); +static void MIm_CpuClear32( register u32 data, register void *destp, register u32 size ); +static void LOADERi_LocateAllSegments( MBDownloadFileInfo *mdfi ); +static void MBi_SearchAndLocateSegmentInfo( MBDownloadFileInfo *mdfi, u16 processor ); +static void LOADERi_Jump(void); +static void MBi_fifo_callback_arm7(PXIFifoTag tag, u32 msg_adr, BOOL err); + +/*----------------------------------------------------------------------------*/ +static MB_LoaderCallback loader_precallback = NULL; + +/*----------------------------------------------------------------------------*/ + + +#if defined(SDK_ARM7) + +/*---------------------------------------------------------------------------* + Name: MIm_CpuCopy32 + + Description: [_[pCpuCopy + + Arguments: srcp, destp, size + + Returns: void + *---------------------------------------------------------------------------*/ + +#include + +asm void MIm_CpuCopy32( register const void *srcp, register void *destp, register u32 size ) +{ + add r12, r1, r2 // r12: destEndp = destp + size + +@30: + cmp r1, r12 // while (destp < destEndp) + ldmltia r0!, {r2} // *((vu32 *)(destp)++) = *((vu32 *)(srcp)++) + stmltia r1!, {r2} + blt @30 + + bx lr +} + +#ifndef SDK_SMALL_BUILD +static asm void MIm_CpuClear32( register u32 data, register void *destp, register u32 size ) +{ + add r12, r1, r2 // r12: destEndp = destp + size + +@20: + cmp r1, r12 // while (destp < destEndp) + stmltia r1!, {r0} // *((vu32 *)(destp++)) = data + blt @20 + + bx lr +} +#endif + +#include + + +/*---------------------------------------------------------------------------* + Name: LOADERi_LocateAllSegments + + Description: ARM9,ARM7̊eZOgKvɉčĔzuB + + Arguments: mdfi + + Returns: void + *---------------------------------------------------------------------------*/ + +static void LOADERi_LocateAllSegments( MBDownloadFileInfo *mdfi ) +{ + MBi_SearchAndLocateSegmentInfo(mdfi, MI_PROCESSOR_ARM9); // ARM9ZOgɂ‚Ă̔zu + MBi_SearchAndLocateSegmentInfo(mdfi, MI_PROCESSOR_ARM7); // ARM7ZOgɂ‚Ă̔zu +} + + +/* w̃ZOg, Ĕzu */ +static void MBi_SearchAndLocateSegmentInfo( MBDownloadFileInfo *mdfi, u16 processor ) +{ + int i; + MbSegmentInfo *seg_info; + + if( mdfi ) { + for( i = 0 ; i < MB_DL_SEGMENT_NUM ; ++i ) { + seg_info = &mdfi->seg[i]; + if ( seg_info->target == processor ) { + if ( seg_info->recv_addr != seg_info->load_addr ) { + MIm_CpuCopy32( (void*)seg_info->recv_addr, (void*)seg_info->load_addr, seg_info->size ); +#ifndef SDK_SMALL_BUILD // IPL2̏ꍇ́ÃNAIPL2ōsB + MIm_CpuClear32( 0, (void*)seg_info->recv_addr, seg_info->size ); +#endif + } + } + } + } +} + + +/*---------------------------------------------------------------------------* + Name: LOADERi_Jump + + Description: [_[N (ARM7/9 ) + + Arguments: + + Returns: void + *---------------------------------------------------------------------------*/ + +static void LOADERi_Jump(void) +{ +#if defined(SDK_ARM7) + + MBDownloadFileInfo *mdfi = (MBDownloadFileInfo*)MB_DOWNLOAD_FILEINFO_ADDRESS; + MBParam *p_param = (MBParam*)HW_WM_BOOT_BUF; + + if( p_param->boot_type != MB_TYPE_MULTIBOOT ) { // u[g^Cv}`u[głȂꍇ́ATRUE^[B + return; + } + + LOADERi_LocateAllSegments( mdfi ); // u[gvO̍ĔzusB + +#endif +} + + +/*---------------------------------------------------------------------------* + Name: MBi_fifo_callback_arm7 + + Description: p PXI ^OoRŃ[_[N + + Arguments: + + Returns: None. + *---------------------------------------------------------------------------*/ + +static void MBi_fifo_callback_arm7(PXIFifoTag tag, u32 msg_adr, BOOL err) +{ +#pragma unused( err ) + + if (tag == PXI_FIFO_TAG_MB && msg_adr == (u32)MB_TRIGGER_SIGNAL_TO_ARM7) + { + if ( loader_precallback ) { + (*loader_precallback)(); + } + } +} + +#endif /* defined(SDK_ARM7) */ + + +/*---------------------------------------------------------------------------* + Name: LOADER_Start + + Description: [_[̃X^[g + + Arguments: None. + + Returns: TRUE - success FALSE - failed + *---------------------------------------------------------------------------*/ + + +void LOADER_Start(void) +{ + +#if defined(SDK_ARM9) + int result; + MBDownloadFileInfo *mdfi = (MBDownloadFileInfo*)MB_DOWNLOAD_FILEINFO_ADDRESS; + MBParam *p_param = (MBParam*)HW_WM_BOOT_BUF; + + // }`u[g̎̓fobKGgɔ΂Ȃ悤NAB +#ifdef SDK_SMALL_BUILD + GetMovedInfoFromIPL1Addr()->isOnDebugger = 0; // USG-WW-3rd & USG-China-2ndł́AGetSharedWorkAddr()->isOnDebugger̓pb`̈ƃobeBOĂ邪Ã[`ARM9̃}`u[g[`ŌĂ΂ꂽŁAARM7Ńpb`}[`Ă΂̂ŁAvB + // AfobKŃrhɂ́AQƂ鑤isOnDebuggertONAĂȂ̂ŁACB +#endif // SDK_SMALL_BUILD + + // VXëփ}`u[gtO + p_param->boot_type = MB_TYPE_MULTIBOOT; + // e@VXë֏ + MI_CpuCopy8((void*)MB_BSSDESC_ADDRESS, &p_param->parent_bss_desc, MB_BSSDESC_SIZE); + + // ARM7փ[_[Nʒm + result = PXI_SendWordByFifo( PXI_FIFO_TAG_MB, (u32)MB_TRIGGER_SIGNAL_TO_ARM7, FALSE ); + SDK_ASSERTMSG((result >= 0), "ARM9:FIFO SEND ERROR!\n"); + + return; + +#else /* defined(SDK_ARM9) */ + + // [_[R[ + LOADERi_Jump(); + +#endif +} + + +/*---------------------------------------------------------------------------* + Name: LOADER_Init + + Description: [_[̏ + + Arguments: callback - u[g̏oƂɕԂR[obN + + Returns: None. + *---------------------------------------------------------------------------*/ + +void LOADER_Init(MB_LoaderCallback callback) +{ + MBParam *p_param = (MBParam*)HW_WM_BOOT_BUF; + + PXI_Init(); // ĂȂAs + +#if defined(SDK_ARM7) + + loader_precallback = callback; + + /* u[gtO̕␳(}`u[gtOw肳ĂȂꍇROMƂ݂ȂB) */ + if (p_param->boot_type != MB_TYPE_MULTIBOOT) { + p_param->boot_type = MB_TYPE_NORMAL; + } + /* ̏, K MB_TYPE_MULTIBOOT MB_TYPE_NORMAL ɂȂ */ + + // }`u[gĎFIFOR[obNZbg + PXI_SetFifoRecvCallback( PXI_FIFO_TAG_MB, MBi_fifo_callback_arm7 ); + +#else /* defined(SDK_ARM7) */ + + #pragma unused(callback) + +#endif +} + + + +/*----------------------------------------------------------------------------* +/* sgp + *----------------------------------------------------------------------------*/ + +#if defined(LOADER_USE_OVT_BUF) + +//---------------------------------------------------------------------- +// I[o[Ce[u +//---------------------------------------------------------------------- +typedef struct { + u32 id; // I[o[C ID + void *ram_address; // [h擪ʒu + u32 ram_size; // [hTCY + u32 bss_size; // bss ̈TCY + void *sinit_init; // static initializer 擪AhX + void *sinit_init_end; // static initializer ŏIAhX + u32 file_id; // I[o[Ct@CID + u32 rsv; // \B +} ROM_OVT; + + +// OVT̍őTCYiɂ‚Ă͍čl̗]nj +#define MB_OVT_MAX_SIZE MB_COMM_BLOCKSIZE + +// Overlay Table Buffer +// }`u[gvOŁAX^eBbNCjVCUN̂ɕKv +// I[o[Ce[uŗeʂςĂB +// IPL2ɂdlł܂܂ŁAɒuĂ +static u32 mb_ovt_buf[MB_OVT_MAX_SIZE/sizeof(u32)]; + +static void MB_SetOverlayTable(ROM_OVT *srcp, u16 sec_num) +{ + if (srcp && sec_num) + { + MI_CpuCopy8((void*)srcp, (void*)mb_ovt_buf, sec_num*sizeof(ROM_OVT)); + } +} + +#endif diff --git a/build/libraries_sysmenu/sysmenu/ARM9/MakeCrt0 b/build/libraries_sysmenu/sysmenu/ARM9/MakeCrt0 new file mode 100644 index 0000000..95df676 --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/MakeCrt0 @@ -0,0 +1,46 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + + +SUBDIRS = + + +#---------------------------------------------------------------------------- +TARGET_PLATFORM = TWL +TWL_ARCHGEN = LIMITED +TWL_PROC = ARM9 + +SRCS = crt1.c + +TARGET_OBJ = crt1.o + +LINCLUDES = $(COMMON_DIR) + +include $(TWLIPL_ROOT)/build/buildtools/commondefs.sysmenu + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(SYSMENU_INSTALL_LIBDIR) + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules.sysmenu + + +#===== End of Makefile ===== diff --git a/build/libraries_sysmenu/sysmenu/ARM9/Makefile b/build/libraries_sysmenu/sysmenu/ARM9/Makefile new file mode 100644 index 0000000..41d3503 --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/Makefile @@ -0,0 +1,53 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +MYSUBDIRS = ./ + +#---------------------------------------------------------------------------- +TARGET_FIRM = SYSTEMMENU +TARGET_PLATFORM = TWL +TWL_ARCHGEN = LIMITED +TWL_PROC = ARM9 + +SRCS = sysmenu_lib.c sysmenu_card.c sysmenu_util.c gameBoot.c ninLogoFunc.c cmn.c \ + nitroSettingsEx.c + +TARGET_LIB = libsysmenu$(TWL_LIBSUFFIX).a + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(SYSMENU_INSTALL_LIBDIR) + +LINCLUDES = $(TWLSDK_ROOT)/build/libraries/mb/common/include \ + $(TWLSDK_ROOT)/build/libraries/spi/ARM9/include \ + +#---------------------------------------------------------------------------- + +do-build: $(MYSUBDIRS) $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +$(MYSUBDIRS):: +# $(MAKE) -C $@ -f MakeCrt0 + +#===== End of Makefile ===== diff --git a/build/libraries_sysmenu/sysmenu/ARM9/include/sysmenu_card.h b/build/libraries_sysmenu/sysmenu/ARM9/include/sysmenu_card.h new file mode 100644 index 0000000..eeee6e8 --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/include/sysmenu_card.h @@ -0,0 +1,248 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: SYSM_card.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef SYSM_CARD_H_ +#define SYSM_CARD_H_ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +//---------------------------------------------------------------------- +// J[ho +// +//EARM7 J[h̃_E[h܂ł͌oJn܂B +//Eo̓J[hoXւ̃ANZXbN܂B +//EAvP[VNO SYSM_FinalizeCardPulledOut() +// ĂяoĊmɌo悤ɂĉB +//---------------------------------------------------------------------- + +BOOL SYSM_IsCardPulledOut(void); + + +//---------------------------------------------------------------------- +// J[hoI +//---------------------------------------------------------------------- + +void SYSM_FinalizeCardPulledOut(void); + + +//---------------------------------------------------------------------- +// J[ho +//---------------------------------------------------------------------- + +BOOL SYSM_IsDetectingCardPulledOut(void); + + +//---------------------------------------------------------------------- +// J[ho +//---------------------------------------------------------------------- + +void SYSMi_InitCardPulledOut(void); + + +//---------------------------------------------------------------------- +// J[hIDǂݍ +//---------------------------------------------------------------------- + +u32 SYSMi_ReadCardID(void); + + +//---------------------------------------------------------------------- +// J[hf[^ǂݍ +//---------------------------------------------------------------------- + +void SYSM_ReadCard(void *romp, void *ramp, s32 size); + + +//---------------------------------------------------------------------- +// J[h̃f[^]̓fBH +//---------------------------------------------------------------------- + +#define SYSMi_IsCardDataReady() \ + \ + (*(vu32 *)REG_CARDCNT & CARD_DATA_READY) + +//EJ[h̃f[^]̓fBǂԂ܂B + +//---------------------------------------------------------------------- +// J[hf[^҂ +//---------------------------------------------------------------------- + +#define SYSMi_WaitCardData() \ +{ \ + while (!SYSMi_IsCardDataReady()) ; \ +} + +//EJ[hf[^]̏I҂܂B + + +//---------------------------------------------------------------------- +// J[h̓rW[H +//---------------------------------------------------------------------- + +#define SYSMi_IsCardBusy() \ + \ + (*(vu32 *)REG_CARDCNT & CARD_START) + +//EJ[hrW[ǂԂ܂B + +//---------------------------------------------------------------------- +// J[h҂ +//---------------------------------------------------------------------- + +#define SYSMi_WaitCard() \ +{ \ + while (SYSMi_IsCardBusy()) ; \ +} + +//EJ[h̏I҂܂B + + +//---------------------------------------------------------------------- +// Rg[p[^liGAME[hj +//---------------------------------------------------------------------- + +#define SYSMi_GetCardCnt4Game() \ + \ + (*(vu32 *)MROMCNT_GAME_BUF) + +//EGAME[h̃Rg[p[^l܂B + + + +//---------------------------------------------------------------------- +// qnlGAE}bv +//---------------------------------------------------------------------- + +#define MROM_SECURE_AREA 0x4000 // SECUREGA +#define MROM_GAME_AREA 0x8000 // GAMEGA + +//---------------------------------------------------------------------- +// qnlGAETCY +//---------------------------------------------------------------------- + +#define MROM_SEGMENT_SIZE 0x1000 // ZOgTCY +#define MROM_SECURE_SIZE 0x4000 // SECUREGATCY + +#ifndef MROM_PAGE_SIZE +#define MROM_PAGE_SIZE 512 // }XNqnlEy[W +#endif + +//---------------------------------------------------------------------- +// E}bv +//---------------------------------------------------------------------- + +#define MROMCNT_GAME_BUF (HW_ROM_HEADER_BUF + 0x60) // GAME[hERg[f[^ +#define MROMCNT_SECURE_BUF (HW_ROM_HEADER_BUF + 0x64) // SECURE[hERg[f[^ + + +//---------------------------------------------------------------------- +// WX^EAhX +//---------------------------------------------------------------------- + +#ifndef REG_BASE +#define REG_BASE 0x04000000 // WX^Q +#endif +#ifndef REG_IME +#define REG_IME (REG_BASE + 0x208) // 荞݃}X^Cl[u +#endif + +#define REG_CARDMST_SPI_CNT (REG_BASE + 0x1a0) // J[h}X^[rohRg[ + +#define REG_CARD_MASTER_CNT (REG_BASE + 0x1a1) // J[h}X^[Rg[ + +#define REG_CARD_SPI_CNT (REG_BASE + 0x1a0) // J[hrohRg[ +#define REG_CARD_SPI_DATA (REG_BASE + 0x1a2) // f[^ + +#define REG_CARDCNT (REG_BASE + 0x1a4) // J[hRg[ +#define REG_CARD_CMD (REG_BASE + 0x1a8) // R}hݒ +#define REG_CARD_DATA (REG_BASE + 0x100010) // f[^ + + +//---------------------------------------------------------------------- +// J[h }X^[Rg[ +//---------------------------------------------------------------------- + +#define CARDMST_SEL_DEVICE 0x20 // foCXI +#define CARDMST_SEL_ROM 0x00 // }XNqnl^RcI +#define CARDMST_SEL_SPI 0x20 // rohI + +#define CARDMST_IF_ENABLE 0x40 // 荞ݗv +#define CARDMST_ENABLE 0x80 // J[hCl[u + + +//---------------------------------------------------------------------- +// J[hANZX Rg[ +//---------------------------------------------------------------------- + +#define CARD_LATENCY1_CYCLES_MASK 0x00001fff // CeVP̃TCN +#define CARD_LATENCY2_CYCLES_MASK 0x003f0000 // CeVQ̃TCN +#define CARD_LATENCY_MASK 0x003f1fff // L킹}XN + +#define CARD_LATENCY1_CYCLES_SHIFT 0 +#define CARD_LATENCY2_CYCLES_SHIFT 16 + +#define CARD_DATA_SCRAMBLE_ON 0x00002000 // f[^XNu nm +#define CARD_SCRAMBLE_UNIT_ON 0x00004000 // XNuH nm +#define CARD_CMD_SCRAMBLE_ON 0x00400000 // R}hXNu nm + // XNutOQ̃Zbg +#define CARD_SCRAMBLE_SET_MASK ( CARD_SCRAMBLE_UNIT_ON | CARD_DATA_SCRAMBLE_ON \ + | CARD_CMD_SCRAMBLE_ON) + +#define CARD_DATA_READY 0x00800000 // f[^ fB + +#define CARD_1_PAGE 0x01000000 // Py[W +#define CARD_STATUS 0x07000000 // Xe[^X[h + +#define CARD_RESET_LO 0x00000000 // ZbgMx k +#define CARD_RESET_HI 0x20000000 // g +#define CARD_ACCESS_MODE 0x40000000 // ANZX [h +#define CARD_READ_MODE 0x00000000 // [h[h +#define CARD_WRITE_MODE 0x40000000 // Cg[h +#define CARD_START 0x80000000 // X^[g + +// \̃op萔 + +#define ST_CARD_1_PAGE 1 // Py[W +#define ST_CARD_STATUS 7 // Xe[^X[h + +#define ST_CARD_READ_MODE 0 // [h[h +#define ST_CARD_WRITE_MODE 1 // Cg[h + + +//---------------------------------------------------------------------- +// }XNqnlR}h +//---------------------------------------------------------------------- + +// GAME[h + +#define MROMOP_G_OP_MASK 0xff000000 // R}h}XN + +#define MROMOP_G_READ_ID 0xb8000000 // hcǂݍ +#define MROMOP_G_READ_PAGE 0xb7000000 // y[Wǂݍ + + + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // SYSM_CARD_H_ diff --git a/build/libraries_sysmenu/sysmenu/ARM9/include/sysmenu_define.h b/build/libraries_sysmenu/sysmenu/ARM9/include/sysmenu_define.h new file mode 100644 index 0000000..05e8886 --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/include/sysmenu_define.h @@ -0,0 +1,50 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: SYSM_define.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef __SYSM_DEFINE_H__ +#define __SYSM_DEFINE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// define data------------------------------------------- + + // 萔 +#define POW_LCDC_SW_TOP 0x0000 // LCDɉʕ\ +#define POW_LCDC_SW_BOTTOM 0x8000 // LCDɉʕ\ +#define POW_E2D2 0x0200 // 2DH2 ̓dON +#define POW_E2D1 0x0002 // 2DH1 ̓dON +#define POW_ELC 0x0001 // LCDCH̓dON + +#define SUBP_RECV_IF_ENABLE 0x4000 // 荞ݗvM + + // rpbNID +#define BOOTFLAG_LOCK_ID (OS_MAINP_LOCK_ID_END-1) +#define CARTRIDGE_LOCK_ID (OS_MAINP_LOCK_ID_END-2) + + // SetBootFlag֐̈int set_clear_flagŎw肷萔 +#define SBF_CLEAR 0 +#define SBF_SET 1 + +#ifdef __cplusplus +} +#endif + +#endif // __SYSM_DEFINE_H__ diff --git a/build/libraries_sysmenu/sysmenu/ARM9/src/cmn.c b/build/libraries_sysmenu/sysmenu/ARM9/src/cmn.c new file mode 100644 index 0000000..055928d --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/src/cmn.c @@ -0,0 +1,250 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: mainFunc.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include + +#include + + +/*---------------------------------------------------------------------------* + Name: CMN_InitFileSystem + + Description: t@CVXeLɂ܂B + ܂At@Ce[uɓǂݍ݂܂B + + Arguments: pAllocator: LȃAP[^ւ̃|C^B + + Returns: ȂB + *---------------------------------------------------------------------------*/ +// t@CVXe +void CMN_InitFileSystem( NNSFndAllocator* pAllocator ) +{ + SDK_NULL_ASSERT( pAllocator ); + + // ARM7Ƃ̒ʐMFIFO荞݋ + (void)OS_EnableIrqMask(OS_IE_SPFIFO_RECV); + + // t@CVXe + FS_Init( FS_DMA_NOT_USE ); + + // t@Ce[uLbV + if( pAllocator != NULL ) + { + const u32 need_size = FS_GetTableSize(); + void *p_table = NNS_FndAllocFromAllocator( pAllocator, need_size ); + SDK_ASSERT(p_table != NULL); + (void)FS_LoadTable(p_table, need_size); + } +} + + + +/*---------------------------------------------------------------------------* + Name: CMN_ClearVram + + Description: VRAM NA܂B + VRAM SĖ蓖ĂłȂ΂Ȃ܂B + + Arguments: ȂB + + Returns: ȂB + *---------------------------------------------------------------------------*/ +// VRAMNA +void CMN_ClearVram( void ) +{ + //--------------------------------------------------------------------------- + // All VRAM banks to LCDC + //--------------------------------------------------------------------------- + GX_SetBankForLCDC(GX_VRAM_LCDC_ALL); + + //--------------------------------------------------------------------------- + // Clear all LCDC space + //--------------------------------------------------------------------------- + MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE); + + //--------------------------------------------------------------------------- + // Disable the banks on LCDC + //--------------------------------------------------------------------------- + (void)GX_DisableBankForLCDC(); + + MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE); // clear OAM + MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE); // clear the standard palette + + MI_CpuFillFast((void*)HW_DB_OAM, 192, HW_DB_OAM_SIZE); // clear OAM + MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE); // clear the standard palette +} + + + +/*---------------------------------------------------------------------------* + Name: CMN_LoadFile + + Description: t@CɃ[h܂B + t@Cf[^svɂȂꍇ + CMN_UnloadFile( *ppFile, pAlloc ) Ńt@Cf[^ + ܂B + + Arguments: ppFile: t@C[hAhX󂯎 + obt@ւ̃|C^B + fpath: [ht@C̃pX + pAlloc: AP[^ւ̃|C^ + + Returns: [ht@C̃t@CTCYԂ܂B + 0 ̏ꍇ̓t@C[hɎs\܂B + ̏ꍇ *ppFile ̒l͖łB + *---------------------------------------------------------------------------*/ +u32 CMN_LoadFile(void** ppFile, const char* fpath, NNSFndAllocator* pAlloc) +{ + BOOL bSuccess; + FSFile f; + u32 length; + u32 read; + + SDK_NULL_ASSERT( ppFile ); + SDK_NULL_ASSERT( fpath ); + SDK_NULL_ASSERT( pAlloc ); + + FS_InitFile(&f); + + bSuccess = FS_OpenFile(&f, fpath); + if( ! bSuccess ) + { + OS_Warning("file (%s) not found", fpath); + return 0; + } + + length = FS_GetLength(&f); + *ppFile = NNS_FndAllocFromAllocator(pAlloc, length); + if( *ppFile == NULL ) + { + OS_Warning("cant allocate memory for file: %s", fpath); + return 0; + } + + read = (u32)FS_ReadFile(&f, *ppFile, (s32)length); + if( read != length ) + { + OS_Warning("fail to load file: %s", fpath); + NNS_FndFreeToAllocator(pAlloc, *ppFile); + return 0; + } + + bSuccess = FS_CloseFile(&f); + if( ! bSuccess ) + { + OS_Warning("fail to close file: %s", fpath); + } + + return length; +} + + + +/*---------------------------------------------------------------------------* + Name: CMN_UnloadFile + + Description: t@Cf[^܂B + + Arguments: pFile: t@Cf[^ւ̃|C^ + pAlloc: t@C[hɗpAP[^ւ̃|C^ + + Returns: ȂB + *---------------------------------------------------------------------------*/ +void CMN_UnloadFile(void* pFile, NNSFndAllocator* pAlloc) +{ + NNS_FndFreeToAllocator(pAlloc, pFile); +} + + + +/*---------------------------------------------------------------------------* + Name: CMN_LoadArchive + + Description: pXŎw肳ꂽA[JCuɓǂݍ݁At@CVX + eɃ}Eg܂B + A[JCusvɂȂꍇ + CMN_RemoveArchive( Ԃl, pAllocator ) ŃA[JCu + ܂B + + Arguments: name: A[JCut@CVXeŎʂׂ̖OB + path: A[JCũpXB + pAllocator: AP[^ւ̃|C^ + + Returns: A[JCũ[hɐ΁ANNSFndArchive \̂ւ̃|C + ^Ԃ܂Bsꍇɂ́ANULLԂ܂B + *---------------------------------------------------------------------------*/ +NNSFndArchive* +CMN_LoadArchive(const char* name, const char* path, NNSFndAllocator* pAllocator) +{ + FSFile file; + NNSFndArchive* archive = NULL; + + SDK_NULL_ASSERT(name); + SDK_NULL_ASSERT(path); + SDK_NULL_ASSERT(pAllocator); + + FS_InitFile(&file); + if (FS_OpenFile(&file, path)) + { + u32 binarySize = FS_GetLength(&file); + u32 memorySize = MATH_ROUNDUP(sizeof(NNSFndArchive), 16) + MATH_ROUNDUP(binarySize, 16); + + u8* memory = (u8*)NNS_FndAllocFromAllocator(pAllocator, memorySize); + + if (memory != NULL) + { + u8* binary = memory + MATH_ROUNDUP(sizeof(NNSFndArchive), 16); + + if ((u32)FS_ReadFile(&file, binary, (s32)binarySize) == binarySize) + { + if (NNS_FndMountArchive((NNSFndArchive*)memory, name, binary)) + { + archive = (NNSFndArchive*)memory; + } + } + } + (void)FS_CloseFile(&file); + } + return archive; +} + + + +/*---------------------------------------------------------------------------* + Name: CMN_RemoveArchive + + Description: w肳ꂽA[JCu폜܂B + + w肳ꂽA[JCut@CVXeA}EgAA + [JCuǂݍ܂Ă܂B + + Arguments: archive: NNSA[JCu\̂ւ̃|C^B + pAllocator: A[JCu[hɗpAP[^ւ̃|C^B + + Returns: ȂB + *---------------------------------------------------------------------------*/ +void +CMN_RemoveArchive(NNSFndArchive* archive, NNSFndAllocator* pAllocator) +{ + SDK_NULL_ASSERT(archive); + SDK_NULL_ASSERT(pAllocator); + + (void)NNS_FndUnmountArchive(archive); + NNS_FndFreeToAllocator(pAllocator, archive); +} + diff --git a/build/libraries_sysmenu/sysmenu/ARM9/src/crt1.c b/build/libraries_sysmenu/sysmenu/ARM9/src/crt1.c new file mode 100644 index 0000000..c5d8408 --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/src/crt1.c @@ -0,0 +1,559 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: crt1.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include // SYSM changed. + +#define SDK_NOCOMPRESS // SYSM changed. + + +extern void NitroMain( void ); +extern void OS_IrqHandler( void ); +static void do_autoload( void ); +static void init_cp15( void ); +void _start( void ); +extern void* const _start_ModuleParams[]; +void _start_AutoloadDoneCallback( void* argv[] ); + +extern void __call_static_initializers( void ); +extern void _fp_init( void ); + +// from LCF +extern u32 SDK_IRQ_STACKSIZE[]; +extern void SDK_AUTOLOAD_START( void ); // autoload data will start from here +extern void SDK_AUTOLOAD_LIST( void ); // start pointer to autoload information +extern void SDK_AUTOLOAD_LIST_END( void ); // end pointer to autoload information +extern void SDK_STATIC_BSS_START( void ); // static bss start address +extern void SDK_STATIC_BSS_END( void ); // static bss end address + + +/*---------------------------------------------------------------------------* + Name: _start + + Description: Start up + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +#define INITi_HW_DTCM SDK_AUTOLOAD_DTCM_START + +__declspec ( weak ) asm void _start( void ) +{ + //---- set IME = 0 + // ( use that LSB of HW_REG_BASE equal to 0 ) + mov r12, #HW_REG_BASE + str r12, [r12, #REG_IME_OFFSET] + + //---- initialize cp15 + bl init_cp15 + + //---- initialize stack pointer + // SVC mode + mov r0, #HW_PSR_SVC_MODE + msr cpsr_c, r0 + ldr r0, =INITi_HW_DTCM + add r0, r0, #0x3fc0 + mov sp, r0 + + // IRQ mode + mov r0, #HW_PSR_IRQ_MODE + msr cpsr_c, r0 + ldr r0, =INITi_HW_DTCM + add r0, r0, #0x3fc0 + sub r0, r0, #HW_SVC_STACK_SIZE + mov sp, r0 + + // System mode + ldr r1, =SDK_IRQ_STACKSIZE + sub r1, r0, r1 + mov r0, #HW_PSR_SYS_MODE + msr cpsr_csfx, r0 + sub sp, r1, #4 // 4byte for stack check code + + //---- load autoload block and initialize bss +#ifndef SDK_NOCOMPRESS + ldr r1, =_start_ModuleParams + ldr r0, [r1, #20] // r0 = bottom of compressed data + bl MIi_UncompressBackward +#endif + bl do_autoload + + //---- clear memory + // DTCM (16KB) + mov r0, #0 + ldr r1, =INITi_HW_DTCM + mov r2, #HW_DTCM_SIZE + bl MIi_CpuClear32 + +/* // BG/OBJ palette (1KB) // SYSM changed. + mov r0, #0 + ldr r1, =HW_PLTT + mov r2, #HW_PLTT_SIZE + bl MIi_CpuClear32 + + // OAM (1KB) + mov r0, #0x0200 + ldr r1, =HW_OAM + mov r2, #HW_OAM_SIZE + bl MIi_CpuClear32 +*/ + //---- set interrupt vector + ldr r1, =INITi_HW_DTCM + add r1, r1, #0x3fc0 + add r1, r1, #HW_DTCM_SYSRV_OFS_INTR_VECTOR + ldr r0, =OS_IrqHandler + str r0, [r1, #0] + +#ifndef SDK_NOINIT + //---- for C++ + bl _fp_init + bl NitroStartUp + bl __call_static_initializers +#endif + //---- start (to 16bit code) + ldr r1, =NitroMain +// ldr lr, =HW_RESET_VECTOR + ldr lr, =RETURN_FROM_MAIN_ARM9_FUNCP // SYSM changed. + + bx r1 +} + +/*---------------------------------------------------------------------------* + Name: _start_ModuleParams + + Description: autoload/compress/arguments data block + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void* const _start_ModuleParams[] = +{ + (void*)SDK_AUTOLOAD_LIST, + (void*)SDK_AUTOLOAD_LIST_END, + (void*)SDK_AUTOLOAD_START, + (void*)SDK_STATIC_BSS_START, + (void*)SDK_STATIC_BSS_END, +#ifndef SDK_NOCOMPRESS + (void*)0, // CompressedStaticEnd +#endif +}; + +/*---------------------------------------------------------------------------* + Name: MIi_UncompressBackward + + Description: Uncompress special archive for module compression + + Arguments: bottom = Bottom adrs of packed archive + 1 + bottom[-12] = offset for top of compressed data + inp_top = bottom + bottom[-12] + bottom[ -8] = offset for bottom of compressed data + inp = bottom + bottom[ -8] + bottom[ -4] = offset for bottom of original data + outp = bottom + bottom[ -4] + + typedef struct + { + int bufferTop; + int compressBottom; + int originalBottom; + } CompFooter; + + Returns: None. + *---------------------------------------------------------------------------*/ +asm void MIi_UncompressBackward( register void* bottom ) +{ +#define data r0 +#define inp_top r1 +#define outp r2 +#define inp r3 +#define outp_save r4 +#define flag r5 +#define count8 r6 +#define index r7 +#define len r12 + cmp bottom, #0 + beq @exit + stmfd sp!, {r4-r7} + ldmdb bottom, {r1-r2} + add outp, bottom, outp + sub inp, bottom, inp_top, LSR #24 + bic inp_top, inp_top, #0xff000000 + sub inp_top, bottom, inp_top + mov outp_save, outp +@loop: + cmp inp, inp_top // exit if inp==inp_top + ble @end_loop + ldrb flag, [inp, #-1]! // r4 = compress_flag = *--inp + mov count8, #8 +@loop8: + subs count8, count8, #1 + blt @loop + tst flag, #0x80 + bne @blockcopy +@bytecopy: + ldrb data, [inp, #-1]! +#ifdef SDK_TEG + sub outp, outp, #1 + swpb data, data, [outp] +#else + strb data, [outp, #-1]! // Copy 1 byte +#endif + b @joinhere +@blockcopy: + ldrb len, [inp, #-1]! + ldrb index, [inp, #-1]! + orr index, index, len, LSL #8 + bic index, index, #0xf000 + add index, index, #0x0002 + add len, len, #0x0020 +@patterncopy: + ldrb data, [outp, index] +#ifdef SDK_TEG + sub outp, outp, #1 + swpb data, data, [outp] +#else + strb data, [outp, #-1]! +#endif + subs len, len, #0x0010 + bge @patterncopy + +@joinhere: + cmp inp, inp_top + mov flag, flag, LSL #1 + bgt @loop8 +@end_loop: + + // DC_FlushRange & IC_InvalidateRange + bic inp, inp_top, #HW_CACHE_LINE_SIZE - 1 +@cacheflush: + mcr p15, 0, inp, c7, c5, 1 // ICache + mcr p15, 0, inp, c7, c14, 1 // DCache + add inp, inp, #HW_CACHE_LINE_SIZE + cmp inp, outp_save + blt @cacheflush + + ldmfd sp!, {r4-r7} +@exit bx lr +} + + +/*---------------------------------------------------------------------------* + Name: do_autoload + + Description: put autoload data block according to autoload information, + and clear static bss by filling with 0. + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +static asm void do_autoload( void ) +{ +#define ptable r0 +#define infop r1 +#define infop_end r2 +#define src r3 +#define dest r4 +#define dest_size r5 +#define dest_end r6 +#define tmp r7 + + ldr ptable, =_start_ModuleParams + ldr infop, [ptable, #0] // r1 = start pointer to autoload_info + ldr infop_end, [ptable, #4] // r2 = end pointer to autoload_info + ldr src, [ptable, #8] // r3 = autoload block + +@2: + cmp infop, infop_end // reach to end? + beq @fill_bss + + ldr dest, [infop], #4 // dest + ldr dest_size, [infop], #4 // size + add dest_end, dest, dest_size // dest_end +@1: + cmp dest, dest_end + ldrmi tmp, [src], #4 // [dest++] <- [src++] + strmi tmp, [dest], #4 + bmi @1 + + //---- fill bss with 0 + ldr dest_size, [infop], #4 // size + add dest_end, dest, dest_size // bss end + mov tmp, #0 +@4: + cmp dest, dest_end + strcc tmp, [dest], #4 + bcc @4 + + beq @2 + + //---- fill static static bss with 0 +@fill_bss: + ldr dest, [ptable, #12] // BSS segment start + ldr dest_end, [ptable, #16] // BSS segment end + mov tmp, #0 +@3: + cmp dest, dest_end + strcc tmp, [dest], #4 + bcc @3 + + // r0 = _start_ModuleParams + b _start_AutoloadDoneCallback // Jump into the callback +} + +/*---------------------------------------------------------------------------* + Name: _start_AutoloadDoneCallback + + Description: hook for end of autoload (This is dummy target for DEBUGGER) + + Arguments: argv: pointer for autoload parameters + argv[0] = SDK_AUTOLOAD_LIST + argv[1] = SDK_AUTOLOAD_LIST_END + argv[2] = SDK_AUTOLOAD_START + argv[3] = SDK_STATIC_BSS_START + argv[4] = SDK_STATIC_BSS_END + + Returns: None. + *---------------------------------------------------------------------------*/ +__declspec ( weak ) asm void _start_AutoloadDoneCallback( void* argv[] ) +{ + bx lr +} + +//----------------------------------------------------------------------- +// VXeRvZbT +//----------------------------------------------------------------------- +static asm void init_cp15(void) +{ + // veNVjbg/LbV/TCM fBZ[u + + mrc p15, 0, r0, c1, c0, 0 + ldr r1, =HW_C1_ICACHE_ENABLE | HW_C1_DCACHE_ENABLE \ + | HW_C1_ITCM_ENABLE | HW_C1_DTCM_ENABLE \ + | HW_C1_ITCM_LOAD_MODE | HW_C1_DTCM_LOAD_MODE \ + | HW_C1_LD_INTERWORK_DISABLE \ + | HW_C1_PROTECT_UNIT_ENABLE + bic r0, r0, r1 + mcr p15, 0, r0, c1, c0, 0 + + // LbV + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 // ߃LbV + mcr p15, 0, r0, c7, c6, 0 // f[^LbV + + // Cgobt@ GveB҂ + mcr p15, 0, r0, c7, c10, 4 + +/* +; Region G: BACK_GROUND: Base = 0x0, Size = 4GB, I:NC NB / D:NC NB, I:NA / D:NA +; Region 0: IO_VRAM: Base = 0x04000000, Size = 64MB, I:NC NB / D:NC NB, I:RW / D:RW +; Region 1Rel: MAIN_MEM: Base = 0x02000000, Size = 4MB, I:Cach Buf / D:Cach Buf, I:RW / D:RW +; Region 1Dbg: MAIN_MEM: Base = 0x02000000, Size = 8MB, I:Cach Buf / D:Cach Buf, I:RW / D:RW +; Region 2Rel: SOUND_DATA: Base = 0x02380000, Size = 512KB, I:NC NB / D:NC NB, I:NA / D:NA +; Region 2D4M: SOUND_DATA: Base = 0x02300000, Size = 1MB, I:NC NB / D:NC NB, I:NA / D:NA +; Region 2D8M: SOUND_DATA: Base = 0x02600000, Size = 2MB, I:NC NB / D:NC NB, I:NA / D:NA +; Region 3: CARTRIDGE: Base = 0x08000000, Size = 128MB, I:NC NB / D:NC NB, I:NA / D:RW +; Region 4: DTCM: Base = SOUND_DATA, Size = 16KB, I:NC NB / D:NC NB, I:NA / D:RW +; Region 5: ITCM: Base = 0x01000000, Size = 16MB, I:NC NB / D:NC NB, I:RW / D:RW + +; Region 6: BIOS: Base = 0xffff0000, Size = 32KB, I:Cach NB / D:Cach NB, I:RO / D:RO +; Region 7: SHARE_WORK: Base = 0x027ff000, Size = 4KB, I:NC NB / D:NC NB, I:NA / D:RW +;(Region 7: DBG_RESERVE: Base = 0x02700000, Size = 1MB, I:NC NB / D:NC NB, I:RW / D:RW) +*/ +#define SET_PROTECTION_A( id, adr, siz ) ldr r0, =(adr|HW_C6_PR_##siz|HW_C6_PR_ENABLE) +#define SET_PROTECTION_B( id, adr, siz ) mcr p15, 0, r0, c6, id, 0 +#define REGION_BIT(a,b,c,d,e,f,g,h) (((a)<<0)|((b)<<1)|((c)<<2)|((d)<<3)|((e)<<4)|((f)<<5)|((g)<<6)|((h)<<7)) +#define REGION_ACC(a,b,c,d,e,f,g,h) (((a)<<0)|((b)<<4)|((c)<<8)|((d)<<12)|((e)<<16)|((f)<<20)|((g)<<24)|((h)<<28)) +#define NA 0 +#define RW 1 +#define RO 5 + + + // + // [W + // + //---- I/O WX^ & VRAM + SET_PROTECTION_A( c0, HW_IOREG, 64MB ) + SET_PROTECTION_B( c0, HW_IOREG, 64MB ) + + //---- C + SET_PROTECTION_A( c1, HW_MAIN_MEM_MAIN, 4MB ) + SET_PROTECTION_B( c1, HW_MAIN_MEM_MAIN, 4MB ) + +/* //---- TEhf[^̈ // SYSM changed. +#if HW_MAIN_MEM_SUB_SIZE+HW_MAIN_MEM_SHARED_SIZE == 0x1000 + SET_PROTECTION_A( c2, HW_MAIN_MEM_SUB, 4KB ) + SET_PROTECTION_B( c2, HW_MAIN_MEM_SUB, 4KB ) +#elif HW_MAIN_MEM_SUB_SIZE+HW_MAIN_MEM_SHARED_SIZE == 0x2000 + SET_PROTECTION_A( c2, HW_MAIN_MEM_SUB, 8KB ) + SET_PROTECTION_B( c2, HW_MAIN_MEM_SUB, 8KB ) +#elif HW_MAIN_MEM_SUB_SIZE+HW_MAIN_MEM_SHARED_SIZE == 0x4000 + SET_PROTECTION_A( c2, HW_MAIN_MEM_SUB, 16KB ) + SET_PROTECTION_B( c2, HW_MAIN_MEM_SUB, 16KB ) +#elif HW_MAIN_MEM_SUB_SIZE+HW_MAIN_MEM_SHARED_SIZE == 0x8000 + SET_PROTECTION_A( c2, HW_MAIN_MEM_SUB, 32KB ) + SET_PROTECTION_B( c2, HW_MAIN_MEM_SUB, 32KB ) +#elif HW_MAIN_MEM_SUB_SIZE+HW_MAIN_MEM_SHARED_SIZE == 0x10000 + SET_PROTECTION_A( c2, HW_MAIN_MEM_SUB, 64KB ) + SET_PROTECTION_B( c2, HW_MAIN_MEM_SUB, 64KB ) +#elif HW_MAIN_MEM_SUB_SIZE+HW_MAIN_MEM_SHARED_SIZE == 0x20000 + SET_PROTECTION_A( c2, HW_MAIN_MEM_SUB, 128KB ) + SET_PROTECTION_B( c2, HW_MAIN_MEM_SUB, 128KB ) +#elif HW_MAIN_MEM_SUB_SIZE+HW_MAIN_MEM_SHARED_SIZE == 0x40000 + SET_PROTECTION_A( c2, HW_MAIN_MEM_SUB, 256KB ) + SET_PROTECTION_B( c2, HW_MAIN_MEM_SUB, 256KB ) +#elif HW_MAIN_MEM_SUB_SIZE+HW_MAIN_MEM_SHARED_SIZE == 0x80000 + SET_PROTECTION_A( c2, HW_MAIN_MEM_SUB, 512KB ) + SET_PROTECTION_B( c2, HW_MAIN_MEM_SUB, 512KB ) +#elif HW_MAIN_MEM_SUB_SIZE+HW_MAIN_MEM_SHARED_SIZE == 0x100000 + SET_PROTECTION_A( c2, HW_MAIN_MEM_SUB, 1MB ) + SET_PROTECTION_B( c2, HW_MAIN_MEM_SUB, 1MB ) +#elif HW_MAIN_MEM_SUB_SIZE+HW_MAIN_MEM_SHARED_SIZE == 0x200000 + SET_PROTECTION_A( c2, HW_MAIN_MEM_SUB, 2MB ) + SET_PROTECTION_B( c2, HW_MAIN_MEM_SUB, 2MB ) +#else +#pragma message(ERROR: Size unmatch HW_MAIN_MEM_SUB_SIZE) +#endif +*/ + //---- J[gbW̗͑pr + // CPU [N RAM + SET_PROTECTION_A( c3, HW_CTRDG_ROM, 128MB ) + SET_PROTECTION_B( c3, HW_CTRDG_ROM, 128MB ) + + //---- f[^ TCM + // + CPU [N RAM ̏ꍇ +//#if (HW_DTCM & 0x3FFF) != 0 +//#pragma message(ERROR: HW_DTCM need to be aligned 16KB!) +//#endif + +// SET_PROTECTION_A( c4, HW_DTCM, 16KB ) + ldr r0, =SDK_AUTOLOAD_DTCM_START + orr r0, r0, #HW_C6_PR_16KB + orr r0, r0, #HW_C6_PR_ENABLE + SET_PROTECTION_B( c4, HW_DTCM, 16KB ) + + //---- TCM + // f[^ TCM D悪AC̈܂ł̃C[W + SET_PROTECTION_A( c5, HW_ITCM_IMAGE, 16MB ) + SET_PROTECTION_B( c5, HW_ITCM_IMAGE, 16MB ) + + //---- BIOS + SET_PROTECTION_A( c6, HW_BIOS, 32KB ) + SET_PROTECTION_B( c6, HW_BIOS, 32KB ) + + //---- SHARED CPU ԒʐM[N̈ + SET_PROTECTION_A( c7, HW_MAIN_MEM_SHARED, 4KB ) + SET_PROTECTION_B( c7, HW_MAIN_MEM_SHARED, 4KB ) + +#if HW_MAIN_MEM_SHARED_SIZE != 0x1000 +#pragma message(ERROR: Size unmatch HW_MAIN_MEM_SHARED_SIZE) +#endif + + // + // ߂sbl ݒ + // + mov r0, #HW_C9_TCMR_32MB + mcr p15, 0, r0, c9, c1, 1 + + // + // f[^sbl ݒ + // + ldr r0, =INITi_HW_DTCM + orr r0, r0, #HW_C9_TCMR_16KB + mcr p15, 0, r0, c9, c1, 0 + + // + // ߃LbV Cl[u ([Wݒ) + // 1: MAIN_MEM + // 6: BIOS + // + mov r0, #REGION_BIT(0,1,0,0,0,0,1,0) + mcr p15, 0, r0, c2, c0, 1 + + // + // f[^LbV Cl[u ([Wݒ) + // 1: MAIN_MEM + // 6: BIOS + // + mov r0, #REGION_BIT(0,1,0,0,0,0,1,0) + mcr p15, 0, r0, c2, c0, 0 + + // + // Cgobt@ Cl[u([Wݒ) + // 1: MAIN_MEM + // + mov r0, #REGION_BIT(0,1,0,0,0,0,0,0) + mcr p15, 0, r0, c3, c0, 0 + + // + // ߃ANZX ([Wݒ) + // IO_VRAM : RW + // MAIN_MEM_MAIN : RW + // MAIN_MEM_SUB : NA + // CTRDG : NA + // DTCM : NA + // ITCM : RW + // BIOS : RO + // SHARED : NA + // + ldr r0, =REGION_ACC(RW,RW,NA,NA,NA,RW,RO,NA) + mcr p15, 0, r0, c5, c0, 3 + + // + // f[^ANZXi[Wݒj + // IO_VRAM : RW + // MAIN_MEM_MAIN : RW + // MAIN_MEM_SUB : NA + // CTRDG : RW + // DTCM : RW + // ITCM : RW + // BIOS : RO + // SHARED : RW + // + ldr r0, =REGION_ACC(RW,RW,NA,RW,RW,RW,RO,RW) + mcr p15, 0, r0, c5, c0, 2 + + // + // VXeRvZbT }X^[ݒ + // + mrc p15, 0, r0, c1, c0, 0 + ldr r1,=HW_C1_ICACHE_ENABLE | HW_C1_DCACHE_ENABLE | HW_C1_CACHE_ROUND_ROBIN \ + | HW_C1_ITCM_ENABLE | HW_C1_DTCM_ENABLE \ + | HW_C1_SB1_BITSET | HW_C1_EXCEPT_VEC_UPPER \ + | HW_C1_PROTECT_UNIT_ENABLE + orr r0, r0, r1 + mcr p15, 0, r0, c1, c0, 0 + + bx lr +} + + +/*---------------------------------------------------------------------------* + Name: NitroStartUp + + Description: hook for user start up + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +__declspec ( weak ) void NitroStartUp( void ) +{ +} diff --git a/build/libraries_sysmenu/sysmenu/ARM9/src/gameBoot.c b/build/libraries_sysmenu/sysmenu/ARM9/src/gameBoot.c new file mode 100644 index 0000000..558b328 --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/src/gameBoot.c @@ -0,0 +1,247 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: gameBoot.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include + +// define data------------------------------------------------------- +#define C1_DTCM_ENABLE 0x00010000 // f[^sbl Cl[u +#define C1_EXCEPT_VEC_UPPER 0x00002000 // OxN^ ʃAhXiɐݒ肵ĉj +#define C1_SB1_BITSET 0x00000078 // WX^PpPŒrbgiA{[gfADATA32\VOiAPROG32\VOiACgobt@Cl[uj + +#define INITi_HW_DTCM SDK_AUTOLOAD_DTCM_START + +// extern data------------------------------------------------------- + +// from LCF +extern u32 SDK_IRQ_STACKSIZE[]; + +// function's prototype---------------------------------------------- +void ReturnFromMain(void); +void ResetCP15(void); +void ClearBankregAndStack(void); +void CpuClear32Byte(void); +void BootFuncEnd(void); + +// global variables-------------------------------------------------- + +// static variables-------------------------------------------------- + +// const data-------------------------------------------------------- + + +#include // ̃\[X̓ftHgłARMŃRpCB + +//----------------------------------------------------------------------- +// C[`̃^[ +//----------------------------------------------------------------------- + +/* + ReturnFromMainRam̌ɃRs[@AReturnFromMainAhXA +@@@(BootFuncEnd - ReturnFromMain)TCYRs[ƂĂ邪A +@@@̕@ƁARpC̍œKdlŊ֐тςĂ܂ɂȂB +@@@ɂ@͂ȂH +*/ + + +asm void ReturnFromMain(void) +{ + //--------------------------------------- + // f[^LbVSĖɁBiDC_InvalidateAll𔲂oĎj + //--------------------------------------- + mov r0, #0 + mcr p15, 0, r0, c7, c6, 0 + + //--------------------------------------- + // ARM7Ƃ̓Ƃisubp_state2ɂȂ̂҂āAmainp_state2ɂBj + //--------------------------------------- + ldr r1, =REG_SUBPINTF_ADDR +@0 ldrh r0, [r1] + and r0, r0, #0x000f + cmp r0, #0x0002 + bne @0 + mov r0, #0x0200 + strh r0, [r1] + + //--------------------------------------- + // ISfobKtO̊i[ + //--------------------------------------- +#ifdef __IS_DEBUGGER_BUILD + ldr r3, =HW_MAIN_MEM_EX_END + sub r0, r3, #0x400 + ldrh r11, [r0, #0x14] // r11 = GetMovedInfoFromIPL1Addr()->isOnDebugger +#endif + //--------------------------------------- + // ARM7Ƃ̓Ƃisubp_state1ɂȂ̂҂āAmainp_state1ɂBj + //--------------------------------------- + ldr r1, =REG_SUBPINTF_ADDR +@1 ldrh r0, [r1] + and r0, r0, #0x000f + cmp r0, #0x0001 + bne @1 + mov r0, #0x0100 + strh r0, [r1] + + //--------------------------------------- + // oNWX^X^bNNA + //--------------------------------------- + bl ClearBankregAndStack + + //--------------------------------------- + // veNVjbg̉ + //--------------------------------------- + bl ResetCP15 + + //--------------------------------------- + // ARM7Ƃ̍ŏIƂ(subp_state0ɂȂ̂҂āAmainp_state0ɂj + //--------------------------------------- + ldr r1, =REG_SUBPINTF_ADDR +@2 ldrh r0, [r1] + and r0, r0, #0x000f + cmp r0, #0x0001 + beq @2 + ldr r3, =REG_VCOUNT_ADDR // VJE^SIPL2o[Wœl(=0)ŃAvɈn悤ɂB +@3 ldrh r0, [r3] + cmp r0, #0 + bne @3 +// mov r0, #0 // R0ɓǂVJEgl"0"Ȃ̂ŁA͂Ȃ + strh r0, [r1] + + //--------------------------------------- + // R11̒lƂɃu[gAhX擾 + //--------------------------------------- + ldr r3, =HW_MAIN_MEM_EX_END // Q[EGg|Cg l + ldr r12, [r3, #-(0x200 - 0x24)] // rmhp->arm9->entryAddr + mov lr, r12 + +#ifdef __IS_DEBUGGER_BUILD + cmp r11, #1 // if (!GetMovedInfoFromIPL1Addr()->isOnDebugger) + ldreq r12, [r3, #-(0x200 - 0x168)] // fobKEGg|Cg l +#endif + + //--------------------------------------- + // ėpWX^NA + //--------------------------------------- + ldr r11, =INITi_HW_DTCM // NADTCMf[^ǂݏoāAėpWX^NAB + ldmia r11, {r0-r10} + mov r11, #0 + + //--------------------------------------- + // Q[u[g + //--------------------------------------- + bx r12 +} + + +//----------------------------------------------------------------------- +// VXeRvZbT Zbg +//----------------------------------------------------------------------- +asm void ResetCP15(void) +{ + // veNVjbgLbVITCMBDTCM͗LiX^bNNA邽߁j + ldr r0, = C1_DTCM_ENABLE | C1_EXCEPT_VEC_UPPER | C1_SB1_BITSET + mcr p15, 0, r0, c1, c0, 0 + + // ITCM̊蓖Ă + mov r0, #0 + mcr p15, 0, r0, c6, c5, 0 + + // DTCM̊蓖Ă +// mov r0,#0 +// mcr p15, 0, r0, c9, c1, 0 + + // LbV + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 // ߃LbV + mcr p15, 0, r0, c7, c6, 0 // f[^LbV + + // Cgobt@ GveB҂ + mcr p15, 0, r0, c7, c10, 4 + + bx lr +} + + +//----------------------------------------------------------------------- +// oNWX^ Zbg X^bN̈ NA +//----------------------------------------------------------------------- +asm void ClearBankregAndStack(void) +{ + mov r12, lr + +#ifndef IPL2_ONLYMULTIBOOT + mov r0, #0xc0 | HW_PSR_SVC_MODE // SVC[h֐؂芷 & IRQ/FIQs + msr cpsr_cxsf, r0 + ldr r0, =INITi_HW_DTCM + add r0, r0, #0x3fc0 + mov sp, r0 // SP ̃Zbg + mov lr, #0 + msr spsr_csxf, lr + + mov r0, #0xc0 | HW_PSR_IRQ_MODE // IRQ[h֐؂芷 & IRQ/FIQs + msr cpsr_cxsf, r0 + ldr r0, =INITi_HW_DTCM + add r0, r0, #0x3fc0 + sub r0, r0, #HW_SVC_STACK_SIZE + mov sp, r0 // SP ̃Zbg + mov lr, #0 + msr spsr_cxsf, lr + + ldr r1, =SDK_IRQ_STACKSIZE + sub r1, r0, r1 + mov r0, #0xc0 | HW_PSR_SYS_MODE // VXe[h֐؂芷 & IRQ/FIQs + msr cpsr_cxsf, r0 + sub sp, r1, #4 // SP ̃Zbg & 4byte for stack check code +#endif // IPL2_ONLYMULTIBOOT + + ldr r0, =HW_ITCM // ITCM̃NA + mov r1, #HW_ITCM_SIZE + bl CpuClear32Byte + + ldr r0, =INITi_HW_DTCM // X^bN܂߂DTCM̃NA + mov r1, #HW_DTCM_SIZE + bl CpuClear32Byte + + bx r12 +} + + +// 32bytePʂ̃NA r0 dstp,r1 byteSize +asm void CpuClear32Byte(void) +{ + add r2, r0, r1 // IAhX̎Zo + mov r1, r1, lsr #5 // TCY32byteP + mov r3, #0 + mov r4, r3 + mov r5, r3 + mov r6, r3 + mov r7, r3 + mov r8, r3 + mov r9, r3 + mov r10, r3 +@0 cmp r0, r2 // NAIH + stmltia r0!, {r3-r10} + blt @0 + bx lr +} + + +void BootFuncEnd(void) +{ +} +#include // ܂ŁB + diff --git a/build/libraries_sysmenu/sysmenu/ARM9/src/ninLogoFunc.c b/build/libraries_sysmenu/sysmenu/ARM9/src/ninLogoFunc.c new file mode 100644 index 0000000..cb4387a --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/src/ninLogoFunc.c @@ -0,0 +1,168 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: ninLogoFunc.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include + +// define data----------------------------------------------------------- + +// extern data----------------------------------------------------------- + +// function's prototype-------------------------------------------------- +static void UnCompNintendoLogo2(u16 *NintendoLogoDatap, u16 *dstp, u32 *temp); +static void SVC_DiffUnFilter16_16_2(u16 *srcp,u16 *dstp); +static s32 MEMBm_InitFunc(const u8 *devicep, void *ramp, const void *paramp); +static s32 MEMBm_TerminateFunc(const u8 *devicep); +static u8 MEMBm_ByteStreamFunc(const u8 *devicep); +static u32 MEMBm_WordStreamFunc(const u8 *devicep); + + +// global variable------------------------------------------------------- + +// static variable------------------------------------------------------- +static MIUnpackBitsParam Nin_UnPackBitsParam2 = { (8 * 8 / 2) * ( 7 * 2 ), 1, 4, 0, 0 }; + +// const data------------------------------------------------------------ +static const u8 Nin_Char_Diff_Huff_Table2[]={ + 0x24,0xd4,0x00,0x00, + 0x0f,0x40,0x00,0x00,0x00,0x01,0x81,0x82,0x82,0x83,0x0f,0x83,0x0c,0xc3,0x03,0x83, + 0x01,0x83,0x04,0xc3,0x08,0x0e,0x02,0xc2,0x0d,0xc2,0x07,0x0b,0x06,0x0a,0x05,0x09, +}; + + +const MIReadStreamCallbacks memb_ifp2={ + MEMBm_InitFunc, + MEMBm_TerminateFunc, + MEMBm_ByteStreamFunc, + NULL, + MEMBm_WordStreamFunc, +}; + + +// function's description-------------------------------------------- + +// NintendoSf[^̓WJ[`iOBJ2D}bv[hœWJj +// tempBuffpɂ́A0x700byteKvłB +void SYSM_LoadNintendoLogo2D( u16 *ninLogoDatap, u16 *dstp, u16 color, u32 *tempBuffp ) +{ + u32 work[ 0x100 / sizeof(u32) ]; + + Nin_UnPackBitsParam2.destOffset = color - 1; + UnCompNintendoLogo2( ninLogoDatap, (u16 *)tempBuffp, work ); + MI_CpuCopyFast( (u16 *)( (u32)tempBuffp + 0 ), dstp + 0x0000 / sizeof(u16), 0x1a0 ); + MI_CpuCopyFast( (u16 *)( (u32)tempBuffp + 0x1a0), dstp + 0x0400 / sizeof(u16), 0x1a0 ); +} + + +void SYSM_LoadNintendoLogo1D( u16 *ninLogoDatap, u16 *dstp, u16 color, u32 *tempBuffp ) +{ + u32 work[ 0x100 / sizeof(u32) ]; + + Nin_UnPackBitsParam2.destOffset = color - 1; + UnCompNintendoLogo2( ninLogoDatap, (u16 *)tempBuffp, work ); + MI_CpuCopyFast( (u16 *)tempBuffp, dstp, 0x340 ); +} + +/* UnCompNintendoLogo2[N + + zu恄 dstp(0x700) temp(0x100) + + NintendoS{wb_ 0x0c0 + nt}WJobt@ 0x200 + nt}WJ̃obt@ 0x0d0 + diff̃f[^ 0x0d0 + UnpackBits̃f[^ 0x700 + +*/ + +//@NintendoSWJ[`@(r0=Skf[^ r1=WJAhX) +#include +static asm void UnCompNintendoLogo2(u16 *NintendoLogoDatap, u16 *dstp, u32 *temp) +{ + push {r0-r2,r4, lr} + + ldr r0, =Nin_Char_Diff_Huff_Table2 + mov r1, r2 // r1 <- temp + mov r4, r1 // r4 <- temp + mov r2, #36 + bl MIi_CpuCopy16 // NintendoS̈ke[û݂Rs[Ă + + ldr r0, [sp, #0] // r0 <- NintendoLogoDatap + mov r2, #36 + add r1, r4, r2 // r1 <- temp + 36 + mov r2, #NINTENDO_LOGO_LENGTH + bl MIi_CpuCopy16 // NintendoLogoDatapNintendoSf[^{̂Rs[Ă + + mov r0, r4 // r0 <- temp + ldr r1, [sp, #4] // r1 <- dstp + mov r2, #1 + lsl r2, r2, #8 + add r2, r2, r1 // r2 <- dstp + 0x100 + ldr r3, =memb_ifp2 // r3 <- memb_ifp2 + bl SVC_UncompressHuffmanFromDevice // nt}WJ + + ldr r0, [sp, #4] + ldr r2, =0x0000d082 + str r2, [r0,#0] + + mov r1, r4 // temp + bl SVC_DiffUnFilter16_16_2 // DiffWJ + + mov r0, r4 // temp + ldr r1, [sp, #4] // dstp + ldr r2, =Nin_UnPackBitsParam2 + bl SVC_UnpackBits // rbgWJ + + pop {r0-r2,r4, pc} +} + + +// tB^WJVXeR[i16Bit16Bitj (r0=Srcp, r1=Destp) +static asm void SVC_DiffUnFilter16_16_2(u16 *srcp,u16 *dstp) +{ + swi 24 + bx lr +} +#include + + +// ============================================================================ +// oCgANZX”\pANZX[`Q +// ============================================================================ +static s32 MEMBm_InitFunc(const u8 *devicep, void *ramp, const void *paramp) +{ + #pragma unused(ramp) + if(paramp) return (s32)MEMBm_WordStreamFunc(devicep); + else return 0; +} + +static s32 MEMBm_TerminateFunc(const u8 *devicep) +{ + #pragma unused(devicep) + return 0; +} + +static u8 MEMBm_ByteStreamFunc(const u8 *devicep) +{ + return *devicep; +} + +static u32 MEMBm_WordStreamFunc(const u8 *devicep) +{ + return *(u32 *)devicep; +} diff --git a/build/libraries_sysmenu/sysmenu/ARM9/src/nitroSettingsEx.c b/build/libraries_sysmenu/sysmenu/ARM9/src/nitroSettingsEx.c new file mode 100644 index 0000000..6cfbd2b --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/src/nitroSettingsEx.c @@ -0,0 +1,505 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: nitroSettingsEx.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include "spi.h" + +// define data---------------------------------------------------------- + +#define NCD_EX_FORCE_ENABLE // ̃XCb``ƁASYSMo[WɊւ炸INitroConfigDataExLɂȂB + // @ł́ÃtOON,OFFɊ֌WȂ퓮삷邪AAvrhfobK⑼@œ삳ۂɁAONłȂƃ_B + // ǂݍ܂ĂȂNCDEX[hĎSĂ܂̂ŒӁB + +#define SAVE_COUNT_MAX 0x0080 // NitroConfigData.saveCount̍ől +#define SAVE_COUNT_MASK 0x007f // NitroConfigData.saveCount̒l͈̔͂}XNB(0x00-0x7fj +#define NCD_NOT_CORRECT 0x00ff // NITROݒf[^ǂݏoĂȂ or LȂ̂ȂƂB +#define NVRAM_RETRY_NUM 8 // NVRAMgC + +// NVRAMXe[^XWX^l +#define SR_WIP 0x01 // 0:READY 1:CgAC[X +#define SR_WEN 0x02 // 0:Cg֎~ 1:Cg +#define SR_EER 0x20 // 1:C[XG[iSANYOFLASĤ݁j + +#define READ_IPL2_HEADER_ADDR 0x18 // IPL2wb_̂Aǂݍ݂Kvȕ̐擪AhX +#define READ_IPL2_HEADER_SIZE 0x0a // IPL2wb_̂Aǂݍ݂KvȃTCY +#define NCD_ROM_ADDR_SHIFT 3 + +// NVRAM֘AMR}hXe[g +static enum NvramCommState{ + COMM_READY = 0, + COMM_RD, + COMM_WE, + COMM_WR, + COMM_RDSR_WE, + COMM_RDSR_WR, + COMM_SRST +}NvramCommState; + + +// IPL2wb_̈ꕔi0x18̃f[^) +typedef struct IPL2HeaderPart { + struct { + u8 timestamp[5]; // IPL2^CX^v [0]:,[1]:,[2]:,[3]:,[4]:N + u8 ipl2_type; // IPL2^Cv(nitroConfigData.hŒ`IPL2_TYPE...j + u8 rsv[2]; + } version; + + u16 ncd_rom_addr; + + u8 pad[ 0x16 ]; // LbVCɍ킹邽߂̃pfBOB{͕KvȂB +} IPL2HeaderPart; // 0x20bytes + + +// function's prototype------------------------------------------------- +static void NCD_ReadIPL2Header( void ); +static int NVRAMm_checkCorrectNCD(NCDStoreEx *ncdsp); +static BOOL NCD_CheckDataValue( NCDStoreEx *ncdsp ); +static BOOL NVRAMm_ExecuteCommand( int nv_state, u32 addr, u16 size, u8 *srcp ); +static void Callback_NVRAM(PXIFifoTag tag, u32 data, BOOL err); + +// const data----------------------------------------------------------- + +// global variables----------------------------------------------------- +NitroConfigDataEx ncdEx; + +// static variables----------------------------------------------------- +static volatile BOOL nv_cb_occurred; +static volatile u16 nv_result; +static u16 ena_ncd_num = NCD_NOT_CORRECT; +static u16 next_saveCount; +static NCDStoreEx ncds[2] ATTRIBUTE_ALIGN(32); + +static IPL2HeaderPart ipl2Header ATTRIBUTE_ALIGN(32); +static BOOL read_ipl2h = FALSE; + +// function's description----------------------------------------------- + +//---------------------------------------------------------------------- +// IPL2wb_̓ǂݏo +//---------------------------------------------------------------------- +// R|[lgł̎gp + +// IPL2wb_̓ǂݏo +static void NCD_ReadIPL2Header( void ) +{ + if( !read_ipl2h ) { + OS_TPrintf( "IPL2Header:%x\n", sizeof(IPL2HeaderPart) ); + DC_InvalidateRange( &ipl2Header, sizeof(IPL2HeaderPart) ); + while( !NVRAMm_ExecuteCommand( COMM_RD, READ_IPL2_HEADER_ADDR, READ_IPL2_HEADER_SIZE, (u8 *)&ipl2Header ) ) {} + read_ipl2h = TRUE; + } +} + +// IPL2^Cv̎擾 +u8 NCD_GetIPL2Type( void ) +{ + NCD_ReadIPL2Header(); + return ipl2Header.version.ipl2_type; +} + +// IPL2o[W̎擾 +u8 *NCD_GetIPL2Version( void ) +{ + NCD_ReadIPL2Header(); + return ipl2Header.version.timestamp; +} + +// NCDi[ROMAhX̎擾 +u32 NCD_GetNCDRomAddr( void ) +{ + NCD_ReadIPL2Header(); + return (u32)( ipl2Header.ncd_rom_addr << NCD_ROM_ADDR_SHIFT ); +} + +//---------------------------------------------------------------------- +// NITROݒf[^̃[h +//---------------------------------------------------------------------- +int NVRAMm_ReadNitroConfigData(NitroConfigData *dstp) +{ + int result = 0; + NCDStoreEx *ncdsp = &ncds[ 0 ]; + + DC_InvalidateRange( ncdsp, sizeof(NCDStoreEx) * 2 ); + + // tbVjdĂNITROݒf[^ǂݏoB + while( !NVRAMm_ExecuteCommand( COMM_RD, NCD_GetNCDRomAddr(), sizeof(NCDStoreEx), (u8 *)&ncdsp[0]) ) {} + while( !NVRAMm_ExecuteCommand( COMM_RD, NCD_GetNCDRomAddr() + SPI_NVRAM_PAGE_SIZE, sizeof(NCDStoreEx), (u8 *)&ncdsp[1]) ) {} + OS_TPrintf("NCD read addr=%08x\n", NCD_GetNCDRomAddr() ); + + // ǂݏof[^̂ǂ炪L𔻒肷B + if(NVRAMm_checkCorrectNCD(ncdsp)) { + next_saveCount = 1; + result = 1; + goto END; // Lȃf[^Ȃ΃G[IB + } + next_saveCount = (u8)((ncdsp[ena_ncd_num].saveCount + 1) & SAVE_COUNT_MASK); + + // LNITROݒf[^obt@ɓ] + if( dstp != NULL ) { + SVC_CpuCopy( (void *)&ncdsp[ ena_ncd_num ].ncd, (void *)dstp, sizeof(NitroConfigData), 16); + SVC_CpuCopy( (void *)&ncdsp[ ena_ncd_num ].ncd_ex, (void *)&ncdEx, sizeof(NitroConfigDataEx), 16); + } + +END: + return result; +} + + +//---------------------------------------------------------------------- +// NITROݒf[^̃Cg +//---------------------------------------------------------------------- +void NVRAMm_WriteNitroConfigData( NitroConfigData *srcp ) +{ + NCDStoreEx *ncdsp = &ncds[ 0 ]; + u16 size = sizeof(NCDStore); + u32 flash_addr; + int retry; + + // ܂NITROݒf[^[hĂȂ΁A[hsĕKvȏ擾B + if( ena_ncd_num == NCD_NOT_CORRECT ) { + if( NVRAMm_ReadNitroConfigData( NULL ) ) { + ena_ncd_num = 0; // Lȃf[^Ȃ"0"ɃCgB + } + } + + // NCD CRCAZ[uJEglACgAhX̎ZoB + ncdsp->ncd = *srcp; // *GetNCDWork();@łꏏB + ncdsp->ncd.version = NITRO_CONFIG_DATA_VERSION; // o[Ŵ݂̂ɐݒB + ncdsp->crc16 = SVC_GetCRC16( 0xffff, (const void *)&ncdsp->ncd, sizeof(NitroConfigData) ); + ncdsp->saveCount = next_saveCount; + next_saveCount = (u8)( ( next_saveCount + 1 ) & SAVE_COUNT_MASK ); + + // NCD_EXCRCZoB +#ifndef NCD_EX_FORCE_ENABLE + if( ( NCD_GetIPL2Type() != IPL2_TYPE_NTR_WW ) && ( NCD_GetIPL2Type() & IPL2_TYPE_NCD_EX_FLAG ) ) +#endif + { + ncdsp->ncd_ex = *GetNCDExWork(); + ncdsp->ncd_ex.version = NITRO_CONFIG_DATA_EX_VERSION; // o[Ŵ݂̂ɐݒB + ncdsp->ncd_ex.valid_language_bitmap = VALID_LANG_BITMAP; + ncdsp->crc16_ex = SVC_GetCRC16( 0xffff, (const void *)&ncdsp->ncd_ex, sizeof(NitroConfigDataEx) ); + size = sizeof(NCDStoreEx); // ݃TCYNCDStoreExɊgB + } + + // NITROݒf[^̃Cg + DC_FlushRange(ncdsp, sizeof(NCDStoreEx)); + retry = NVRAM_RETRY_NUM; + while( retry-- ) { + ena_ncd_num ^= 0x01; // gC̓xɏ݃AhX؂ւB + flash_addr = NCD_GetNCDRomAddr() + ena_ncd_num * SPI_NVRAM_PAGE_SIZE; + OS_TPrintf("NCD write addr=%08x\n", flash_addr ); + + if( NVRAMm_ExecuteCommand( COMM_WE, flash_addr, size, (u8 *)ncdsp) ) { + OS_TPrintf("NVRAM Write succeeded.\n"); + break; + } + SVC_WaitByLoop( 0x4000 ); + OS_TPrintf("NVRAM Write retry = %d.\n", NVRAM_RETRY_NUM - retry ); + } +} + + +//---------------------------------------------------------------------- +// ~[OĂNITROݒf[^̂ǂ炪L𔻒 +//---------------------------------------------------------------------- + +static int NVRAMm_checkCorrectNCD(NCDStoreEx *ncdsp) +{ + u16 i; + u16 ncd_valid = 0; + + // e~[f[^CRC & saveCount`FbN + for(i = 0; i < 2; i++) { + u16 crc; + BOOL invalid = FALSE; + + crc = SVC_GetCRC16( 0xffff, (const void *)&ncdsp[i].ncd, sizeof(NitroConfigData) ); + + if( ( ncdsp[ i ].crc16 != crc ) // CRCAsaveCountl0x80ȉŁAƒo[Wvf[^𐳓ƔfB + || ( ncdsp[ i ].ncd.version != NITRO_CONFIG_DATA_VERSION ) + || ( ncdsp[ i ].saveCount >= SAVE_COUNT_MAX ) ) { + OS_TPrintf("NCD crc error.\n"); + invalid = TRUE; + } + + // NCDExLIPL2TypeȂ΁ANCDExCRC`FbNsB +#ifndef NCD_EX_FORCE_ENABLE + if( ( NCD_GetIPL2Type() != IPL2_TYPE_NTR_WW ) && ( NCD_GetIPL2Type() & IPL2_TYPE_NCD_EX_FLAG ) ) +#endif + { + crc = SVC_GetCRC16( 0xffff, (const void *)&ncdsp[i].ncd_ex, sizeof(NitroConfigDataEx) ); + + if( ( ncdsp[ i ].crc16_ex != crc ) + || ( ncdsp[ i ].ncd_ex.version != NITRO_CONFIG_DATA_EX_VERSION ) ) { + OS_TPrintf("NCDEx crc error.\n"); + invalid = TRUE; + } + } + // NCD, NCDExCRCȂAf[^̒g`FbNB + if( !invalid ) { + if( NCD_CheckDataValue( &ncdsp[ i ] ) ) { + ncd_valid |= 0x01 << i; // f[^lłȂ`FbNB + ena_ncd_num = i; // LNCD̃CfbNX؂ւB + }else { + invalid = TRUE; + } + } + + if( ncd_valid & ( 0x01 << i ) ) { + OS_TPrintf("NCD mirror%d is valid.:saveCount = %d\n", i, ncdsp[i].saveCount); + }else { + OS_TPrintf("NCD mirror%d is invalid.\n", i); + } + } + + + if( ncd_valid == 0 ) { + return 1; + }else if( ncd_valid == 0x03 ) { + // ~[OꂽNCDƂɐȏꍇAZ[uJEgl傫LƂB + u16 saveCount = (u8)( ( ncdsp[ 0 ].saveCount + 1 ) & SAVE_COUNT_MASK ); + if( saveCount != ncdsp[ 1 ].saveCount ) { + ena_ncd_num = 0; + } + } + + OS_TPrintf("use NCD mirror%d.:saveCount = %d\n", ena_ncd_num, ncdsp[ena_ncd_num].saveCount); + + return 0; +} + + +// NITROݒf[^̒ll`FbNB // FALSE:ȂBTRUEFB +static BOOL NCD_CheckDataValue( NCDStoreEx *ncdsp ) +{ + NitroConfigData *ncdp = &ncdsp->ncd; + NitroConfigDataEx *ncdexp = &ncdsp->ncd_ex; + + //ncdp->option; + // NCDlanguage`FbN + if( ~( LANG_BITMAP_WW & VALID_LANG_BITMAP ) & ( 0x0001 << ncdp->option.language ) ) { + OS_TPrintf("NCD: invalid language : org:%02d ex:%02d bitmap:%04x\n", + ncdp->option.language, ncdexp->language, ncdexp->valid_language_bitmap ); + return FALSE; + } + // NCDExlanguage`FbNiNCDExLȂ̂́ALIPL2^Cv̂́j +#ifndef NCD_EX_FORCE_ENABLE + if( ( NCD_GetIPL2Type() != IPL2_TYPE_NTR_WW ) && ( NCD_GetIPL2Type() & IPL2_TYPE_NCD_EX_FLAG ) ) +#endif + { + if( ( ~VALID_LANG_BITMAP & ( 0x0001 << ncdexp->language ) ) + || ( ncdexp->valid_language_bitmap != VALID_LANG_BITMAP ) ) { + + OS_TPrintf("NCDEx: invalid language : org:%02d ex:%02d bitmap:%04x\n", + ncdp->option.language, ncdexp->language, ncdexp->valid_language_bitmap ); + return FALSE; + } + } + + //ncdp->owner; + // favoriteColor4bitȂ̂Ŕ͈͊O͂ȂB + // birthday + if( ncdp->option.input_birthday ) { + if( ( ncdp->owner.birthday.month > 12 ) || ( ncdp->owner.birthday.day > 31 ) ) { + OS_TPrintf("NCD: invalid birthday : %02d/%02d\n", ncdp->owner.birthday.month, ncdp->owner.birthday.day ); + return FALSE; + } + } + + // nickname + if( ncdp->option.input_nickname ) { + if( ncdp->owner.nickname.length > NCD_NICKNAME_LENGTH ) { + OS_TPrintf("NCD: invalid nickname length : %02d\n", ncdp->owner.nickname.length ); + return FALSE; + } + } + + // comment + if( ncdp->owner.comment.length > NCD_COMMENT_LENGTH ) { + OS_TPrintf("NCD: invalid comment length : %02d\n", ncdp->owner.comment.length ); + return FALSE; + } + + //ncdp->alarm; + if( ( ncdp->alarm.hour > 23 ) || ( ncdp->alarm.minute > 59 ) ) { + OS_TPrintf("NCD: invalid alarm time : %02d:%02d\n", ncdp->alarm.hour, ncdp->alarm.minute ); + return FALSE; + } + + //ncdp->tp; + // TPLu[VĺATP_CalcCalibrateParamŒl̃`FbNĂ̂ŁA`FbNȂB + + OS_TPrintf( "NCD: correct data.\n" ); + return TRUE; +} + + +//---------------------------------------------------------------------- +// NVRAMւ̃ANZX[`{ ( nv_state <- COMM_RD or COMM_WE ) +//---------------------------------------------------------------------- +static BOOL NVRAMm_ExecuteCommand( int nv_state, u32 addr, u16 size, u8 *srcp ) +{ + OSTick start; + BOOL nv_sending = FALSE; + u8 *nvram_srp = (u8 *)&ncds[1]; + + PXI_SetFifoRecvCallback( PXI_FIFO_TAG_NVRAM , Callback_NVRAM ); + + while( 1 ) { + //--------------------------------------- + // NVRAMR}h𔭍s + //--------------------------------------- + if( !nv_sending ) { + + nv_cb_occurred = FALSE; + + switch( nv_state ) { + case COMM_RD: + nv_sending = SPI_NvramReadDataBytes( addr, size, srcp ); + break; + + case COMM_WE: + nv_sending = SPI_NvramWriteEnable(); + break; + + case COMM_WR: + nv_sending = SPI_NvramPageWrite( addr, size , srcp ); + start = OS_GetTick(); + break; + + case COMM_RDSR_WE: + case COMM_RDSR_WR: + nv_sending = SPI_NvramReadStatusRegister( nvram_srp ); + break; + + case COMM_SRST: + nv_sending = SPI_NvramSoftwareReset(); + break; + } + //--------------------------------------- + // R}hsʁiR[obNj҂Čʂ + //--------------------------------------- + }else { // nv_sending == TRUE + if( nv_cb_occurred == TRUE ) { // R[obN҂B + + nv_sending = FALSE; + + if( nv_result == SPI_PXI_RESULT_SUCCESS ) { + switch( nv_state ) { + case COMM_RD: + return TRUE; + + case COMM_WE: + nv_state = COMM_RDSR_WE; + break; + + case COMM_WR: + nv_state = COMM_RDSR_WR; + break; + + case COMM_RDSR_WE: + case COMM_RDSR_WR: + + DC_InvalidateRange( nvram_srp, 1 ); + + if( nv_state == COMM_RDSR_WE ) { // CgCl[umFXe[gȂ + if( ( *nvram_srp & SR_WEN ) ) { + nv_state = COMM_WR; + }else { + OS_TPrintf("NVRAM ERR: Write Enable Invalid.\n"); + return FALSE; + } + }else { + if( ( *nvram_srp & SR_WIP ) == 0 ) { // Cg^C[XI + return TRUE; + }else { + if( ( *nvram_srp & SR_EER ) // SR_EERĂG[ + || ( OS_TicksToMilliSeconds( OS_GetTick() - start ) > 4000 ) ) { + // R}hs4bo߂G[iیj + OS_TPrintf( "NVRAM SR : %02x\n", *nvram_srp ); + nv_state = COMM_SRST; + }else { + SVC_WaitByLoop( 0x4000 ); + } + } + } + break; + + case COMM_SRST: + OS_TPrintf("NVRAM ERR: PageErase Timeout and SoftReset.\n"); + return FALSE; + } + }else { // nv_result != SPI_PXI_RESULT_SUCCESS + OS_TPrintf("NVRAM ERR: NVRAM PXI command failed.\n"); + return FALSE; + } + } + } + } +} + + +//---------------------------------------------------------------------- +// R[obN +//---------------------------------------------------------------------- +static void Callback_NVRAM( PXIFifoTag tag, u32 data, BOOL err ) +{ + #pragma unused(tag) + + u16 command = (u16)( ( ( data & SPI_PXI_DATA_MASK ) & 0x7f00 ) >> 8 ); + + nv_result = (u16)( data & 0x00ff ); + nv_cb_occurred = TRUE; // R[obNtOTRUE + + if( err ) { + OS_TPrintf("NVRAM-ARM9: Received PXI data is error.\n"); + nv_result = 0x00ff; + } + + switch(command){ // R}h\ + case SPI_PXI_COMMAND_NVRAM_READ: + OS_TPrintf("NVRAM-ARM9:ReadDataBytes"); + break; + case SPI_PXI_COMMAND_NVRAM_WREN: + OS_TPrintf("NVRAM-ARM9:WriteEnable"); + break; + case SPI_PXI_COMMAND_NVRAM_PW: + OS_TPrintf("NVRAM-ARM9:PageWrite"); + break; + case SPI_PXI_COMMAND_NVRAM_RDSR: + OS_TPrintf("NVRAM-ARM9:ReadStatusRegister"); + break; + case SPI_PXI_COMMAND_NVRAM_WRDI: + OS_TPrintf("NVRAM-ARM9:WriteDisable"); + break; + case SPI_PXI_COMMAND_NVRAM_PE: + OS_TPrintf("NVRAM-ARM9:PageErase"); + break; + case SPI_PXI_COMMAND_NVRAM_SR: + OS_TPrintf("NVRAM-ARM9:SoftwareReset"); + break; + default: + OS_TPrintf("NVRAM-ARM9:?????"); + break; + } + if( nv_result != SPI_PXI_RESULT_SUCCESS ) { + OS_TPrintf(" Error! ->%x", nv_result ); + } + OS_TPrintf("\n"); +} + diff --git a/build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_card.c b/build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_card.c new file mode 100644 index 0000000..1bc09cd --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_card.c @@ -0,0 +1,253 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: SYSM_card.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "sysmenu_card.h" + + +typedef enum { + CARD_NOT_DETECTING = 0, + CARD_DETECTING +} CARDPullStatus; + + +typedef struct SYSMCardPullWork +{ + CARDPullStatus pullStatus; + u32 cardCnt; + u16 lockID; + u16 detectPullOut; + +} SYSMCardPullWork; + + +static SYSMCardPullWork cpw; + + +// ֐ +void SYSMi_InitCardPulledOut(void); +BOOL SYSMi_IsDetectableCardPulledOut(void); +void SYSMi_StartReadCardID(void); +void SYSMi_ReadCardPage(void *romp, void *ramp, s32 size); +static void SYSMi_SetCardOp(const u32 *op); + + +//---------------------------------------------------------------------- +// J[ho +//---------------------------------------------------------------------- + +void SYSMi_InitCardPulledOut(void) +{ + cpw.lockID = (u16 )OS_GetLockID(); + cpw.cardCnt = *(vu32 *)MROMCNT_GAME_BUF; +} + + +//---------------------------------------------------------------------- +// J[ho +//---------------------------------------------------------------------- + +BOOL SYSM_IsCardPulledOut(void) +{ + if (SYSMi_IsDetectableCardPulledOut() == FALSE) return FALSE; + + switch (cpw.pullStatus) { + case CARD_NOT_DETECTING: + if (OS_TryLockCard( cpw.lockID ) == OS_LOCK_SUCCESS ) + { + SYSMi_StartReadCardID(); + cpw.pullStatus = CARD_DETECTING; + } + break; + + case CARD_DETECTING: + if (SYSMi_IsCardDataReady()) { + u32 cardID = *(vu32 *)REG_CARD_DATA; + if (cardID != GetSYSMWork()->nCardID + && SYSM_IsNITROCard()) + { + cpw.detectPullOut = TRUE; + } + + (void)OS_UnlockCard( cpw.lockID ); + cpw.pullStatus = CARD_NOT_DETECTING; + } + break; + } + + return cpw.detectPullOut; +} + + +//---------------------------------------------------------------------- +// J[hoI +//---------------------------------------------------------------------- + +void SYSM_FinalizeCardPulledOut(void) +{ + while (SYSM_IsDetectingCardPulledOut()) { + (void)SYSM_IsCardPulledOut(); + } +} + + +//---------------------------------------------------------------------- +// J[ho +//---------------------------------------------------------------------- + +BOOL SYSM_IsDetectingCardPulledOut(void) +{ + return (cpw.pullStatus == CARD_DETECTING); +} + + +//---------------------------------------------------------------------- +// J[hȍłĂ邩 +//---------------------------------------------------------------------- + +BOOL SYSMi_IsDetectableCardPulledOut(void) +{ + return (SYSM_GetBootFlag() & BFLG_LOAD_CARD_COMPLETED ) ? TRUE : FALSE; +} + + +//---------------------------------------------------------------------- +// J[hIDǂݍ݊Jn +//---------------------------------------------------------------------- + +void SYSMi_StartReadCardID(void) +{ + u32 op[2]; + + op[0] = 0; // R}hݒ + op[1] = MROMOP_G_READ_ID; + + SYSMi_SetCardOp( op ); + // Rg[ݒ + *(vu32 *)REG_CARDCNT = cpw.cardCnt + | CARD_READ_MODE | CARD_STATUS + | CARD_START | CARD_RESET_HI; +} + + +//---------------------------------------------------------------------- +// J[hIDǂݍ +//---------------------------------------------------------------------- + +u32 SYSMi_ReadCardID(void) +{ + u32 op[2]; + + op[0] = 0; // R}hݒ + op[1] = MROMOP_G_READ_ID; + + SYSMi_SetCardOp( op ); + // Rg[ݒ + *(vu32 *)REG_CARDCNT = *(vu32 *)MROMCNT_GAME_BUF + | CARD_READ_MODE | CARD_STATUS + | CARD_START | CARD_RESET_HI; + + SYSMi_WaitCardData(); + + return *(vu32 *)REG_CARD_DATA; +} + + +//---------------------------------------------------------------------- +// J[hf[^ǂݍ +//---------------------------------------------------------------------- + +void SYSM_ReadCard(void *romp, void *ramp, s32 size) +{ + s32 restSize = size; + s32 blockSize = MROM_PAGE_SIZE; + + while (restSize > 0) { // ubNǂݍ + if (restSize >= MROM_PAGE_SIZE) { size = MROM_PAGE_SIZE; + } else { size = restSize; + } + + SYSMi_ReadCardPage(romp, ramp, size); + + (u8 *)romp += size; + (u8 *)ramp += size; + restSize -= size; + } +} + + +//---------------------------------------------------------------------- +// y[Wǂݍ +//---------------------------------------------------------------------- + +void SYSMi_ReadCardPage(void *romp, void *ramp, s32 size) +{ + { u32 op[2]; + + op[0] = (u32 )romp <<24; // R}hݒ + op[1] = MROMOP_G_READ_PAGE | (u32 )romp >>8; + + SYSMi_SetCardOp( op ); + } + + // y[W[h + { void *ramEndp; + u32 cardCntTmp; + + *(vu32 *)REG_CARDCNT = *(vu32 *)MROMCNT_GAME_BUF // Rg[ݒ + | CARD_READ_MODE | CARD_1_PAGE + | CARD_START | CARD_RESET_HI; + + ramEndp = (u8 *)ramp + size; // i[IAhXZo + + do { // CPUǂݍ + cardCntTmp = *(vu32 *)REG_CARDCNT; + + if (cardCntTmp & CARD_DATA_READY) { + u32 dataTmp = *(vu32 *)REG_CARD_DATA; + + if (ramp < ramEndp) + *((vu32 *)ramp) = dataTmp; // wTCY܂Ŋi[i㑱f[^͓ǂݎ̂āj + ((vu32 *)ramp)++; + } + } while (cardCntTmp & CARD_START); + } +} + + +//---------------------------------------------------------------------- +// R}hݒ +//---------------------------------------------------------------------- + +static void SYSMi_SetCardOp(const u32 *op) +{ + int i; + + *(vu8 *)REG_CARD_MASTER_CNT = CARDMST_SEL_ROM // }X^[Cl[u + | CARDMST_ENABLE; + + for (i=0; i<2; i++) { // R}hݒ + u32 opTmp = op[1 - i]; + vu8 *opDestBasep = (vu8 *)(REG_CARD_CMD + i*4); + + opDestBasep[0] = (u8 )(opTmp >>24); + opDestBasep[1] = (u8 )(opTmp >>16); + opDestBasep[2] = (u8 )(opTmp >>8); + opDestBasep[3] = (u8 )(opTmp >>0); + } +} + diff --git a/build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_lib.c b/build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_lib.c new file mode 100644 index 0000000..8b40ee0 --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_lib.c @@ -0,0 +1,743 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: SYSM_lib.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include "sysmenu_define.h" +#include "sysmenu_card.h" +#include "spi.h" +#include "mb_child.h" + +// define data----------------------------------------------------------------- + +#define SCREEN_RED 0 +#define SCREEN_YELLOW 1 + +typedef struct BannerCheckParam { + u8 *srcp; + u32 size; +}BannerCheckParam; + +// extern data----------------------------------------------------------------- +extern void ReturnFromMain( void ); +extern void BootFuncEnd( void ); + +FS_EXTERN_OVERLAY( ipl2_data ); +FS_EXTERN_OVERLAY( bm_mainp ); + +// function's prototype------------------------------------------------------- +static void SYSMi_WaitInitARM7( void ); +static BOOL SYSMi_IsDebuggerBannerViewMode( void ); + +static BOOL SYSMi_CheckTitlePointer( TitleProperty *pBootTitle ); +void SYSM_Finalize( void ); +void SYSM_RebootLauncher( void ); +void SYSM_RebootTitle( u64 titleID ); + + + +static void INTR_SubpIRQ( void ); + +static void SYSMi_CheckCardLoadAddressAndSize( void ); +static void LoadRomRegSizeAdjust( CARDRomRegion *romRegp, u32 load_limit_lo, u32 load_limit_hi ); +static void SYSMi_ReadyBootNitroGame( void ); +static BOOL SYSMi_CheckARM7LoadNITROCard( void ); +static void SYSMi_MainpRegisterAndRamClear( BOOL isPlatformTWL ); +static void ClearMemory( int addr1, int addr2 ); + +static void SYSMi_CopyInfoFromIPL1( void ); + +static void SYSMi_ReadNTRSetting( void ); +static void SYSMi_ReadTWLSetting( void ); +static void SYSMi_VerifyNTRSetting( void ); +static BOOL SYSMi_CheckEntryAddress( void ); +static void SYSMi_WriteAdjustRTC( void ); +static BOOL SYSMi_SendMessageToARM7( u32 msg ); +static BOOL SYSMi_CheckNitroCardRightly( void ); +static int SYSMi_ExistCard( void ); +static u32 SYSMi_SelectBootType( void ); +static void SYSMi_DispInitialDebugData( void ); +static void SYSMi_DispDebugData( void ); + +static void DispSingleColorScreen( int mode ); + +static void SYSMi_ReadCardBannerFile( void ); +static void SYSMi_CheckCardCloneBoot( void ); + + +// global variable------------------------------------------------------------- +#ifdef __SYSM_DEBUG +SharedWork *swp; // fobKłIPL1SharedWork̃EHb`p +SYSM_work *pSysm; // fobKłSYSM[ÑEHb`p +NitroConfigData *ncdp; // fobKłNCf[^@̃EHb`p +#endif + +// static variable------------------------------------------------------------- +static BOOL s_isBanner = FALSE; +static BannerFile s_bannerBuf; + +// const data------------------------------------------------------------------ + +static BannerCheckParam s_bannerCheckList[ BNR_VER_MAX ] = { + { (u8 *)&s_bannerBuf.v1, sizeof( BannerFileV1 ) }, + { (u8 *)&s_bannerBuf.v2, sizeof( BannerFileV2 ) }, + { (u8 *)&s_bannerBuf.v3, sizeof( BannerFileV3 ) }, +}; + +#ifdef __DEBUG_SECURITY_CODE +static GXRgb security_detection_color[] = { GX_RGB( 31, 0, 0 ), + GX_RGB( 31, 31, 0 ), }; +#endif + +// inline functions------------------------------------------------------------ + +static inline void DBG_SetRed(u32 y_pos) +{ + *(u16 *)(HW_DB_BG_VRAM + 0xf000 + 0x20*2*y_pos) = (1<<12) | 0x100; + MI_CpuFill16(((u8 *)HW_DB_BG_VRAM + 0x20*0x100), 0x1111, 0x20); +} + +// ============================================================================ +// function's description +// ============================================================================ + +// SystemMenȕ +void SYSM_Init( void ) +{ +#ifdef __SYSM_DEBUG + pSysm = GetSYSMWork(); + ncdp = GetNCDWork(); +// SYSMi_DispInitialDebugData(); // fobO\ +#endif /* __SYSM_DEBUG */ + + TP_Init(); + RTC_Init(); + + // WRAMݒ͂H +// MI_SetMainMemoryPriority(MI_PROCESSOR_ARM7); +// MI_SetWramBank(MI_WRAM_ARM7_ALL); + + SVC_CpuClearFast(0x0000, (u16 *)GetSYSMWork(), sizeof(SYSM_work)); // SYSM[ÑNA + + // ISfobKǂ̔B@BootROM̃p[^nH + SYSMi_WaitInitARM7(); +} + + +// ARM7̏҂ +static void SYSMi_WaitInitARM7( void ) +{ +/* while( !( SYSM_GetBootFlag() & BFLG_ARM7_INIT_COMPLETED ) ) { + SVC_WaitByLoop(0x1000); // ARM7̏Î҂B + } +*/ + reg_OS_PAUSE |= REG_OS_PAUSE_CHK_MASK; // PAUSEWX^̃`FbNtÕZbg + + SYSMi_ReadTWLSetting(); // NANDTWL{̐ݒf[^[h + PMm_SetBackLightBrightness(); + + SYSMi_ReadNTRSetting(); // NOR NTR{̐ݒf[^[h + SYSMi_VerifyNTRSetting(); // NVRAMNTR{̐ݒf[^[hAsvӏNTRJoB + + SYSM_CaribrateTP(); // ǂݏoTWL{̐ݒf[^ƂTPLu[VB + SYSMi_WriteAdjustRTC(); // ǂݏoTWL{̐ݒf[^ƂRTCNbN␳lZbgB + + SYSMi_CheckCardCloneBoot(); // J[hN[u[g`FbN + SYSMi_ReadCardBannerFile(); // J[hoi[t@C̓ǂݏoB + + // ============================================================== + // fobKΉR[h +#ifdef __IS_DEBUGGER_BUILD + if( GetSYSMWork()->isOnDebugger ) { + if( SYSMi_ExistCard() && + !SYSMi_IsDebuggerBannerViewMode() ){ // fobK㓮̏ꍇ́A̒ŃJ[hu[g܂łĂ܂B + SYSM_GetResetParam()->isLogoSkip = TRUE; + SYSM_GetResetParam()->bootTitleID = SYSM_GetCardTitleID(); + } + }else { + while( 1 ) {} // ISfobKrhISfobKołȂ~B + } +#endif // __IS_DEBUGGER_BUILD + // ============================================================== +} + + +int SYSM_GetCardTitleList( TitleProperty *pTitleList_Card ) +{ +#pragma unused( pTitleList_Card ) + return 0; +} + + +int SYSM_GetNandTitleList( TitleProperty *pTitleList_Nand ) +{ +#pragma unused( pTitleList_Nand ) + // filter_flag : ALL, ALL_APP, SYS_APP, USER_APP, Data only, ̏w肵ă^CgXg擾B + // return : *TitleProperty Array + return 0; +} + + +// w^Cgu[g”\ȃ|C^`FbN +static BOOL SYSMi_CheckTitlePointer( TitleProperty *pBootTitle ) +{ +#pragma unused( pBootTitle ) + + return TRUE; +} + + +// w^Cg̔F؁[h@Pt[IB +AuthResult SYSM_LoadAndAuthenticateTitle( TitleProperty *pBootTitle ) +{ + // C̃NA + // DS_E[hvC̎́AROMwb_ޔ + // Av[h + // AvF + + // p[^`FbN + if( !SYSMi_CheckTitlePointer( pBootTitle ) ) { + return AUTH_RESULT_TITLE_POINTER_ERROR; + } + // GgAhX̐`FbN + if( !SYSMi_CheckEntryAddress() ) { + return AUTH_RESULT_ENTRY_ADDRESS_ERROR; + } + + return AUTH_RESULT_SUCCEEDED; +} + + +// u[ĝ߂̏I +void SYSM_Finalize( void ) +{ + // ARM7ւ̃u[gʒm + // WX^ERAMNA + + // u[gɃveNVjbgOFFɂȂ΁AsȃAhXł̋Nĥł́H + + u32 i; + + // u[g̑O + MI_CpuCopyFast( (void *)ReturnFromMain, (void *)RETURN_FROM_MAIN_ARM9_FUNCP, (u32)( (u32)BootFuncEnd - (u32)ReturnFromMain ) ); + DC_StoreRange ( (void *)ReturnFromMain, 0x200 ); // Q[u[g̍ŏIČ̕ɃRs[iSYSMs̃X^bN㏸Ŕj󂳂Ȃ悤ɁÃ^C~OŃRs[Bj + + for( i = 0; i <= MI_DMA_MAX_NUM; i++ ) { // DMA̒~ + MI_StopDma( i ); + } + SYSM_FinalizeCardPulledOut(); // J[hoI + SYSMi_MainpRegisterAndRamClear( TRUE ); // WX^RAMNA + ( void )GX_VBlankIntr(FALSE); + ( void )OS_SetIrqFunction(OS_IE_SUBP, INTR_SubpIRQ); + ( void )OS_SetIrqMask(OS_IE_SUBP); // TuvZbT荞݂݂̂B + reg_PXI_SUBPINTF = SUBP_RECV_IF_ENABLE | 0x0f00; // ARM9Xe[g "0x0f" + GetSYSMWork()->mainp_state = MAINP_STATE_WAIT_BOOT_REQ; + // FIFO̓NAς݂Ȃ̂ŁAgȂB + // ARM7̒ʒm҂ + OS_WaitIrq(1, OS_IE_SUBP); // SVC_WaitIntr(0,OS_IE_SUBP);ύXB + + // 荞݂NAčŏIu[gV[PXցB + reg_PXI_SUBPINTF &= 0x0f00; // TuvZbT荞݋ƒtONA + ( void )OS_DisableIrq(); + ( void )OS_SetIrqMask(0); + ( void )OS_ResetRequestIrqMask( (u32)~0 ); +} + + +// `[u[g +void SYSM_RebootLauncher( void ) +{ +} + + +// ċN^Cgw肵Ẵu[g +void SYSM_RebootTitle( u64 titleID ) +{ +#pragma unused( titleID ) + +} + + +#if 0 +// NITRONARM7ɒʒm +BOOL SYSM_BootCard( void ) +{ // NintendoS`FbŃÃ^C~OōsB + + ( void )SYSMi_SendMessageToARM7(MSG_BOOT_TYPE_CARD); // ARM7ɃJ[hNʒmB + + if( SYSM_CheckNinLogo( (u16 *)GetRomHeaderAddr()->nintendo_logo ) == FALSE + || GetSYSMWork()->enableCardNormalOnly == TRUE ) { // NORMALJ[hΉ + SYSM_SetBootFlag( BFLG_ILLEGAL_NITRO_CARD ); + return FALSE; + }else { + SYSM_SetBootFlag( BFLG_BOOT_DECIDED | BFLG_BOOT_NITRO ); + return TRUE; + } +} +#endif + +#if 0 +// TP[h”\ǂ𒲂ׂB +BOOL SYSM_IsTPReadable( void ) +{ + if( SYSM_GetBootFlag() & BFLG_BOOT_DECIDED ) return FALSE; + else return TRUE; +} +#endif + + +// ARM7-ARM9L\[XbootFlagւ̒l̃Zbg +void SYSM_SetBootFlag( u32 value ) +{ + BOOL preIrq = OS_DisableIrq(); + LockVariable *lockp = &GetSYSMWork()->boot_flag; + ( void )OS_LockByWord( BOOTFLAG_LOCK_ID, &(lockp->lock), (void (*)( void ))0x00000000); + lockp->value |= value; + ( void )OS_UnLockByWord(BOOTFLAG_LOCK_ID, &(lockp->lock), (void (*)( void ))0x00000000); + ( void )OS_RestoreIrq( preIrq ); +} + + +void SYSM_ClearBootFlag( u32 value ) +{ + BOOL preIrq = OS_DisableIrq(); + LockVariable *lockp = &GetSYSMWork()->boot_flag; + ( void )OS_LockByWord( BOOTFLAG_LOCK_ID, &(lockp->lock), (void (*)( void ))0x00000000); + lockp->value &= ~value; + ( void )OS_UnLockByWord(BOOTFLAG_LOCK_ID, &(lockp->lock), (void (*)( void ))0x00000000); + ( void )OS_RestoreIrq( preIrq ); +} + + +// ============================================================================ +// 荞ݏ +// ============================================================================ + +// TuvZbT荞 +static void INTR_SubpIRQ( void ) +{ + OS_SetIrqCheckFlag( OS_IE_SUBP ); +} + + +// ============================================================================ +// AvN +// ============================================================================ + +// GgAhX̐`FbN +static BOOL SYSMi_CheckEntryAddress( void ) +{ + // GgAhXROMo^GAAGBJ[gbWGAȂA[vɓB + if( !( ( (u32)GetRomHeaderAddr()->main_entry_address >= HW_MAIN_MEM ) + && ( (u32)GetRomHeaderAddr()->main_entry_address < SYSM_ARM9_MMEM_ENTRY_ADDR_LIMIT ) ) + || !( ( ( (u32)GetRomHeaderAddr()->sub_entry_address >= HW_MAIN_MEM ) + && ( (u32)GetRomHeaderAddr()->sub_entry_address < SYSM_ARM7_LOAD_MMEM_LAST_ADDR ) ) + || ( ( (u32)GetRomHeaderAddr()->sub_entry_address >= HW_WRAM ) + && ( (u32)GetRomHeaderAddr()->sub_entry_address < SYSM_ARM7_LOAD_WRAM_LAST_ADDR ) ) ) ) + { + OS_TPrintf("entry address invalid.\n"); +#ifdef __DEBUG_SECURITY_CODE + DispSingleColorScreen( SCREEN_YELLOW ); +#endif + return FALSE; + } + OS_TPrintf("entry address valid.\n"); + return TRUE; +} + + +// ARM7ɂNITROQ[̃[hmFB +static BOOL SYSMi_CheckARM7LoadNITROCard( void ) +{ + if( SYSMi_ExistCard() +// && !( SYSM_GetBootFlag() & BFLG_LOAD_CARD_COMPLETED ) + ) { + return FALSE; + } + return TRUE; +} + + + +// SystemMenuŎgpWX^̃NA +static void SYSMi_MainpRegisterAndRamClear( BOOL isPlatformTWL ) +{ + // ŌオTuvZbT荞ݑ҂Ȃ̂ŁAIME̓NAȂB + ( void )OS_SetIrqMask(0); + ( void )OS_ResetRequestIrqMask( (u32)~0 ); + + // NA + GX_SetBankForLCDC(GX_VRAM_LCDC_ALL); // VRAM NA + MI_CpuClearFast((void*)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE); + ( void )GX_DisableBankForLCDC(); +// MI_CpuClearFast((void *)HW_ITCM, HW_ITCM_SIZE); // ITCM NA ITCMɂSDK̃R[hĂ̂ŁAgameBoot.cŃNAB +// MI_CpuClearFast((void *)HW_DTCM, HW_DTCM_SIZE-0x800); // DTCM NA DTCM̓X^bN&SDKϐȂ̂ŁAŌgameBoot.cŃNAĂB + MI_CpuClearFast((void *)HW_OAM, HW_OAM_SIZE); // OAM NA + MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE); // pbg NA + MI_CpuClearFast((void *)HW_DB_OAM, HW_DB_OAM_SIZE); // OAM NA + MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE); // pbg NA + + // WX^NA + MI_CpuClearFast((void*)(HW_REG_BASE + 0x8), 0x12c); // BG0CNT ` KEYCNT + MI_CpuClearFast((void*)(HW_REG_BASE + 0x280), 0x40); // DIVCNT ` SQRTD3 + MI_CpuClearFast((void*)(HW_REG_BASE + 0x1000), 0x6e); // DISP1CNT1 ` DISPBRTCNT1 + CP_SetDiv32_32( 0, 1 ); + reg_PXI_SUBP_FIFO_CNT = 0x4008; + reg_GX_DISPCNT = 0; + reg_GX_DISPSTAT = 0; // reg_GX_VCOUNT̓x^NAłȂ̂ŁA̐擪̃NA𕪗B + + + // NTR̎ɂ́Aoi[鎞́AMCCNT̃J[hCl[urbg"1"ŁAƂɂ"0"ɂȂĂA + // NTRN̎ɂ́Ał𓥏PȂƃ_BBB + + // NAĂȂWX^́AVCOUNT, PIFCNT, MC-, EXMEMCNT, IME, RBKCNT1, PAUSE, POWLCDCNT, S3DnłB + if( isPlatformTWL ) { + // TWLpWX^̃NA + } +} + + +// ============================================================================ +// Tu[` +// ============================================================================ + +// SfXLbvH +BOOL SYSM_IsLogoDemoSkip( void ) +{ + // VXeAṽn[hZbgɂ郍Sf΂ɓB + + return SYSMi_IsDebuggerBannerViewMode(); +} + +// ISfobK̃oi[r[[hNǂH +static BOOL SYSMi_IsDebuggerBannerViewMode( void ) +{ +#ifdef __IS_DEBUGGER_BUILD + return ( GetSYSMWork()->isOnDebugger && + SYSMi_ExistCard() && + GetRomHeaderAddr()->dbgRomSize == 0 ) ? TRUE : FALSE; +#else + return FALSE; +#endif // __IS_DEBUGGER_BUILD +} + + +// NITROݒf[^̓ǂݏoB +static void SYSMi_ReadNTRSetting( void ) +{ + RTCDate date; + RTCTime time; + + GetSYSMWork()->ncd_invalid = NVRAMm_ReadNitroConfigData( GetNCDWork() ); + // NVRAMNITROݒf[^[hB + if( GetSYSMWork()->ncd_invalid ) { // [hNITROݒf[^A0NÂgpB + OS_TPrintf(" NCD destroyed.\n" ); + SVC_CpuClearFast( 0x0000, GetNCDExWork(), sizeof(NitroConfigDataEx) ); + GetNCDExWork()->version = NITRO_CONFIG_DATA_EX_VERSION; + GetNCDWork()->option.backLightBrightness= 2; // o׎ƓlɁB + GetNCDWork()->option.language = LANG_ENGLISH; // vZbgKvȃf[^̓vZbgĂ + GetNCDWork()->option.destroyFlashFlag = 1; + GetNCDWork()->owner.birthday.month = 1; + GetNCDWork()->owner.birthday.day = 1; + GetNCDExWork()->valid_language_bitmap = VALID_LANG_BITMAP; + } + + // RTC̃Zbg or loꍇ͏NV[PXցB + ( void )RTC_GetDateTime( &date, &time ); + if( !SYSM_CheckRTCDate( &date ) || + !SYSM_CheckRTCTime( &time ) +#ifndef __IS_DEBUGGER_BUILD // ƒfobKłRTC̓drȂ̂ŁA񂱂ɂЂĐݒf[^ЕNAĂ܂BhXCb`B + || ( GetSYSMWork()->rtcStatus & 0x01 ) +#endif + ) { // RTCُ̈oArtc̓tOrtcOffset0ɂNVRAMɏ݁B + OS_TPrintf("\"RTC reset\" or \"Illegal RTC data\" detect!\n"); + GetNCDWork()->option.input_rtc = 0; + GetNCDWork()->option.rtcOffset = 0; + GetNCDWork()->option.rtcLastSetYear = 0; + ( void )NVRAMm_WriteNitroConfigData( GetNCDWork() ); + } +} + + +// TWLݒf[^̓ǂݏo +static void SYSMi_ReadTWLSetting( void ) +{ + +} + + +// NTRݒTWLݒxt@CāAsv΁ANTRݒXV +static void SYSMi_VerifyNTRSetting( void ) +{ +} + + +// RTC̓t`FbN +BOOL SYSM_CheckRTCDate( RTCDate *datep ) +{ + if( ( datep->year >= 100 ) + || ( datep->month < 1 ) || ( datep->month > 12 ) + || ( datep->day < 1 ) || ( datep->day > 31 ) + || ( datep->week >= RTC_WEEK_MAX ) ) { + return FALSE; + } + return TRUE; +} + + +// RTC̎`FbN +BOOL SYSM_CheckRTCTime( RTCTime *timep ) +{ + if( ( timep->hour > 23 ) + || ( timep->minute > 59 ) + || ( timep->second > 59 ) ) { + return FALSE; + } + return TRUE; +} + + +// oi[t@C̓ǂݍ݂̎ +static void SYSMi_ReadCardBannerFile( void ) +{ + s32 lockCardID; + BannerFile *pBanner = &s_bannerBuf; + + if( ( !SYSMi_ExistCard() ) || ( *(void** )BANNER_ROM_OFFSET == NULL ) ) { + s_isBanner = FALSE; + return; + } + + // ROMJ[h̃oi[f[^̃[h + if ( ( lockCardID = OS_GetLockID() ) > 0 ) { + ( void )OS_LockCard( (u16 )lockCardID ); + DC_FlushRange( pBanner, sizeof(BannerFile) ); + SYSM_ReadCard(*(void** )BANNER_ROM_OFFSET, pBanner, sizeof(BannerFile) ); + ( void )OS_UnLockCard( (u16 )lockCardID ); + OS_ReleaseLockID( (u16 )lockCardID ); + } + + // oi[f[^̐`FbN + { + int i; + u16 calc_crc = 0xffff; + u16 *hd_crcp = (u16 *)&pBanner->h.crc16_v1; + BannerCheckParam *chkp = &s_bannerCheckList[ 0 ]; + + s_isBanner = TRUE; + + for( i = 0; i < BNR_VER_MAX; i++ ) { + if( i < pBanner->h.version ) { + calc_crc = SVC_GetCRC16( calc_crc, chkp->srcp, chkp->size ); + if( calc_crc != *hd_crcp++ ) { + s_isBanner = FALSE; + break; + } + }else { + MI_CpuClear16( chkp->srcp, chkp->size ); + } + chkp++; + } + if( !s_isBanner ) { + MI_CpuClear16( &s_bannerBuf, sizeof(BannerFile) ); + } + } +} + + +// N[u[g +static void SYSMi_CheckCardCloneBoot( void ) +{ + s32 lockCardID; + u8 *buffp = (u8 *)&s_bannerBuf; // oi[pobt@e|ƂĎgp + u32 total_rom_size = GetRomHeaderAddr()->total_rom_size ? GetRomHeaderAddr()->total_rom_size : 0x01000000; + u32 file_offset = total_rom_size & 0xFFFFFE00; + + if( !SYSMi_ExistCard() ) { + return; + } + + if ( ( lockCardID = OS_GetLockID() ) > 0 ) { + ( void )OS_LockCard( (u16 )lockCardID ); + DC_FlushRange( buffp, BNR_IMAGE_SIZE ); + SYSM_ReadCard( (void *)file_offset, buffp, BNR_IMAGE_SIZE ); + ( void )OS_UnLockCard( (u16 )lockCardID ); + OS_ReleaseLockID( (u16 )lockCardID ); + } + + buffp += total_rom_size & 0x000001FF; + if( *buffp++ == 'a' && *buffp == 'c' ) { + GetSYSMWork()->clone_boot_mode = CLONE_BOOT_MODE; + }else { + GetSYSMWork()->clone_boot_mode = OTHER_BOOT_MODE; + } +} + + +// ^b`plLu[V +void SYSM_CaribrateTP( void ) +{ +#ifndef __TP_OFF + TPCalibrateParam calibrate; + + ( void )TP_CalcCalibrateParam( &calibrate, // ^b`pl + GetNCDWork()->tp.raw_x1, GetNCDWork()->tp.raw_y1, (u16)GetNCDWork()->tp.dx1, (u16)GetNCDWork()->tp.dy1, + GetNCDWork()->tp.raw_x2, GetNCDWork()->tp.raw_y2, (u16)GetNCDWork()->tp.dx2, (u16)GetNCDWork()->tp.dy2 ); + TP_SetCalibrateParam( &calibrate ); + OS_Printf("TP_calib: %4d %4d %4d %4d %4d %4d\n", + GetNCDWork()->tp.raw_x1, GetNCDWork()->tp.raw_y1, (u16)GetNCDWork()->tp.dx1, (u16)GetNCDWork()->tp.dy1, + GetNCDWork()->tp.raw_x2, GetNCDWork()->tp.raw_y2, (u16)GetNCDWork()->tp.dx2, (u16)GetNCDWork()->tp.dy2 ); +#endif +} + + +// RTCNbN␳lZbg +static void SYSMi_WriteAdjustRTC( void ) +{ +#ifndef __IS_DEBUGGER_BUILD // fobKprh͕␳ȂB + RTCRawAdjust raw; + + raw.adjust = GetNCDWork()->option.rtcClockAdjust; // ncd_invalidɂrtcClockAdjust + // 0NAĂ邽ߕ␳@\͎gpȂ + ( void )RTCi_SetRegAdjust( &raw ); +#endif /* __IS_DEBUGGER_BUILD */ +} + + +// FIFOoRARM7ɃbZ[WʒmBPXI_FIFO_TAG_USER_1gpB +static BOOL SYSMi_SendMessageToARM7(u32 msg) +{ +#pragma unused(msg) + return TRUE; +} + + +// NTR,TWLJ[h݃`FbN u^[@1FJ[hF@0FJ[hȂv +static int SYSMi_ExistCard( void ) +{ + if( ( GetRomHeaderAddr()->nintendo_logo_crc16 == 0xcf56 ) && + ( GetRomHeaderAddr()->header_crc16 == GetSYSMWork()->cardHeaderCrc16) ) { + return TRUE; // NTR,TWLJ[hiNintendoSCRCAJ[hwb_CRCꍇj + // NintendoSf[^̃`FbŃA̓sAS\[`Nɍs܂B + }else { + return FALSE; // NTR,TWLJ[hȂ + } +} + + +// NintendoS`FbN u^[@1:NintendoSF@0Fsv +BOOL SYSM_CheckNinLogo(u16 *logo_cardp) +{ + u16 *logo_orgp = (u16 *)SYSROM9_NINLOGO_ADR; // ARM9̃VXeROM̃Sf[^ƃJ[gbŴ̂r + u16 length = NINTENDO_LOGO_LENGTH >> 1; + + while(length--) { + if(*logo_orgp++ != *logo_cardp++) return FALSE; + } + return TRUE; +} + + +// X[v[hւ̑J +void SYSM_GoSleepMode( void ) +{ +#ifndef __IS_DEBUGGER_BUILD // fobKprh̓X[vȂB + PM_GoSleepMode( (PMWakeUpTrigger)( (PAD_DetectFold() ? PM_TRIGGER_COVER_OPEN : 0) | PM_TRIGGER_RTC_ALARM ), + 0, + 0 ); +#endif /* __IS_DEBUGGER_BUILD */ +} + + +// obNCgPx +void PMm_SetBackLightBrightness( void ) +{ + ( void )PMi_WriteRegister( 4, (u16)NCD_GetBackLightBrightness() ); + ( void )PM_SetBackLight( PM_LCD_ALL, PM_BACKLIGHT_ON ); +} + + +//====================================================================== +// fobO֐ +//====================================================================== + +// f[^̃fobO\ +#ifdef __SYSM_DEBUG +static void SYSMi_DispInitialDebugData( void ) +{ + OS_Printf("SYSM version :20%x\n", SYSMENU_VER); + if( GetMovedInfoFromIPL1Addr()->isOnDebugger ) OS_Printf("Run On IS-DEBUGGER\n"); + else OS_Printf("Run On IS-EMULATOR\n"); + if(GetMovedInfoFromIPL1Addr()->rtcStatus & 0x01) OS_Printf("RTC reset is detected!\n"); + if(GetMovedInfoFromIPL1Addr()->rtcError) OS_Printf("RTC error is detected!\n"); +#if 0 + OS_Printf("NvDate :%4d\n",sizeof(NvDate)); + OS_Printf("NvNickname :%4d\n",sizeof(NvNickname)); + OS_Printf("NvComment :%4d\n",sizeof(NvComment)); + OS_Printf("NvOwnerInfo :%4d\n",sizeof(NvOwnerInfo)); + OS_Printf("NvAlarm :%4d\n",sizeof(NvAlarm)); + OS_Printf("NvTpCalibData:%4d\n",sizeof(NvTpCalibData)); + OS_Printf("NvOption :%4d\n",sizeof(NvOption)); + OS_Printf("NCD :%4d\n",sizeof(NitroConfigData)); + OS_Printf("NCDStore :%4d\n",sizeof(NCDStore)); +#endif +#if 0 + { // ROM_HEADER_BUFF̓eo + int i,j; + u32 *romhp = (u32 *)GetRomHeaderAddr(); + OS_Printf("ROM Header Buff\n "); + for(i = 0; i < 6; i++) { + for(j = 0; j < 4; j++) OS_Printf(" 0x%8x", *romhp++); + OS_Printf("\n "); + } + OS_Printf("\n"); + } + { // ROM_HEADER_BUFF̓eo + int i,j; + u32 *romhp = (u32 *)MB_CARD_ROM_HEADER_ADDRESS; + OS_Printf("MB Card ROM Header Buff\n "); + for(i = 0; i < 6; i++) { + for(j = 0; j < 4; j++) OS_Printf(" 0x%8x", *romhp++); + OS_Printf("\n "); + } + OS_Printf("\n"); + } +#endif /* 0 */ +} +#endif /* __SYSM_DEBUG */ + + + +#ifdef __DEBUG_SECURITY_CODE +// ZLeBƓĂ邩mFfobOR[h +static void DispSingleColorScreen( int mode ) +{ + ( void )OS_DisableIrq(); + GX_LoadBGPltt ( &security_detection_color[ mode ], 0, sizeof(GXRgb) ); + GXS_LoadBGPltt ( &security_detection_color[ mode ], 0, sizeof(GXRgb) ); + GX_DispOn(); + GXS_DispOn(); + GX_SetGraphicsMode ( GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_2D ); + GXS_SetGraphicsMode( GX_BGMODE_0 ); + GX_SetMasterBrightness( 0 ); + GXS_SetMasterBrightness( 0 ); + GX_SetVisiblePlane ( GX_PLANEMASK_NONE ); + GXS_SetVisiblePlane( GX_PLANEMASK_NONE ); +} +#endif + + diff --git a/build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_util.c b/build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_util.c new file mode 100644 index 0000000..76c45b1 --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/ARM9/src/sysmenu_util.c @@ -0,0 +1,172 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: SYSM_util.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include + +// define data------------------------------------------ + +// extern data------------------------------------------ + +// function's prototype declaration--------------------- +static s64 SYSMi_CalcRtcSecOffset( RTCDate *datep, RTCTime *timep ); + +// global variable ------------------------------------- + +// static variable ------------------------------------- + +// const data ----------------------------------------- + +// function's description------------------------------- + +//====================================================================== +// NITROݒf[^@[N +//====================================================================== + +// NITROݒf[^̃jbNl[EFEȁB +void NCD_ClearOwnerInfo( void ) +{ + NitroConfigData *ncdp = GetNCDWork(); + + MI_CpuClear16( &ncdp->owner, sizeof(NvOwnerInfo) ); + ncdp->owner.birthday.month = 1; + ncdp->owner.birthday.day = 1; + ncdp->option.input_birthday = 0; + ncdp->option.input_favoriteColor = 0; + ncdp->option.input_nickname = 0; +} + + +//====================================================================== +// RTCItZbg +//====================================================================== + +// RTCɐVݒlZbgāA̒lƂrtcOffsetlZoB +s64 SYSM_CalcRtcOffsetAndSetDateTime( RTCDate *newDatep, RTCTime *newTimep ) +{ + RTCDate oldDate; + RTCTime oldTime; + s64 offset0; + s64 offset1; + s64 offset; + + // RTCւ̐Vl̐ݒ + (void)RTC_GetDateTime( &oldDate, &oldTime ); // CgOɌ݂RTCl擾B + (void)RTC_SetDateTime( newDatep, newTimep ); // VRTCݒl̃ZbgB + oldTime.second = 0; + + // RTCݒ莞́A̐ݒłǂꂾRTClωibItZbgPʁjZoB + if( ( oldDate.year < NCD_GetRtcLastSetYear() ) && ( NCD_GetInputRTC() ) ) { + oldDate.year += 100; // O̐ݒ`̐ݒ̊ԂRTCĂ܂Ayear100ZoffsetvZB + } + NCD_SetRtcLastSetYear( (u8)newDatep->year ); + + offset0 = SYSMi_CalcRtcSecOffset( &oldDate, &oldTime ); // ݒ蒼ORTCl̃ItZbgZo + offset1 = SYSMi_CalcRtcSecOffset( newDatep, newTimep ); // VZbgꂽRTCl̃ItZbgZo + offset = NCD_GetRtcOffset() + offset1 - offset0; // VRTC_ofs ݂RTC_ofs ̍̒lZă^[B + + OS_Printf ("Now Date = year:%3d month:%3d date:%3d hour:%3d minute:%3d second:%3d\n", + oldDate.year, oldDate.month, oldDate.day, + oldTime.hour, oldTime.minute, oldTime.second); + OS_Printf ("Set Date = year:%3d month:%3d date:%3d hour:%3d minute:%3d second:%3d\n", + newDatep->year, newDatep->month, newDatep->day, + newTimep->hour, newTimep->minute, newTimep->second); + OS_Printf ("offset[0] = %x\n", offset0 ); + OS_Printf ("offset[1] = %x\n", offset1 ); + OS_Printf ("rtcOffset = %x\n", offset ); + + return offset; +} + + +// RTCItZbgl̎Zo +#define SECOND_OFFSET +static s64 SYSMi_CalcRtcSecOffset( RTCDate *datep, RTCTime *timep ) +{ + u32 i; + int uruu = 0; + int dayNum = 0; + s64 offset; + + // AAb@b or ItZbg +#ifdef SECOND_OFFSET + offset = ( timep->hour * 60 + timep->minute ) * 60 + timep->second; +#else + offset = timep->hour * 60 + timep->minute; +#endif + + // A@ɊZĂA@b or ItZbg + dayNum = (int)datep->day - 1; + for( i = 1; i < datep->month; i++ ) { + dayNum += SYSM_GetDayNum( datep->year, i ); + } + + // N@ɊZ + if( datep->year > 0 ) { + uruu = ( ( (int)datep->year - 1 ) >> 2 ) + 1; // wN-1܂ł̂邤ҐZoāA̓ZB + } + dayNum += uruu + (u32)( datep->year * 365 ); + + // NEEɊZl@b or ItZbg +#ifdef SECOND_OFFSET + offset += (s64)( dayNum * 24 * 3600 ); +#else + offset += (s64)( dayNum * 24 * 60 ); +#endif + + return offset; +} + + +// w肳ꂽNE̓ԂB +u32 SYSM_GetDayNum( u32 year, u32 month ) +{ + u32 dayNum = 31; + if( month == 2 ) { + if( SYSM_IsLeapYear100( year ) ) { + dayNum -= 2; + }else { + dayNum -= 3; + } + }else if( ( month == 4 ) || ( month == 6 ) || ( month == 9 ) || ( month == 11 ) ) { + dayNum--; + } + return dayNum; +} + +/* +u32 SYSM_GetDayNum( u32 year, u32 month ) +{ + u8 date_tbl[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if( ( month == 2 ) && SYSM_IsLeapYear100( year ) ) { + return 29; + } + return date_tbl[ month - 1 ]; // PPQP +} +*/ + +// ȈՂ邤N̔ (邤NF1Aʏ̔NF0jRTĈƂ肤2000`2100NɌ肷B +BOOL SYSM_IsLeapYear100( u32 year ) +{ + if( ( year & 0x03 ) || ( year == 100 ) ) { // 邤ŃAu4Ŋ؂@@100Ŋ؂ȂNv܂́u400Ŋ؂Nv + return FALSE; + }else { + return TRUE; + } +} + diff --git a/build/libraries_sysmenu/sysmenu/Makefile b/build/libraries_sysmenu/sysmenu/Makefile new file mode 100644 index 0000000..52c5a13 --- /dev/null +++ b/build/libraries_sysmenu/sysmenu/Makefile @@ -0,0 +1,33 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +TARGET_FIRM = SYSTEMMENU + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM9 + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/nand_formatter/.DS_Store b/build/nand_formatter/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c865c9d9f50a0072f63dd737a1d50b13720be529 GIT binary patch literal 6148 zcmeHKJ5Iwu5S;-Rk&sYI$~^+9kUJ+bB@MX%3Xz~lj>k$!MJgjFTQxTb95S7Y^&^+oo@?biZdu;Az%iC_d8`iCX5>l3gdbz5a`8E02Vw)&a%_| bi8|sM$KH^;(4NzQ@gtB4i76QP0R}z*gNQz0 literal 0 HcmV?d00001 diff --git a/build/nand_formatter/ARM7/Makefile b/build/nand_formatter/ARM7/Makefile new file mode 100644 index 0000000..3a6a2fe --- /dev/null +++ b/build/nand_formatter/ARM7/Makefile @@ -0,0 +1,53 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-09#$ +# $Rev: 1486 $ +# $Author: terui $ +#---------------------------------------------------------------------------- + +TARGET_PLATFORM = TWL +#TWL_ARCHGEN = LIMITED +TWL_PROC = ARM7 +TWL_NO_STD_PCHDR = TRUE + +#---------------------------------------------------------------------------- + +SRCS = main.c \ + dummy.FLXMAIN.c \ + dummy.FLXWRAM.c \ + dummy.LTDMAIN.c \ + dummy.LTDWRAM.c + +TARGET_NAME = formatter_sub + +TARGET_NEF = $(TARGET_NAME).tef +LCFILE_SPEC = $(TARGET_NAME).lsf +LCFILE_TEMPLATE = $(TARGET_NAME).lcf.template +LDRES_TEMPLATE = $(TARGET_NAME).response.template + +CRT0_O = crt0.LTD.TWL.o + +#---------------------------------------------------------------------------- +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +MACRO_FLAGS += -DSDK_ARM7COMP_LTD + +MAKELCF_FLAGS += -DISTD_LIBS='$(ISTD_LIBS)' + +do-build: $(TARGETS) + +#---------------------------------------------------------------------------- +include $(TWLSDK_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/nand_formatter/ARM7/formatter_sub.lcf.template b/build/nand_formatter/ARM7/formatter_sub.lcf.template new file mode 100644 index 0000000..87fabc1 --- /dev/null +++ b/build/nand_formatter/ARM7/formatter_sub.lcf.template @@ -0,0 +1,897 @@ +#--------------------------------------------------------------------------- +# Project: TwlSDK - demos - FATFS - formatter - formatter_sub.TWL +# File: mongoose.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 > + + + (RWX) : ORIGIN = , LENGTH = 0x0 >> + + binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + F (RW) : ORIGIN = 0, LENGTH = 0x0 > + F (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + + arena.MAIN (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + check.WORKRAM (RWX) : ORIGIN = 0x037f8000, LENGTH = 0x18000 > workram.check + check.MAINMEM (RWX) : ORIGIN = 0x02fe0000, LENGTH = 0x1c000 > mainmem.check + + binary.LTDAUTOLOAD_TOP (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWX) : ORIGIN = , LENGTH = 0x0 >> + + binary.LTDAUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + L (RW) : ORIGIN = 0, LENGTH = 0x0 > + L (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + + check.LTDWRAM (RWX) : ORIGIN = 0x03000000, LENGTH = 0x40000 > ltdwram.check + check.LTDMAIN (RWX) : ORIGIN = 0x02f88000, LENGTH = 0x58000 > ltdmain.check +} + +KEEP_SECTION +{ + .sinit +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + OBJECT(_start,*) + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + #:::::::::: text/rodata + SDK_STATIC_TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(4); + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_STATIC_DATA_END =.; + . = ALIGN(4); + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_STATIC_BSS_END = .; + + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.MAIN.START = 0x02fe0000; + SDK_AUTOLOAD.MAIN.END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.BSS_END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.SIZE = 0; + SDK_AUTOLOAD.MAIN.BSS_SIZE = 0; + SDK_AUTOLOAD.WRAM.START = 0x037f8000; + SDK_AUTOLOAD.WRAM.END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.BSS_END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.SIZE = 0; + SDK_AUTOLOAD.WRAM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + __exception_table_start__ =.; + EXCEPTION + __exception_table_end__ =.; + SDK_STATIC_ETABLE_END =.; + + + + + + + + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + . = ALIGN(4); + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_AUTOLOAD..DATA_END =.; + . = ALIGN(4); + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_MAIN_START = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD_MAIN_END = SDK_AUTOLOAD.MAIN.END; + SDK_AUTOLOAD_MAIN_BSS_END = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_AUTOLOAD_MAIN_SIZE = SDK_AUTOLOAD.MAIN.SIZE; + SDK_AUTOLOAD_MAIN_BSS_SIZE = SDK_AUTOLOAD.MAIN.BSS_SIZE; + SDK_AUTOLOAD_WRAM_START = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD_WRAM_END = SDK_AUTOLOAD.WRAM.END; + SDK_AUTOLOAD_WRAM_BSS_END = SDK_AUTOLOAD.WRAM.BSS_END; + SDK_AUTOLOAD_WRAM_SIZE = SDK_AUTOLOAD.WRAM.SIZE; + SDK_AUTOLOAD_WRAM_BSS_SIZE = SDK_AUTOLOAD.WRAM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + + } > binary.AUTOLOAD_INFO + + SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; + SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + #:::::::::: text/rodata + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(4); + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_OVERLAY..DATA_END =.; + . = ALIGN(4); + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + ############################ ARENA ################################## + .arena.MAIN: + { + . = ALIGN(4); + SDK_SECTION_ARENA_START =.; + + } > arena.MAIN + + ############################ OVERLAYDEFS ############################ + .F: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > F + + ############################ OVERLAYTABLE ########################### + .F: + { + + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + } > F + + ############################ OTHERS ################################# + SDK_WRAM_ARENA_LO = SDK_AUTOLOAD.WRAM.BSS_END; + SDK_SUBPRIV_ARENA_LO = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_IRQ_STACKSIZE = ; # allocated in WRAM + SDK_SYS_STACKSIZE = ; # allocated in WRAM + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + + .check.WORKRAM: + { + . = . + SDK_AUTOLOAD.WRAM.BSS_END - SDK_AUTOLOAD.WRAM.START + 0x080 + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + + } > check.WORKRAM + + .check.MAINMEM: + { + . = SDK_SUBPRIV_ARENA_LO; + + } > check.MAINMEM + + ########################### LTDAUTOLOADS ############################ + SDK_LTDAUTOLOAD.LTDMAIN.START = SDK_STATIC_BSS_END; + SDK_LTDAUTOLOAD.LTDMAIN.END = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD.LTDMAIN.BSS_END = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD.LTDMAIN.SIZE = 0; + SDK_LTDAUTOLOAD.LTDMAIN.BSS_SIZE = 0; + SDK_LTDAUTOLOAD.LTDWRAM.START = 0x03000000; + SDK_LTDAUTOLOAD.LTDWRAM.END = SDK_LTDAUTOLOAD.LTDWRAM.START; + SDK_LTDAUTOLOAD.LTDWRAM.BSS_END = SDK_LTDAUTOLOAD.LTDWRAM.START; + SDK_LTDAUTOLOAD.LTDWRAM.SIZE = 0; + SDK_LTDAUTOLOAD.LTDWRAM.BSS_SIZE = 0; + SDK_LTDAUTOLOAD_TOP_START = 0x02e80000; + SDK_LTDAUTOLOAD_TOP_SIZE = 4; # STATIC ̈悪 4 bytes ̃_~[oCit@C̐擪ɓ # + SDK_LTDAUTOLOAD_START = SDK_LTDAUTOLOAD_TOP_START + SDK_LTDAUTOLOAD_TOP_SIZE; + SDK_LTDAUTOLOAD_SIZE = 0; + SDK_LTDAUTOLOAD_NUMBER = ; + + .binary.LTDAUTOLOAD_TOP: + { + WRITEW 0xdeadbeef; + + } > binary.LTDAUTOLOAD_TOP + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + SDK_LTDAUTOLOAD__ID =; + SDK_LTDAUTOLOAD..ID =; + SDK_LTDAUTOLOAD..START =.; + # + # TEXT BLOCK: READ ONLY + # + SDK_LTDAUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + #:::::::::: text/rodata + SDK_LTDAUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + . = ALIGN(4); + SDK_LTDAUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_LTDAUTOLOAD..DATA_END =.; + . = ALIGN(4); + SDK_LTDAUTOLOAD..END =.; + + SDK_LTDAUTOLOAD..TEXT_SIZE = SDK_LTDAUTOLOAD..TEXT_END - SDK_LTDAUTOLOAD..TEXT_START; + SDK_LTDAUTOLOAD..DATA_SIZE = SDK_LTDAUTOLOAD..DATA_END - SDK_LTDAUTOLOAD..DATA_START; + SDK_LTDAUTOLOAD..SIZE = SDK_LTDAUTOLOAD..END - SDK_LTDAUTOLOAD..START; + SDK_LTDAUTOLOAD_SIZE = SDK_LTDAUTOLOAD_SIZE + SDK_LTDAUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_LTDAUTOLOAD..BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_LTDAUTOLOAD..BSS_END =.; + + SDK_LTDAUTOLOAD..BSS_SIZE = SDK_LTDAUTOLOAD..BSS_END - SDK_LTDAUTOLOAD..BSS_START; + + } >> + + + + SDK_LTDAUTOLOAD_LTDMAIN_START = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD_LTDMAIN_END = SDK_LTDAUTOLOAD.LTDMAIN.END; + SDK_LTDAUTOLOAD_LTDMAIN_BSS_END = SDK_LTDAUTOLOAD.LTDMAIN.BSS_END; + SDK_LTDAUTOLOAD_LTDMAIN_SIZE = SDK_LTDAUTOLOAD.LTDMAIN.SIZE; + SDK_LTDAUTOLOAD_LTDMAIN_BSS_SIZE = SDK_LTDAUTOLOAD.LTDMAIN.BSS_SIZE; + SDK_LTDAUTOLOAD_LTDWRAM_START = SDK_LTDAUTOLOAD.LTDWRAM.START; + SDK_LTDAUTOLOAD_LTDWRAM_END = SDK_LTDAUTOLOAD.LTDWRAM.END; + SDK_LTDAUTOLOAD_LTDWRAM_BSS_END = SDK_LTDAUTOLOAD.LTDWRAM.BSS_END; + SDK_LTDAUTOLOAD_LTDWRAM_SIZE = SDK_LTDAUTOLOAD.LTDWRAM.SIZE; + SDK_LTDAUTOLOAD_LTDWRAM_BSS_SIZE = SDK_LTDAUTOLOAD.LTDWRAM.BSS_SIZE; + + ######################### LTDAUTOLOAD_INFO ########################## + .binary.LTDAUTOLOAD_INFO: + { + + WRITEW ADDR(.); + WRITEW SDK_LTDAUTOLOAD..SIZE; + WRITEW SDK_LTDAUTOLOAD..BSS_SIZE; + + + } > binary.LTDAUTOLOAD_INFO + + SDK_LTDAUTOLOAD_LIST = SDK_LTDAUTOLOAD_START + SDK_LTDAUTOLOAD_SIZE; + SDK_LTDAUTOLOAD_LIST_END = SDK_LTDAUTOLOAD_LIST + SIZEOF(.binary.LTDAUTOLOAD_INFO); + SDK_LTDAUTOLOAD_SIZE = SDK_LTDAUTOLOAD_SIZE + SIZEOF(.binary.LTDAUTOLOAD_INFO); + + ########################### LTDOVERLAYS ############################# + SDK_LTDOVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + SDK_LTDOVERLAY__ID =; + SDK_LTDOVERLAY..ID =; + SDK_LTDOVERLAY..START =.; + # + # TEXT BLOCK: READ ONLY + # + SDK_LTDOVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_LTDOVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_LTDOVERLAY..SINIT_END =.; + #:::::::::: text/rodata + SDK_LTDOVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(4); + SDK_LTDOVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_LTDOVERLAY..DATA_END =.; + . = ALIGN(4); + SDK_LTDOVERLAY..END =.; + + SDK_LTDOVERLAY..TEXT_SIZE = SDK_LTDOVERLAY..TEXT_END - SDK_LTDOVERLAY..TEXT_START; + SDK_LTDOVERLAY..DATA_SIZE = SDK_LTDOVERLAY..DATA_END - SDK_LTDOVERLAY..DATA_START; + SDK_LTDOVERLAY..SIZE = SDK_LTDOVERLAY..END - SDK_LTDOVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_LTDOVERLAY..BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_LTDOVERLAY..BSS_END =.; + + SDK_LTDOVERLAY..BSS_SIZE = SDK_LTDOVERLAY..BSS_END - SDK_LTDOVERLAY..BSS_START; + + } >> + + + + ########################## LTDOVERLAYDEFS ########################### + .L: + { + ### TWL limited extended static module information + WRITEW SDK_LTDAUTOLOAD_TOP_START; # load address + WRITEW 0; # padding + WRITEW SDK_LTDAUTOLOAD_SIZE + SDK_LTDAUTOLOAD_TOP_SIZE; # size of module + WRITEW 0; # padding + + ### TWL limited overlay filename + + WRITES (""); + + + } > L + + ######################### LTDOVERLAYTABLE ########################### + .L: + { + + WRITES # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_LTDOVERLAY..SIZE; # size of module + WRITEW SDK_LTDOVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_LTDOVERLAY..SINIT_START; # start address of static init + WRITEW SDK_LTDOVERLAY..SINIT_END; # end address of static init + WRITEW # ROM file ID + WRITEW 0; # Reserved + + + } > L + + ############################ OTHERS ################################# + .check.LTDWRAM: + { + . = SDK_LTDAUTOLOAD.LTDWRAM.BSS_END; + + } > check.LTDWRAM + + .check.LTDMAIN: + { + . = SDK_LTDAUTOLOAD.LTDMAIN.BSS_END; + + } > check.LTDMAIN + +} diff --git a/build/nand_formatter/ARM7/formatter_sub.lsf b/build/nand_formatter/ARM7/formatter_sub.lsf new file mode 100644 index 0000000..390cb60 --- /dev/null +++ b/build/nand_formatter/ARM7/formatter_sub.lsf @@ -0,0 +1,79 @@ +#---------------------------------------------------------------------------- +# Project: TwlSDK - demos - FATFS - formatter - formatter_sub +# File: mongoose.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# Nitro LCF SPEC FILE +# +#-------- +Static $(TARGET_NAME) +{ + Address 0x02f88000 + Library crt0.HYB.TWL.o + StackSize 1024 1024 +} + +#-------- +Autoload WRAM +{ + Address 0x037f8000 + + Library libsubpsyscall.a \ + $(CW_LIBS) \ + libos_sp.TWL$(CODEGEN).a \ + libmi_sp.TWL$(CODEGEN).a \ + libpad_sp.TWL$(CODEGEN).a \ + libpxi_sp.TWL$(CODEGEN).a \ + libstd_sp.TWL$(CODEGEN).a \ + libexi_sp.TWL$(CODEGEN).a \ + libsnd_sp.TWL$(CODEGEN).a \ + libspi_sp.TWL$(CODEGEN).a \ + libpm_sp.TWL$(CODEGEN).a \ + libcdc_sp.TWL$(CODEGEN).a \ + libtp_sp.TWL$(CODEGEN).a \ + libtpex_sp.TWL$(CODEGEN).a \ + libnvram_sp.TWL$(CODEGEN).a \ + $(ISTD_LIBS) + + Object * (.etable) + Object * (.wram) + Object $(OBJDIR)/main.o + Object $(OBJDIR)/dummy.FLXWRAM.o +} + +#-------- +Autoload MAIN +{ + Address 0x02fe0000 + Object $(OBJDIR)/dummy.FLXMAIN.o +} + +#-------- +Ltdautoload LTDWRAM +{ + Address 0x03000000 + Object * (.ltdwram) + Object $(OBJDIR)/dummy.LTDWRAM.o +} + +#-------- +Ltdautoload LTDMAIN +{ + After $(TARGET_NAME) + Object * (.ltdmain) + Object $(OBJDIR)/dummy.LTDMAIN.o + Library libfatfs_sp.TWL$(CODEGEN).a +} + diff --git a/build/nand_formatter/ARM7/formatter_sub.response.template b/build/nand_formatter/ARM7/formatter_sub.response.template new file mode 100644 index 0000000..88b1808 --- /dev/null +++ b/build/nand_formatter/ARM7/formatter_sub.response.template @@ -0,0 +1,40 @@ + + + + + -l + + + + + + + -l + + + + -og ,0 -ol + + + + + -l + + + + + + + + -l + + + + -og ,0 -ol + + + + + -l + + diff --git a/build/nand_formatter/ARM7/src/dummy.EXTWRAM.c b/build/nand_formatter/ARM7/src/dummy.EXTWRAM.c new file mode 100644 index 0000000..0f2e61f --- /dev/null +++ b/build/nand_formatter/ARM7/src/dummy.EXTWRAM.c @@ -0,0 +1,27 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +extern void Dummy_EXTWRAM(void); + +void +Dummy_EXTWRAM(void) +{ + OS_Printf("Printed from extra wram area. [%p]\n", Dummy_EXTWRAM); +} + diff --git a/build/nand_formatter/ARM7/src/dummy.FLXMAIN.c b/build/nand_formatter/ARM7/src/dummy.FLXMAIN.c new file mode 100644 index 0000000..3001470 --- /dev/null +++ b/build/nand_formatter/ARM7/src/dummy.FLXMAIN.c @@ -0,0 +1,27 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +extern void Dummy_FLXMAIN(void); + +void +Dummy_FLXMAIN(void) +{ + OS_Printf("Printed from flexible main memory area. [%p]\n", Dummy_FLXMAIN); +} + diff --git a/build/nand_formatter/ARM7/src/dummy.FLXWRAM.c b/build/nand_formatter/ARM7/src/dummy.FLXWRAM.c new file mode 100644 index 0000000..75e7057 --- /dev/null +++ b/build/nand_formatter/ARM7/src/dummy.FLXWRAM.c @@ -0,0 +1,27 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +extern void Dummy_FLXWRAM(void); + +void +Dummy_FLXWRAM(void) +{ + OS_Printf("Printed from flexible wram area. [%p]\n", Dummy_FLXWRAM); +} + diff --git a/build/nand_formatter/ARM7/src/dummy.LTDMAIN.c b/build/nand_formatter/ARM7/src/dummy.LTDMAIN.c new file mode 100644 index 0000000..48d46a1 --- /dev/null +++ b/build/nand_formatter/ARM7/src/dummy.LTDMAIN.c @@ -0,0 +1,27 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +extern void Dummy_LTDMAIN(void); + +void +Dummy_LTDMAIN(void) +{ + OS_Printf("Printed from limited main memory area. [%p]\n", Dummy_LTDMAIN); +} + diff --git a/build/nand_formatter/ARM7/src/dummy.LTDWRAM.c b/build/nand_formatter/ARM7/src/dummy.LTDWRAM.c new file mode 100644 index 0000000..aec15de --- /dev/null +++ b/build/nand_formatter/ARM7/src/dummy.LTDWRAM.c @@ -0,0 +1,27 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include + +extern void Dummy_LTDWRAM(void); + +void +Dummy_LTDWRAM(void) +{ + OS_Printf("Printed from limited wram area. [%p]\n", Dummy_LTDWRAM); +} + diff --git a/build/nand_formatter/ARM7/src/main.c b/build/nand_formatter/ARM7/src/main.c new file mode 100644 index 0000000..436aa1b --- /dev/null +++ b/build/nand_formatter/ARM7/src/main.c @@ -0,0 +1,393 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct FileProperty { + u32 size; + const char *path; +}FileProperty; + +extern void Dummy_FLXWRAM(void); +extern void Dummy_FLXMAIN(void); +#ifdef SDK_WIRELESS_IN_VRAM +extern void Dummy_EXTWRAM(void); +#endif +extern void Dummy_LTDWRAM(void); +extern void Dummy_LTDMAIN(void); + +static void Pragma_LTDWRAM(void); +static void Pragma_LTDMAIN(void); + +static void CreateDirectory( const char *pDrive, const char **ppDirList ); +static void CheckDirectory ( const char *pDrive, const char **ppDirList ); +static void CreateFile( const FileProperty *pFileList ); +static void CheckFile ( const FileProperty *pFileList ); + +// const data-------------------------------------------------------- + +// FATFS̃NX^TCY16KB +static const FileProperty s_fileList[] = { + { 128, "F:/sys/ID.sgn" }, // ASTCY͓KBgB + { 4096, "F:/sys/HWINFO.dat" }, + { 4096, "F:/shared1/TWLCFG0.dat" }, + { 4096, "F:/shared1/TWLCFG1.dat" }, // ~[ + { 4096, "F:/shared1/WIFICFG0.dat" }, + { 4096, "F:/shared1/WIFICFG1.dat" }, // ~[ + { 0, NULL }, +}; + +static const char *s_pDirList0[] = { + (const char *)"sys", + (const char *)"title", + (const char *)"ticket", + (const char *)"shared1", + (const char *)"import", + (const char *)"tmp", + NULL, + }; + +static const char *s_pDirList1[] = { + (const char *)"photo", + (const char *)"shared2", + NULL, + }; + + + +/*---------------------------------------------------------------------------*/ +#include +static void +Pragma_LTDWRAM(void) +{ + OS_Printf("Printed from limited wram area by pragma. [%p]\n", Pragma_LTDWRAM); +} +#include + +/*---------------------------------------------------------------------------*/ +#include +static void +Pragma_LTDMAIN(void) +{ + OS_Printf("Printed from limited main memory area by pragma. [%p]\n", Pragma_LTDMAIN); +} +#include + + +/*---------------------------------------------------------------------------* + Name: InitializeAllocateSystem + + Description: ăVXeB + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +static void InitializeAllocateSystem(void) +{ + void *tempLo; + OSHeapHandle hh; + + OS_TPrintf("OS_GetWramSubPrivArenaLo() = %p\n", OS_GetWramSubPrivArenaLo()); + OS_TPrintf("OS_GetWramSubPrivArenaHi() = %p\n", OS_GetWramSubPrivArenaHi()); + OS_TPrintf("OS_GetWramSubArenaLo() = %p\n", OS_GetWramSubArenaLo()); + OS_TPrintf("OS_GetWramSubArenaHi() = %p\n", OS_GetWramSubArenaHi()); + OS_TPrintf("OS_GetSubPrivArenaLo() = %p\n", OS_GetSubPrivArenaLo()); + OS_TPrintf("OS_GetSubPrivArenaHi() = %p\n", OS_GetSubPrivArenaHi()); + + OS_TPrintf("call OS_SetWramSubPrivArenaHi(0x0380f980); to fix arena.\n"); + OS_SetWramSubPrivArenaHi((void*)0x0380f980); + + // ď + tempLo = OS_InitAlloc(OS_ARENA_WRAM_SUBPRIV, + OS_GetWramSubPrivArenaLo(), OS_GetWramSubPrivArenaHi(), 1); + + // A[i0NA + MI_CpuClear8(tempLo, (u32)OS_GetWramSubPrivArenaHi() - (u32)tempLo); + + // A[iʃAhXݒ + OS_SetArenaLo(OS_ARENA_WRAM_SUBPRIV, tempLo); + // q[v쐬 + hh = OS_CreateHeap(OS_ARENA_WRAM_SUBPRIV, + OS_GetWramSubPrivArenaLo(), OS_GetWramSubPrivArenaHi()); + + if (hh < 0) + { + OS_Panic("ARM7: Fail to create heap.\n"); + } + + // Jgq[vɐݒ + (void)OS_SetCurrentHeap(OS_ARENA_WRAM_SUBPRIV, hh); +} + +/*---------------------------------------------------------------------------* + Name: TwlSpMain + Description: NxN^B + Arguments: None. + Returns: None. + *---------------------------------------------------------------------------*/ +void +TwlSpMain(void) +{ + int nand_fat_partition_num; + + OS_Init(); + SPI_Init(2); + OS_InitTick(); + OS_InitAlarm(); + OS_InitThread(); + (void)PAD_InitXYButton(); + InitializeAllocateSystem(); + + // 荞݂̗L + (void)OS_EnableIrq(); + (void)OS_EnableInterrupts(); + + // FATFSCupq[v𐶐 (}IARM9̋󔒕Ԏ؂) + { + OSHeapHandle hh; + u8 *lo = (u8*)0x02A00000; // OS_GetSubPrivArenaLo() + u8 *hi = (u8*)0x02B00000; // OS_GetSubPrivArenaHi() + OS_SetSubPrivArenaLo(OS_InitAlloc(OS_ARENA_MAIN_SUBPRIV, lo, hi, 1)); + hh = OS_CreateHeap(OS_ARENA_MAIN_SUBPRIV, lo + 32, hi - 32); + OS_SetCurrentHeap(OS_ARENA_MAIN_SUBPRIV, hh); + } + + // FATFSCuSDIOFATp[T + if(!FATFS_Init(FATFS_DMA_NOT_USE, 8)) + { + OS_TPanic("FATFS_Init() failed.\n"); + } + + // NANDtH[}bg + { +#define FATAL_ERROR() do {} while (TRUE) + // ҏWASDKFATFS_Init̓p[^CKvB +#define NAND_SIZE 245 // 256MB mobiNANDł̎gp”\TCYiiNANDł͈ႤlɂȂBBj +#define PARTITION_RAW_SIZE 4 +#define PARTITION_0_SIZE 213 +#define PARTITION_1_SIZE ( NAND_SIZE - PARTITION_RAW_SIZE - PARTITION_0_SIZE ) +#define NAND_FAT_PARTITION_NUM 2 // FATp[eBViRAWp[eBVj + + int i; + + /* p[eBVTCYvvgݒ */ + u32 partition_MB_size[5]; + partition_MB_size[0] = PARTITION_RAW_SIZE; // RAẄ + partition_MB_size[1] = PARTITION_0_SIZE; // FAT0̈ + partition_MB_size[2] = PARTITION_1_SIZE; // FAT1̈ + nand_fat_partition_num = NAND_FAT_PARTITION_NUM; + + for( i=0; imain_ram_address = 0x00000000; + } + + while (TRUE) + { + OS_Halt(); + } +} + + +// fBNg쐬 +static void CreateDirectory( const char *pDrive, const char **ppDirList ) +{ + // ftHghCu̎w + OS_TPrintf( "\nCreate directory : %s\n", pDrive ); + if( !FATFS_SetDefaultDrive( pDrive ) ) { + FATAL_ERROR(); + } + // w肳ꂽfBNg[gɍ쐬 + while( *ppDirList ) { + OS_TPrintf( " %s...", *ppDirList ); + if( !FATFS_CreateDirectory( *ppDirList, "rwxrwxrwx") ) { + OS_TPrintf( "ng.\n" ); + FATAL_ERROR(); + } + OS_TPrintf( "ok.\n" ); + ppDirList++; + } +} + + +// fBNg݃`FbN +static void CheckDirectory( const char *pDrive, const char **ppDirList ) +{ + // ftHghCu̎w + OS_TPrintf( "\nCheck directory : %s\n", pDrive ); + if( !FATFS_SetDefaultDrive( pDrive ) ) { + FATAL_ERROR(); + } + + // w肳ꂽfBNg`FbN + while( *ppDirList ) { + FATFSDirectoryHandle dir = FATFS_OpenDirectory( *ppDirList, "rw"); + OS_TPrintf( " %s...", *ppDirList ); + if (dir != NULL) + { + OS_TPrintf( "ok.\n" ); + (void)FATFS_CloseDirectory( dir ); + }else { + OS_TPrintf( "ng.\n" ); + FATAL_ERROR(); + } + ppDirList++; + } +} + + +// t@C쐬 +static void CreateFile( const FileProperty *pFileList ) +{ + // ftHghCu̎w + OS_TPrintf( "\nCreate File :\n" ); + + // w肳ꂽfBNg[gɍ쐬 + while( pFileList->path ) { + FATFSFileHandle file; + + OS_TPrintf( " %s, %dbytes...", pFileList->path, pFileList->size ); + if( !FATFS_CreateFile( pFileList->path, TRUE, "rwxrwxrwx" ) ) { + OS_TPrintf( "ng.\n" ); + FATAL_ERROR(); + } + file = FATFS_OpenFile( pFileList->path, "w" ); + if( !file ) { + OS_TPrintf( "ng.\n" ); + FATAL_ERROR(); + } + if( !FATFS_SetFileLength( file, (int)pFileList->size ) ) { + OS_TPrintf( "ng.\n" ); + FATAL_ERROR(); + } + (void)FATFS_CloseFile( file ); + OS_TPrintf( "ok.\n" ); + pFileList++; + } +} + + +// t@C`FbN +static void CheckFile( const FileProperty *pFileList ) +{ + // ftHghCu̎w + OS_TPrintf( "\nCheck File :\n" ); + + // w肳ꂽfBNg[gɍ쐬 + while( pFileList->path ) { + FATFSFileHandle file; + + OS_TPrintf( " %s, %dbytes...", pFileList->path, pFileList->size ); + file = FATFS_OpenFile( pFileList->path, "r" ); + if( !file ) { + OS_TPrintf( "ng.\n" ); + FATAL_ERROR(); + } + if( FATFS_GetFileLength( file ) != pFileList->size ) { + OS_TPrintf( "ng. size = %d\n", FATFS_GetFileLength( file ) ); + FATAL_ERROR(); + } + (void)FATFS_CloseFile( file ); + OS_TPrintf( "ok.\n" ); + pFileList++; + } +} + diff --git a/build/nand_formatter/ARM9/Makefile b/build/nand_formatter/ARM9/Makefile new file mode 100644 index 0000000..780ac45 --- /dev/null +++ b/build/nand_formatter/ARM9/Makefile @@ -0,0 +1,42 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-18 #$ +# $Rev: 972 $ +# $Author: hatamoto_minoru $ +#---------------------------------------------------------------------------- + +TARGET_PLATFORM = TWL + +TWL_PROC = ARM9 +#TWL_ARCHGEN = LIMITED +TARGET_BIN = formatter.srl + +MAKEROM_ARM7_BASE = ../ARM7/bin/$(TWL_BUILDTYPE_ARM7)/formatter_sub +MAKEROM_ARM7 = $(MAKEROM_ARM7_BASE).tef + +SRCS = main.c + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +SUBDIRS = ../ARM7 + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/nand_formatter/ARM9/src/main.c b/build/nand_formatter/ARM9/src/main.c new file mode 100644 index 0000000..6446b4d --- /dev/null +++ b/build/nand_formatter/ARM9/src/main.c @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + + +#include +#include +#include + + +//================================================================================ + + +/*---------------------------------------------------------------------------* + Name: VBlankIntr + + Description: VBlank interrupt handler + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static void VBlankIntr(void) +{ + //---- check interrupt flag + OS_SetIrqCheckFlag(OS_IE_V_BLANK); +} + +/*---------------------------------------------------------------------------* + Name: NitroMain + + Description: main + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void NitroMain(void) +{ + OS_InitArena(); + PXI_Init(); + OS_InitLock(); + OS_InitArenaEx(); + OS_InitIrqTable(); + OS_SetIrqStackChecker(); + MI_Init(); + OS_InitVAlarm(); + OSi_InitVramExclusive(); + OS_InitThread(); + OS_InitReset(); + OS_Init(); + GX_Init(); + + (void)OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr); + (void)OS_EnableIrqMask(OS_IE_V_BLANK); + (void)OS_EnableIrq(); + (void)GX_VBlankIntr(TRUE); + + FATFS_Init(); + + // ARM7̃tH[}bgʒm҂ (ĂƂ΂₭ȕ@ŒʒmĂ) + OS_TPrintf("now formatting NAND partitions...\n"); + { + const CARDRomHeader *header = CARD_GetOwnRomHeader(); + while (*(u32 *)header->main_ram_address != 0x00000000) + { + OS_WaitVBlankIntr(); + } + } + + OS_TPrintf("format has completed!\n"); + OS_Terminate(); +} + + +/*====== End of main.c ======*/ diff --git a/build/nand_formatter/Makefile b/build/nand_formatter/Makefile new file mode 100644 index 0000000..aa8f3c0 --- /dev/null +++ b/build/nand_formatter/Makefile @@ -0,0 +1,34 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - firmware +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + ARM7 \ + ARM9 \ + + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/nandfirm/.DS_Store b/build/nandfirm/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..728f19e80b56ea095a30c5003aa7ed404d6cf809 GIT binary patch literal 6148 zcmeHKy-ve05I#eO2q@~v=ojeFHwaZ2n7c62A4)4FBr0UjBk%}}@DMD#3oFmScRmX> zO5=zH0lJgUpL4#meP3l?O+;o=EyqMdB8s7m(Gi+G!sDzhIq;SfpmB4ID5DuwbVrMp zw;GfIW#G3lz-M4pwDj!j&n*83$MYe5Mo<5tEzer4ldD8{W0 zyLIkl5ye;xnidj9Kmg6OXkZED-%8;AqfB8Te5KJ^>X1iFW`1 literal 0 HcmV?d00001 diff --git a/build/nandfirm/Makefile b/build/nandfirm/Makefile new file mode 100644 index 0000000..c74b708 --- /dev/null +++ b/build/nandfirm/Makefile @@ -0,0 +1,35 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - firmware +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + nandfirm-print \ + sdmc-launcher \ + menu-launcher \ + + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/nandfirm/menu-launcher/ARM7/Makefile b/build/nandfirm/menu-launcher/ARM7/Makefile new file mode 100644 index 0000000..2513f59 --- /dev/null +++ b/build/nandfirm/menu-launcher/ARM7/Makefile @@ -0,0 +1,51 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - tools - menu-launcher +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +FIRM_PROC = ARM7 +FIRM_TARGET = FIRM + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = menu_launcher7.tef + +SRCS = main.c + +CRT0_O = crt0_firm.o + +#LCFILE_TEMPLATE = $(FIRM_SPECDIR)/$(FIRM_PROC)-$(FIRM_PLATFORM)-PARTNER.lcf.template + +#SRCDIR = # using default +#LCFILE = # using default + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +LLIBRARIES = libaes_sp$(TWL_LIBSUFFIX).a + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/nandfirm/menu-launcher/ARM7/main.c b/build/nandfirm/menu-launcher/ARM7/main.c new file mode 100644 index 0000000..a84cee9 --- /dev/null +++ b/build/nandfirm/menu-launcher/ARM7/main.c @@ -0,0 +1,182 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - nandfirm - menu-launcher + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include + +#define FATFS_HEAP_SIZE (64*1024) // FATFSpq[v (TCYKv) + +#define BOOT_DEVICE FATFS_MEDIA_TYPE_NAND +#define PARTITION_NO 0 // Ώۃp[eBV + +#define DRIVE_LETTER 'A' // }EghCu +#define DRIVE_NO (DRIVE_LETTER - 'A') // }EghCuԍ + +static u8 fatfsHeap[FATFS_HEAP_SIZE] __attribute__ ((aligned (32))); + +static SDPortContextData nandContext; // ꎞҔp (ɓnȂSHARED̂ǂ̃AhXɂ) + +#ifndef SDK_FINALROM +static u8 step = 0x80; +#endif + +/* + Profile +*/ +#ifndef SDK_FINALROM +#define PRFILE_MAX 128 +u32 profile[PRFILE_MAX]; +u32 pf_cnt = 0; +#endif + +/*************************************************************** + PreInit + + FromBoot̑Ή܂Ƃ߂違C̏ + OS_InitOȂ̂Œ (ARM9ɂ郁CŏȂ悤ɒ) +***************************************************************/ +static void PreInit(void) +{ + + /* + FromBrom֘A + */ + + /* ͂ǂցH */ + + // NANDp[^̑Ҕ + nandContext = OSi_GetFromBromAddr()->SDNandContext; + + MIi_CpuClearFast( 0, (void*)OSi_GetFromBromAddr(), sizeof(OSFromBromBuf) ); +} + +/*************************************************************** + EraseAll + + sI܂ + 낢Ă + DS[hɂďÎ悢H +***************************************************************/ +static void EraseAll(void) +{ +#ifdef SDK_FINALROM + // TODO +#endif +} + +void TwlSpMain( void ) +{ + // OS_InitDebugLED and OS_SetDebugLED are able to call after OS_Init +#ifndef SDK_FINALROM + I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x03, 0x00); + I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x01, ++step); +#endif + + PreInit(); + +#ifndef SDK_FINALROM + I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x01, ++step); + + // 0: before PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + OS_InitFIRM(); + +#ifndef SDK_FINALROM + // 1: after PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + OS_SetDebugLED(++step); + + PM_InitFIRM(); + +#ifndef SDK_FINALROM + // 2: after PM + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + OS_SetDebugLED(++step); + + /* FATFSCupɃJgq[vɐݒ */ + { + { + OSHeapHandle hh; + u8 *lo = (u8*)fatfsHeap; + u8 *hi = (u8*)fatfsHeap + FATFS_HEAP_SIZE; + lo = OS_InitAlloc(OS_ARENA_MAIN_SUBPRIV, lo, hi, 1); + OS_SetArenaLo(OS_ARENA_MAIN_SUBPRIV, lo); + hh = OS_CreateHeap(OS_ARENA_MAIN_SUBPRIV, OS_GetSubPrivArenaLo(), hi); + OS_SetCurrentHeap(OS_ARENA_MAIN_SUBPRIV, hh); + } + } + + OS_SetDebugLED(++step); + + if ( FATFS_InitFIRM( &nandContext ) ) + { +#ifndef SDK_FINALROM + // 3: after FATFS + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + OS_SetDebugLED(++step); + + if ( FATFS_MountDriveFIRM( DRIVE_NO, BOOT_DEVICE, PARTITION_NO ) ) + { + BOOL result; +#ifndef SDK_FINALROM + // 4: after Mount + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + OS_SetDebugLED(++step); + + result = FATFS_OpenRecentMenu( DRIVE_NO ); + + if ( result ) + { +#ifndef SDK_FINALROM + // 5: after Open + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + OS_SetDebugLED(++step); + + if ( FATFS_LoadHeader() && FATFS_LoadStatic() ) + { +#ifndef SDK_FINALROM + // 127: before Boot + pf_cnt = PRFILE_MAX-1; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + OS_SetDebugLED(++step); + + FATFS_Boot(); + } + } + } + } + + OS_SetDebugLED( (u8)(0xF0 | step)); + + EraseAll(); + + // failed + while (1) + { + PXI_NotifyID( FIRM_PXI_ID_NULL ); + } +} + diff --git a/build/nandfirm/menu-launcher/ARM9/Makefile b/build/nandfirm/menu-launcher/ARM9/Makefile new file mode 100644 index 0000000..c426b86 --- /dev/null +++ b/build/nandfirm/menu-launcher/ARM9/Makefile @@ -0,0 +1,50 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - nandfirm - menu-launcher +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +FIRM_TARGET = FIRM + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = menu_launcher9.tef + +SRCS = main.c + +CRT0_O = crt0_firm.o + +#LCFILE_TEMPLATE = $(FIRM_SPECDIR)/$(FIRM_PROC)-$(FIRM_PLATFORM)-PARTNER.lcf.template + +#SRCDIR = # using default +#LCFILE = # using default + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/nandfirm/menu-launcher/ARM9/main.c b/build/nandfirm/menu-launcher/ARM9/main.c new file mode 100644 index 0000000..a208eab --- /dev/null +++ b/build/nandfirm/menu-launcher/ARM9/main.c @@ -0,0 +1,134 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - nandfirm - menu-launcher + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include + +/* ͂ǂցH */ +#define RSA_KEY_ADDR OSi_GetFromBromAddr()->rsa_pubkey[7] + +#define RSA_HEAP_SIZE (4*1024) // RSApq[vTCY (TCYKv) + +static u8 acHeap[RSA_HEAP_SIZE] __attribute__ ((aligned (32))); +static SVCSignHeapContext acPool; + +/* + PROFILE_ENABLE `Ƃx̃ptH[}X`FbNł܂B + p邽߂ɂ́Amain.cǂɁAu32 profile[256]; u32 pf_cnt = 0; + `Kv܂B +*/ +#define PROFILE_ENABLE + +#ifdef SDK_FINALROM // FINALROMŖ +#undef PROFILE_ENABLE +#endif + +#ifdef PROFILE_ENABLE +#define PRFILE_MAX 128 +u32 profile[PRFILE_MAX]; +u32 pf_cnt = 0; +#endif + +/*************************************************************** + PreInit + + FromBoot̑Ή܂Ƃ߂違C̏ + OS_InitOȂ̂Œ +***************************************************************/ +static void PreInit(void) +{ + /* + C֘A + */ + + // SHARED̈NA (IS-TWL-DEBUGGER̍XV҂) +#ifdef SDK_FINALROM + MIi_CpuClearFast( 0, (void*)HW_MAIN_MEM_SHARED, HW_MAIN_MEM_SHARED_END-HW_MAIN_MEM_SHARED ); +#endif + + /* + FromBrom֘A + */ + + /* ͂ǂցH */ + + MIi_CpuClearFast( 0, (void*)OSi_GetFromBromAddr(), sizeof(OSFromBromBuf) ); +} + +/*************************************************************** + CheckHeader + + wb_VXej[ƂĖȂ`FbN + 擪32B͌ŒlƎv (}X^[o[W͈Ⴄ) +***************************************************************/ +static BOOL CheckHeader(void) +{ + // TODO + return TRUE; +} + +/*************************************************************** + EraseAll + + sI܂ + 낢Ă + DS[hɂďÎ悢H +***************************************************************/ +static void EraseAll(void) +{ +#ifdef SDK_FINALROM + // TODO +#endif +} + +void TwlMain( void ) +{ + PreInit(); + +#ifdef PROFILE_ENABLE + // 0: before PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + OS_InitFIRM(); +#ifdef PROFILE_ENABLE + OS_InitTick(); + // 1: after PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + SVC_InitSignHeap( &acPool, acHeap, sizeof(acHeap) ); + + // load menu + if ( MI_LoadHeader( &acPool, RSA_KEY_ADDR ) && CheckHeader() && MI_LoadStatic() ) + { +#ifdef PROFILE_ENABLE + // 127: before Boot + pf_cnt = PRFILE_MAX-1; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + MI_Boot(); + } + + EraseAll(); + + // failed + while (1) + { + PXI_NotifyID( FIRM_PXI_ID_NULL ); + } +} + diff --git a/build/nandfirm/menu-launcher/Makefile b/build/nandfirm/menu-launcher/Makefile new file mode 100644 index 0000000..b4674eb --- /dev/null +++ b/build/nandfirm/menu-launcher/Makefile @@ -0,0 +1,59 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - nandfirm - menu-launcher +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + + +FIRM_TARGET = FIRM + +# if you have valid keys, set environment value like below +#export TWL_KEYSDIR='$(FIRM_ROOT)/../twl_firmware/bootrom/build/keys' + + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + ARM7 \ + ARM9 \ + wram_regs \ + +TARGET_FIRM_BIN = menu_launcher.nand menu_launcher.srl +BINDIR = . +MAKEFIRM_ARM9 = ARM9/bin/ARM9-$(FIRM_PLATFORM)$(CODEGEN_ARCH)/$(FIRM_BUILD_DIR)/menu_launcher9.tef +MAKEFIRM_ARM7 = ARM7/bin/ARM7-$(FIRM_PLATFORM)$(CODEGEN_ARCH)/$(FIRM_BUILD_DIR)/menu_launcher7.tef +MAKEFIRM_RSA_PRVKEY = $(TWL_KEYSDIR)/rsa/private_nand.der +LDEPENDS_BIN += wram_regs/wram_regs.rbin + +MAKEROM_ARM7_BASE = $(basename $(MAKEFIRM_ARM7)) +MAKEROM_FLAGS += -F + +NITRO_MAKEROM = TRUE +MAKEFIRM_FLAGS += -p +FIRM_SPEC = nandfirm.nandsf + +LDIRT_CLEAN += $(TARGETS) \ + $(basename $(firstword $(TARGETS))).tlf \ + rsa_public.sbin \ + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build: $(TARGET_BIN) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/nandfirm/menu-launcher/nandfirm.nandsf b/build/nandfirm/menu-launcher/nandfirm.nandsf new file mode 100644 index 0000000..84c9ff2 --- /dev/null +++ b/build/nandfirm/menu-launcher/nandfirm.nandsf @@ -0,0 +1,24 @@ +#NANDSF --- Nandfirm Spec File + +VERSION : GENERATE + +RSA_KEY : $(MAKEFIRM_RSA_PRVKEY) +OUT_KEY : rsa_public.sbin + +WRAM_RBIN: ./wram_regs/wram_regs.rbin + +MIRROR_OFS: 0x100000 + +DECOMP_PROC : ARM9 # ARM9 or ARM7 + +ARM9_COMP : FALSE # TRUE or FALSE, should be before ARM9_SBIN +ARM9_SBIN : $(MAKEFIRM_ARM9).FLX.TWL.sbin +ARM9_ELF : $(MAKEFIRM_ARM9).tef + +ARM7_COMP : FALSE # TRUE or FALSE, should be before ARM7_SBIN +ARM7_SBIN : $(MAKEFIRM_ARM7).FLX.TWL.sbin +ARM7_ELF : $(MAKEFIRM_ARM7).tef + +ARM9_X2 : TRUE # TRUE or FALSE + +NCD_ROMOFS : 0x07fe00 diff --git a/build/nandfirm/menu-launcher/wram_regs/Makefile b/build/nandfirm/menu-launcher/wram_regs/Makefile new file mode 100644 index 0000000..cb6c305 --- /dev/null +++ b/build/nandfirm/menu-launcher/wram_regs/Makefile @@ -0,0 +1,48 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - tools - norfirm-print +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = wram_regs.rbin + +SRCS = \ + wram_regs.c \ + +#SRCDIR = # using default +#LCFILE = # using default + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_DIR = . +INSTALL_TARGETS = $(BINDIR)/$(TARGET_BIN) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/nandfirm/menu-launcher/wram_regs/wram_regs.c b/build/nandfirm/menu-launcher/wram_regs/wram_regs.c new file mode 100644 index 0000000..bafe67b --- /dev/null +++ b/build/nandfirm/menu-launcher/wram_regs/wram_regs.c @@ -0,0 +1,91 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - nandfirm + File: wram_regs.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include + +MIHeader_WramRegs wram_regs_init = +{ + // ARM9 + { + REG_MI_MBK_A0_FIELD( 1, MI_WRAM_A_OFFSET_0KB , MI_WRAM_ARM9 ), + REG_MI_MBK_A1_FIELD( 1, MI_WRAM_A_OFFSET_64KB , MI_WRAM_ARM9 ), + REG_MI_MBK_A2_FIELD( 1, MI_WRAM_A_OFFSET_128KB, MI_WRAM_ARM9 ), + REG_MI_MBK_A3_FIELD( 1, MI_WRAM_A_OFFSET_192KB, MI_WRAM_ARM9 ), + }, + { + REG_MI_MBK_B0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM7 ), + }, + { + REG_MI_MBK_C0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_C1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM7 ), + REG_MI_MBK_C2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_C3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM7 ), + REG_MI_MBK_C4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_C5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM7 ), + REG_MI_MBK_C6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM7 ), + REG_MI_MBK_C7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM7 ), + }, + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, HW_WRAM_AREA_HALF + 0x00040000 ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, HW_WRAM_AREA_HALF ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, HW_WRAM_AREA_HALF + 0x00080000 ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, HW_WRAM_AREA_HALF + 0x00040000 ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, MI_WRAM_MAP_NULL ) + ), + + // ARM7 + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, MI_WRAM_MAP_NULL ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, HW_WRAM_AREA_HALF + 0x00080000 ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, HW_WRAM_AREA_HALF + 0x00040000 ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, HW_WRAM_AREA_HALF + 0x00040000 ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, HW_WRAM_AREA_HALF ) + ), + + // WRAM Lock + { + 0, + 0, + 0, + }, + + // WRAM-0/1 + 3, + + // VRAM-C + 7, + // VRAM-D + 7, +}; + diff --git a/build/nandfirm/nandfirm-print/Makefile b/build/nandfirm/nandfirm-print/Makefile new file mode 100644 index 0000000..b92d2c1 --- /dev/null +++ b/build/nandfirm/nandfirm-print/Makefile @@ -0,0 +1,50 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - build +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + + +FIRM_TARGET = FIRM + + +#---------------------------------------------------------------------------- + +SUBDIRS = ../../norfirm/norfirm-print + +TARGET_FIRM_BIN = nandfirm_print.nand +BINDIR = . +MAKEFIRM_ARM9 = ../../norfirm/norfirm-print/ARM9/bin/ARM9-$(FIRM_PLATFORM)$(CODEGEN_ARCH)/$(FIRM_BUILD_DIR)/twl_norfirm9_print.tef +MAKEFIRM_ARM7 = ../../norfirm/norfirm-print/ARM7/bin/ARM7-$(FIRM_PLATFORM)$(CODEGEN_ARCH)/$(FIRM_BUILD_DIR)/twl_norfirm7_print.tef +MAKEFIRM_RSA_PRVKEY = $(TWL_KEYSDIR)/rsa/private_nand.der +LDEPENDS_BIN += ../../norfirm/norfirm-print/wram_regs/wram_regs.rbin + +NITRO_MAKEROM = TRUE +MAKEFIRM_FLAGS += -p +FIRM_SPEC = nandfirm-BB.nandsf + +LDIRT_CLEAN += $(BINDIR)/$(TARGET_BIN) \ + rsa_public.sbin \ + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build: $(TARGET_BIN) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/nandfirm/nandfirm-print/nandfirm-BB.nandsf b/build/nandfirm/nandfirm-print/nandfirm-BB.nandsf new file mode 100644 index 0000000..71e6491 --- /dev/null +++ b/build/nandfirm/nandfirm-print/nandfirm-BB.nandsf @@ -0,0 +1,24 @@ +#NANDSF --- Nandfirm Spec File + +VERSION : GENERATE + +RSA_KEY : $(MAKEFIRM_RSA_PRVKEY) +OUT_KEY : rsa_public.sbin + +WRAM_RBIN: ../../norfirm/norfirm-print/wram_regs/wram_regs.rbin + +MIRROR_OFS: 0x100000 + +DECOMP_PROC : ARM9 # ARM9 or ARM7 + +ARM9_COMP : FALSE # TRUE or FALSE, should be before ARM9_SBIN +ARM9_SBIN : $(MAKEFIRM_ARM9).FLX.TWL.sbin +ARM9_ELF : $(MAKEFIRM_ARM9).tef + +ARM7_COMP : FALSE # TRUE or FALSE, should be before ARM7_SBIN +ARM7_SBIN : $(MAKEFIRM_ARM7).FLX.TWL.sbin +ARM7_ELF : $(MAKEFIRM_ARM7).tef + +ARM9_X2 : TRUE # TRUE or FALSE + +NCD_ROMOFS : 0x07fe00 diff --git a/build/nandfirm/sdmc-launcher/ARM7/Makefile b/build/nandfirm/sdmc-launcher/ARM7/Makefile new file mode 100644 index 0000000..8a02e2d --- /dev/null +++ b/build/nandfirm/sdmc-launcher/ARM7/Makefile @@ -0,0 +1,51 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - nandfirm - sdmc-launcher +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +FIRM_PROC = ARM7 +FIRM_TARGET = FIRM + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = sdmc_launcher7.tef + +SRCS = main.c + +CRT0_O = crt0_firm.o + +#LCFILE_TEMPLATE = $(FIRM_SPECDIR)/$(FIRM_PROC)-$(FIRM_PLATFORM)-PARTNER.lcf.template + +#SRCDIR = # using default +#LCFILE = # using default + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +LLIBRARIES = libaes_sp$(TWL_LIBSUFFIX).a + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/nandfirm/sdmc-launcher/ARM7/main.c b/build/nandfirm/sdmc-launcher/ARM7/main.c new file mode 100644 index 0000000..110f81a --- /dev/null +++ b/build/nandfirm/sdmc-launcher/ARM7/main.c @@ -0,0 +1,222 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - nandfirm - sdmc-launcher + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include + +#define FATFS_HEAP_SIZE (64*1024) // FATFSpq[v (TCYKv) + +#define BOOT_DEVICE FATFS_MEDIA_TYPE_SD +#define PARTITION_NO 0 // 0Œ +#define MENU_FILE (char*)L"A:\\menu.srl" // Ώۃt@C(DRIVE_LETTERƍ킹邱) +#define MENU_FILE_A (char*)L"A:\\menu_a.srl" // Ώۃt@C(DRIVE_LETTERƍ킹邱) +#define MENU_FILE_B (char*)L"A:\\menu_b.srl" // Ώۃt@C(DRIVE_LETTERƍ킹邱) +#define MENU_FILE_L (char*)L"A:\\menu_l.srl" // Ώۃt@C(DRIVE_LETTERƍ킹邱) +#define MENU_FILE_R (char*)L"A:\\menu_r.srl" // Ώۃt@C(DRIVE_LETTERƍ킹邱) + +#define DRIVE_LETTER 'A' // }EghCu +#define DRIVE_NO (DRIVE_LETTER - 'A') // }EghCuԍ + +static u8 fatfsHeap[FATFS_HEAP_SIZE] __attribute__ ((aligned (32))); + +static SDPortContextData nandContext; // ꎞҔp (ɓnȂSHARED̂ǂ̃AhXɂ) + +#ifndef SDK_FINALROM +static u8 step = 0x80; +#endif + +/* + Profile +*/ +#ifndef SDK_FINALROM +#define PROFILE_MAX 0x100 +u32 profile[PROFILE_MAX]; +u32 pf_cnt = 0; +#endif + +/*************************************************************** + PreInit + + FromBoot̑Ή܂Ƃ߂違C̏ + OS_InitOȂ̂Œ (ARM9ɂ郁CŏȂ悤ɒ) +***************************************************************/ +static void PreInit(void) +{ + + /* + FromBrom֘A + */ + + // NANDp[^̑Ҕ + nandContext = OSi_GetFromBromAddr()->SDNandContext; + + MIi_CpuClearFast( 0, (void*)OSi_GetFromBromAddr(), sizeof(OSFromBromBuf) ); +} + +/*************************************************************** + EraseAll + + sI܂ + 낢Ă + DS[hɂďÎ悢H +***************************************************************/ +static void EraseAll(void) +{ +#ifdef SDK_FINALROM + // TODO +#endif +} + +void TwlSpMain( void ) +{ + // OS_InitDebugLED and OS_SetDebugLED are able to call after OS_Init +#ifndef SDK_FINALROM + I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x03, 0x00); + I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x01, ++step); +#endif + + PreInit(); + +#ifndef SDK_FINALROM + I2Ci_WriteRegister(I2C_SLAVE_DEBUG_LED, 0x01, ++step); + + // 0: before PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSecondsBROM(OS_GetTick()); +#endif + + OS_InitFIRM(); + OS_EnableIrq(); // PMOS_InitTick()gĂ̂ (łgĂH) + +#ifndef SDK_FINALROM + //OS_EnableIrq(); + // 1: after PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + OS_SetDebugLED(++step); + + PM_InitFIRM(); + PM_BackLightOn( FALSE ); + +#ifndef SDK_FINALROM + // 2: after PM + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + OS_SetDebugLED(++step); + + /* FATFSCupɃJgq[vݒ */ + /* WRAMfatfsHeapCq[vƂēo^Ă */ + { + OSHeapHandle hh; + u8 *lo = (u8*)fatfsHeap; + u8 *hi = (u8*)fatfsHeap + FATFS_HEAP_SIZE; + lo = OS_InitAlloc(OS_ARENA_MAIN_SUBPRIV, lo, hi, 1); + OS_SetArenaLo(OS_ARENA_MAIN_SUBPRIV, lo); + hh = OS_CreateHeap(OS_ARENA_MAIN_SUBPRIV, OS_GetSubPrivArenaLo(), hi); + OS_SetCurrentHeap(OS_ARENA_MAIN_SUBPRIV, hh); + } + + OS_SetDebugLED(++step); + + if ( FATFS_InitFIRM( &nandContext ) ) + { +#ifndef SDK_FINALROM + // 3: after FATFS + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + OS_SetDebugLED(++step); + PM_BackLightOn( FALSE ); + + if ( FATFS_MountDriveFIRM( DRIVE_NO, BOOT_DEVICE, PARTITION_NO ) ) + { + BOOL result; +#ifndef SDK_FINALROM + // 4: after Mount + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + OS_SetDebugLED(++step); + PM_BackLightOn( FALSE ); + + switch ( PAD_Read() & PAD_KEYPORT_MASK ) + { + case 0: + result = FATFS_OpenSpecifiedSrl( MENU_FILE ); + break; + case PAD_BUTTON_A: + result = FATFS_OpenSpecifiedSrl( MENU_FILE_A ); + break; + case PAD_BUTTON_B: + result = FATFS_OpenSpecifiedSrl( MENU_FILE_B ); + break; + case PAD_BUTTON_L: + result = FATFS_OpenSpecifiedSrl( MENU_FILE_L ); + break; + case PAD_BUTTON_R: + result = FATFS_OpenSpecifiedSrl( MENU_FILE_R ); + break; + default: + OS_SetDebugLED( (u8)(PAD_Read() & PAD_KEYPORT_MASK) ); + OS_Terminate(); + break; + } + + if ( result ) + { +#ifndef SDK_FINALROM + // 5: after Open + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + OS_SetDebugLED(++step); + PM_BackLightOn( FALSE ); + + if ( FATFS_LoadHeader() && FATFS_LoadStatic() ) + { +#ifndef SDK_FINALROM + // 127: before Boot + pf_cnt = PROFILE_MAX-1; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); + { + int i; + PXI_RecvID(); + OS_TPrintf("\n[ARM7] Begin\n"); + for (i = 0; i < PROFILE_MAX; i++) + { + OS_TPrintf("0x%08X\n", profile[i]); + } + OS_TPrintf("\n[ARM7] End\n"); + } +#endif + OS_SetDebugLED(++step); + PM_BackLightOn( TRUE ); // last chance + + FATFS_Boot(); + } + } + } + } + + OS_SetDebugLED( (u8)(0xF0 | step)); + + EraseAll(); + + // failed + while (1) + { + PXI_NotifyID( FIRM_PXI_ID_NULL ); + } +} + diff --git a/build/nandfirm/sdmc-launcher/ARM9/Makefile b/build/nandfirm/sdmc-launcher/ARM9/Makefile new file mode 100644 index 0000000..8e9e540 --- /dev/null +++ b/build/nandfirm/sdmc-launcher/ARM9/Makefile @@ -0,0 +1,50 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - nandfirm - sdmc-launcher +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +FIRM_TARGET = FIRM + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = sdmc_launcher9.tef + +SRCS = main.c + +CRT0_O = crt0_firm.o + +#LCFILE_TEMPLATE = $(FIRM_SPECDIR)/$(FIRM_PROC)-$(FIRM_PLATFORM)-PARTNER.lcf.template + +#SRCDIR = # using default +#LCFILE = # using default + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/nandfirm/sdmc-launcher/ARM9/main.c b/build/nandfirm/sdmc-launcher/ARM9/main.c new file mode 100644 index 0000000..a6d3631 --- /dev/null +++ b/build/nandfirm/sdmc-launcher/ARM9/main.c @@ -0,0 +1,173 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - nandfirm - sdmc-launcher + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include + +#define RSA_KEY_ADDR rsa_key +static const u8 rsa_key[128] = +{ + 0xdf, 0x56, 0x30, + 0xc9, 0xae, 0x05, 0x55, 0xe8, 0xdf, 0xbe, 0xe6, 0xb9, 0x30, 0xb9, 0x76, 0x93, 0xb4, 0xc2, 0x20, + 0xe7, 0xae, 0x4c, 0x3e, 0xc3, 0xed, 0x27, 0xcf, 0x5d, 0x4f, 0xb5, 0x7d, 0xde, 0x38, 0xbc, 0xfe, + 0x25, 0x32, 0xd8, 0x23, 0x98, 0x52, 0xb5, 0xda, 0xf7, 0x39, 0xdc, 0xb3, 0x0a, 0x94, 0x7a, 0x2b, + 0x79, 0xe6, 0xe0, 0x4c, 0xbc, 0x21, 0xbd, 0x59, 0xb2, 0xc7, 0xf1, 0xc0, 0xf1, 0xfb, 0x29, 0x75, + 0xa1, 0x21, 0x93, 0x01, 0x29, 0x1c, 0x9a, 0xe1, 0x2d, 0x55, 0xfc, 0x7b, 0xb8, 0xcb, 0x07, 0x33, + 0xc5, 0x91, 0x0d, 0xc8, 0x45, 0x59, 0xef, 0xbe, 0x58, 0xc7, 0xc1, 0x1d, 0xd5, 0xf2, 0xcf, 0x1f, + 0xe0, 0x6d, 0x21, 0x00, 0xcd, 0x42, 0xd8, 0x84, 0x85, 0xe3, 0xb2, 0x02, 0x1a, 0xa5, 0x89, 0x02, + 0xa1, 0x96, 0xc6, 0xf7, 0x61, 0x68, 0x66, 0xe6, 0x65, 0x12, 0xb7, 0xf1, 0x49 +}; + +#define RSA_HEAP_SIZE (4*1024) // RSApq[vTCY (TCYKv) + +static u8 acHeap[RSA_HEAP_SIZE] __attribute__ ((aligned (32))); +static SVCSignHeapContext acPool; + +/* + Profile +*/ +#ifndef SDK_FINALROM +#define PROFILE_MAX 0x100 +u32 profile[PROFILE_MAX]; +u32 pf_cnt = 0; +#endif + +/*************************************************************** + PreInit + + FromBoot̑Ή܂Ƃ߂違C̏ + OS_InitOȂ̂Œ + MI_LoadHeaderOɂȂ(100msec)Ԃ̂ŁA”\Ȃ + OS_Initɂ낢돈I +***************************************************************/ +static void PreInit(void) +{ + /* + C֘A + */ + + // SHARED̈NA (IS-TWL-DEBUGGER̍XV҂) +#ifdef SDK_FINALROM + //MIi_CpuClearFast( 0, (void*)HW_MAIN_MEM_SHARED, HW_MAIN_MEM_SHARED_END-HW_MAIN_MEM_SHARED ); +#endif + // SHARED̈NA (OK?) + MIi_CpuClearFast( 0, (void*)HW_PXI_SIGNAL_PARAM_ARM9, HW_MAIN_MEM_SHARED_END-HW_PXI_SIGNAL_PARAM_ARM9); + + /* + FromBrom֘A + */ + + MIi_CpuClearFast( 0, (void*)OSi_GetFromBromAddr(), sizeof(OSFromBromBuf) ); +} + +/*************************************************************** + PostInit + + MI_LoadHeaderOɂȂ(100msec)Ԃ̂ŁA”\Ȃ + OS_Initɂ낢돈I + C̏ +***************************************************************/ +static void PostInit(void) +{ + /* + C֘A (ARM9p̗̈SNA) + */ + + MIi_CpuClearFast( 0, (void*)HW_DELIVER_ARG_BUF_END, HW_TWL_MAIN_MEM_MAIN_SIZE-HW_DELIVER_ARG_BUF_SIZE ); + DC_FlushAll(); +} + +/*************************************************************** + CheckHeader + + wb_VXej[ƂĖȂ`FbN + 擪32B͌ŒlƎv (}X^[o[W͈Ⴄ) +***************************************************************/ +static BOOL CheckHeader(void) +{ + return TRUE; +} + +/*************************************************************** + EraseAll + + sI܂ + 낢Ă + DS[hɂďÎ悢H +***************************************************************/ +static void EraseAll(void) +{ +#ifdef SDK_FINALROM + // TODO +#endif +} + +void TwlMain( void ) +{ + PreInit(); + +#ifndef SDK_FINALROM + // 0: before PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSecondsBROM(OS_GetTick()); +#endif + + OS_InitFIRM(); +#ifndef SDK_FINALROM + OS_EnableIrq(); + OS_InitTick(); + // 1: after PXI + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + SVC_InitSignHeap( &acPool, acHeap, sizeof(acHeap) ); + + PostInit(); + +#ifndef SDK_FINALROM + // 2: after PostInit + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); +#endif + + // load menu + if ( MI_LoadHeader( &acPool, RSA_KEY_ADDR ) && CheckHeader() && MI_LoadStatic() ) + { +#ifndef SDK_FINALROM + // 127: before Boot + pf_cnt = PROFILE_MAX-1; + profile[pf_cnt++] = (u32)OS_TicksToMicroSeconds(OS_GetTick()); + { + int i; + OS_TPrintf("\n[ARM9] Begin\n"); + for (i = 0; i < PROFILE_MAX; i++) + { + OS_TPrintf("0x%08X\n", profile[i]); + } + OS_TPrintf("\n[ARM9] End\n"); + PXI_NotifyID( FIRM_PXI_ID_NULL ); + } +#endif + + MI_Boot(); + } + + EraseAll(); + + // failed + while (1) + { + PXI_NotifyID( FIRM_PXI_ID_NULL ); + } +} + diff --git a/build/nandfirm/sdmc-launcher/Makefile b/build/nandfirm/sdmc-launcher/Makefile new file mode 100644 index 0000000..565f8a1 --- /dev/null +++ b/build/nandfirm/sdmc-launcher/Makefile @@ -0,0 +1,59 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - nandfirm - sdmc-launcher +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + + +FIRM_TARGET = FIRM + +# if you have valid keys, set environment value like below +#export TWL_KEYSDIR='$(FIRM_ROOT)/../twl_firmware/bootrom/build/keys' + + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + ARM7 \ + ARM9 \ + wram_regs \ + +TARGET_FIRM_BIN = sdmc_launcher.nand sdmc_launcher.srl +BINDIR = . +MAKEFIRM_ARM9 = ARM9/bin/ARM9-$(FIRM_PLATFORM)$(CODEGEN_ARCH)/$(FIRM_BUILD_DIR)/sdmc_launcher9.tef +MAKEFIRM_ARM7 = ARM7/bin/ARM7-$(FIRM_PLATFORM)$(CODEGEN_ARCH)/$(FIRM_BUILD_DIR)/sdmc_launcher7.tef +MAKEFIRM_RSA_PRVKEY = $(TWL_KEYSDIR)/rsa/private_nand.der +LDEPENDS_BIN += wram_regs/wram_regs.rbin + +MAKEROM_ARM7_BASE = $(basename $(MAKEFIRM_ARM7)) +MAKEROM_FLAGS += -F + +NITRO_MAKEROM = TRUE +MAKEFIRM_FLAGS += -p +FIRM_SPEC = nandfirm.nandsf + +LDIRT_CLEAN += $(TARGETS) \ + $(basename $(firstword $(TARGETS))).tlf \ + rsa_public.sbin \ + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build: $(TARGET_BIN) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/nandfirm/sdmc-launcher/nandfirm.nandsf b/build/nandfirm/sdmc-launcher/nandfirm.nandsf new file mode 100644 index 0000000..84c9ff2 --- /dev/null +++ b/build/nandfirm/sdmc-launcher/nandfirm.nandsf @@ -0,0 +1,24 @@ +#NANDSF --- Nandfirm Spec File + +VERSION : GENERATE + +RSA_KEY : $(MAKEFIRM_RSA_PRVKEY) +OUT_KEY : rsa_public.sbin + +WRAM_RBIN: ./wram_regs/wram_regs.rbin + +MIRROR_OFS: 0x100000 + +DECOMP_PROC : ARM9 # ARM9 or ARM7 + +ARM9_COMP : FALSE # TRUE or FALSE, should be before ARM9_SBIN +ARM9_SBIN : $(MAKEFIRM_ARM9).FLX.TWL.sbin +ARM9_ELF : $(MAKEFIRM_ARM9).tef + +ARM7_COMP : FALSE # TRUE or FALSE, should be before ARM7_SBIN +ARM7_SBIN : $(MAKEFIRM_ARM7).FLX.TWL.sbin +ARM7_ELF : $(MAKEFIRM_ARM7).tef + +ARM9_X2 : TRUE # TRUE or FALSE + +NCD_ROMOFS : 0x07fe00 diff --git a/build/nandfirm/sdmc-launcher/wram_regs/Makefile b/build/nandfirm/sdmc-launcher/wram_regs/Makefile new file mode 100644 index 0000000..cb6c305 --- /dev/null +++ b/build/nandfirm/sdmc-launcher/wram_regs/Makefile @@ -0,0 +1,48 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - tools - norfirm-print +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = wram_regs.rbin + +SRCS = \ + wram_regs.c \ + +#SRCDIR = # using default +#LCFILE = # using default + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_DIR = . +INSTALL_TARGETS = $(BINDIR)/$(TARGET_BIN) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/nandfirm/sdmc-launcher/wram_regs/wram_regs.c b/build/nandfirm/sdmc-launcher/wram_regs/wram_regs.c new file mode 100644 index 0000000..bafe67b --- /dev/null +++ b/build/nandfirm/sdmc-launcher/wram_regs/wram_regs.c @@ -0,0 +1,91 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - nandfirm + File: wram_regs.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include + +MIHeader_WramRegs wram_regs_init = +{ + // ARM9 + { + REG_MI_MBK_A0_FIELD( 1, MI_WRAM_A_OFFSET_0KB , MI_WRAM_ARM9 ), + REG_MI_MBK_A1_FIELD( 1, MI_WRAM_A_OFFSET_64KB , MI_WRAM_ARM9 ), + REG_MI_MBK_A2_FIELD( 1, MI_WRAM_A_OFFSET_128KB, MI_WRAM_ARM9 ), + REG_MI_MBK_A3_FIELD( 1, MI_WRAM_A_OFFSET_192KB, MI_WRAM_ARM9 ), + }, + { + REG_MI_MBK_B0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM7 ), + }, + { + REG_MI_MBK_C0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_C1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM7 ), + REG_MI_MBK_C2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_C3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM7 ), + REG_MI_MBK_C4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_C5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM7 ), + REG_MI_MBK_C6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM7 ), + REG_MI_MBK_C7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM7 ), + }, + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, HW_WRAM_AREA_HALF + 0x00040000 ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, HW_WRAM_AREA_HALF ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, HW_WRAM_AREA_HALF + 0x00080000 ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, HW_WRAM_AREA_HALF + 0x00040000 ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, MI_WRAM_MAP_NULL ) + ), + + // ARM7 + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, MI_WRAM_MAP_NULL ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, HW_WRAM_AREA_HALF + 0x00080000 ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, HW_WRAM_AREA_HALF + 0x00040000 ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, HW_WRAM_AREA_HALF + 0x00040000 ), + MI_WRAM_IMAGE_256KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, HW_WRAM_AREA_HALF ) + ), + + // WRAM Lock + { + 0, + 0, + 0, + }, + + // WRAM-0/1 + 3, + + // VRAM-C + 7, + // VRAM-D + 7, +}; + diff --git a/build/norfirm/.DS_Store b/build/norfirm/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..599a4674d1a0d3515eec86f91042d49feec0bf5a GIT binary patch literal 6148 zcmeHKT}lH%3{Gl=iU@u5aV{WI@Bm|3PtXfUtv`jXvq*jLZH}Xd@X51y55G*p(xtW5 zmx7W&^3Bd9vzc#TvmqiLKhH))Ln0bL1$##@8${Mc*Q94NvdCqRIXzKLXLJke@)sD8 zyE~yrO1QZ@TD`x9mh`f?A5Csj-RMycKel_5m|z$Uvm#a?tf4>+Wot25!!aMsFB)b=4JWqd zgYC_19SWDXWB*XxiKC)hXTTZgGH{@eL#h8)-}nFBAb)ZOoPmGE0Qaj&HO7&wwyqsc tYHfgCLq)_dE4CpRlu`^|DaEJIBA5>{07k>Ch#83g2oxIJI0JiS;0ps@Ui$z5 literal 0 HcmV?d00001 diff --git a/build/norfirm/Makefile b/build/norfirm/Makefile new file mode 100644 index 0000000..1501817 --- /dev/null +++ b/build/norfirm/Makefile @@ -0,0 +1,34 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - firmware +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + norfirm-print \ + norfirm-empty \ + + +#---------------------------------------------------------------------------- + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/norfirm/norfirm-empty/Makefile b/build/norfirm/norfirm-empty/Makefile new file mode 100644 index 0000000..32cfdec --- /dev/null +++ b/build/norfirm/norfirm-empty/Makefile @@ -0,0 +1,48 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - build +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + + +FIRM_TARGET = FIRM + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + +TARGET_FIRM_BIN = norfirm_empty.nor +BINDIR = . +MAKEFIRM_RSA_PRVKEY = $(TWL_KEYSDIR)/rsa/private_nor.der + +MAKEFIRM_ARM9 = +MAKEFIRM_ARM7 = + +NITRO_MAKEROM = TRUE +MAKEFIRM_FLAGS += -p +FIRM_SPEC = norfirm-BB.norsf + +LDIRT_CLEAN += $(BINDIR)/$(TARGET_BIN) \ + rsa_public.sbin \ + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build: $(TARGET_BIN) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/norfirm/norfirm-empty/norfirm-BB.norsf b/build/norfirm/norfirm-empty/norfirm-BB.norsf new file mode 100644 index 0000000..319e685 --- /dev/null +++ b/build/norfirm/norfirm-empty/norfirm-BB.norsf @@ -0,0 +1,8 @@ +#NORSF --- Norfirm Spec File + +VERSION : GENERATE + +BOOT_NAND : TRUE # TRUE or FALSE + +NCD_ROMOFS : 0x07fe00 + diff --git a/build/norfirm/norfirm-print/ARM7/Makefile b/build/norfirm/norfirm-print/ARM7/Makefile new file mode 100644 index 0000000..d00372e --- /dev/null +++ b/build/norfirm/norfirm-print/ARM7/Makefile @@ -0,0 +1,50 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - tools - norfirm-print +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +FIRM_PROC = ARM7 +FIRM_TARGET = FIRM + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = twl_norfirm7_print.tef + +CRT0_O = crt0_firm.o + +SRCS = \ + main.c \ + +#SRCDIR = # using default +#LCFILE = # using default + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/norfirm/norfirm-print/ARM7/main.c b/build/norfirm/norfirm-print/ARM7/main.c new file mode 100644 index 0000000..13134a0 --- /dev/null +++ b/build/norfirm/norfirm-print/ARM7/main.c @@ -0,0 +1,31 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - norfirm-print + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include + + +void TwlSpMain( void ) +{ + OS_TPrintf( "\nNOR Boot time is %d msec.\n", OS_TicksToMilliSecondsBROM32(OS_GetTick())); + + OS_InitFIRM(); + + OS_TPrintf( "\nARM7 starts.\n" ); + OS_TPrintf( "\nARM7 ends.\n" ); + + OS_Terminate(); +} + diff --git a/build/norfirm/norfirm-print/ARM9/Makefile b/build/norfirm/norfirm-print/ARM9/Makefile new file mode 100644 index 0000000..503c9c1 --- /dev/null +++ b/build/norfirm/norfirm-print/ARM9/Makefile @@ -0,0 +1,49 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - tools - norfirm-print +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +FIRM_TARGET = FIRM + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = twl_norfirm9_print.tef + +CRT0_O = crt0_firm.o + +SRCS = \ + main.c \ + +#SRCDIR = # using default +#LCFILE = # using default + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/norfirm/norfirm-print/ARM9/main.c b/build/norfirm/norfirm-print/ARM9/main.c new file mode 100644 index 0000000..08f1fdb --- /dev/null +++ b/build/norfirm/norfirm-print/ARM9/main.c @@ -0,0 +1,31 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - norfirm-print + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include + + +void TwlMain( void ) +{ + OS_TPrintf( "\nNOR Boot time is %d msec.\n", OS_TicksToMilliSecondsBROM32(OS_GetTick())); + + OS_InitFIRM(); + + OS_TPrintf( "\nARM9 starts.\n" ); + OS_TPrintf( "\nARM9 ends.\n" ); + + OS_Terminate(); +} + diff --git a/build/norfirm/norfirm-print/Makefile b/build/norfirm/norfirm-print/Makefile new file mode 100644 index 0000000..0b6a16a --- /dev/null +++ b/build/norfirm/norfirm-print/Makefile @@ -0,0 +1,60 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - build +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + + +FIRM_TARGET = FIRM + +# if you have no valid key, comment out next line +#TWL_KEYSDIR = $(FIRM_ROOT)/../twl_firmware/bootrom/build/keys + + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + ARM7 \ + ARM9 \ + wram_regs \ + +TARGET_FIRM_BIN = norfirm_print.nor norfirm_print.srl +BINDIR = . +MAKEFIRM_ARM9 = ARM9/bin/ARM9-$(FIRM_PLATFORM)$(CODEGEN_ARCH)/$(FIRM_BUILD_DIR)/twl_norfirm9_print.tef +MAKEFIRM_ARM7 = ARM7/bin/ARM7-$(FIRM_PLATFORM)$(CODEGEN_ARCH)/$(FIRM_BUILD_DIR)/twl_norfirm7_print.tef +MAKEFIRM_RSA_PRVKEY = $(TWL_KEYSDIR)/rsa/private_nor.der +LDEPENDS_BIN += wram_regs/wram_regs.rbin + +MAKEROM_ARM7_BASE = $(basename $(MAKEFIRM_ARM7)) +MAKEROM_FLAGS += -F + +NITRO_MAKEROM = TRUE +MAKEFIRM_FLAGS += -p +FIRM_SPEC = norfirm-BB.norsf + +LDIRT_CLEAN += $(TARGETS) \ + $(basename $(firstword $(TARGETS))).tlf \ + rsa_public.sbin \ + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build: $(TARGET_BIN) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/norfirm/norfirm-print/norfirm-BB.norsf b/build/norfirm/norfirm-print/norfirm-BB.norsf new file mode 100644 index 0000000..a472dc2 --- /dev/null +++ b/build/norfirm/norfirm-print/norfirm-BB.norsf @@ -0,0 +1,25 @@ +#NORSF --- Norfirm Spec File + +VERSION : GENERATE + +BOOT_NAND : TRUE # TRUE or FALSE + +RSA_KEY : $(MAKEFIRM_RSA_PRVKEY) +OUT_KEY : rsa_public.sbin + +WRAM_RBIN: ./wram_regs/wram_regs.rbin + +DECOMP_PROC : ARM9 # ARM9 or ARM7 + +ARM9_COMP : TRUE # TRUE or FALSE, should be before ARM9_SBIN +ARM9_SBIN : $(MAKEFIRM_ARM9).FLX.TWL.sbin +ARM9_ELF : $(MAKEFIRM_ARM9).tef + +ARM7_COMP : TRUE # TRUE or FALSE, should be before ARM7_SBIN +ARM7_SBIN : $(MAKEFIRM_ARM7).FLX.TWL.sbin +ARM7_ELF : $(MAKEFIRM_ARM7).tef + +NCD_ROMOFS : 0x07fe00 + +BAUDRATE : 8M # 4M or 8M +ARM9_X2 : TRUE # TRUE or FALSE diff --git a/build/norfirm/norfirm-print/wram_regs/Makefile b/build/norfirm/norfirm-print/wram_regs/Makefile new file mode 100644 index 0000000..f0ecbed --- /dev/null +++ b/build/norfirm/norfirm-print/wram_regs/Makefile @@ -0,0 +1,48 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - tools - norfirm-print +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = wram_regs.rbin + +SRCS = \ + wram_regs.c \ + +#SRCDIR = # using default +#LCFILE = # using default + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_DIR = . +INSTALL_TARGETS = $(BINDIR)/$(TARGET_BIN) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/norfirm/norfirm-print/wram_regs/wram_regs.c b/build/norfirm/norfirm-print/wram_regs/wram_regs.c new file mode 100644 index 0000000..ea59c65 --- /dev/null +++ b/build/norfirm/norfirm-print/wram_regs/wram_regs.c @@ -0,0 +1,91 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: wram_regs.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev:$ + $Author:$ + *---------------------------------------------------------------------------*/ +#include +#include + +MIHeader_WramRegs wram_regs_init = +{ + // ARM9 + { + REG_MI_MBK_A0_FIELD( 1, MI_WRAM_A_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_A1_FIELD( 1, MI_WRAM_A_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_A2_FIELD( 1, MI_WRAM_A_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_A3_FIELD( 1, MI_WRAM_A_OFFSET_192KB, MI_WRAM_ARM7 ), + }, + { + REG_MI_MBK_B0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM7 ), + }, + { + REG_MI_MBK_C0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM9 ), + }, + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, MI_WRAM_MAP_NULL ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, MI_WRAM_MAP_NULL ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, HW_WRAM_AREA_HALF + 0x00020000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, HW_WRAM_AREA_HALF ) + ), + + // ARM7 + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, HW_WRAM_AREA_HALF + 0x00020000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, HW_WRAM_AREA_HALF ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, HW_WRAM_AREA_HALF + 0x00040000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, HW_WRAM_AREA_HALF + 0x00020000 ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, MI_WRAM_MAP_NULL ) + ), + + // WRAM Lock + { + 0, + 0, + 0, + }, + + // WRAM-0/1 + 3, + + // VRAM-C + 7, + // VRAM-D + 7, +}; + diff --git a/build/systemMenu_RED/.DS_Store b/build/systemMenu_RED/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7a69c3a540ead5f136ce7f02495ff26345754dfa GIT binary patch literal 6148 zcmeHKJx;?g7=11+DloJI18liM4}cU(*g&e(1JLwGZKak}&?|Ck9D+kIvcnx1 zd7o{eT1lD>0rDr=&-v`ne&1_i*8o&|HEaP*0Cg6@>OQL+lYS`~t60w=QOO*$ajQE> z=8Mco@9+wE1%9If^6geJM2sb3=liX_t~dMUNfh;GNuNI14Avhn&!=wxaBKf!vavVp z%6@|eB6M-ZI>8;TF(bz0(qSvcy~75dkL3{s981=jC%Mc^qMUqGNAjuTg1lGEWPk}q zxN$O2wd1@o1)MW;6|l^Vb9w2lxPeRZ5>8Wc8&UHSf9<7y8spYw`Sz}L-WpNBxn!M! z3`(M$d@4PX!yey|Df3zKeK})Re0QB3aPp8ps(^RSd<9%{MmqfPB>eu0@yr&h9~ktt zSHLUa75G*__J@E)FtnH&)LREDeFY#^>DI=!KHG_bIEbOe)F3@HWkQK2RM{(rGU4Jqv53jI)SwPwWshUskfZpBMH~A9X%It;sX=;Z{*Qo`!B<{^ HA64KBBu~R| literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/DS_DownloadPlay/ARM9/ARM9-TS.lsf b/build/systemMenu_RED/DS_DownloadPlay/ARM9/ARM9-TS.lsf new file mode 100644 index 0000000..1b0a503 --- /dev/null +++ b/build/systemMenu_RED/DS_DownloadPlay/ARM9/ARM9-TS.lsf @@ -0,0 +1,70 @@ +#---------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ARM9-BB.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TWL LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x02800000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) +} + +Overlay bm_mainp +{ + After $(TARGET_NAME) + Object $(OBJDIR)/DS_Setting.o $(OBJDIR)/settingMenu.o $(OBJDIR)/rtcSet.o $(OBJDIR)/langSelect.o \ + $(OBJDIR)/tpCalib.o $(OBJDIR)/ownerInfo.o $(OBJDIR)/AgbLcdSel.o $(OBJDIR)/autoBoot.o \ + $(OBJDIR)/unicode.o $(OBJDIR)/misc.o \ + $(OBJDIR)/DS_DownloadPlay.o \ + $(OBJDIR)/DS_Chat.o +} + +Overlay ipl2_data +{ + After bm_mainp + Object ./font/f12han.o +} + + +Autoload ITCM +{ + Address 0x01ff8000 + Object * (.itcm) + Object $(OBJS_AUTOLOAD) (.text) + Object $(OBJS_AUTOLOAD) (.rodata) +} + +Autoload DTCM +{ + Address $(ADDRESS_DTCM) + Object * (.dtcm) + Object $(OBJS_AUTOLOAD) (.data) + Object $(OBJS_AUTOLOAD) (.sdata) + Object $(OBJS_AUTOLOAD) (.bss) + Object $(OBJS_AUTOLOAD) (.sbss) +} + +Ltdautoload LTDMAIN +{ + # NITRO/TWL L̃I[o[C݂ꍇ́Aɂ̌ɔzuKv܂B + After ipl2_data + Object * (.ltdmain) + Object $(OBJS_LTDAUTOLOAD) + Library $(LLIBS_EX) $(GLIBS_EX) +} diff --git a/build/systemMenu_RED/DS_DownloadPlay/ARM9/Makefile b/build/systemMenu_RED/DS_DownloadPlay/ARM9/Makefile new file mode 100644 index 0000000..bd252c8 --- /dev/null +++ b/build/systemMenu_RED/DS_DownloadPlay/ARM9/Makefile @@ -0,0 +1,52 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - demos - simpleShoot-1 +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev: $ +# $Author: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +#---------------------------------------------------------------------------- + +TARGET_FIRM = SYSTEMMENU +TARGET_PLATFORM = TWL +TWL_ARCHGEN = LIMITED + +TARGET_BIN = dlplay.srl + +LCFILE_SPEC = ARM9-TS.lsf +ROM_SPEC = main.rsf + +SRCS = main.c mainFunc.c DS_DownloadPlay.c + +LINCLUDES = $(TWLSDK_ROOT)/build/libraries/spi/arm9/include \ + $(TWLSDK_ROOT)/build/libraries/mb/common/include \ + +LLIBRARY_DIRS = +LLIBRARIES = +LDEPENDS_NEF = + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build : $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#---------------------------------------------------------------------------- + +#===== End of Makefile ===== diff --git a/build/systemMenu_RED/DS_DownloadPlay/ARM9/main.rsf b/build/systemMenu_RED/DS_DownloadPlay/ARM9/main.rsf new file mode 100644 index 0000000..511b587 --- /dev/null +++ b/build/systemMenu_RED/DS_DownloadPlay/ARM9/main.rsf @@ -0,0 +1,146 @@ +#---------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ROM-BB.rsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TWL ROM SPEC FILE +# + +Arm9 +{ + Static "$(MAKEROM_ARM9:r).FLX.TWL.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.FLX.TWL.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.FLX.TWL.sbin$(COMPSUFFIX9)" + Elf "$(MAKEROM_ARM9:r).tef" +} + +Arm7 +{ + Static "$(MAKEROM_ARM7_BASE:r).FLX.TWL.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.FLX.TWL.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.FLX.TWL.sbin$(COMPSUFFIX7)" + Elf "$(MAKEROM_ARM7_BASE:r).tef" +} + +Arm9.Ltd +{ + Static "$(MAKEROM_ARM9:r).LTD.TWL.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.LTD.TWL.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.LTD.TWL.sbin$(COMPSUFFIX9)" +} + +Arm7.Ltd +{ + Static "$(MAKEROM_ARM7_BASE:r).LTD.TWL.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.LTD.TWL.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.LTD.TWL.sbin$(COMPSUFFIX7)" +} + +Property +{ + ### + ### Settings for FinalROM + ### + #### BEGIN + # + # TITLE NAME: Your product name within 12bytes + # + #TitleName "YourAppName" + + # + # MAKER CODE: Your company ID# in 2 ascii words + # issued by NINTENDO + # + #MakerCode "00" + + # + # REMASTER VERSION: Mastering version + # + #RomVersion 0 + + # + # ROM SPEED TYPE: [MROM/1TROM/UNDEFINED] + # + RomSpeedType $(MAKEROM_ROMSPEED) + + # + # ROM SIZE: in bit [64M/128M/256M/512M/1G/2G] + # + #RomSize 128M + #RomSize 256M + + # + # ROM PADDING: TRUE if finalrom + # + #RomFootPadding TRUE + + # + # ROM HEADER TEMPLATE: Provided to every product by NINTENDO + # + #RomHeaderTemplate ./etc/rom_header.template.sbin + + # + # BANNER FILE: generated from Banner Spec File + # + BannerFile ../banner/banner.bnr + + ### + ### Setting for TWL + ### + # + # BANNER FILE: + # + BannerTWLFile $(TWLSDK_ROOT)/include/twl/specfiles/default.bnr + + # + # Boot allowed Media: [GameCard/NAND/SDCard/DownloadPlay] + # possible to choose one or more. + # + BootMedia GameCard NAND SDCard DownloadPlay + + # + # Certification FILE: + # + Certificate $(TWLSDK_ROOT)/include/twl/specfiles/default_sgn.sbin + + # + # Digest parameters: + # + DigestParam 1024 32 + + # + # WRAM mapping: [MAP_BB_HYB/MAP_BB_LTD/MAP_TS_HYB/MAP_TS_LTD] + # don't have to edit + # + WramMapping $(MAKEROM_WRAM_MAPPING) + + # + # Codec mode: + # don't have to edit + # + CodecMode $(MAKEROM_CODEC_MODE) + + ### + #### END +} + +RomSpec +{ + Offset 0x00000000 + Segment ALL + HostRoot data + Root /data + File NTR_IPL_font_m.NFTR +} diff --git a/build/systemMenu_RED/DS_DownloadPlay/ARM9/src/DS_DownloadPlay.c b/build/systemMenu_RED/DS_DownloadPlay/ARM9/src/DS_DownloadPlay.c new file mode 100644 index 0000000..13d9abb --- /dev/null +++ b/build/systemMenu_RED/DS_DownloadPlay/ARM9/src/DS_DownloadPlay.c @@ -0,0 +1,1618 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: DS_DownloadPlay.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +// mb_private.hPRINT_DEBUG"1"ɂĂƁA_E[hɐɃu[głȂȂĂ̂ŁAӁB + +#include +#include // Ƃ̂OK? +#include +#include "mb_child.h" +#include "mb_private.h" + + +#include "misc.h" +#include "DS_Setting.h" +#include "DS_DownloadPlay.h" + +// define data------------------------------------------ +#define PARENT_VIEW_NUM 4 // e@񃊃Xg̈ʕ\ +#define PLIST_X 1 // e@񃊃Xg̕\Xʒu +#define PLIST_Y 4 // e@񃊃Xg̕\Yʒu +#define MB_DMA_NO 2 // }`u[gpDMAԍ +#define PRG_NEXT_SEQ_QUE_NUM 4 // ̃vOV[PXi[L[̐ +#define MY_GGID 0x00000000 // }`u[gpGGID +#define G_INTRO_X 1 // Q[e\Xʒu +#define G_INTRO_Y 4 // Q[e\Yʒu +#define G_MEMBER_X 1 // ʐMo[\Xʒu +#define G_MEMBER_Y 10 // ʐMo[\Yʒu +#define MSG_VIEW_COUNT 75 // bZ[W\VJEg +#define MSG_BLINK_COUNT 12 // bZ[W_ŃJEg + +#define NINLOGO_LOAD_1D_CHAR // NintendoSf[^1D}bsOLN^Ń[hB + + // vOV[PX +typedef enum PrgSeq { + PSEQ_READY = 0, + PSEQ_INIT, + PSEQ_INITIALIZING, + PSEQ_ENDING, + PSEQ_END, + PSEQ_CANCELLED, + PSEQ_DISCONNECTED_BY_PARENT, + PSEQ_SCANNING, + PSEQ_CONNECTING, + PSEQ_CONNECT_SUCCEEDED, + PSEQ_CONNECT_FAILED, + PSEQ_REQ_REFUSED, + PSEQ_MEMBER_FULL, + PSEQ_DOWNLOAD_READY, + PSEQ_DOWNLOADING, + PSEQ_DOWNLOAD_COMPLETED, + PSEQ_DOWNLOAD_FAILED, + PSEQ_BOOT_REQ_WAIT, + PSEQ_BOOT_READY, + PSEQ_BOOT_START, + PSEQ_BOOT_FAILED +}PrgSeq; + +static char *str_prgSeq[] = { + "PSEQ_READY", + "PSEQ_INIT", + "PSEQ_INITIALIZING", + "PSEQ_ENDING", + "PSEQ_END", + "PSEQ_CANCELLED", + "PSEQ_DISCONNECTED_BY_PARENT", + "PSEQ_SCANNING", + "PSEQ_CONNECTING", + "PSEQ_CONNECT_SUCCEEDED", + "PSEQ_CONNECT_FAILED", + "PSEQ_REQ_REFUSED", + "PSEQ_MEMBER_FULL", + "PSEQ_DOWNLOAD_READY", + "PSEQ_DOWNLOADING", + "PSEQ_DOWNLOAD_COMPLETED", + "PSEQ_DOWNLOAD_FAILED", + "PSEQ_BOOT_REQ_WAIT", + "PSEQ_BOOT_READY", + "PSEQ_BOOT_START", + "PSEQ_BOOT_FAILED", +}; + + + // e@񔭌ԃf[^ +typedef struct FindTime { + BOOL find; // ǂ + int vcount; // +}FindTime; + + // bZ[W\Xe[^X +typedef struct MsgViewStatus { + u16 handle; + u16 vcount; + u16 flag; + u16 color; + const u8 *str; + int (*nextProcessp)(void); +}MsgViewStatus; + + // vOV[PXi[pL[ +typedef struct PrgNextSeqQue { + BOOL lock; + u8 pad; + u8 num; + u8 top; + u8 bottom; + PrgSeq seq[ PRG_NEXT_SEQ_QUE_NUM ]; +}PrgNextSeqQue; + + +// extern data------------------------------------------ +extern void MBw_SetMaxScanTime( u16 time ); +extern int MBw_GetScanChannel( void ); +extern void UnCompNintendoLogo( u16 *NintendoLogoDatap, u16 *dstp, u32 *temp ); + +// function's prototype declaration--------------------- + // CV[PX +static void SEQ_DSDL_init( void ); +static int SEQ_DSDL_Connect( void ); +static int SEQ_DSDL_Download( void ); +static BOOL CheckNextSeq_Connect( void ); +static BOOL CheckNextSeq_Download( void ); + // R[obN +static void CallbackChild_MB( u32 status, void *arg ); // }`u[gpR[obN֐ + // \n +static void DispTopScreen( void ); +static void DispScanStatus( void ); +static void DispParentNum( void ); +static void DispParentList( void ); +static void DispGameIntroduction( void ); +static void DispPlayMember( void ); +static void DispParentGameInfo( u32 view_no, u32 listNo, BOOL drawFixedDataFlag ); +static void ClearDispParentGameInfo( u32 view_no, u32 listNo ); +static void DispGameIntroduction_Core( u32 listNo ); +static void DispPlayMember_Core( u32 listNo ); +static void ClearDispGameIntroduction( void ); +static void ClearDispPlayMember( void ); +static void DecimalToString( u8 *dstp, const void *valuep, u8 drawLength, u8 size ); +static void InitParentFindTime( void ); +static void CountParentFindTime( void ); +static BOOL CheckParentFindTime( u32 index ); +static void CountAndDispTotalTime( void ); +static void SetIconOBJ( u32 index ); +static void ClearIconOBJ( u32 index ); +static void SetDispMessage( u16 color, const u8 *str ); +static BOOL DispMessage( void ); +static void SetBlinkMessage( u16 color, const u8 *str ); +static void DispBlinkMessage( void ); + // NintendoS\ +static void InitDispNintendoLogo( void ); +static BOOL DispNintendoLogo( void ); + // ̑ +static void SetMyUserInfo( MBUserInfo *my ); +static BOOL IsScanLock( void ); + // 荞 +static void VBlankIntr_WDL( void ); + // V[PXL[ +static void InitPrgNextSeqQue( void ); +static BOOL SetPrgNextSeqQue( PrgSeq seq ); +static BOOL GetPrgNextSeqQue( PrgSeq *seqp ); +static void LockPrgNextSeqQue( void ); +static void UnlockPrgNextSeqQue( void ); +static BOOL IsEmptyPrgNextSeqQue( void ); + +void SearchPatchAddress( void ); + +// global variable ------------------------------------- + +// static variable ------------------------------------- +static int (*wdProcess)( void ); // ݎs̃vZXւ̃|C^ +static int csrC; // j[̃J[\ʒu +static int csrC_old; // j[̑OJ[\ʒu +static PrgSeq prgSeq; // vOV[PX +static PrgNextSeqQue nextSeq; // ̃vOV[PXi[L[ +static BOOL end_flag; // ItO +static MsgViewStatus msgStat; // bZ[W\Xe[^X +static MBUserInfo myUser; // ̃[U[ +static u16 tgid = 0; +static u16 tp_touch_count = 0; +static u32 gameInfoLostCount = 0; +// e@Xg̕\Ɏgp +static int unrenewalFlag; +static int total_vcount; +static int time_ms; // e@ms +static int time_sec; // e@sec +static u16 msgHandle; // bZ[W\nh +static u16 dispGameInfoFlag; // ɕ\Q[rbgŎB +static u16 dispIntroFlag; // Q[̏ڍ׃f[^`tO +static u16 dispMemberFlag; // Q[̏ڍ׃f[^`tO +static u16 gameName[ MB_GAME_NAME_LENGTH + 1 ]; // e@Q[l[ +static u16 userName[ MB_USER_NAME_LENGTH + 1 ]; // e@[U[l[ +static u16 gameIntroduction[2][ MB_GAME_INTRO_LENGTH / 2 + 1 ]; + // e@Q[e +static u16 playMember[ MB_MEMBER_MAX_NUM ][ MB_USER_NAME_LENGTH + 1]; + // ʐMo[Xg +static u8 parentListNo[ PARENT_VIEW_NUM ][ 4 ] ATTRIBUTE_ALIGN(2); + // e@Xgԍ +static u32 objVramBuff[ (MB_ICON_DATA_SIZE * PARENT_VIEW_NUM + 0x20) / sizeof(u32) ] ATTRIBUTE_ALIGN(32); +static FindTime findTime[ MB_GAME_INFO_RECV_LIST_NUM ]; // e@ԃf[^ +static GXOamAttr oamBakM[ 128 ] ATTRIBUTE_ALIGN(32); // OAM obNAbv + +static const MbBeaconRecvStatus *mbrsp; + +// MBCup[N +static u32 mbwork[ MB_CHILD_SYSTEM_BUF_SIZE / sizeof(u32) ]; + +// NintendoS\ +static int loop_count; +static u32 ninLogoBuff[ 0x700 / sizeof(u32) ]; + +static MBDownloadFileInfo dlfileinfo; +static u8 output_buffer[ AUTH_BUFFER_LEN ]; + +// const data ----------------------------------------- + // \p +static const u8 str_sura[] ATTRIBUTE_ALIGN(2) = "/"; +static const u8 str_period[] ATTRIBUTE_ALIGN(2) = "."; +static const u8 str_sec[] ATTRIBUTE_ALIGN(2) = "sec"; +static const u8 str_disconnected[] ATTRIBUTE_ALIGN(2) = "disconnected by parent."; +static const u8 str_connect_succeeded[] ATTRIBUTE_ALIGN(2) = "connect succeeded."; +static const u8 str_connect_failed[] ATTRIBUTE_ALIGN(2) = "connect failed."; +static const u8 str_req_refused[] ATTRIBUTE_ALIGN(2) = "req refused."; +static const u8 str_member_full[] ATTRIBUTE_ALIGN(2) = "member full."; +static const u8 str_downloading[] ATTRIBUTE_ALIGN(2) = "DOWNLOADING...."; +static const u8 str_download_completed[] ATTRIBUTE_ALIGN(2) = "download completed."; +static const u8 str_download_cancelled[] ATTRIBUTE_ALIGN(2) = "download cancelled."; + + // j[֐p@e@Xg񃊃Xg +static u8 *str_parentListNo[] ATTRIBUTE_ALIGN(2) = { + parentListNo[0], + parentListNo[1], + parentListNo[2], + parentListNo[3], +}; + + // j[֐p@j[\f[^ +static const MenuComponent childModeSel = { + PARENT_VIEW_NUM, // ڐ + PLIST_X, // XʒuiLj + PLIST_Y, // Yʒui@V@@j + 0, // ̍ڂւXʒuL + 4, // ̍ڂւYʒuL + 3, + WHITE, // IF + HIGHLIGHT_Y, // IF + (const u8 **)&str_parentListNo, // j[ڕ񃊃Xg +}; + + +//====================================================== +// C[v +//====================================================== + +// }`u[g̃C[v +int DS_DownloadPlayMain(void) +{ + SEQ_DSDL_init(); + + wdProcess = SEQ_DSDL_Connect; + + OS_TPrintf("MbBeaconRecvStatus:%d\n", sizeof(MbBeaconRecvStatus) ); + + while(1) { + OS_WaitIrq(1, OS_IE_V_BLANK); + ReadKeyPad(); + mf_KEYPAD_rapid(); + + mbrsp = MB_GetBeaconRecvStatus(); + + if( wdProcess != NULL ) { + if(wdProcess()) { + return 0; + } + } + + //// //// + { + static int touch = 0; + TPData tmp1 ATTRIBUTE_ALIGN(32); + TPData tmp2 ATTRIBUTE_ALIGN(32); + + while (TP_RequestRawSampling(&tmp1) != 0) {} + TP_GetCalibratedPoint(&tmp2, &tmp1); + + if (tmp2.touch != touch) + { + tp_touch_count++; + (void)DrawDecimalSJIS( 16, 0, RED, &tp_touch_count, 4, 2 ); + OS_Printf("touch change %d validity = %d\n", tmp2.touch, tmp2.validity); + touch = tmp2.touch; + } + } + //// ܂ //// + +// if (SYSM_IsCardPulledOut()) { // J[ho + if ( 0 ) { + OS_Printf("Card is pulled out.\n"); +#ifdef __DEBUG + OS_Terminate(); +#endif + } + + if (PAD_DetectFold() == TRUE) { // X[v[hւ̑J + SYSM_GoSleepMode(); + } + + OS_PrintServer(); // ARM7̃vgfobO + } + return 0; +} + + +//====================================================== +// }`u[gij +//====================================================== + +// }`u[g̏ +static void SEQ_DSDL_init(void) +{ + GXS_SetVisiblePlane( GX_PLANEMASK_NONE ); + GX_SetVisiblePlane ( GX_PLANEMASK_NONE ); + + (void)OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr_WDL); + GXS_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_1D_32K); + + // NITROJ[hROMo^f[^̃NA + MI_CpuClearFast( (void *)HW_ROM_HEADER_BUF, 0x160 ); + + // TuXN[̃NA + MI_CpuClearFast( bgBakS, sizeof(bgBakS) ); + MI_CpuFillFast ( (void *)HW_OAM, 192 , HW_OAM_SIZE ); + MI_CpuFillFast ( (void *)oamBakS, 192 , sizeof(oamBakS) ); // 192ŃtBȂƁAgpOBJ(0, 0)ɃLNo.0őS\Ă܂B + + // CXN[̃NA + MI_CpuClearFast( (void *)HW_BG_VRAM, 0x10000 ); + MI_CpuClearFast( (void *)HW_OBJ_VRAM, 0x8000 ); + MI_CpuClearFast( bgBakM, sizeof(bgBakM) ); + MI_CpuFillFast ( (void *)oamBakM, 192 , sizeof(oamBakM) ); // 192ŃtBȂƁAgpOBJ(0, 0)ɃLNo.0őS\Ă܂B + MI_CpuFillFast ( (void *)HW_OAM, 192 , HW_OAM_SIZE ); + MI_CpuCopyFast ( myPlttData, (void *)HW_BG_PLTT, sizeof(myPlttData) ); // BGpbg Zbg + + ClearAllStringSJIS(); + + (void)DrawStringSJIS ( 1, 0, WHITE, (const u8 *)"NICKNAME="); + (void)DrawStringSJIS ( 1, 2, LIGHTGREEN, (const u8 *)"PARENT NUM ="); +// (void)DrawStringSJIS ( 1, 22, LIGHTGREEN, (const u8 *)"GINFO LOST COUNT ="); + (void)DrawStringSJISEx( 26, 2, CYAN, str_period, PARENT_VIEW_NUM); + (void)DrawStringSJISEx( 29, 2, CYAN, str_sec, PARENT_VIEW_NUM); + + InitPrgNextSeqQue(); + unrenewalFlag = 0; + end_flag = FALSE; + prgSeq = PSEQ_INIT; + msgHandle = 0x8000; + dispGameInfoFlag = 0; + dispIntroFlag = 0; + dispMemberFlag = 0; + csrC_old = 2; // ŏ͂킴ƈႤlɂĂ + csrC = 0; + { + int i; + for( i = 0; i < PARENT_VIEW_NUM; i++ ) { + parentListNo[i][2] = '.'; + parentListNo[i][3] = 0x00; + } + } + SetMyUserInfo( &myUser ); // MBUserInfoNITROݒf[^ǂݏoăZbg + { + // jbNl[\ + u16 nickname[ MB_USER_NAME_LENGTH + 1 ]; + ExUTF16_LEtoSJIS_BE( (u8 *)nickname, (u16 *)myUser.name, myUser.nameLength ); + nickname[ myUser.nameLength ] = 0; + (void)DrawStringSJIS( 8, 0, WHITE, (const u8 *)nickname ); + } + + InitParentFindTime(); // e@ԕϐ̃NA + + while( (SYSM_GetBootFlag() & BFLG_WM_INITIALIZED) == 0 ) {} + + LOADER_Init( NULL ); + + GXS_SetVisiblePlane( GX_PLANEMASK_OBJ | GX_PLANEMASK_BG1 ); + GX_SetVisiblePlane ( GX_PLANEMASK_OBJ | GX_PLANEMASK_BG1 ); +} + + +// TOPXN[ւ̕\ +static void DispTopScreen( void ) +{ + SetTargetScreenSJIS( TOP_SCREEN ); + ClearAllStringSJIS(); + (void)DrawStringSJIS( 1, 0, YELLOW, (const u8 *)"WIRELESS DOWNLOAD"); + (void)DrawStringSJIS( G_INTRO_X, G_INTRO_Y, LIGHTGREEN, (const u8 *)"GAME INTRODUCTION"); + (void)DrawStringSJIS( G_MEMBER_X, G_MEMBER_Y, LIGHTGREEN, (const u8 *)"MEMBER LIST"); + SetTargetScreenSJIS( BOTTOM_SCREEN ); +} + + +//====================================================== +// }`u[gie@T[` ` ڑj +//====================================================== + +// }`u[g̐ڑV[PX +static int SEQ_DSDL_Connect(void) +{ + // ݂prgSeqɉ + BOOL getSeqFlag = CheckNextSeq_Connect(); + + switch ( prgSeq ) { + case PSEQ_INIT: // q@[h̊JniCȕ`StartScan܂ł̗sj + if ( MB_Init( mbwork, &myUser, MY_GGID, tgid, MB_DMA_NO ) != WM_ERRCODE_SUCCESS ) { + OS_Printf("MB init failed.\n"); + break; + } + MB_CommSetChildStateCallback( CallbackChild_MB ); + if ( MB_StartChild() != WM_ERRCODE_SUCCESS ) { + OS_Printf("MB start failed.\n"); + break; + } + tgid++; + DispTopScreen(); + prgSeq = PSEQ_INITIALIZING; + break; + + case PSEQ_INITIALIZING: + break; + + case PSEQ_SCANNING: // XL͐AV[PX`FbNsB + case PSEQ_ENDING: + if( !getSeqFlag ) { + return 0; + } + break; + + case PSEQ_CONNECTING: // ڑ̓L[͂󂯕tɃ^[BiV[PX`FbN͍sj + return 0; + + case PSEQ_CONNECT_SUCCEEDED: // bZ[W\A_E[hV[PXɈڍsB + if( DispMessage() ) { + UnlockPrgNextSeqQue(); // V[PXbN + wdProcess = SEQ_DSDL_Download; + } + return 0; + + case PSEQ_CONNECT_FAILED: // bZ[W\AXLĊJBiXLĊĴ̂́ACuōsBj + if( DispMessage() ) { + UnlockPrgNextSeqQue(); // V[PXbN + prgSeq = PSEQ_SCANNING; + } + break; + + case PSEQ_DISCONNECTED_BY_PARENT: // ؒfobZ[W\ݒB + if( DispMessage() ) { + UnlockPrgNextSeqQue(); // V[PXbN + prgSeq = PSEQ_INIT; + } + break; + + case PSEQ_CANCELLED: // I + return 0; + + default: + break; + } + + + // J[\ړ + if(pad.trg & PAD_KEY_DOWN){ // J[\̈ړ + if( ++csrC == MB_GAME_INFO_RECV_LIST_NUM ){ + csrC = 0; + } + } + if(pad.trg & PAD_KEY_UP){ + if( --csrC & 0x80 ){ + csrC = MB_GAME_INFO_RECV_LIST_NUM - 1; + } + } + DrawMenu((u16)(csrC & (PARENT_VIEW_NUM - 1)), &childModeSel); // XgԍiJ[\j̕\ + DispParentNum(); // e@̕\ + DispParentList(); // e@Xg̕\ + DispScanStatus(); // WMXLԂ̕\ + CountAndDispTotalTime(); // g[^Ԃ̃JEg\ + CountParentFindTime(); // e@Ԃ̃JEg + + + // e@ւ̐ڑ + if(pad.trg & PAD_BUTTON_A) { + if( mbrsp->usefulGameInfoFlag & (0x0001 << csrC) ) { + if( MB_CommDownloadRequest( csrC ) == WM_ERRCODE_SUCCESS ) { // ڑJn + OS_Printf("start conntct to parent.\n"); + prgSeq = PSEQ_CONNECTING; + }else { + OS_Printf("this parent info is invalid.\n"); + } + } + }else if(pad.trg & PAD_BUTTON_B) { // IJn + if( prgSeq == PSEQ_SCANNING ) { + OS_Printf("MB End start\n"); + prgSeq = PSEQ_ENDING; +// end_flag = TRUE; + MB_End(); + } + }else if( pad.trg & PAD_BUTTON_R ) { + unrenewalFlag ^= 0x01; +// MB_SetUnrenewalGameInfoFlag( (BOOL)unrenewalFlag ); + } + + csrC_old = csrC; // J[\ʒȗޔ + return 0; +} + + +// V[PX̃`FbNiR[obNŃC[vƂ͔񓯊ɕԂ鎟V[PXւ̈ڍsC[ṽvOisɍ킹Bj +static BOOL CheckNextSeq_Connect(void) +{ + PrgSeq seq; + // MBR[obNɂāAV[PXڍsĂꍇ̏ + if( GetPrgNextSeqQue( &seq) ) { // MBR[obNɂāAV[PXڍsĂꍇ̏ + prgSeq = seq; + OS_Printf("prgSeq = %s\n", str_prgSeq[ prgSeq ]); + + switch( seq ) { + case PSEQ_SCANNING: + { +/* + u8 *ver = MBw_GetWLVersion(); + (void)DrawStringSJIS( 21, 0, WHITE, (const u8 *)"WL ver=" ); + (void)DrawStringSJIS( 26, 0, WHITE, (const u8 *)ver ); +*/ + } + break; + + case PSEQ_CONNECT_SUCCEEDED: // ڑbZ[W\ݒB + SetDispMessage( YELLOW, str_connect_succeeded ); + LockPrgNextSeqQue(); // prgSeqbNB + return FALSE; + + case PSEQ_CONNECT_FAILED: // ڑsbZ[W\ݒB + SetDispMessage( RED, str_connect_failed); + LockPrgNextSeqQue(); // prgSeqbNB + return FALSE; + + case PSEQ_DISCONNECTED_BY_PARENT: // ؒfobZ[W\ݒB + SetDispMessage( RED, str_disconnected); + LockPrgNextSeqQue(); // prgSeqbNB + return FALSE; + + case PSEQ_CANCELLED: // I + { + u32 i; + for( i = 0; i < PARENT_VIEW_NUM; i++ ) { + ClearIconOBJ( i ); // SACȐ + } +// if( end_flag ) { +// ClearAllStringSJIS(); +// SetTargetScreenSJIS( TOP_SCREEN ); +// ClearAllStringSJIS(); +// SetTargetScreenSJIS( BOTTOM_SCREEN ); +// (void)DrawStringSJIS( 11, 11, WHITE, (const u8 *)"イ傤܂B"); +// }else { + prgSeq = PSEQ_INIT; +// } + } + return FALSE; + } + } + return TRUE; // V[PXڍsȂꍇFALSE^[̃V[PXłȂꍇTRUE^[B +} + + +//====================================================== +// }`u[gi_E[hj +//====================================================== + +// }`u[g̃t@C_E[hV[PX +static int SEQ_DSDL_Download(void) +{ + static int count_old = 0; + // ݂prgSeqɉ + BOOL getSeqFlag = CheckNextSeq_Download(); + + switch(prgSeq) { + + case PSEQ_REQ_REFUSED: + case PSEQ_MEMBER_FULL: // bZ[W\AUIď蒼B + if( DispMessage() ) { + UnlockPrgNextSeqQue(); // V[PXbN + prgSeq = PSEQ_ENDING; + wdProcess = SEQ_DSDL_Connect; + MB_End(); + } + break; + + // _E[ht@CMA_E[hł + case PSEQ_DOWNLOAD_READY: +// if (pad.trg & PAD_BUTTON_A) { // _E[hJn + OS_Printf("Start download.\n"); + ClearStringSJIS_handle(msgHandle); + (void)MB_CommStartDownload(); + SetBlinkMessage( YELLOW, str_downloading ); +// } + break; + + // _E[h + case PSEQ_DOWNLOADING: + if( getSeqFlag ) { + DispBlinkMessage(); + msgHandle = msgStat.handle; + + if( 1 ) { + u16 percent = MB_GetChildProgressPercentage(); + msgHandle = DrawDecimalSJIS( 16, 21, WHITE, &percent ,3, 2 ); + } + } + break; + + // _E[h + case PSEQ_DOWNLOAD_COMPLETED: + if( DispMessage() ) { + { + msgHandle = DrawStringSJIS( 4, 21, LIGHTGREEN, "Sign Digest...."); + if ( ACSignDigest ( output_buffer, &dlfileinfo ) ) { + ClearStringSJIS_handle( msgHandle ); + msgHandle = DrawStringSJIS( 4, 21, LIGHTGREEN, "Digest SUCCEEDED."); + }else { + ClearStringSJIS_handle( msgHandle ); + msgHandle = DrawStringSJIS( 4, 21, RED, "Digest FAILED."); + } + { + int i; + for ( i = 0; i < 120; i++ ) { + SVC_WaitVBlankIntr(); + } + } + ClearStringSJIS_handle( msgHandle ); + } + UnlockPrgNextSeqQue(); // V[PXbN + prgSeq = PSEQ_BOOT_REQ_WAIT; + msgHandle = DrawStringSJIS( 4, 21, WHITE, "Waiting BOOT-REQ from parent."); + } + break; + + // e@̃u[g‘҂ + case PSEQ_BOOT_REQ_WAIT: + break; + + // _E[hAu[gł +// case PSEQ_BOOT_READY: +// (void)LOADER_Start(); // ARM7ɂāA_E[hvO̍ĔzusB +// return 1; // "1"Ń^[邱ƂŁA}`u[g̃C[v甲IPL2ɏ߂B + + // e@̃u[gvMɂAN”ۃ`FbNsBiNintendoS\`FbNj + case PSEQ_BOOT_READY: + if( DispNintendoLogo() ) { + if( SYSM_CheckNinLogo( (u16 *)GetRomHeaderAddr()->nintendo_logo ) ) { + prgSeq = PSEQ_BOOT_START; + }else { + SetDispMessage( RED, (const u8 *)"Illegal game data."); + prgSeq = PSEQ_BOOT_FAILED; + } + } + break; + + // u[gJn + case PSEQ_BOOT_START: + ClearStringSJIS_handle(msgHandle); + + SearchPatchAddress(); + + (void)LOADER_Start(); // ARM7ɂāA_E[hvO̍ĔzusB + return 1; // "1"Ń^[邱ƂŁA}`u[g̃C[v甲IPL2ɏ߂B + + // u[gs + // e@ɂāAڑؒfꂽ + // LZꍇ + case PSEQ_BOOT_FAILED: + case PSEQ_DISCONNECTED_BY_PARENT: + case PSEQ_CANCELLED: + if( DispMessage() ) { // w胁bZ[Wԕ\ + UnlockPrgNextSeqQue(); // V[PXbN + ClearStringSJIS_handle( msgHandle ); + prgSeq = PSEQ_INIT; + wdProcess = SEQ_DSDL_Connect; + } + break; + + default: + break; + } + + // B{^ŏIs + if( pad.trg & PAD_BUTTON_B ) { + MB_End(); // LŹAe@T[`Ԃ蒼B + } + + DrawMenu((u16)(csrC & (PARENT_VIEW_NUM - 1)), &childModeSel); // XgԍiJ[\j̕\ + DispParentNum(); // e@̕\ + DispParentList(); // e@Xg̕\ + DispScanStatus(); // WMXLԂ̕\ + CountAndDispTotalTime(); // g[^Ԃ̃JEg\ + CountParentFindTime(); // e@Ԃ̃JEg + return 0; +} + + +// V[PX̃`FbNiR[obNŃC[vƂ͔񓯊ɕԂ鎟V[PXւ̈ڍsC[ṽvOisɍ킹Bj +static BOOL CheckNextSeq_Download(void) +{ + PrgSeq seq; + + // MBR[obNɂāAV[PXڍsĂꍇ̏ + if( GetPrgNextSeqQue( &seq) ) { + prgSeq = seq; + OS_Printf("prgSeq = %s\n", str_prgSeq[ prgSeq ]); + + switch( seq ) { + + case PSEQ_REQ_REFUSED: // ڑۃbZ[W\ݒ + SetDispMessage( RED, str_req_refused); + LockPrgNextSeqQue(); // prgSeqbNB + return FALSE; + + case PSEQ_MEMBER_FULL: // o[FULLbZ[W\ݒB + SetDispMessage( RED, str_member_full); + LockPrgNextSeqQue(); // prgSeqbNB + return FALSE; + + case PSEQ_DOWNLOAD_READY: // _E[h + ClearStringSJIS_handle( msgHandle ); + { + msgHandle = DrawStringSJIS( 4, 21, WHITE, "Sign Decript...."); + if ( ACSignDecrpto( output_buffer, &dlfileinfo ) ) { + ClearStringSJIS_handle( msgHandle ); + msgHandle = DrawStringSJIS( 4, 21, LIGHTGREEN, "Decript SUCCEEDED."); + }else { + ClearStringSJIS_handle( msgHandle ); + msgHandle = DrawStringSJIS( 4, 21, RED, "Decript FAILED."); + } + { + int i; + for ( i = 0; i < 120; i++ ) { + SVC_WaitVBlankIntr(); + } + } + ClearStringSJIS_handle( msgHandle ); + } + + msgHandle = DrawStringSJIS( 4, 21, WHITE, "PUSH [A] TO DOWNLOAD."); + break; + + case PSEQ_DOWNLOAD_COMPLETED: // _E[h + ClearStringSJIS_handle( msgHandle ); + SetDispMessage( YELLOW, str_download_completed ); + LockPrgNextSeqQue(); // V[PXbN + return FALSE; + +// case PSEQ_BOOT_READY: // u[g +// ClearStringSJIS_handle( msgHandle ); +// break; + + case PSEQ_BOOT_READY: // u[g + ClearStringSJIS_handle( msgHandle ); + InitDispNintendoLogo(); + break; + + case PSEQ_CANCELLED: + ClearStringSJIS_handle( msgHandle ); + SetDispMessage( RED, str_download_cancelled ); + LockPrgNextSeqQue(); // V[PXbN + return FALSE; + + case PSEQ_DISCONNECTED_BY_PARENT: // ؒfobZ[W\ݒB + ClearStringSJIS_handle( msgHandle ); + SetDispMessage( RED, str_disconnected ); + LockPrgNextSeqQue(); // prgSeqbNB + return FALSE; + + default: + break; + } + } + return TRUE; +} + + +//====================================================== +// R[obN +//====================================================== + +// q@[hł̃R[obN +static void CallbackChild_MB( u32 status, void *arg ) +{ + switch (status) + { + case MB_COMM_CSTATE_INIT_COMPLETE: // + OS_Printf("CB: init completed.\n"); + (void)SetPrgNextSeqQue( PSEQ_SCANNING ); + break; + +// case MB_COMM_CSTATE_END_COMPLETE: // }`u[gI +// OS_Printf("CB: end completed.\n"); +// (void)SetPrgNextSeqQue( PSEQ_END ); +// break; + + case MB_COMM_CSTATE_REQ_REFUSED: // e@̃Gg[ + OS_Printf("CB: request refused.\n"); + (void)SetPrgNextSeqQue( PSEQ_REQ_REFUSED ); + break; + + case MB_COMM_CSTATE_MEMBER_FULL: // Q[ɒB + OS_Printf("CB: member full.\n"); + (void)SetPrgNextSeqQue( PSEQ_MEMBER_FULL ); + break; + + case MB_COMM_CSTATE_CONNECT: // e@ւ̐ڑ + OS_Printf("CB: connected.\n"); + (void)SetPrgNextSeqQue( PSEQ_CONNECT_SUCCEEDED ); + break; + + case MB_COMM_CSTATE_CONNECT_FAILED: // e@ւ̐ڑs + OS_Printf("CB: connect failed!\n"); + (void)SetPrgNextSeqQue( PSEQ_CONNECT_FAILED ); + break; + + case MB_COMM_CSTATE_DLINFO_ACCEPTED: // e@_E[hM + OS_Printf("CB: dlinfo accepted.\n"); + (void)SetPrgNextSeqQue( PSEQ_DOWNLOAD_READY ); + MI_CpuCopy16( (void *)arg, (void *)&dlfileinfo, sizeof( MBDownloadFileInfo ) ) ; + break; + + case MB_COMM_CSTATE_RECV_PROCEED: // MJn + OS_Printf("CB: recv proceed.\n"); + (void)SetPrgNextSeqQue( PSEQ_DOWNLOADING ); + break; + + case MB_COMM_CSTATE_RECV_COMPLETE: // M + OS_Printf("CB: recv completed.\n"); + (void)SetPrgNextSeqQue( PSEQ_DOWNLOAD_COMPLETED ); + break; + + case MB_COMM_CSTATE_BOOT_READY: // u[g + OS_Printf("CB: boot ready.\n"); +// GetSYSMWork()->mb_flag = 1; +// GetSYSMWork()->mb_ggid = *(u32 *)( MB_GetBeaconRecvStatus()->list[ pCwork->connectTargetNo ].bssDesc.gameInfo.ggid ); +// GetSYSMWork()->mb_ggid = MB_GetBeaconRecvStatus()->list[ pCwork->connectTargetNo ].gameInfo.ggid; + (void)SetPrgNextSeqQue( PSEQ_BOOT_READY ); + break; + + case MB_COMM_CSTATE_CANCELLED: // _E[hLZ + OS_Printf("CB: download cancel.\n"); + (void)SetPrgNextSeqQue( PSEQ_CANCELLED ); + break; + + case MB_COMM_CSTATE_DISCONNECTED_BY_PARENT: // e@̐ؒfʒm + OS_Printf("CB: disconnected by parent!\n"); + (void)SetPrgNextSeqQue( PSEQ_DISCONNECTED_BY_PARENT ); + break; + + case MB_COMM_CSTATE_GAMEINFO_LOST: + gameInfoLostCount++; + break; + } +} + + +//====================================================== +// \nTu[` +//====================================================== + +// XLԂ̕\ +static void DispScanStatus(void) +{ +#if 0 + int channel = MBw_GetScanChannel(); + + (void)DrawHexSJIS( 13, 2, WHITE, &channel, 2); + if( IsScanLock() ) { // XLbNȂA̎Ԃ\ + (void)DrawStringSJIS( 15, 2, RED, (const u8 *)"LOCK"); + (void)DrawHexSJIS ( 19, 2, WHITE, &mbrsp->nowLockTimeCount, 4); + }else { + (void)DrawStringSJIS( 15, 2, RED, (const u8 *)" "); + } +#endif +} + + +// e@̕\ +static void DispParentNum(void) +{ + int i; + int num = 0; + + for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++) { // e@̃JEg + if( mbrsp->usefulGameInfoFlag & (0x0001 << i) ) num++; + } + (void)DrawDecimalSJIS( 10, 2, LIGHTGREEN, &num, 2, 4); +} + + +// e@񃊃Xg̕\ +static void DispParentList(void) +{ + u32 i; + u32 listNo = (u32)( csrC & ~(PARENT_VIEW_NUM - 1) ); // ݕ\̃Xg̐擪Zoi~\Ń}XNj + u32 listNo_old = (u32)( csrC_old & ~(PARENT_VIEW_NUM - 1) ); // O\Xg̐擪Zo + +// (void)DrawDecimalSJISEx( 15, 22, WHITE, &gameInfoLostCount, 8, 4, 0); + + // Q[e̕\ + DispGameIntroduction(); + + // ʐMo[̕\ + DispPlayMember(); + + // e@Xg̕\ + for( i = 0; i < PARENT_VIEW_NUM; i++ ) { + if( (listNo != listNo_old) || !(mbrsp->usefulGameInfoFlag & (0x0001 << listNo)) ){ + if( dispGameInfoFlag & (0x0001 << listNo_old) ) { // \XgʒuύX or Ye@LłȂȂꍇAO\f[^ɕ\ς݂ȂNAB + ClearDispParentGameInfo( i, listNo_old); + dispGameInfoFlag ^= 0x0001 << listNo_old; + } + } + + if( mbrsp->usefulGameInfoFlag & (0x0001 << listNo) ) { // YXg̃f[^LŁA–\Ȃ\B + DispParentGameInfo( i, listNo , !(dispGameInfoFlag & (0x0001 << listNo)) ); + dispGameInfoFlag |= 0x0001 << listNo; + } + if( csrC != csrC_old ) { + DecimalToString( parentListNo[i], &listNo, 2, 2); // r[ʂ̐擪Xgio[𕶎obt@ɓB + } + listNo++; + listNo_old++; + } +} + + +// Q[e̕\ +static void DispGameIntroduction( void ) +{ + BOOL clear = FALSE; + + if( ( ( csrC != csrC_old ) && ( dispIntroFlag & (0x0001 << csrC_old) ) ) + || ( !(mbrsp->usefulGameInfoFlag & (0x0001 << csrC)) && ( dispIntroFlag & (0x0001 << csrC) ) ) ) { + ClearDispGameIntroduction(); // J[\āAOJ[\ʒȕڍו\sĂA + dispIntroFlag = 0; + clear = TRUE; + } + + if( (mbrsp->usefulGameInfoFlag & (0x0001 << csrC)) && !( dispIntroFlag & (0x0001 << csrC) ) ) { + if ( !clear ){ // ݃J[\ʒũQ[񂪗LŁA܂ڍו\sĂȂ\B + ClearDispGameIntroduction(); + } + DispGameIntroduction_Core( (u32)csrC ); + dispIntroFlag = (u16)( 0x0001 << csrC ); // J[\ړꂽA݈ʒũQ[񂪖\̎ɂ̂ݕ\ or NAsB + } +} + + +// ʐMo[̃NA\ +static void DispPlayMember( void ) +{ + BOOL clear = FALSE; + + if( ( ( csrC != csrC_old ) && ( dispMemberFlag & (0x0001 << csrC_old) ) ) + || ( !(mbrsp->validGameInfoFlag & (0x0001 << csrC)) && ( dispMemberFlag & (0x0001 << csrC) ) ) ) { + ClearDispPlayMember(); // J[\ʒũQ[ڍ׏\ĂāÃQ[񂪖ɂȂNAB + dispMemberFlag = 0; + clear = TRUE; + } + + if( (mbrsp->validGameInfoFlag & (0x0001 << csrC)) && !( dispMemberFlag & (0x0001 << csrC) ) ) { + if ( !clear ){ // ݃J[\ʒũQ[񂪗LŁA܂ڍו\sĂȂ\B + ClearDispPlayMember(); + } + DispPlayMember_Core( (u32)csrC ); + dispMemberFlag = (u16)( 0x0001 << csrC ); // J[\ړꂽA݈ʒũQ[񂪖\̎ɂ̂ݕ\ or NAsB + } +} + + +// w肳ꂽe@̕\ +static void DispParentGameInfo( u32 view_no, u32 listNo, BOOL drawFixedDataFlag) +{ + if(drawFixedDataFlag) { // ωȂ̕\ + + MI_CpuClear16( gameName, MB_GAME_NAME_LENGTH * 2 ); + MI_CpuClear16( userName, MB_USER_NAME_LENGTH * 2 ); + ExUTF16_LEtoSJIS_BE( (u8 *)gameName, (u16 *)mbrsp->list[ listNo ].gameInfo.fixed.gameName, MB_GAME_NAME_LENGTH * 2 ); + ExUTF16_LEtoSJIS_BE( (u8 *)userName, (u16 *)mbrsp->list[ listNo ].gameInfo.fixed.parent.name, (u16)( mbrsp->list[ listNo ].gameInfo.fixed.parent.nameLength * 2)); +// MI_CpuCopy16( mbrsp->list[ listNo ].gameInfo.fixed.gameName, gameName, MB_GAME_NAME_LENGTH * 2); +// MI_CpuCopy16( mbrsp->list[ listNo ].gameInfo.fixed.parent.name, userName, mbrsp->list[ listNo ].gameInfo.fixed.parent.nameLength * 2); + gameName[ MB_GAME_NAME_LENGTH ] = 0; + userName[ mbrsp->list[ listNo ].gameInfo.fixed.parent.nameLength ] = 0; + + (void)ClearStringSJISEx( gameName, view_no); + (void)ClearStringSJISEx( userName, view_no); + (void)DrawStringSJISEx( 9, (PLIST_Y + (int)view_no*4), WHITE, gameName, view_no); + (void)DrawStringSJISEx( 9, (PLIST_Y + (int)view_no*4 + 2), WHITE, userName, view_no); + + (void)DrawStringSJISEx( 26, (PLIST_Y + (int)view_no*4), YELLOW, str_sura, view_no); + (void)DrawDecimalSJIS ( 27, (PLIST_Y + (int)view_no*4), YELLOW, &mbrsp->list[ listNo ].gameInfo.fixed.maxPlayerNum, 2, 1); + + // e@Ԃ̕\ + (void)CheckParentFindTime( listNo ); // Őe@𔭌Ă邩ĊmFĂB + time_ms = (int)findTime[listNo].vcount * 17; + time_sec = time_ms / 1000; + time_ms = (time_ms % 1000) / 10; + (void)DrawDecimalSJISEx( 23, (PLIST_Y + (int)view_no*4 + 2), CYAN, &time_sec, 4, 4, view_no); + (void)DrawDecimalSJISEx( 27, (PLIST_Y + (int)view_no*4 + 2), CYAN, &time_ms, 2, 4, view_no); + (void)DrawStringSJISEx ( 26, (PLIST_Y + (int)view_no*4 + 2), CYAN, str_period, view_no); + (void)DrawStringSJISEx ( 29, (PLIST_Y + (int)view_no*4 + 2), CYAN, str_sec, view_no); + + SetIconOBJ( listNo ); // ACR̕\ + } + { // ωio[Ee@JEg̕\j + (void)DrawDecimalSJIS( 24, (PLIST_Y + (int)view_no*4), YELLOW, &mbrsp->list[ listNo ].gameInfo.volat.nowPlayerNum, 2, 1); + (void)DrawHexSJIS ( 19, (PLIST_Y + (int)view_no*4 + 2), CYAN, &mbrsp->list[ listNo ].lifetimeCount, 4); + { + u16 color = RED; + if ( mbrsp->validGameInfoFlag & ( 0x0001 << listNo ) ) { + color = CYAN; + } + (void)DrawHexSJIS ( 19, (PLIST_Y + (int)view_no*4), color, &mbrsp->list[ listNo ].gameInfo.seqNoVolat, 2); + } + } +} + + +// w肳ꂽe@̕\NA +static void ClearDispParentGameInfo( u32 view_no, u32 listNo) +{ + // ̕ϐ̃AhX́ADispParentGameInfô̂ƈvĂȂƁA\NA邱ƂłȂ̂ŒӁBiϐŕ\Ƃ̓AhXςĂ܂j + // iDrawStringSJIS֐̎dlj + ClearStringSJISEx( gameName, view_no ); // Q[ + ClearStringSJISEx( userName, view_no ); // [U[ + ClearStringSJISEx( &time_sec, view_no ); // e@sec + ClearStringSJISEx( &time_ms, view_no ); // e@ms + ClearStringSJISEx( (void *)str_sura, view_no ); // "/" + ClearStringSJISEx( (void *)str_period, view_no ); // "." + ClearStringSJISEx( (void *)str_sec, view_no ); // "sec" + ClearStringSJIS ( (void *)&mbrsp->list[ listNo ].lifetimeCount ); // e@JEg + ClearStringSJIS ( (void *)&mbrsp->list[ listNo ].gameInfo.volat.nowPlayerNum ); // vCl + ClearStringSJIS ( (void *)&mbrsp->list[ listNo ].gameInfo.fixed.maxPlayerNum ); // ővCl + ClearStringSJIS ( (void *)&mbrsp->list[ listNo ].gameInfo.seqNoVolat ); // ővCl + + ClearIconOBJ( listNo ); // ACȐ +} + + +// Q[e̕\i) +static void DispGameIntroduction_Core( u32 listNo ) +{ + int i; + const u16 *strp = mbrsp->list[ listNo ].gameInfo.fixed.gameIntroduction; + u16 *dstp; + u16 gameIntroTmp[ MB_GAME_INTRO_LENGTH / 2 + 1 ]; + + MI_CpuClear16( gameIntroduction[0], (MB_GAME_INTRO_LENGTH / 2 + 1) * sizeof(u16) ); + MI_CpuClear16( gameIntroduction[1], (MB_GAME_INTRO_LENGTH / 2 + 1) * sizeof(u16) ); + + dstp = gameIntroTmp; + for ( i = 0; i < MB_GAME_INTRO_LENGTH / 2; i++ ) { // oCgPʂł̃Rs[Ȃ̂ŁA1śAMB_GAME_INTRO_LENGTH/2*2B + if( ( *strp == NULL) || ( *strp == 0x000a ) ) { + *dstp++ = 0x0000; + }else { + *dstp++ = *strp++; + } + } + ExUTF16_LEtoSJIS_BE( (u8 *)gameIntroduction[ 0 ], gameIntroTmp, MB_GAME_INTRO_LENGTH / 2 ); + + if( *strp == 0x000a ) { + strp++; + } + + dstp = gameIntroTmp; + for ( i = 0; i < MB_GAME_INTRO_LENGTH / 2; i++ ) { + if( ( *strp == NULL) || ( *strp == 0x000a ) ) { + *dstp++ = 0x00; + }else { + *dstp++ = *strp++; + } + } + ExUTF16_LEtoSJIS_BE( (u8 *)gameIntroduction[ 1 ], gameIntroTmp, MB_GAME_INTRO_LENGTH / 2 + 1 ); + + ClearDispGameIntroduction(); + + SetTargetScreenSJIS( TOP_SCREEN ); + (void)DrawStringSJIS( ( G_INTRO_X + 1 ), ( G_INTRO_Y + 2 ), WHITE, (const u8 *)gameIntroduction[0] ); + (void)DrawStringSJIS( ( G_INTRO_X + 1 ), ( G_INTRO_Y + 4 ), WHITE, (const u8 *)gameIntroduction[1] ); + SetTargetScreenSJIS( BOTTOM_SCREEN ); +} + + +// Q[e\̃NA +static void ClearDispGameIntroduction( void ) +{ + SetTargetScreenSJIS( TOP_SCREEN ); + ClearStringSJIS( (void *)gameIntroduction[0] ); + ClearStringSJIS( (void *)gameIntroduction[1] ); + SetTargetScreenSJIS( BOTTOM_SCREEN ); +} + + +// ʐMo[̕\ij +static void DispPlayMember_Core( u32 listNo ) +{ + int n, count_x; + u16 nameLength; + int pos_x, pos_y; + const MBUserInfo *memberp = &mbrsp->list[ listNo ].gameInfo.volat.member[ 0 ]; + u16 *dstp; + + SetTargetScreenSJIS( TOP_SCREEN ); + + MI_CpuClear16( playMember, sizeof(playMember) ); + count_x = 0; + pos_x = G_MEMBER_X + 1; + pos_y = G_MEMBER_Y + 2; + for ( n = 0; n < MB_MEMBER_MAX_NUM; n++ ) { + + if( memberp->nameLength > MB_USER_NAME_LENGTH ) { // Õ`FbN + nameLength = MB_USER_NAME_LENGTH; + }else { + nameLength = memberp->nameLength; + } + dstp = playMember[ n ]; + if( mbrsp->list[ listNo ].gameInfo.volat.nowPlayerFlag & (0x0002 << n ) ) { + + ExUTF16_LEtoSJIS_BE( (u8 *)dstp, (u16 *)memberp->name, nameLength ); + playMember[ n ][ nameLength ] = 0; + (void)DrawStringSJIS( pos_x, pos_y, WHITE, (const u8 *)playMember[ n ] ); + }else { + MI_CpuCopy16( (void *)"----------", (void *)playMember[ n ], MB_USER_NAME_LENGTH + 1); + (void)DrawStringSJIS( pos_x, pos_y, WHITE, playMember[ n ] ); + } + memberp++; + + if( ++count_x == 3 ) { // \ʒu̎Zo + pos_x -= 20; + pos_y += 2; + count_x = 0; + }else { + pos_x += 10; + } + } + + SetTargetScreenSJIS( BOTTOM_SCREEN ); +} + + +// ʐMo[\̃NA +static void ClearDispPlayMember( void ) +{ + int i; + + SetTargetScreenSJIS( TOP_SCREEN ); + for( i = 0; i < MB_MEMBER_MAX_NUM + 1; i++ ) { + ClearStringSJIS( (void *)playMember[ i ] ); + } + SetTargetScreenSJIS( BOTTOM_SCREEN ); +} + + +// 10if[^𕶎ɕϊ +static void DecimalToString(u8 *dstp, const void *valuep, u8 drawLength, u8 size) +{ + u16 count; + u32 mask, divisor, target; + + mask = 0xff; + while(--size > 0) { + mask = (mask << 8) | 0xff; + } + target=(*(u32 *)valuep) & mask; + count=10; + divisor=1000000000; + while(count) { + CP_SetDiv32_32(target, divisor); + if (count <= drawLength) { + *dstp++ = (u8)(CP_GetDivResult32()+0x0030); + } + target=(u32)CP_GetDivRemainder32(); + CP_SetDiv32_32(divisor, 10); + divisor=(u32)CP_GetDivResult32(); + count--; + } +} + + +// e@ԕϐ̃NA +static void InitParentFindTime( void ) +{ + int i; + for( i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++) { + findTime[i].find = FALSE; + findTime[i].vcount = 0; + } + total_vcount = 0; +} + + +// e@Ԃ̃JEg +static void CountParentFindTime( void ) +{ + u32 i; + + for( i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++ ) { + if( !CheckParentFindTime( i ) ) { + findTime[i].vcount = total_vcount; // e@񂪌‚܂ŃJEg + } + } +} + + +// e@񂪑ǂ`FbNāAԃJEg~B +static BOOL CheckParentFindTime( u32 index ) +{ + if( mbrsp->validGameInfoFlag & (0x01 << index) ) { // e@񂪔ꂽȂAJEg~B + findTime[ index ].find = TRUE; + } + return findTime[ index ].find; +} + + +// g[^Ԃ̃JEg\ +static void CountAndDispTotalTime( void ) +{ + total_vcount++; + time_ms = total_vcount * 17; + time_sec = time_ms / 1000; + time_ms = (time_ms % 1000) / 10; + (void)DrawDecimalSJISEx( 23, 2, CYAN, &time_sec, 4, 4, PARENT_VIEW_NUM); + (void)DrawDecimalSJISEx( 27, 2, CYAN, &time_ms, 2, 4, PARENT_VIEW_NUM); +} + + +// ACROBJ̃[h +static void SetIconOBJ( u32 index ) +{ + u16 view_no = (u16)( index & 0x03 ); + const MBIconInfo *iconp = &mbrsp->list[ index ].gameInfo.fixed.icon; + + GXS_LoadOBJPltt( iconp->palette, (u32)( MB_ICON_PALETTE_SIZE * view_no ), MB_ICON_PALETTE_SIZE ); + MI_CpuCopyFast( iconp->data, (void *)((u32)objVramBuff + 0x20 + MB_ICON_DATA_SIZE * view_no), MB_ICON_DATA_SIZE ); + G2_SetOBJAttr( (GXOamAttr*)&oamBakS[ view_no ], // OAM pointer + 8 * (PLIST_X + 3), // X position + 8 * PLIST_Y + (view_no * 32), // Y position + 0, // Priority + GX_OAM_MODE_NORMAL, // Bitmap mode + FALSE, // mosaic off + GX_OAM_EFFECT_NONE, // affine off + GX_OAM_SHAPE_32x32, // 16x16 size + GX_OAM_COLOR_16, // 16 color + 1 + view_no * 16, // charactor + view_no, // palette + 0); // affine +} + +// ACROBJ̃NA +static void ClearIconOBJ( u32 index ) +{ + u16 view_no = (u16)( index & 0x03 ); + u16 *oamp = (u16 *)&oamBakS[ view_no ]; + + *oamp++ = 192; // YWʊOɁBiI[0NAł̓_j + *oamp++ = 0; + *oamp++ = 0; + *oamp = 0; +} + + +// bZ[W\̃Zbg +static void SetDispMessage( u16 color, const u8 *str ) +{ + msgStat.vcount = MSG_VIEW_COUNT; + msgStat.color = color; + msgStat.str = str; +} + + +// bZ[W\ +static BOOL DispMessage(void) +{ + if( msgStat.vcount == MSG_VIEW_COUNT ) { + msgStat.handle = DrawStringSJIS( 4, 21, msgStat.color, msgStat.str ); + } + + if ( --msgStat.vcount == 0 ) { + ClearStringSJIS_handle( msgStat.handle ); + return TRUE; + } + return FALSE; +} + + +// bZ[W\̃Zbgi_ŕ\j +static void SetBlinkMessage( u16 color, const u8 *str ) +{ + msgStat.vcount = MSG_BLINK_COUNT; + msgStat.flag = 1; + msgStat.color = color; + msgStat.str = str; +} + + +// bZ[W\ +static void DispBlinkMessage( void ) +{ + if( ( msgStat.vcount == MSG_BLINK_COUNT ) && msgStat.flag ) { + msgStat.handle = DrawStringSJIS( 4, 21, msgStat.color, msgStat.str ); + } + + if ( --msgStat.vcount == 0 ) { + ClearStringSJIS_handle( msgStat.handle ); + msgStat.flag ^= 0x01; + msgStat.vcount = MSG_BLINK_COUNT; + } +} + + +//============================================================================= +// NintendoS\ +//============================================================================= + +// NintendoS\̏ +static void InitDispNintendoLogo( void ) +{ + int i; + u16 *palettep = (u16 *)(HW_OBJ_PLTT + 0x20 * 15 ) + 1; // pbg15̃J[1ɁB + *palettep++ = 0x7fff; + *palettep = 0x1111; + + // TOPʂ̑S\NA + SetTargetScreenSJIS( TOP_SCREEN ); + ClearAllStringSJIS(); + SetTargetScreenSJIS( BOTTOM_SCREEN ); + + // ʏɎMQ[NintendoS\B +#ifdef NINLOGO_LOAD_1D_CHAR + // 1D}bsOł̃[h\ + GX_SetOBJVRamModeChar( GX_OBJVRAMMODE_CHAR_1D_32K ); + SYSM_LoadNintendoLogo1D( (u16 *)GetRomHeaderAddr()->nintendo_logo, (u16 *)( HW_OBJ_VRAM + 0x40 ), 1, ninLogoBuff ); +// SYSM_LoadNintendoLogo1D( (u16 *)SYSROM9_NINLOGO_ADR, (u16 *)( HW_OBJ_VRAM + 0x40 ), 1, ninLogoBuff ); + + for ( i = 0; i < 3; i++ ) { + G2_SetOBJAttr( &oamBakM[ 10 + i ], // OAM pointer + 72 + 32 * i, // X position + 88, // Y position + 0, // Priority + GX_OAM_MODE_NORMAL, // Bitmap mode + FALSE, // mosaic off + GX_OAM_EFFECT_NONE, // affine off + GX_OAM_SHAPE_32x8, // 16x16 size + GX_OAM_COLOR_16, // 16 color + 0x2 + i * 4, // charactor + 15, // palette + 0); // affine + } + { + G2_SetOBJAttr( &oamBakM[ 13 ], // OAM pointer + 72 + 32 * 3, // X position + 88, // Y position + 0, // Priority + GX_OAM_MODE_NORMAL, // Bitmap mode + FALSE, // mosaic off + GX_OAM_EFFECT_NONE, // affine off + GX_OAM_SHAPE_8x8, // 16x16 size + GX_OAM_COLOR_16, // 16 color + 0x2 + 3 * 4, // charactor + 15, // palette + 0); // affine + } + for ( i = 0; i < 3; i++ ) { + G2_SetOBJAttr( &oamBakM[ 14 + i ], // OAM pointer + 72 + 32 * i, // X position + 96, // Y position + 0, // Priority + GX_OAM_MODE_NORMAL, // Bitmap mode + FALSE, // mosaic off + GX_OAM_EFFECT_NONE, // affine off + GX_OAM_SHAPE_32x8, // 16x16 size + GX_OAM_COLOR_16, // 16 color + 0x0f + i * 4, // charactor + 15, // palette + 0); // affine + } + { + G2_SetOBJAttr( &oamBakM[ 17 ], // OAM pointer + 72 + 32 * 3, // X position + 96, // Y position + 0, // Priority + GX_OAM_MODE_NORMAL, // Bitmap mode + FALSE, // mosaic off + GX_OAM_EFFECT_NONE, // affine off + GX_OAM_SHAPE_8x8, // 16x16 size + GX_OAM_COLOR_16, // 16 color + 0xf + 3 * 4, // charactor + 15, // palette + 0); // affine + } +#else + // 2D}bsOł̃[h\ + GX_SetOBJVRamModeChar( GX_OBJVRAMMODE_CHAR_2D ); + SYSM_LoadNintendoLogo2D( (u16 *)GetRomHeaderAddr()->nintendo_logo, (u16 *)( HW_OBJ_VRAM + 0x40 ), 1, ninLogoBuff ); +// SYSM_LoadNintendoLogo2D( (u16 *)SYSROM9_NINLOGO_ADR, (u16 *)( HW_OBJ_VRAM + 0x40 ), 1, ninLogoBuff ); + + for ( i = 0; i < 4; i++ ) { + G2_SetOBJAttr( &oamBakM[11 + i], // OAM pointer + 72 + 32 * i, // X position + 88, // Y position + 0, // Priority + GX_OAM_MODE_NORMAL, // Bitmap mode + FALSE, // mosaic off + GX_OAM_EFFECT_NONE, // affine off + GX_OAM_SHAPE_32x16, // 16x16 size + GX_OAM_COLOR_16, // 16 color + 0x2 + i * 4, // charactor + 15, // palette + 0); // affine + } +#endif + + loop_count = 120; +} + + +// NintendoS\ +static BOOL DispNintendoLogo( void ) +{ + if( --loop_count == 0 ) { + { + int i; + for ( i = 0; i < 4; i++ ) { + G2_SetOBJPosition( &oamBakM[ 11 + i ], 0, 192 ); + } + } + return TRUE; + } + return FALSE; +} + + +//============================================================================= +// ̑Tu[` +//============================================================================= + +// ̃[U[NITROݒf[^ǂݏoăZbg +static void SetMyUserInfo( MBUserInfo *my ) +{ + NvNickname *nickname = NCD_GetNickname(); + + MI_CpuCopy16( nickname->str, my->name, (u32)( nickname->length * 2 ) ); + my->nameLength = nickname->length; + my->playerNo = 0; // Ƃ肠OɂB + my->favoriteColor = NCD_GetFavoriteColor(); +} + + +// ݃XLbNǂ擾B +static BOOL IsScanLock(void) +{ + return mbrsp->nowScanTargetFlag ? TRUE : FALSE; +} + + +//============================================================================= +// 荞݃[` +//============================================================================= + +// VuN荞 +static void VBlankIntr_WDL(void) +{ + // OAM, BG-VRAM̍XV + DC_FlushRange (oamBakM, sizeof(oamBakM)); + DC_FlushRange (oamBakS, sizeof(oamBakS)); + DC_FlushRange (bgBakM, sizeof(bgBakM)); + DC_FlushRange (bgBakS, sizeof(bgBakS)); + DC_FlushRange (objVramBuff, sizeof(objVramBuff)); + MI_CpuCopyFast(oamBakM, (void*)HW_OAM, sizeof(oamBakM)); + MI_CpuCopyFast(oamBakS, (void*)HW_DB_OAM, sizeof(oamBakS)); + MI_CpuCopyFast(bgBakM, (void*)(HW_BG_VRAM + 0xf000), sizeof(bgBakM)); + MI_CpuCopyFast(bgBakS, (void*)(HW_DB_BG_VRAM + 0xf000), sizeof(bgBakS)); + MI_CpuCopyFast(objVramBuff, (void*)HW_DB_OBJ_VRAM, sizeof(objVramBuff)); + //---- 荞݃`FbNtO + OS_SetIrqCheckFlag(OS_IE_V_BLANK); +} + + +//============================================================================= +// vOV[PXL[ +//============================================================================= + +// L[ +static void InitPrgNextSeqQue( void ) +{ + MI_CpuClear16( &nextSeq, sizeof(nextSeq) ); +} + + +// PrgSeqL[ɃZbgB +static BOOL SetPrgNextSeqQue( PrgSeq seq ) +{ + BOOL preIRQ = OS_DisableIrq(); + BOOL retval = FALSE; + + if( nextSeq.num != PRG_NEXT_SEQ_QUE_NUM ) { + nextSeq.seq[ nextSeq.bottom ] =seq; + nextSeq.num++; + nextSeq.bottom++; + if( nextSeq.bottom == PRG_NEXT_SEQ_QUE_NUM ) { + nextSeq.bottom = 0; + } + retval = TRUE; + } + (void)OS_RestoreIrq( preIRQ ); + return retval; +} + + +// PrgSeqL[o +static BOOL GetPrgNextSeqQue( PrgSeq *seqp ) +{ + BOOL preIRQ = OS_DisableIrq(); + BOOL retval = FALSE; + + if( ( !nextSeq.lock ) && ( nextSeq.num != 0 ) ) { // L[bNĂ炸AŽSeq݂ȂAL[oB + *seqp = nextSeq.seq[ nextSeq.top ]; + nextSeq.num--; + nextSeq.top++; + if( nextSeq.top == PRG_NEXT_SEQ_QUE_NUM ) { + nextSeq.top = 0; + } + retval = TRUE; + } + (void)OS_RestoreIrq( preIRQ ); + return retval; +} + + +// L[bNBibNGetPrgNextSeqQueŎSeqoȂȂ܂Bj +static void LockPrgNextSeqQue(void) +{ + nextSeq.lock = TRUE; +} + + +// L[̃bNB +static void UnlockPrgNextSeqQue(void) +{ + nextSeq.lock = FALSE; +} + +// L[󂩁H +static BOOL IsEmptyPrgNextSeqQue(void) +{ + return nextSeq.num ? FALSE : TRUE; +} + + + +static const u32 searchCode[] = { + 0xe59f1028, + 0xe59f2028, + 0xe1d200b0, + 0xe2100001, + 0x1afffffc, + 0xe1d100b0, + 0xe3500006, + 0x0afffff9, + 0xe1d100b0, + 0xe3500005, + 0x0afffff6, + 0xe12fff1e, + 0x04808214, + 0x0480819c, +}; + + +void SearchPatchAddress( void ) +{ + MBDownloadFileInfo *dlfinfo = (MBDownloadFileInfo *)MB_DOWNLOAD_FILEINFO_ADDRESS; + BOOL find = FALSE; + u32 *tgtp = (u32 *)MB_ARM7_STATIC_RECV_BUFFER; + u32 size = dlfinfo->seg[ 2 ].size >> 2; + + while( size-- ) { + if( *tgtp++ == searchCode[0] ) { + u32 *srcp = (u32 *)&searchCode[ 1 ]; + u32 *checkp = tgtp ; + int i = sizeof( searchCode ) / sizeof(u32) - 1; + while( i-- ) { + if( *srcp++ != *checkp++ ) break; + } + if( i < 0 ) { + u32 addr = (u32)tgtp - 0x04 + 0x18; + OS_TPrintf("Found! -> 0x%08x\n", addr ); + find = TRUE; + } + } + } + if( !find ) { + OS_TPrintf("Not found.\n"); + } +} + diff --git a/build/systemMenu_RED/DS_DownloadPlay/ARM9/src/DS_DownloadPlay.h b/build/systemMenu_RED/DS_DownloadPlay/ARM9/src/DS_DownloadPlay.h new file mode 100644 index 0000000..1c9a8f8 --- /dev/null +++ b/build/systemMenu_RED/DS_DownloadPlay/ARM9/src/DS_DownloadPlay.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: DS_DownloadPlay.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef __DS_DOWNLOAD_PLAY_H__ +#define __DS_DOWNLOAD_PLAY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include + +// define data---------------------------------------------------------- + +int DS_DownloadPlayMain( void ); + + +#ifdef __cplusplus +} +#endif + +#endif // __DS_DOWNLOAD_PLAY_H__ diff --git a/build/systemMenu_RED/DS_DownloadPlay/Makefile b/build/systemMenu_RED/DS_DownloadPlay/Makefile new file mode 100644 index 0000000..9cf34e1 --- /dev/null +++ b/build/systemMenu_RED/DS_DownloadPlay/Makefile @@ -0,0 +1,30 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +SUBDIRS = banner ARM9 + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/systemMenu_RED/DS_DownloadPlay/banner/Makefile b/build/systemMenu_RED/DS_DownloadPlay/banner/Makefile new file mode 100644 index 0000000..efdcadf --- /dev/null +++ b/build/systemMenu_RED/DS_DownloadPlay/banner/Makefile @@ -0,0 +1,52 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +ICON_DIR = ./icon +TOOLS_DIR = $(TWLIPL_ROOT)/tools/bin +NTEXCONV = $(TOOLS_DIR)/ntexconv.exe +MAKEBANNER = $(TOOLS_DIR)/makebanner.exe + +BANNER_ICON = $(ICON_DIR)/gameIcon.bmp +BANNER_SPEC = banner_v3.bsf + +TARGETS = banner.bnr +INSTALL_DIR = ./ +INSTALL_TARGETS = $(TARGETS) + +BANNER_ICON_NAME = $(basename $(BANNER_ICON)) + +LDIRT_CLEAN = $(TARGETS) \ + $(BANNER_ICON_NAME).nbfs \ + $(BANNER_ICON_NAME).nbfc \ + $(BANNER_ICON_NAME).nbfp \ + $(TARGETS:.bnr=.srl) + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + +#---------------------------------------------------------------------------- +# build +#---------------------------------------------------------------------------- +do-build: $(TARGETS) + +$(TARGETS): $(BANNER_SPEC) $(BANNER_ICON) + $(NTEXCONV) -no -bg -bgb -bgnc $(BANNER_ICON) >/dev/null && \ + $(MAKEBANNER) -d -N $(BANNER_ICON_NAME) $(BANNER_SPEC) $(TARGETS) + +# diff --git a/build/systemMenu_RED/DS_DownloadPlay/banner/banner_v3.bsf b/build/systemMenu_RED/DS_DownloadPlay/banner/banner_v3.bsf new file mode 100644 index 0000000000000000000000000000000000000000..8209887b95f200f9837b217ce0c507f60f8d1224 GIT binary patch literal 828 zcmc&yyGjE=6g{O+{Dpz7S4RX9OEv2Q3Biq4HoKb`7xoc0tHHu=@F&C%kQ6Dc6hA<0 zENuc>*@}AZ>?Q{7m0^aNJ7>;4=id4Ju&@Rf4is!N6we+KjwUijU9`CixN{I9;(iuW zuu63C=5N*_uRhK`B!J+?tr>PU5J!=SE+ExXp*}f)EJq>20L=2uk@RK)$jUVKk65KsRdC%b%apF zrL022j-~Y6AXklh4`+ta!Jfg^F<^AS{uY&KQ9*2KCiRhA!n{fDVQ%{uvu*xJ$XAg; zZ?mce`lo^+pF8r>q}#ysq{a0+FW8#N;2n*lC810!t-_S_OSodQ>@Lab zuj1h!pv`7=Q2Q5{)b}nG>lf~l&%JNHFOREiTk{}g;l7S*ZMx=Q0pC#5dJ5^D;3JdC zKt7*`QmF*Gu0yq2g?haX&1Mr?trj?r1D#F>dc7V5K>&ln0HP>@$z%dx{1YsirimxI zrfFH!^0&nsCNnfOtE`}M-!|vy(D5MUHhERF5@Oxmnl%vHGYPr4Tl-5;R&uddYo~@M zYC-JU7PVN_R7EMq{$7_1wbz2KDOt&6*cl;jNcP;e{d6!Y&`%cQV6X4FcA3~v)nXhT z``*<%F*7P!F+uKMKJ1^q70h4uz3%=QGOOqY)&sxq)sP!z#W0e`7|Vd1IGJmWFnj^OVQYv)}K!n-)Jbv5vF6Py$XN`R?=jg%WUz!v;%+;^g*2Cb;$y zXGtXPMjv4)4d=u|!N*^CU6Bws#Ax6syeDQ@#6uw-@dMd{C1@2wgwq7JG)^^5xS&g) G5&QsSy%i1s literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/Launcher/ARM9/ARM9-TS.lsf b/build/systemMenu_RED/Launcher/ARM9/ARM9-TS.lsf new file mode 100644 index 0000000..199d6f8 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/ARM9-TS.lsf @@ -0,0 +1,54 @@ +#---------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ARM9-BB.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TWL LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x02800000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) +} + + +Autoload ITCM +{ + Address 0x01ff8000 + Object * (.itcm) + Object $(OBJS_AUTOLOAD) (.text) + Object $(OBJS_AUTOLOAD) (.rodata) +} + +Autoload DTCM +{ + Address $(ADDRESS_DTCM) + Object * (.dtcm) + Object $(OBJS_AUTOLOAD) (.data) + Object $(OBJS_AUTOLOAD) (.sdata) + Object $(OBJS_AUTOLOAD) (.bss) + Object $(OBJS_AUTOLOAD) (.sbss) +} + +Ltdautoload LTDMAIN +{ + # NITRO/TWL L̃I[o[C݂ꍇ́Aɂ̌ɔzuKv܂B + After $(TARGET_NAME) + Object * (.ltdmain) + Object $(OBJS_LTDAUTOLOAD) + Library $(LLIBS_EX) $(GLIBS_EX) +} diff --git a/build/systemMenu_RED/Launcher/ARM9/Makefile b/build/systemMenu_RED/Launcher/ARM9/Makefile new file mode 100644 index 0000000..bab2460 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/Makefile @@ -0,0 +1,54 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - demos - simpleShoot-1 +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev: $ +# $Author: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +#---------------------------------------------------------------------------- + +TARGET_FIRM = SYSTEMMENU +TARGET_PLATFORM = TWL +TWL_ARCHGEN = LIMITED + +TARGET_BIN = main.srl + +LCFILE_SPEC = ARM9-TS.lsf +ROM_SPEC = main.rsf + +LOGO_DIR = Logo + +SRCS_LOGO = logoDemo.c logoData.c +SRCS = main.c launcher.c misc.c $(addprefix $(LOGO_DIR)/, $(SRCS_LOGO)) +#SRCS_OVERLAY = + +LINCLUDES = $(SRCDIR)/$(LOGO_DIR) +#LLIBRARY_DIRS = +#LLIBRARIES = +#LDEPENDS_NEF = + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build : $(FONT_OBJS) $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#---------------------------------------------------------------------------- + +#===== End of Makefile ===== diff --git a/build/systemMenu_RED/Launcher/ARM9/main.rsf b/build/systemMenu_RED/Launcher/ARM9/main.rsf new file mode 100644 index 0000000..ca53113 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/main.rsf @@ -0,0 +1,147 @@ +#---------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ROM-BB.rsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TWL ROM SPEC FILE +# + +Arm9 +{ + Static "$(MAKEROM_ARM9:r).FLX.TWL.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.FLX.TWL.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.FLX.TWL.sbin$(COMPSUFFIX9)" + Elf "$(MAKEROM_ARM9:r).tef" +} + +Arm7 +{ + Static "$(MAKEROM_ARM7_BASE:r).FLX.TWL.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.FLX.TWL.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.FLX.TWL.sbin$(COMPSUFFIX7)" + Elf "$(MAKEROM_ARM7_BASE:r).tef" +} + +Arm9.Ltd +{ + Static "$(MAKEROM_ARM9:r).LTD.TWL.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.LTD.TWL.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.LTD.TWL.sbin$(COMPSUFFIX9)" +} + +Arm7.Ltd +{ + Static "$(MAKEROM_ARM7_BASE:r).LTD.TWL.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.LTD.TWL.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.LTD.TWL.sbin$(COMPSUFFIX7)" +} + +Property +{ + ### + ### Settings for FinalROM + ### + #### BEGIN + # + # TITLE NAME: Your product name within 12bytes + # + #TitleName "YourAppName" + + # + # MAKER CODE: Your company ID# in 2 ascii words + # issued by NINTENDO + # + #MakerCode "00" + + # + # REMASTER VERSION: Mastering version + # + #RomVersion 0 + + # + # ROM SPEED TYPE: [MROM/1TROM/UNDEFINED] + # + RomSpeedType $(MAKEROM_ROMSPEED) + + # + # ROM SIZE: in bit [64M/128M/256M/512M/1G/2G] + # + #RomSize 128M + #RomSize 256M + + # + # ROM PADDING: TRUE if finalrom + # + #RomFootPadding TRUE + + # + # ROM HEADER TEMPLATE: Provided to every product by NINTENDO + # + #RomHeaderTemplate ./etc/rom_header.template.sbin + + # + # BANNER FILE: generated from Banner Spec File + # + #BannerFile ./etc/myGameBanner.bnr + BannerFile $(TWLSDK_ROOT)/include/twl/specfiles/default.bnr + + ### + ### Setting for TWL + ### + # + # BANNER FILE: + # + BannerTWLFile $(TWLSDK_ROOT)/include/twl/specfiles/default.bnr + + # + # Boot allowed Media: [GameCard/NAND/SDCard/DownloadPlay] + # possible to choose one or more. + # + BootMedia GameCard NAND SDCard DownloadPlay + + # + # Certification FILE: + # + Certificate $(TWLSDK_ROOT)/include/twl/specfiles/default_sgn.sbin + + # + # Digest parameters: + # + DigestParam 1024 32 + + # + # WRAM mapping: [MAP_BB_HYB/MAP_BB_LTD/MAP_TS_HYB/MAP_TS_LTD] + # don't have to edit + # + WramMapping $(MAKEROM_WRAM_MAPPING) + + # + # Codec mode: + # don't have to edit + # + CodecMode $(MAKEROM_CODEC_MODE) + + ### + #### END +} + +RomSpec +{ + Offset 0x00000000 + Segment ALL + HostRoot ../../data + Root /data + File NTR_IPL_font_m.NFTR CardBanner.bnr DownloadBanner.bnr EmptyBanner.bnr PictoChatBanner.bnr SettingBanner.bnr +} \ No newline at end of file diff --git a/build/systemMenu_RED/Launcher/ARM9/src/Logo/logoData.c b/build/systemMenu_RED/Launcher/ARM9/src/Logo/logoData.c new file mode 100644 index 0000000..03fa5f1 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/src/Logo/logoData.c @@ -0,0 +1,204 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: logoData.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "misc.h" + +// define data----------------------------------------------------------- +#define NIN_LOGO_LENGTH 0x9c // NintendoSf[^TCY + +#define OAM_OBJ_BLEND 0x00000400 // nai[h +#define OAM_SIZE_64x32 0xc0004000 // nai USRQhbg +#define OAM_COLOR_256 0x00002000 // QTUF I +#define OAM_AFFINE_NONE 0x00000000 // AtB[h +#define OAM_V_POS_SHIFT 0 +#define OAM_H_POS_SHIFT 16 +#define OAM_AFFINE_NO_SHIFT 25 +#define OAM_PRIORITY_SHIFT 10 +#define OAM_PLTT_SHIFT 12 + + +// extern data----------------------------------------------------------- + +// function's prototype-------------------------------------------------- +void LoadLogoData( void ); +static void UnCompNintendoLogo( u16 *NintendoLogoDatap, u16 *dstp, u32 *temp ); +static void SVC_DiffUnFilter16_16( u16 *srcp,u16 *dstp ); +static s32 MEMB_InitFunc( const u8 *devicep, void *ramp, const void *paramp ); +static s32 MEMB_TerminateFunc( const u8 *devicep ); +static u8 MEMB_ByteStreamFunc( const u8 *devicep ); +static u32 MEMB_WordStreamFunc( const u8 *devicep ); + +// global variable------------------------------------------------------- + +// static variable------------------------------------------------------- + +// const data------------------------------------------------------------ +const u32 OamLogoData[ 2 ][ 2 ] = { + { + OAM_OBJ_BLEND | OAM_SIZE_64x32 | OAM_AFFINE_NONE | OAM_COLOR_256 | + 71 << OAM_H_POS_SHIFT | + 88 << OAM_V_POS_SHIFT | + 0 << OAM_AFFINE_NO_SHIFT, + 0 << 1 | 5 << OAM_PLTT_SHIFT | 2 << OAM_PRIORITY_SHIFT + }, + + { + OAM_OBJ_BLEND | OAM_SIZE_64x32 | OAM_AFFINE_NONE | OAM_COLOR_256 | + 71 + 64 << OAM_H_POS_SHIFT | + 88 << OAM_V_POS_SHIFT | + 0 << OAM_AFFINE_NO_SHIFT, + 8 << 1 | 5 << OAM_PLTT_SHIFT | 2 << OAM_PRIORITY_SHIFT + }, +}; + +static const MIReadStreamCallbacks memb_ifp={ + MEMB_InitFunc, + MEMB_TerminateFunc, + MEMB_ByteStreamFunc, + NULL, + MEMB_WordStreamFunc, +}; + +static const MIUnpackBitsParam Nin_UnPackBitsParam={ + (8*8/2)*( 7*2), 1, 8, 0x1e, 0 +}; + +static const u8 Nin_Char_Diff_Huff_Table[] = { + 0x24,0xd4,0x00,0x00, + 0x0f,0x40,0x00,0x00,0x00,0x01,0x81,0x82,0x82,0x83,0x0f,0x83,0x0c,0xc3,0x03,0x83, + 0x01,0x83,0x04,0xc3,0x08,0x0e,0x02,0xc2,0x0d,0xc2,0x07,0x0b,0x06,0x0a,0x05,0x09, +}; + +static const u8 Nin_Char_Diff_Huff[] ATTRIBUTE_ALIGN( 2 ) = { + 0x24, 0xff, 0xae, 0x51, 0x69, 0x9a, 0xa2, 0x21, 0x3d, 0x84, 0x82, 0x0a, 0x84, 0xe4, 0x09, 0xad, + 0x11, 0x24, 0x8b, 0x98, 0xc0, 0x81, 0x7f, 0x21, 0xa3, 0x52, 0xbe, 0x19, 0x93, 0x09, 0xce, 0x20, + 0x10, 0x46, 0x4a, 0x4a, 0xf8, 0x27, 0x31, 0xec, 0x58, 0xc7, 0xe8, 0x33, 0x82, 0xe3, 0xce, 0xbf, + 0x85, 0xf4, 0xdf, 0x94, 0xce, 0x4b, 0x09, 0xc1, 0x94, 0x56, 0x8a, 0xc0, 0x13, 0x72, 0xa7, 0xfc, + 0x9f, 0x84, 0x4d, 0x73, 0xa3, 0xca, 0x9a, 0x61, 0x58, 0x97, 0xa3, 0x27, 0xfc, 0x03, 0x98, 0x76, + 0x23, 0x1d, 0xc7, 0x61, 0x03, 0x04, 0xae, 0x56, 0xbf, 0x38, 0x84, 0x00, 0x40, 0xa7, 0x0e, 0xfd, + 0xff, 0x52, 0xfe, 0x03, 0x6f, 0x95, 0x30, 0xf1, 0x97, 0xfb, 0xc0, 0x85, 0x60, 0xd6, 0x80, 0x25, + 0xa9, 0x63, 0xbe, 0x03, 0x01, 0x4e, 0x38, 0xe2, 0xf9, 0xa2, 0x34, 0xff, 0xbb, 0x3e, 0x03, 0x44, + 0x78, 0x00, 0x90, 0xcb, 0x88, 0x11, 0x3a, 0x94, 0x65, 0xc0, 0x7c, 0x63, 0x87, 0xf0, 0x3c, 0xaf, + 0xd6, 0x25, 0xe4, 0x8b, 0x38, 0x0a, 0xac, 0x72, 0x21, 0xd4, 0xf8, 0x07, 0x56, 0xcf, 0x00, 0x00, +}; + + +// ============================================================================ +// Sf[^[h +// ============================================================================ +void LoadLogoData(void) +{ + u32 temp[ 0x500 / sizeof(u32) ]; + u16 *pBuff = NNS_FndAllocFromAllocator( &g_allocator, 0x1000 ); + MI_CpuClear32( pBuff, 0x1000 ); + + if( pBuff == NULL ) { + OS_TPrintf( " %s : memory allocate error.\n", __FUNCTION__ ); + return; + } + + UnCompNintendoLogo( (u16 *)Nin_Char_Diff_Huff, pBuff, temp ); // NintendoSpBuffɓWJ + MI_CpuCopy32( pBuff, (u32 *)HW_OBJ_VRAM, 0x340 ); // OBJ-VRAMɃ[h + MI_CpuCopy32( (void *)( (u32)pBuff + 0x340 ), (u32 *)( HW_OBJ_VRAM + 0x400 ), 8*8*13 ); + + *(vu16 *)( HW_OBJ_PLTT + 0x3e ) = 0x0000; // OBJpbgZbg + *(vu16 *)HW_BG_PLTT = 0xffff; // obNhbvuvɂB + + MI_CpuCopy32( OamLogoData, (u32 *)HW_OAM, sizeof(OamLogoData) ); // NintendoSpOAMf[^Zbg + NNS_FndFreeToAllocator( &g_allocator, pBuff ); +} + + +//@NintendoSWJ[`@(r0=Skf[^ r1=WJAhX) +#include + +asm void UnCompNintendoLogo(u16 *NintendoLogoDatap, u16 *dstp, u32 *temp) +{ + push {r0-r2,r4, lr} + + ldr r0, =Nin_Char_Diff_Huff_Table + mov r2, #0x0e + lsl r2, r2, #8 + add r1, r1, r2 // P+0xe00 + mov r4, r1 + mov r2, #36 + bl MIi_CpuCopy16 // NintendoS̈ke[û݂Rs[Ă + + ldr r0, [sp, #0] // OiNinLogoBak[36]) + mov r2, #36 + add r1, r4, r2 // P+0xe00+36 + mov r2, #NIN_LOGO_LENGTH + bl MIi_CpuCopy16 // ONintendoSf[^{̂Rs[Ă + + mov r0, r4 // P+0xe00 + ldr r1, [sp, #4] // P + ldr r2, [sp, #8] // Q + ldr r3, =memb_ifp + bl SVC_UncompressHuffmanFromDevice // nt}WJ + + ldr r0, [sp, #4] + ldr r2, =0x0000d082 + str r2, [r0,#0] + + mov r1, r4 // P+0xe00 + bl SVC_DiffUnFilter16_16 // DiffWJ + + mov r0, r4 // P+0xe00 + ldr r1, [sp, #4] // P + ldr r2, =Nin_UnPackBitsParam + bl SVC_UnpackBits // rbgWJ + + pop {r0-r2,r4, pc} +} + + +// tB^WJVXeR[i16Bit16Bitj (r0=Srcp, r1=Destp) +static asm void SVC_DiffUnFilter16_16(u16 *srcp,u16 *dstp) +{ + swi 24 + bx lr +} +#include + + +// ============================================================================ +// oCgANZX”\pANZX[`Q +// ============================================================================ +static s32 MEMB_InitFunc(const u8 *devicep, void *ramp, const void *paramp) +{ +#pragma unused(ramp) + if(paramp) return (s32)MEMB_WordStreamFunc(devicep); + else return 0; +} + +static s32 MEMB_TerminateFunc(const u8 *devicep) +{ +#pragma unused(devicep) + return 0; +} + +static u8 MEMB_ByteStreamFunc(const u8 *devicep) +{ + return *devicep; +} + +static u32 MEMB_WordStreamFunc(const u8 *devicep) +{ + return *(u32 *)devicep; +} + diff --git a/build/systemMenu_RED/Launcher/ARM9/src/Logo/logoDemo.c b/build/systemMenu_RED/Launcher/ARM9/src/Logo/logoDemo.c new file mode 100644 index 0000000..91467d7 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/src/Logo/logoDemo.c @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: logoDemo.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include "logoDemo.h" + +// define data-------------------------------------------------------- + +#define LOGO_DISP_FRAME 60 // S\t[ + +// S\Xe[^X\ +typedef struct LogoStatus { + s32 state; + BOOL enable; + s32 value_A; + s32 value_B; + s32 mainCounter; +}LogoStatus; + +// extern data-------------------------------------------------------- +extern void LoadLogoData( void ); + +// function's prototype----------------------------------------------- + +// static variables--------------------------------------------------- +static LogoStatus s_logo = { 0, TRUE, 0, 0, 0 }; + +// const data--------------------------------------------------------- + +static void LogoInit( void ) +{ + // OFF + GX_DispOff(); + GXS_DispOff(); + + // VRAM蓖āNA + GX_SetBankForOBJ( GX_VRAM_OBJ_128_A ); // @V@@@@@OBJp + GX_SetGraphicsMode( GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_2D ); + MI_CpuClearFast( (void *)HW_OBJ_VRAM, 0x1000 ); // OBJ-VRAM NA + MI_DmaFill32( 3, (void *)HW_OAM, 192, HW_OAM_SIZE ); // OAM NA + + // ʐݒ + GX_SetGraphicsMode( GX_DISPMODE_GRAPHICS, GX_BGMODE_2, GX_BG0_AS_2D ); + GX_SetOBJVRamModeChar( GX_OBJVRAMMODE_CHAR_2D ); + G2_SetBlendAlpha( GX_BLEND_PLANEMASK_OBJ, GX_BLEND_PLANEMASK_BD, s_logo.value_A, s_logo.value_B ); + GX_SetVisiblePlane( GX_PLANEMASK_OBJ ); + + // Sf[^[h + LoadLogoData(); + + s_logo.value_A = 0; + s_logo.value_B = 16; + G2_ChangeBlendAlpha( s_logo.value_A, s_logo.value_B ); + + // Cʂ̂ON + GX_DispOn(); +} + + +// SC +int LogoMain() +{ + if( !IsLogoEnable() ) { + return 1; + } + + switch( s_logo.state ) { + case 0: // ݒ + LogoInit(); + + s_logo.mainCounter = 0; + s_logo.state++; + break; + + case 1: // NintendoStF[hC + if( s_logo.mainCounter++ < 16 ){ // Nintendoۺ \ + G2_ChangeBlendAlpha( ++s_logo.value_A, --s_logo.value_B ); + }else { + s_logo.mainCounter = 0; + s_logo.state++; + } + break; + + + case 2: // NintendoS\ + if( s_logo.mainCounter++ == LOGO_DISP_FRAME ) { + s_logo.mainCounter = 0; + s_logo.state++; + } + break; + + case 3: // NintendoStF[hAEg + if( s_logo.mainCounter++ < 16 ) { + G2_ChangeBlendAlpha( --s_logo.value_A, ++s_logo.value_B ); + }else { + return 1; + } + break; + + default: + break; + } + + return 0; +} + + +// S\OFFɂB +void SetLogoEnable( BOOL enable ) +{ + s_logo.enable = enable; +} + +// S\Ԏ擾 +BOOL IsLogoEnable(void) +{ + return s_logo.enable; +} diff --git a/build/systemMenu_RED/Launcher/ARM9/src/Logo/logoDemo.h b/build/systemMenu_RED/Launcher/ARM9/src/Logo/logoDemo.h new file mode 100644 index 0000000..3923a33 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/src/Logo/logoDemo.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: logoDemo.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef _LOGO_DEMO_H +#define _LOGO_DEMO_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int LogoMain( void ); +extern void SetLogoEnable( BOOL enable ); +extern BOOL IsLogoEnable( void ); + +#ifdef __cplusplus +} +#endif + +#endif /* _LOGO_DEMO_H */ diff --git a/build/systemMenu_RED/Launcher/ARM9/src/launcher.c b/build/systemMenu_RED/Launcher/ARM9/src/launcher.c new file mode 100644 index 0000000..5581150 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/src/launcher.c @@ -0,0 +1,388 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: launcher.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "misc.h" +#include "launcher.h" + + +// define data------------------------------------------ +#define LAUNCHER_ELEMENT_NUM 4 // Sj[̍ڐ + +#define B_LIGHT_BUTTON_TOP_X 24 +#define B_LIGHT_BUTTON_TOP_Y 21 +#define B_LIGHT_BUTTON_BOTTOM_X ( B_LIGHT_BUTTON_TOP_X + 7 ) +#define B_LIGHT_BUTTON_BOTTOM_Y ( B_LIGHT_BUTTON_TOP_Y + 2 ) + + +// extern data------------------------------------------ + +// function's prototype declaration--------------------- +static void DrawBackLightSwitch(void); +static void DrawLauncher(u16 nowCsr, const MenuParam *pMenu); + +// global variable ------------------------------------- + +// static variable ------------------------------------- +static int s_csr = 0; // j[̃J[\ʒu +static const u16 *s_pStrLauncher[ LAUNCHER_ELEMENT_NUM ]; // Sj[pe[uւ̃|C^Xg + +// const data ----------------------------------------- +//=============================================== +// Launcher.c +//=============================================== +static const u16 *const s_pStrLauncherElemTbl[ LAUNCHER_ELEMENT_NUM ][ LANG_CODE_MAX ] = { + { + (const u16 *)L"DSJ[h", + (const u16 *)L"DS Card", + (const u16 *)L"DS Card(F)", + (const u16 *)L"DS Card(G)", + (const u16 *)L"DS Card(I)", + (const u16 *)L"DS Card(S)", + }, + { + (const u16 *)L"sNg`bg", + (const u16 *)L"PictoChat", + (const u16 *)L"PictoChat(F)", + (const u16 *)L"PictoChat(G)", + (const u16 *)L"PictoChat(I)", + (const u16 *)L"PictoChat(S)", + }, + { + (const u16 *)L"DS_E[hvC", + (const u16 *)L"DS Download Play", + (const u16 *)L"DS Download Play(F)", + (const u16 *)L"DS Download Play(G)", + (const u16 *)L"DS Download Play(I)", + (const u16 *)L"DS Download Play(S)", + }, + { + (const u16 *)L"{̐ݒ", + (const u16 *)L"Machine Settings", + (const u16 *)L"Machine Settings(F)", + (const u16 *)L"Machine Settings(G)", + (const u16 *)L"Machine Settings(I)", + (const u16 *)L"Machine Settings(S)", + }, +}; + +static MenuPos s_launcherPos[] = { + { TRUE, 4 * 8, 8 * 8 }, + { TRUE, 4 * 8, 10 * 8 }, + { TRUE, 4 * 8, 12 * 8 }, + { TRUE, 4 * 8, 14 * 8 }, + { TRUE, 4 * 8, 16 * 8 }, +}; + +static const MenuParam s_launcherParam = { + LAUNCHER_ELEMENT_NUM, + TXT_COLOR_BLACK, + TXT_COLOR_GREEN, + TXT_COLOR_RED, + &s_launcherPos[0], + (const u16 **)&s_pStrLauncher, +}; + +static const u16 *const str_backlight[] = { + (const u16 *)L"BLT:ON ", + (const u16 *)L"BLT:OFF", +}; + +//====================================================== +// `[ +//====================================================== + +// oi[\֌Wibj +#define DBGBNR +#ifdef DBGBNR + +static const u8 TITLE_PROPERTY_NUM = 40; +static BannerFile *empty_banner; +static BannerFile *card_banner; +static BannerFile *pictochat_banner; +static BannerFile *download_banner; +static BannerFile *setting_banner; +static TitleProperty tp[TITLE_PROPERTY_NUM]; +static u8 image_index_list[TITLE_PROPERTY_NUM]; +static const int MAX_SHOW_BANNER = 6; +static GXOamAttr banner_oam_attr[MAX_SHOW_BANNER]; +static u8 *pbanner_image_list[TITLE_PROPERTY_NUM*2]; +static int banner_count = 0; + +static void LoadBannerFiles() +{ + // t@CǂݍݕBemptyoi[ǂݍގɂȂB{AAvn͊O擾 + // ŌɉȂƑʖځBAǂʼn΂̂cc + u32 size = CMN_LoadFile( (void **)&empty_banner, "data/EmptyBanner.bnr", &g_allocator); + NNS_G2D_ASSERT( size > 0 ); + size = CMN_LoadFile( (void **)&card_banner, "data/CardBanner.bnr", &g_allocator); + NNS_G2D_ASSERT( size > 0 ); + size = CMN_LoadFile( (void **)&pictochat_banner, "data/PictochatBanner.bnr", &g_allocator); + NNS_G2D_ASSERT( size > 0 ); + size = CMN_LoadFile( (void **)&download_banner, "data/DownloadBanner.bnr", &g_allocator); + NNS_G2D_ASSERT( size > 0 ); + size = CMN_LoadFile( (void **)&setting_banner, "data/SettingBanner.bnr", &g_allocator); + NNS_G2D_ASSERT( size > 0 ); +} + +// pbg̓ǂݍ݂OBJ֌W̏ +static void BannerInit() +{ + int l; + LoadBannerFiles(); + + // łׂȂCBGOBJ̐ݒ + GX_SetVisiblePlane(GX_PLANEMASK_OBJ | GX_PLANEMASK_BG0); // display only OBJ&BG0 + GX_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_1D_128K); // 2D mapping mode + + // pbgǂݍ + GX_LoadOBJPltt( empty_banner->v1.pltt, 0, BNR_PLTT_SIZE ); + + //OBJATTȐccŒlMďꏊLN^[ς肷 + for(l=0;lv1.image; + for(m=0;mv1.gameName[GetNCDWork()->option.language]; + int width = NNS_G2dTextCanvasGetStringWidth(&gTextCanvas, str, NULL); + PutStringUTF16( (256-width)/2, 48, TXT_COLOR_BLACK, str ); + } +} + +#endif //DBGBNR + + +// `[̏ +void LauncherInit( TitleProperty *pTitleList ) +{ +#pragma unused( pTitleList ) + + int i; + GX_DispOff(); + GXS_DispOff(); + NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_WHITE ); + + DrawBackLightSwitch(); + + PrintfSJIS( 0, 0, TXT_COLOR_BLUE, "TWL-SYSTEM MENU ver.%06x", SYSMENU_VER ); + + // NITROݒf[^languageɉCj[\̐؂ւ + for( i = 0; i < LAUNCHER_ELEMENT_NUM; i++ ) { + s_pStrLauncher[ i ] = s_pStrLauncherElemTbl[ i ][ GetNCDWork()->option.language ]; + } + + if( !SYSM_IsNITROCard() ) { + s_launcherPos[ 0 ].enable = FALSE; // DSJ[h́A擪vf𖳌ɂB + } + + //DrawMenu( s_csr, &s_launcherParam ); + + SVC_CpuClear( 0x0000, &tpd, sizeof(TpWork), 16 ); + + InitGetAndDrawRtcData( RTC_DATE_TOP_X, RTC_DATE_TOP_Y, RTC_TIME_TOP_X, RTC_TIME_TOP_Y ); + + GX_SetVisiblePlane( GX_PLANEMASK_BG0 ); + GX_DispOn(); + GXS_DispOn(); + + #ifdef DBGBNR + BannerInit(); + #endif +} + + +// `[C +TitleProperty *LauncherMain( TitleProperty *pTitleList ) +{ +#pragma unused( pTitleList ) + + static BOOL touch_bl = FALSE; + BOOL tp_bl_on_off = FALSE; + BOOL tp_select = FALSE; + static int csr_v = 0; + static int selected = 0; + + // `NA + NNS_G2dCharCanvasClear(&gCanvas,TXT_COLOR_WHITE); + + PrintfSJIS( 0, 0, TXT_COLOR_BLUE, "TWL-SYSTEM MENU ver.%06x", SYSMENU_VER ); + DrawBackLightSwitch(); + + // RTC̎擾\ + GetAndDrawRtcData(); + + //-------------------------------------- + // obNCgON,OFF + //-------------------------------------- + if(tpd.disp.touch) { + BOOL range = InRangeTp( B_LIGHT_BUTTON_TOP_X*8, B_LIGHT_BUTTON_TOP_Y*8-4, + B_LIGHT_BUTTON_BOTTOM_X*8, B_LIGHT_BUTTON_BOTTOM_Y*8-4, &tpd.disp ); + if( range && !touch_bl ) { + touch_bl = TRUE; + tp_bl_on_off = TRUE; + } + }else { + touch_bl = FALSE; + } + + if( (pad.trg & PAD_BUTTON_R) || (tp_bl_on_off) ) { + GetNCDWork()->option.backLightOffFlag ^= 0x01; + DrawBackLightSwitch(); + } + + //-------------------------------------- + // L[͏ + //-------------------------------------- + if(pad.cont & PAD_KEY_RIGHT){ // oi[I + if(csr_v == 0) csr_v = 1; + } + if( pad.cont & PAD_KEY_LEFT ){ + if(csr_v == 0) csr_v = -1; + } + s_csr += csr_v; + if((TITLE_PROPERTY_NUM-1)*12 < s_csr) s_csr = (TITLE_PROPERTY_NUM-1)*12; + if( s_csr < 0 ) s_csr = 0; + if(s_csr%12 == 0){ + csr_v = 0; + selected = s_csr/12; + } + // tp_select = SelectMenuByTP( &s_csr, &s_launcherParam ); + + // DrawMenu( s_csr, &s_launcherParam ); + + #ifdef DBGBNR + BannerDraw( s_csr, selected, NULL ); + #endif + + if( ( pad.trg & PAD_BUTTON_A ) || ( tp_select ) ) { // j[ڂւ̕ + if( s_launcherPos[ 0 ].enable ) { + NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_WHITE ); + return NULL; + } + } + + return NULL; +} + +#if 0 +// `[` +static void DrawLauncher(u16 nowCsr, const MenuParam *pMenu) +{ + int i; + int color; + + for( i = 0; i < pMenu->num; i++ ) { + if(i == nowCsr) { + if( !pMenu->pos[ i ].enable ) { + color = pMenu->disable_color; + }else { + color = pMenu->select_color; + } + }else { + color = pMenu->normal_color; + } + PutStringUTF16( pMenu->pos[ i ].x, pMenu->pos[ i ].y, color, (pMenu->str_elem)[ i ] ); + } +} +#endif + +// obNCgXCb`̕\ +static void DrawBackLightSwitch(void) +{ + u16 color; + + if( GetNCDWork()->option.backLightOffFlag ) { + color = TXT_COLOR_BLACK; + }else { + color = TXT_COLOR_RED; + } + + PutStringUTF16( B_LIGHT_BUTTON_TOP_X, B_LIGHT_BUTTON_TOP_Y, color, + str_backlight[ GetNCDWork()->option.backLightOffFlag ] ); +} + diff --git a/build/systemMenu_RED/Launcher/ARM9/src/launcher.h b/build/systemMenu_RED/Launcher/ARM9/src/launcher.h new file mode 100644 index 0000000..fd63c32 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/src/launcher.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: launcher.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef __LAUNCHER_H__ +#define __LAUNCHER_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// define data---------------------------------------------------------- + +// global variables-------------------------------------------------- + +// function------------------------------------------------------------- +void LauncherInit( TitleProperty *pTitleList ); +TitleProperty *LauncherMain( TitleProperty *pTitleList ); + + +#ifdef __cplusplus +} +#endif + +#endif // __LAUNCHER_H__ diff --git a/build/systemMenu_RED/Launcher/ARM9/src/main.c b/build/systemMenu_RED/Launcher/ARM9/src/main.c new file mode 100644 index 0000000..6d7dc10 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/src/main.c @@ -0,0 +1,434 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "launcher.h" +#include "misc.h" +#include "logoDemo.h" + +// extern data----------------------------------------------------------------- + +// define data----------------------------------------------------------------- + +// function's prototype------------------------------------------------------- +static void InitAllocator( NNSFndAllocator* pAllocator ); +static void InitAllocSystem( void ); +static BOOL CheckBootStatus( void ); +static void INTR_VBlank( void ); + +// global variable------------------------------------------------------------- +NNSFndAllocator g_allocator; + +// static variable------------------------------------------------------------- +static BannerFile banner; // oi[f[^ + +// const data------------------------------------------------------------------ + +#if 1 + +typedef struct CardStatus { + u16 primarySlot; // PULLOUT, DETECT, VALID, INVALID + u16 secondarySlot; // B +}CardStatus; + + +void TwlMain( void ) +{ + enum { + START = 0, + LOGODEMO = 1, + LAUNCHER_INIT = 2, + LAUNCHER = 3, + AUTHENTICATE = 4, + BOOT = 5, + STOP = 6 + }; + u32 state = START; + TitleProperty *pBootTitle = NULL; + TitleProperty *pTitleList = NULL; + + OS_Init(); + + (void)OS_EnableIrq(); + (void)OS_EnableInterrupts(); + + FS_Init( FS_DMA_NOT_USE ); + GX_Init(); + + // 荞݋-------------------- + (void)OS_SetIrqFunction(OS_IE_V_BLANK, INTR_VBlank); + (void)OS_EnableIrqMask(OS_IE_V_BLANK); + (void)GX_VBlankIntr(TRUE); + + // VXej[---------- + SYSM_Init(); // OS_IniťŃR[B + + // VXȅ---------------- + InitAllocator( &g_allocator ); + CMN_InitFileSystem( &g_allocator ); + + // Zbgp[^̎擾-------- + if( SYSM_GetResetParam()->isLogoSkip ) { + if( SYSM_GetResetParam()->bootTitleID ) { // AvڋN̎w肪烍Sf΂ĎwAvN + pBootTitle = (TitleProperty *)SYSM_GetResetParam(); + state = AUTHENTICATE; + }else { // ȊȌꍇ́ASf΂ă`[N + state = LAUNCHER_INIT; + } + } + + // Regi\[Xjt@C̃[h +// FS_ReadContentFile( ContentID ); + + // LRegt@C̃[h +// FS_ReadSharedContentFile( ContentID ); + + // NANDAvXg̎擾---------- + (void)SYSM_GetNandTitleList( pTitleList ); + + while( 1 ) { + OS_WaitIrq(1, OS_IE_V_BLANK); // VuN荞ݑ҂ + + ReadKeyPad(); // L[͂̎擾 + ReadTpData(); // TP͂̎擾 + + (void)SYSM_GetCardTitleList( pTitleList ); // J[hAvXg̎擾iXbhŐJ[h}ʒm̂C[vŎ擾j + + switch( state ) { + case START: + state = LOGODEMO; + break; + case LOGODEMO: + if( LogoMain() ) { + state = LAUNCHER_INIT; + } + break; + case LAUNCHER_INIT: + InitBG(); // BG + LauncherInit( pTitleList ); + state = LAUNCHER; + break; + case LAUNCHER: + pBootTitle = LauncherMain( pTitleList ); + if( pBootTitle ) { + state = AUTHENTICATE; + } + break; + case AUTHENTICATE: + switch ( SYSM_LoadAndAuthenticateTitle( pBootTitle ) ) { // Av[hF + case AUTH_PROCESSING: + break; + case AUTH_RESULT_SUCCEEDED: + state = BOOT; + break; + case AUTH_RESULT_TITLE_POINTER_ERROR: + case AUTH_RESULT_AUTHENTICATE_FAILED: + case AUTH_RESULT_ENTRY_ADDRESS_ERROR: + state = STOP; + break; + } + break; + case BOOT: + SYSM_Finalize(); // I + return; + case STOP: // ~ + break; + } + } +} +#endif + + +// ============================================================================ +// function's description +// ============================================================================ +/* +void TwlMain(void) +{ + typedef enum PrgState { + STATE_START = 1, + STATE_LOGO_DISP, + STATE_LOGO_MENU, + STATE_WAIT_BOOT + }PrgState; + + PrgState prg_state = STATE_START; + BOOL boot_decision = FALSE; + + // ---------------------------------- + SYSM_Init(); // VXej[֘Af[^̏iTwlMain̐擪ŃR[ĉBj + + OS_Init(); + + (void)OS_EnableIrq(); + (void)OS_EnableInterrupts(); + + FS_Init( FS_DMA_NOT_USE ); + GX_Init(); + GX_SetPower(GX_POWER_ALL); // eWbN p[ON + + // 荞݋---------------------------- + (void)OS_SetIrqFunction(OS_IE_V_BLANK, INTR_VBlank); + (void)OS_EnableIrqMask(OS_IE_V_BLANK); + (void)GX_VBlankIntr(TRUE); + + // foCX------------------------------- +#ifndef __TP_OFF + TP_Init(); +#endif + (void)RTC_Init(); + + // VXȅ------------------ + InitAllocator( &g_allocator ); + CMN_InitFileSystem( &g_allocator ); + +// InitAllocSystem(); + + // ARM7҂-------------------------- +// if( SYSM_WaitARM7Init() ) { // ARM7̏Î҂Ă烁C[vJn +// return; // TRUEԂꂽAfobKu[gȂ̂Ń^[ +// } + + // C[v---------------------------- + while(1){ + OS_WaitIrq(1, OS_IE_V_BLANK); // VuN荞ݑ҂ + ReadKeyPad(); // L[͂̎擾 + + if(SYSM_IsTPReadable()) { + ReadTpData(); // TP͂̎擾 + } + +// if(SYSM_Main()) { // IPL2VXẽC +// return; // TRUEAĂ烁C[v烊^[iNITROQ[Nj +// } + + switch(prg_state) { + case STATE_START: + boot_decision = CheckBootStatus(); // u[gԂ`FbNBiV[gJbgNRpCXCb`ɂ鋭Nj +// if( !SYSM_GetBannerFile( &banner ) ) { // oi[f[^̃[h +// OS_Printf("ROM banner data read failed.\n"); +// } + prg_state = STATE_LOGO_DISP; + break; + + //----------------------------------- + // NITROS\ + //----------------------------------- + case STATE_LOGO_DISP: + if( LogoMain() ) { // S\[`iBFLG_GAMEBOY_LOGO_OFF̎͑Ij + InitBG(); // BG + LauncherInit(); // u[g莞̂݃Sj[B + + prg_state = STATE_LOGO_MENU; + } + break; // NITROJ[hłȂꍇ́Â܂ܖ[vB + + //----------------------------------- + // Sj[ŋN[hI + //----------------------------------- + case STATE_LOGO_MENU: + { + IPL2BootType command = LauncherMain( boot_decision ); + + switch(command) { + case BOOT_TYPE_UNSOLVED: + break; + + case BOOT_TYPE_NITRO: +// if( !SYSM_BootNITRO() ) { +// (void)DrawStringSJIS( 4, 20, RED, (const u8 *)"This NITRO card is invalid!!"); +// } + break; + + case BOOT_TYPE_PICT_CHAT: +// (void)SYSM_BootPictChat(); + break; + + case BOOT_TYPE_WIRELESS_BOOT: +// (void)SYSM_BootDSDownloadPlay(); + break; + + case BOOT_TYPE_BMENU: +// (void)SYSM_BootMachineSetting(); + break; + + default: + OS_Panic( "ERROR: boot code failed : %d\n", command ); + } + if(command) { + prg_state = STATE_WAIT_BOOT; + } + } + break; + case STATE_WAIT_BOOT: +// SYSM_PermitToBootSelectedTarget(); + break; + } + + if ( PAD_DetectFold() == TRUE ) { // X[v[hւ̑J +// SYSM_FinalizeCardPulledOut(); + SYSM_GoSleepMode(); +// (void)SYSM_IsCardPulledOut(); // J[hoR}hs +// SYSM_FinalizeCardPulledOut(); + // J[ho +// if ( SYSM_IsCardPulledOut() ) { + if ( 0 ) { + (void)PM_ForceToPowerOff(); + } + } + +// if (SYSM_IsCardPulledOut()) { // J[ho + if ( 0 ) { + OS_Printf("Card is pulled out.\n"); + OS_Terminate(); + } + + OS_PrintServer(); // ARM7̃vgfobO + + //---- BG-VRAM̍XV +// DC_FlushRange ( bgBakS, sizeof(bgBakS) ); +// MI_CpuCopyFast( bgBakS, (void*)(HW_DB_BG_VRAM+0xf000), sizeof(bgBakS) ); + } +} +*/ + + +// AP[^̏ +static void InitAllocator( NNSFndAllocator* pAllocator ) +{ + u32 arenaLow = MATH_ROUNDUP ((u32)OS_GetMainArenaLo(), 16); + u32 arenaHigh = MATH_ROUNDDOWN((u32)OS_GetMainArenaHi(), 16); + u32 heapSize = arenaHigh - arenaLow; + void* heapMemory = OS_AllocFromMainArenaLo(heapSize, 16); + NNSFndHeapHandle heapHandle; + SDK_NULL_ASSERT( pAllocator ); + + heapHandle = NNS_FndCreateExpHeap(heapMemory, heapSize); + SDK_ASSERT( heapHandle != NNS_FND_HEAP_INVALID_HANDLE ); + + NNS_FndInitAllocatorForExpHeap(pAllocator, heapHandle, 4); +} + +#if 0 +// mallocVXȅ +static void InitAllocSystem(void) +{ + void* tempLo; + OSHeapHandle hh; + + tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 16); + OS_SetArenaLo(OS_ARENA_MAIN, tempLo); + OS_TPrintf( "ArenaLo : %08x ArenaHi : %08x\n", OS_GetMainArenaLo(), OS_GetMainArenaHi() ); + + hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi()); + if(hh < 0) { + OS_Panic("ARM9: Fail to create heap...\n"); + } + hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh); +} +#endif + +// u[gԂmFAS\L𔻒f------- +static BOOL CheckBootStatus(void) +{ + BOOL boot_decision = FALSE; // uu[gev + BOOL other_shortcut_off = FALSE; + + //----------------------------------------------------- + // fobOpRpCXCb`ɂ鋓 + //----------------------------------------------------- + { +#ifdef __FORCE_BOOT_BMENU // u[gj[NXCb`ONH + SYSM_SetBootFlag( BFLG_BOOT_BMENU ); + return TRUE; // uu[gevŃ^[ +#endif /* __FORCE_BOOT_BMENU */ + +#ifdef __LOGO_SKIP // fobOpSXLbv + SetLogoEnable( FALSE ); // S\XLbv +#endif /* __LOGO_SKIP */ + } + + + //----------------------------------------------------- + // NITROݒf[^͎̐ݒ胁j[V[gJbgN + //----------------------------------------------------- +#ifdef __DIRECT_BOOT_BMENU_ENABLE // NITROݒf[^͎̃u[gj[ڋNXCb`ONH + if( ( (GetNCDWork()->option.input_tp == 0) + ||(GetNCDWork()->option.input_language == 0) + ||(GetNCDWork()->option.input_rtc == 0) + ||(GetNCDWork()->option.input_favoriteColor == 0) + ||(GetNCDWork()->option.input_nickname == 0) ) ) { // TP,,RTC,jbNl[ZbgĂȂ΁AS\Q[[hs킸Au[gj[V[gJbgNB + + if( ( pad.cont & PAD_PRODUCTION_NITRO_SHORTCUT ) == PAD_PRODUCTION_NITRO_SHORTCUT ) { + other_shortcut_off = TRUE; // ʎYHp̃L[V[gJbgĂAݒ胁j[N͂ȂB + }else if( !SYSM_IsInspectNITROCard() ) { // AAʎYp̃L[V[gJbgĂ鎞ANITROJ[hĂ鎞́Au[gj[ւ̃V[gJbgN͍sȂB + SYSM_SetBootFlag( BFLG_BOOT_BMENU ); + SetLogoEnable( FALSE ); + return TRUE; // uu[gevŃ^[ + } + } +#endif /* __DIRECT_BOOT_BMENU_ENABLE */ + + + //----------------------------------------------------- + // L[V[gJbgN + //----------------------------------------------------- + if( !other_shortcut_off && !GetNCDWork()->option.autoBootFlag ) { + // V[gJbgONƒI[gNOFF̎ + u32 nowBootFlag = 0; + + if(pad.cont & PAD_BUTTON_R){ // R{^NȂAS\ȂAGBQ[ + SetLogoEnable( FALSE ); + nowBootFlag = BFLG_BOOT_AGB; + }else if(pad.cont & PAD_BUTTON_L){ // L{^NȂAS\NITROQ[ + nowBootFlag = BFLG_BOOT_NITRO; + }else if(pad.cont & PAD_BUTTON_B){ // B{^NȂAS\Ƀu[gj[ + nowBootFlag = BFLG_BOOT_BMENU; + } + if( nowBootFlag ) { + SYSM_SetBootFlag( nowBootFlag ); + return TRUE; // uu[gevŃ^[ + } + } + + + //----------------------------------------------------- + // NIvVL̋ + //----------------------------------------------------- +#ifndef __SYSM_DEBUG + if( GetNCDWork()->option.autoBootFlag ) { + if ( SYSM_IsNITROCard() ) { // NITROJ[ĥ݂̎NITRON + SYSM_SetBootFlag( BFLG_BOOT_NITRO ); + return TRUE; // uu[gevŃ^[ + } + } +#endif /* __SYSM_DEBUG */ + + return FALSE; // uu[gevŃ^[ +} + + +// ============================================================================ +// 荞ݏ +// ============================================================================ + +// VuN荞 +static void INTR_VBlank(void) +{ + OS_SetIrqCheckFlag(OS_IE_V_BLANK); // VuN`FbÑZbg +} + diff --git a/build/systemMenu_RED/Launcher/ARM9/src/misc.c b/build/systemMenu_RED/Launcher/ARM9/src/misc.c new file mode 100644 index 0000000..f92abe4 --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/src/misc.c @@ -0,0 +1,588 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: misc.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "misc.h" + +// define data----------------------------------------------------------------- +#define NTR_IPL_FONT_DATA "data/NTR_IPL_font_m.NFTR" + +#define STRING_LENGTH_MAX 256 + +#define GRAY(x) GX_RGB(x, x, x) + +enum +{ + TXT_CPALETTE_MAIN, + TXT_CPALETTE_USERCOLOR, + TXT_CPALETTE_4BPP, + TXT_NUM_CPALEETE +}; + +// fʂ̃J[pbg +GXRgb TXTColorPalette[TXT_NUM_CPALEETE * 16] = +{ + GX_RGB(31, 31, 31), GX_RGB(31, 31, 31), GX_RGB( 0, 0, 0), GX_RGB(31, 0, 0), + GX_RGB( 0, 31, 0), GX_RGB( 0, 0, 31), GX_RGB( 0, 31, 31), GX_RGB(31, 0, 31), + GX_RGB(31, 31, 0), GX_RGB( 0, 0, 0), GX_RGB( 0, 0, 0), GX_RGB( 0, 0, 0), + GX_RGB( 0, 0, 0), GX_RGB( 0, 0, 0), GX_RGB( 0, 0, 0), GX_RGB( 0, 0, 0), + + GX_RGB( 0, 0, 0), GX_RGB(12, 16, 19), GX_RGB(23, 9, 0), GX_RGB(31, 0, 3), + GX_RGB(31, 17, 31), GX_RGB(31, 18, 0), GX_RGB(30, 28, 0), GX_RGB(21, 31, 0), + GX_RGB( 0, 20, 7), GX_RGB( 9, 27, 17), GX_RGB( 6, 23, 30), GX_RGB( 0, 11, 30), + GX_RGB( 0, 0, 18), GX_RGB(17, 0, 26), GX_RGB(26, 0, 29), GX_RGB(31, 0, 18), + + GRAY(31), GRAY(29), GRAY(27), GRAY(25), + GRAY(23), GRAY(21), GRAY(19), GRAY(17), + GRAY(15), GRAY(14), GRAY(12), GRAY(10), + GRAY( 8), GRAY( 6), GRAY( 3), GRAY( 0), +}; + +// extern data----------------------------------------------------------------- + +// define data----------------------------------------------------------------- +#define CANVAS_WIDTH 32 // `̕ (LN^P) +#define CANVAS_HEIGHT 24 // `̍ (LN^P) +#define CANVAS_LEFT 0 // `̈ʒuX (LN^P) +#define CANVAS_TOP 0 // `̈ʒuY (LN^P) + +#define TEXT_HSPACE 1 // `掞̕ (sNZP) +#define TEXT_VSPACE 1 // `掞̍s (sNZP) + +#define CHARACTER_OFFSET 0 // gpLN^̊Jnԍ + +// RTCf[^\ʒu[N +typedef struct RtcDrawPos{ + int date_x; + int date_y; + int time_x; + int time_y; +}RtcDrawPos; + +// function's prototype------------------------------------------------------- +static void InitScreen( void ); +static void InitCanvas( void ); +static void GetAndDrawRtcDataCore( BOOL forceGetFlag ); + +// global variable------------------------------------------------------------- +KeyWork pad; // L[pbh̓f[^ +TpWork tpd; // ^b`pl̓f[^ + +NNSG2dFont gFont; // tHg +NNSG2dCharCanvas gCanvas; // CharCanvas +NNSG2dTextCanvas gTextCanvas; // TextCanvas +NNSG2dCharCanvas gCanvasSub; // CharCanvas +NNSG2dTextCanvas gTextCanvasSub; // TextCanvas + +// static variable------------------------------------------------------------- +static int s_detach_count; +static RtcDrawPos s_rtcPos; +static RTCDate s_rtcDate; +static RTCTime s_rtcTime; +static u16 s_vcount; + +static char s_strBuffer[ STRING_LENGTH_MAX * 2 ] ATTRIBUTE_ALIGN(2); +static u16 s_strBufferUTF16[ STRING_LENGTH_MAX ]; + +// const data------------------------------------------------------------------ + +// jf[^\pR[h +const u8 *const g_strWeek[] ATTRIBUTE_ALIGN(2) = { + (const u8 *)"SUN", + (const u8 *)"MON", + (const u8 *)"TUE", + (const u8 *)"WED", + (const u8 *)"THU", + (const u8 *)"FRI", + (const u8 *)"SAT", +}; + +// ============================================================================ +// function's description +// ============================================================================ + +// BG +void InitBG(void) +{ + // OFF + GX_DispOff(); + GXS_DispOff(); + + // VRAM̊蓖ĂSĉ + GX_DisableBankForBG(); + GX_DisableBankForOBJ(); + GX_DisableBankForSubBG(); + GX_DisableBankForSubOBJ(); + + // C2DGW̏o͂ʂ + GX_SetDispSelect( GX_DISP_SELECT_SUB_MAIN ); + + // CLCD + { + // VRAM蓖 + GX_SetBankForBG ( GX_VRAM_BG_128_A ); + GX_SetBankForOBJ( GX_VRAM_OBJ_128_B ); + + MI_CpuClearFast( (void *)HW_BG_VRAM, 0x20000 ); // BG -VRAM NA + MI_CpuClearFast( (void *)HW_OBJ_VRAM, 0x20000 ); // OBJ-VRAM NA + + // J[pbgݒ + GX_LoadBGPltt( TXTColorPalette, 0, sizeof(TXTColorPalette) ); + + // BG[hݒ + GX_SetGraphicsMode( GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_2D ); + + GX_SetBGScrOffset ( GX_BGSCROFFSET_0x10000 ); + GX_SetBGCharOffset( GX_BGCHAROFFSET_0x00000 ); + } + // TuLCD + { + // VRAM蓖 + GX_SetBankForSubBG ( GX_VRAM_SUB_BG_128_C ); // VRAM-C for BGs + GX_SetBankForSubOBJ( GX_VRAM_SUB_OBJ_128_D ); // VRAM-D for BGs + + MI_CpuClearFast( (void *)HW_DB_BG_VRAM, 0x20000 ); // BG -VRAM NA + MI_CpuClearFast( (void *)HW_DB_OBJ_VRAM, 0x20000 ); // OBJ -VRAM NA + + // J[pbgݒ + GXS_LoadBGPltt( TXTColorPalette, 0, sizeof(TXTColorPalette) ); + + // BG[hݒ + GXS_SetGraphicsMode( GX_BGMODE_0 ); // BGMODE is 0 + } + InitScreen(); + InitCanvas(); +} + + +// XN[ +static void InitScreen( void ) +{ + // C BG 0 ݒ + G2_SetBG0Control( + GX_BG_SCRSIZE_TEXT_256x256, // XN[TCY 256x256 + GX_BG_COLORMODE_16, // J[[h 16F + GX_BG_SCRBASE_0xf800, // XN[x[X + GX_BG_CHARBASE_0x00000, // LN^x[X + GX_BG_EXTPLTT_01 // gpbgXbg + ); + GX_SetVisiblePlane( GX_PLANEMASK_BG0 ); + + // Tu BG 0 ݒ + G2S_SetBG0Control( + GX_BG_SCRSIZE_TEXT_256x256, // 256pix x 256pix text + GX_BG_COLORMODE_16, // use 256 colors mode + GX_BG_SCRBASE_0xf800, // screen base offset + 0x0000 is the address for BG #0 screen + GX_BG_CHARBASE_0x00000, // character base offset + 0x04000 is the address for BG #0 characters + GX_BG_EXTPLTT_01 // use BGExtPltt slot #0 if BGExtPltt is enabled + ); + GXS_SetVisiblePlane( GX_PLANEMASK_BG0 ); // display only BG #0 +} + + +// `̏ +static void InitCanvas( void ) +{ + // tHgǂݍ݂܂ + { + void* pFontFile; + u32 size = CMN_LoadFile( &pFontFile, NTR_IPL_FONT_DATA, &g_allocator); + NNS_G2D_ASSERT( size > 0 ); + NNS_G2dFontInitUTF16(&gFont, pFontFile); +// NNS_G2dPrintFont(&gFont); + } + + { + // CharCanvas ̏ + NNS_G2dCharCanvasInitForBG( + &gCanvas, + (GXCharFmt16*)G2_GetBG0CharPtr() + CHARACTER_OFFSET, + CANVAS_WIDTH, + CANVAS_HEIGHT, + NNS_G2D_CHARA_COLORMODE_16 + ); + + // TextCanvas̏ + NNS_G2dTextCanvasInit( + &gTextCanvas, + &gCanvas, + &gFont, + TEXT_HSPACE, + TEXT_VSPACE + ); + + // XN[ݒ + NNS_G2dMapScrToCharText( + G2_GetBG0ScrPtr(), + CANVAS_WIDTH, + CANVAS_HEIGHT, + CANVAS_LEFT, + CANVAS_TOP, + NNS_G2D_TEXT_BG_WIDTH_256, + CHARACTER_OFFSET, + TXT_CPALETTE_MAIN + ); + } + { + // CharCanvas ̏ + NNS_G2dCharCanvasInitForBG( + &gCanvasSub, + (GXCharFmt16*)G2S_GetBG0CharPtr() + CHARACTER_OFFSET, + CANVAS_WIDTH, + CANVAS_HEIGHT, + NNS_G2D_CHARA_COLORMODE_16 + ); + + // TextCanvas̏ + NNS_G2dTextCanvasInit( + &gTextCanvasSub, + &gCanvasSub, + &gFont, + TEXT_HSPACE, + TEXT_VSPACE + ); + + // XN[ݒ + NNS_G2dMapScrToCharText( + G2S_GetBG0ScrPtr(), + CANVAS_WIDTH, + CANVAS_HEIGHT, + CANVAS_LEFT, + CANVAS_TOP, + NNS_G2D_TEXT_BG_WIDTH_256, + CHARACTER_OFFSET, + TXT_CPALETTE_MAIN + ); + } +} + + +// UTF16ł̒ڕ\ +void PutStringUTF16( int x, int y, int color, const u16 *strUTF16 ) +{ + NNS_G2dTextCanvasDrawText( &gTextCanvas, x, y, color, TXT_DRAWTEXT_FLAG_DEFAULT, + strUTF16 ); +} + +void PutStringUTF16Sub( int x, int y, int color, const u16 *strUTF16 ) +{ + NNS_G2dTextCanvasDrawText( &gTextCanvasSub, x, y, color, TXT_DRAWTEXT_FLAG_DEFAULT, + strUTF16 ); +} + + +// SJISPrintf`ŕ\iUTF16ɕϊ) +void PrintfSJIS( int x, int y, int color, const char *fmt, ... ) +{ + int srcLen; + int dstLen = sizeof(s_strBufferUTF16); + va_list vlist; + va_start(vlist, fmt); + srcLen = STD_TVSNPrintf( s_strBuffer, sizeof(s_strBuffer), fmt, vlist); + va_end(vlist); + s_strBuffer[ srcLen ] = 0; + + (void)STD_ConvertStringSjisToUnicode( s_strBufferUTF16, &dstLen, s_strBuffer, &srcLen, NULL ); + s_strBufferUTF16[ dstLen ] = 0; + + NNS_G2dTextCanvasDrawText(&gTextCanvas, x, y, color, TXT_DRAWTEXT_FLAG_DEFAULT, + s_strBufferUTF16 ); +} + +void PrintfSJISSub( int x, int y, int color, const char *fmt, ... ) +{ + int srcLen; + int dstLen = sizeof(s_strBufferUTF16); + va_list vlist; + va_start(vlist, fmt); + srcLen = STD_TVSNPrintf( s_strBuffer, sizeof(s_strBuffer), fmt, vlist); + va_end(vlist); + s_strBuffer[ srcLen ] = 0; + + (void)STD_ConvertStringSjisToUnicode( s_strBufferUTF16, &dstLen, s_strBuffer, &srcLen, NULL ); + s_strBufferUTF16[ dstLen ] = 0; + + NNS_G2dTextCanvasDrawText(&gTextCanvasSub, x, y, color, TXT_DRAWTEXT_FLAG_DEFAULT, + s_strBufferUTF16 ); +} + + +// L[͓ǂݏo-------------------------------- +void ReadKeyPad(void) +{ + u16 readData = PAD_Read(); + pad.trg = (u16)(readData & (readData ^ pad.cont)); // gK + pad.cont = readData; // x^ +} + + +// ^b`plf[^̎擾----------------------- +void ReadTpData(void) +{ + TP_GetCalibratedPoint( &tpd.last, &tpd.raw ); // OTPf[^ޔ + + if( TP_RequestRawSampling(&tpd.raw) ) { // ^b`pl̃TvO + SVC_CpuClear(0x0000, &tpd.raw, sizeof(tpd.raw), 16); // SPI-busyŃf[^擾Ɏśhf[^ȂhŃ^[B + return; + } + TP_GetCalibratedPoint( &tpd.disp, &tpd.raw ); // TPWLCDWɕϊB + + if( !WaitDetachTP() ) { // TPf^b`҂sB + SVC_CpuClear(0x0000, &tpd.disp, sizeof(tpd.disp), 16); // SPI-busyŃf[^擾Ɏśhf[^ȂhŃ^[B + return; + } +#if 1 + if(tpd.disp.touch) { // ݂TPf[^\ + switch ( tpd.disp.validity ) { + case TP_VALIDITY_VALID: + OS_Printf("( %3d, %3d ) -> ( %3d, %3d )\n", tpd.raw.x, tpd.raw.y, tpd.disp.x, tpd.disp.y); + break; + case TP_VALIDITY_INVALID_X: + OS_Printf("( *%3d, %3d ) -> ( *%3d, %3d )\n", tpd.raw.x, tpd.raw.y, tpd.disp.x, tpd.disp.y); + break; + case TP_VALIDITY_INVALID_Y: + OS_Printf("( %3d, *%3d ) -> ( %3d, *%3d )\n", tpd.raw.x, tpd.raw.y, tpd.disp.x, tpd.disp.y); + break; + case TP_VALIDITY_INVALID_XY: + OS_Printf("( *%3d, *%3d ) -> ( *%3d, *%3d )\n", tpd.raw.x, tpd.raw.y, tpd.disp.x, tpd.disp.y); + break; + } + } +#endif +} + + +// TPf^b`҂ +BOOL WaitDetachTP( void ) +{ + // s_detach_countnĂAJEgB + if(s_detach_count > 0) { + if(tpd.disp.touch == 0) { // TPĂȂ΁AJEgisKlōē͂󂯕tB + s_detach_count--; + }else { + s_detach_count = TP_CSR_DETACH_COUNT; + } + return FALSE; + } + return TRUE; +} + + +// TPf^b`҂̊Jn +void StartDetachTP( void ) +{ + s_detach_count = TP_CSR_DETACH_COUNT; +} + + +//====================================================== +// j[ +//====================================================== + +// j[` +void DrawMenu( u16 nowCsr, const MenuParam *pMenu ) +{ + int i; + int color; + + for( i = 0; i < pMenu->num; i++ ) { + if(i == nowCsr) { + if( !pMenu->pos[ i ].enable ) { + color = pMenu->disable_color; + }else { + color = pMenu->select_color; + } + }else { + color = pMenu->normal_color; + } + PutStringUTF16( pMenu->pos[ i ].x, pMenu->pos[ i ].y, color, (pMenu->str_elem)[ i ] ); + } +} + + +// ^b`plɂ郁j[I +BOOL SelectMenuByTP( u16 *nowCsr, const MenuParam *pMenu ) +{ + u16 i; + TPData *target; + static u16 detach_count = 0; + static u16 csr_old = 0xff; + static u16 same_csr_count = 0; + + // detach_countnĂAJEgB + if( detach_count > 0 ) { + if( tpd.disp.touch == 0 ) { // TPĂȂ΁AJEgisAPOJEgŃj[I + if( ++detach_count == TP_CSR_DETACH_COUNT ) { + detach_count = 0; + return TRUE; + }else { + return FALSE; + } + } + } + detach_count=0; // detachJEgl̃NA + + // ʏ́ATPf[^j[ɂ邩ǂ𔻒B + if( tpd.disp.touch ) target = &tpd.disp; + else target = &tpd.last; + + for( i = 0; i < pMenu->num; i++ ) { + if( tpd.disp.touch ) { // ^b`plj[̗vfŃ^b`ĂȂA + NNSG2dTextRect rect = NNS_G2dTextCanvasGetTextRect( &gTextCanvas, (pMenu->str_elem)[ i ] ); + u16 top_x = (u16)( pMenu->pos[ i ].x ); // j[vfLCDWZo + u16 top_y = (u16)( pMenu->pos[ i ].y - 4 ); + u16 bottom_x = (u16)( top_x + rect.width ); + u16 bottom_y = (u16)( top_y + rect.height + 4 ); // YẂ}4̃}[W + + OS_TPrintf( "MENU[ %d ] : top_x = %02d top_y = %02d bot_x = %02d bot_y = %02d : ", + i, top_x, top_y, bottom_x, bottom_y ); + + if( InRangeTp( top_x, top_y, bottom_x, bottom_y, target ) ) { + OS_TPrintf( "InRange\n" ); + if( tpd.disp.validity == TP_VALIDITY_VALID ) { // J[\̗vfɈړ + if( csr_old == i ) { + if( same_csr_count < TP_CSR_TOUCH_COUNT ) { + same_csr_count++; + }else { + *nowCsr = i; + } + return FALSE; + }else { + csr_old = i; + } + break; + } + }else { + OS_TPrintf( "OutRange\n" ); + } + }else { // touch==0 + if( same_csr_count == TP_CSR_TOUCH_COUNT ) { + detach_count = 1; + break; + } + } + } + same_csr_count = 0; + return FALSE; +} + + +// ݂̃^b`plWẅɂ邩ǂԂB +BOOL InRangeTp( int top_x, int top_y, int bottom_x, int bottom_y, TPData *tgt ) +{ + if( ( tgt->x >= top_x ) && + ( tgt->x <= bottom_x ) && + ( tgt->y >= top_y ) && + ( tgt->y <= bottom_y ) ) { + return TRUE; + }else { + return FALSE; + } +} + + +//=============================================== +// RTCANZX[` +//=============================================== + +// RTCf[^擾\̏ +void InitGetAndDrawRtcData( int drawDatePos_x, int drawDatePos_y, int drawTimePos_x, int drawTimePos_y) +{ + s_vcount = 0; + s_rtcPos.date_x = drawDatePos_x; + s_rtcPos.date_y = drawDatePos_y; + s_rtcPos.time_x = drawTimePos_x; + s_rtcPos.time_y = drawTimePos_y; + + (void)RTC_GetDateTime( &s_rtcDate, &s_rtcTime); + GetAndDrawRtcDataCore( TRUE ); +} + + +void GetAndDrawRtcData( void ) +{ + GetAndDrawRtcDataCore( FALSE ); +} + + +// RTC̎擾\ +static void GetAndDrawRtcDataCore( BOOL forceGetFlag ) +{ + u32 year; + RTCDate date_old; + RTCTime time_old; + + // RTC̎擾 + if( forceGetFlag || ( s_vcount++ == 60 ) ) { + s_vcount = 0; + MI_CpuCopy16( &s_rtcDate, &date_old, sizeof(RTCDate) ); + MI_CpuCopy16( &s_rtcTime, &time_old, sizeof(RTCTime) ); + + (void)RTC_GetDateTime( &s_rtcDate, &s_rtcTime ); + + // ORTC̏ + { + year = s_rtcDate.year + 2000; + PrintfSJISSub( s_rtcPos.date_x, s_rtcPos.date_y, TXT_COLOR_WHITE, "%d/%02d/%02d[%3s]", + year, + date_old.month, + date_old.day, + g_strWeek[ date_old.week ] + ); + PrintfSJISSub( s_rtcPos.time_x, s_rtcPos.time_y, TXT_COLOR_WHITE, "%02d:%02d:%02d", + time_old.hour, + time_old.minute, + time_old.second + ); + } + // RTC̕\ + { + year = s_rtcDate.year + 2000; + PrintfSJISSub( s_rtcPos.date_x, s_rtcPos.date_y, TXT_COLOR_BLACK, "%d/%02d/%02d[%3s]", + year, + s_rtcDate.month, + s_rtcDate.day, + g_strWeek[ s_rtcDate.week ] + ); + PrintfSJISSub( s_rtcPos.time_x, s_rtcPos.time_y, TXT_COLOR_BLACK, "%02d:%02d:%02d", + s_rtcTime.hour, + s_rtcTime.minute, + s_rtcTime.second + ); + } + } +} + + +// oi[ACROBJ̃[h +void SetBannerIconOBJ( GXOamAttr *pDstOAM, BannerFileV1 *bannerp ) +{ + GXS_LoadOBJPltt( bannerp->pltt, 15, BNR_PLTT_SIZE ); + MI_CpuCopyFast( bannerp->image, (void *)(HW_DB_OBJ_VRAM + 0x20), BNR_IMAGE_SIZE ); + G2_SetOBJAttr( pDstOAM, // OAM pointer + 32, // X position + 32, // Y position + 0, // Priority + GX_OAM_MODE_NORMAL, // Bitmap mode + FALSE, // mosaic off + GX_OAM_EFFECT_NONE, // affine off + GX_OAM_SHAPE_32x32, // 16x16 size + GX_OAM_COLOR_16, // 16 color + 1, // charactor + 15, // palette + 0); // affine +} diff --git a/build/systemMenu_RED/Launcher/ARM9/src/misc.h b/build/systemMenu_RED/Launcher/ARM9/src/misc.h new file mode 100644 index 0000000..67b32bd --- /dev/null +++ b/build/systemMenu_RED/Launcher/ARM9/src/misc.h @@ -0,0 +1,153 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: misc.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef __MISC_H__ +#define __MISC_H__ + +#include +#include + +#define NNS_G2D_UNICODE +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// define data---------------------------------------------------------- +#define TP_CSR_TOUCH_COUNT 2 // TPJ[\̃`^Oẑ߂̃JEgl +#define TP_CSR_DETACH_COUNT 2 // TPJ[\uIvƔ肷TPf^b`̃JEgl + +// DrawText ł̍ +#define TXT_DRAWTEXT_FLAG_DEFAULT (NNS_G2D_VERTICALORIGIN_TOP | NNS_G2D_HORIZONTALORIGIN_LEFT | NNS_G2D_HORIZONTALALIGN_LEFT) + +// TXTColorPalette ̐F 16Fpbgւ̃[hz +enum +{ + // pbg0 TXT_CPALETTE_MAIN + TXT_COLOR_NULL=0, + TXT_COLOR_WHITE, + TXT_COLOR_BLACK, + TXT_COLOR_RED, + TXT_COLOR_GREEN, + TXT_COLOR_BLUE, + TXT_COLOR_CYAN, + TXT_COLOR_MAGENTA, + TXT_COLOR_YELLOW, + + // pbg1 TXT_CPALETTE_USERCOLOR + TXT_UCOLOR_NULL=0, + TXT_UCOLOR_GRAY, + TXT_UCOLOR_BROWN, + TXT_UCOLOR_RED, + TXT_UCOLOR_PINK, + TXT_UCOLOR_ORANGE, + TXT_UCOLOR_YELLOW, + TXT_UCOLOR_LIMEGREEN, + TXT_UCOLOR_DARKGREEN, + TXT_UCOLOR_SEAGREEN, + TXT_UCOLOR_TURQUOISE, + TXT_UCOLOR_BLUE, + TXT_UCOLOR_DARKBLUE, + TXT_UCOLOR_PURPLE, + TXT_UCOLOR_VIOLET, + TXT_UCOLOR_MAGENTA, + + // pbg TXT_CPALETTE_4BPP + TXT_COLOR_4BPP_NULL=0, + TXT_COLOR_4BPP_BG=1, + TXT_COLOR_4BPP_TEXT=1 +}; + + +// v\ꏊ +#define RTC_DATE_TOP_X ( 9 * 8 ) +#define RTC_DATE_TOP_Y ( 10 * 8 ) +#define RTC_TIME_TOP_X ( 12 * 8 ) +#define RTC_TIME_TOP_Y ( 12 * 8 ) + + +// L[f[^[N +typedef struct { + u16 trg; // gK + u16 cont; // x^ +}KeyWork; + + +// ^b`pl[N +typedef struct { + int detached; // ̃f[^͂Ń^b`ꂽƂB + TPData disp; // ̓͒liLCDWj + TPData raw; // ̓͒liTP Wj + TPData last; // O̓͒liLCDWj +}TpWork; + + +// j[vfW +typedef struct MenuPos { + BOOL enable; + int x; + int y; +}MenuPos; + + +// j[\p[^\ +typedef struct MenuParam { + int num; + int normal_color; + int select_color; + int disable_color; + MenuPos *pos; + const u16 **str_elem; +}MenuParam; + + +// global variables-------------------------------------------------- +extern TpWork tpd; // ^b`plf[^ +extern KeyWork pad; // L[pbh̓f[^ +extern const u8 *const g_strWeek[ 7 ]; // j + +extern NNSFndAllocator g_allocator; // AP[^ +extern NNSG2dFont gFont; // tHg +extern NNSG2dCharCanvas gCanvas; // CharCanvas +extern NNSG2dTextCanvas gTextCanvas; // TextCanvas + +// function------------------------------------------------------------- +void InitBG( void ); +void PutStringUTF16 ( int x, int y, int color, const u16 *strUTF16 ); +void PutStringUTF16Sub( int x, int y, int color, const u16 *strUTF16 ); +void PrintfSJIS ( int x, int y, int color, const char *fmt, ... ); +void PrintfSJISSub( int x, int y, int color, const char *fmt, ... ); +void ReadKeyPad( void ); +void ReadTpData( void ); +BOOL WaitDetachTP( void ); +void StartDetachTP( void ); +void DrawMenu( u16 nowCsr, const MenuParam *pMenu ); +BOOL SelectMenuByTP( u16 *nowCsr, const MenuParam *pMenu ); +BOOL InRangeTp( int top_x, int top_y, int bottom_x, int bottom_y, TPData *tgt ); +void InitGetAndDrawRtcData( int drawDatePos_x, int drawDatePos_y, int drawTimePos_x, int drawTimePos_y ); +void GetAndDrawRtcData( void ); +void SetBannerIconOBJ( GXOamAttr *pDstOAM, BannerFileV1 *bannerp ); + +#ifdef __cplusplus +} +#endif + +#endif // __MISC_H__ diff --git a/build/systemMenu_RED/Launcher/Makefile b/build/systemMenu_RED/Launcher/Makefile new file mode 100644 index 0000000..02cacbf --- /dev/null +++ b/build/systemMenu_RED/Launcher/Makefile @@ -0,0 +1,30 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM9 + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/systemMenu_RED/MachineSettings/ARM9/Makefile b/build/systemMenu_RED/MachineSettings/ARM9/Makefile new file mode 100644 index 0000000..6454a1f --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/Makefile @@ -0,0 +1,54 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - demos - simpleShoot-1 +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev: $ +# $Author: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +#---------------------------------------------------------------------------- + +TARGET_FIRM = SYSTEMMENU +TARGET_PLATFORM = TWL +TWL_ARCHGEN = LIMITED + +TARGET_BIN = main.srl + +#LCFILE_SPEC = +ROM_SPEC = main.rsf + +SRCS = main.c misc.c \ + MachineSetting.c setRTC.c selectLanguage.c calibrationTP.c + #setOwnerInfo.c + +#SRCS_OVERLAY = + +#LINCLUDES = +#LLIBRARY_DIRS = +#LLIBRARIES = +#LDEPENDS_NEF = + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build : $(FONT_OBJS) $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#---------------------------------------------------------------------------- + +#===== End of Makefile ===== diff --git a/build/systemMenu_RED/MachineSettings/ARM9/main.rsf b/build/systemMenu_RED/MachineSettings/ARM9/main.rsf new file mode 100644 index 0000000..f7b7ea4 --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/main.rsf @@ -0,0 +1,146 @@ +#---------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ROM-BB.rsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TWL ROM SPEC FILE +# + +Arm9 +{ + Static "$(MAKEROM_ARM9:r).FLX.TWL.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.FLX.TWL.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.FLX.TWL.sbin$(COMPSUFFIX9)" + Elf "$(MAKEROM_ARM9:r).tef" +} + +Arm7 +{ + Static "$(MAKEROM_ARM7_BASE:r).FLX.TWL.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.FLX.TWL.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.FLX.TWL.sbin$(COMPSUFFIX7)" + Elf "$(MAKEROM_ARM7_BASE:r).tef" +} + +Arm9.Ltd +{ + Static "$(MAKEROM_ARM9:r).LTD.TWL.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.LTD.TWL.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.LTD.TWL.sbin$(COMPSUFFIX9)" +} + +Arm7.Ltd +{ + Static "$(MAKEROM_ARM7_BASE:r).LTD.TWL.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.LTD.TWL.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.LTD.TWL.sbin$(COMPSUFFIX7)" +} + +Property +{ + ### + ### Settings for FinalROM + ### + #### BEGIN + # + # TITLE NAME: Your product name within 12bytes + # + #TitleName "YourAppName" + + # + # MAKER CODE: Your company ID# in 2 ascii words + # issued by NINTENDO + # + #MakerCode "00" + + # + # REMASTER VERSION: Mastering version + # + #RomVersion 0 + + # + # ROM SPEED TYPE: [MROM/1TROM/UNDEFINED] + # + RomSpeedType $(MAKEROM_ROMSPEED) + + # + # ROM SIZE: in bit [64M/128M/256M/512M/1G/2G] + # + #RomSize 128M + #RomSize 256M + + # + # ROM PADDING: TRUE if finalrom + # + #RomFootPadding TRUE + + # + # ROM HEADER TEMPLATE: Provided to every product by NINTENDO + # + #RomHeaderTemplate ./etc/rom_header.template.sbin + + # + # BANNER FILE: generated from Banner Spec File + # + BannerFile ../banner/banner.bnr + + ### + ### Setting for TWL + ### + # + # BANNER FILE: + # + BannerTWLFile $(TWLSDK_ROOT)/include/twl/specfiles/default.bnr + + # + # Boot allowed Media: [GameCard/NAND/SDCard/DownloadPlay] + # possible to choose one or more. + # + BootMedia GameCard NAND SDCard DownloadPlay + + # + # Certification FILE: + # + Certificate $(TWLSDK_ROOT)/include/twl/specfiles/default_sgn.sbin + + # + # Digest parameters: + # + DigestParam 1024 32 + + # + # WRAM mapping: [MAP_BB_HYB/MAP_BB_LTD/MAP_TS_HYB/MAP_TS_LTD] + # don't have to edit + # + WramMapping $(MAKEROM_WRAM_MAPPING) + + # + # Codec mode: + # don't have to edit + # + CodecMode $(MAKEROM_CODEC_MODE) + + ### + #### END +} + +RomSpec +{ + Offset 0x00000000 + Segment ALL + HostRoot ../../data + Root /data + File NTR_IPL_font_m.NFTR +} diff --git a/build/systemMenu_RED/MachineSettings/ARM9/src/MachineSetting.c b/build/systemMenu_RED/MachineSettings/ARM9/src/MachineSetting.c new file mode 100644 index 0000000..9105a7d --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/src/MachineSetting.c @@ -0,0 +1,295 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: mainMenu.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "misc.h" +#include "MachineSetting.h" +#include "spi.h" + +// define data------------------------------------------ + // LZ{^LCD̈ +#define CANCEL_BUTTON_TOP_X ( 12 * 8 ) +#define CANCEL_BUTTON_TOP_Y ( 21 * 8 ) +#define CANCEL_BUTTON_BOTTOM_X ( CANCEL_BUTTON_TOP_X + 5 * 8 ) +#define CANCEL_BUTTON_BOTTOM_Y ( CANCEL_BUTTON_TOP_Y + 2 * 8 ) + // OK{^LCD̈ +#define OK_BUTTON_TOP_X ( 22 * 8 ) +#define OK_BUTTON_TOP_Y ( 21 * 8 ) +#define OK_BUTTON_BOTTOM_X ( OK_BUTTON_TOP_X + 2 * 8 ) +#define OK_BUTTON_BOTTOM_Y ( OK_BUTTON_TOP_Y + 2 * 8 ) + + +#define SETTING_MENU_ELEMENT_NUM 4 // Cj[̍ڐ + +// extern data------------------------------------------ + +// function's prototype declaration--------------------- +static BOOL InitialSetting( void ); +static void InitialSettingFinalizeInit( void ); +static int InitialSettingFinalizeMain( void ); + +// global variable ------------------------------------- +BOOL g_initialSet = FALSE; + +// static variable ------------------------------------- +static u16 s_csr = 0; +static const u16 *s_pStrSetting[ SETTING_MENU_ELEMENT_NUM ]; // Cj[pe[uւ̃|C^Xg + +// const data ----------------------------------------- + + +//=============================================== +// mainMenu.c +//=============================================== +static const u16 *const s_pStrSettingElemTbl[ SETTING_MENU_ELEMENT_NUM ][ LANG_CODE_MAX ] = { + { + (const u16 *)L"", + (const u16 *)L"LANGUAGE", + (const u16 *)L"LANGUAGE(F)", + (const u16 *)L"LANGUAGE(G)", + (const u16 *)L"LANGUAGE(I)", + (const u16 *)L"LANGUAGE(S)", + }, + { + (const u16 *)L"t & ", + (const u16 *)L"DATE & TIME", + (const u16 *)L"DATE & TIME(F)", + (const u16 *)L"DATE & TIME(G)", + (const u16 *)L"DATE & TIME(I)", + (const u16 *)L"DATE & TIME(S)", + }, + { + (const u16 *)L"[U[", + (const u16 *)L"USER INFORMATION", + (const u16 *)L"USER INFORMATION(F)", + (const u16 *)L"USER INFORMATION(G)", + (const u16 *)L"USER INFORMATION(I)", + (const u16 *)L"USER INFORMATION(S)", + }, + { + (const u16 *)L"^b`pl␳", + (const u16 *)L"TOUCH PANEL", + (const u16 *)L"TOUCH PANEL(F)", + (const u16 *)L"TOUCH PANEL(G)", + (const u16 *)L"TOUCH PANEL(I)", + (const u16 *)L"TOUCH PANEL(S)", + }, +}; + +static MenuPos s_settingPos[] = { + { TRUE, 4 * 8, 8 * 8 }, + { TRUE, 4 * 8, 10 * 8 }, + { FALSE, 4 * 8, 12 * 8 }, + { TRUE, 4 * 8, 14 * 8 }, +}; + + +static const MenuParam s_settingParam = { + SETTING_MENU_ELEMENT_NUM, + TXT_COLOR_BLACK, + TXT_COLOR_GREEN, + TXT_COLOR_RED, + &s_settingPos[ 0 ], + (const u16 **)&s_pStrSetting, +}; + +//====================================================== +// Cj[ +//====================================================== + +// Cj[̏ +void MachineSettingInit( void ) +{ + int i; + + // NV[PX + if( InitialSetting() ) { + return; + } + + GX_DispOff(); + GXS_DispOff(); + NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_WHITE ); + + PutStringUTF16( 0, 0, TXT_COLOR_BLUE, (const u16 *)L"MACHINE SETTINGS" ); +#ifdef __NCD_CLEAR_ENABLE + (void)PutStringUTF16( 18 * 8, 21 * 8, TXT_COLOR_BLACK, (const u16 *)L"[START]:NCD clear."); +#endif /* __NCD_CLEAR_ENABLE */ + + // NITROݒf[^languageɉCj[\̐؂ւ + for( i = 0; i < SETTING_MENU_ELEMENT_NUM; i++ ) { + s_pStrSetting[ i ] = s_pStrSettingElemTbl[ i ][ GetNCDWork()->option.language ]; + } + + DrawMenu( s_csr, &s_settingParam ); + + SVC_CpuClear( 0x0000, &tpd, sizeof(TpWork), 16 ); + + GX_SetVisiblePlane ( GX_PLANEMASK_BG0 ); + GXS_SetVisiblePlane( GX_PLANEMASK_BG0 ); + GX_DispOn(); + GXS_DispOn(); + + g_pNowProcess = MachineSettingMain; +} + + +// Cj[ +int MachineSettingMain( void ) +{ + BOOL tp_select; + + ReadTP(); + + //-------------------------------------- + // L[͏ + //-------------------------------------- + if( pad.trg & PAD_KEY_DOWN ){ // J[\̈ړ + if( ++s_csr == SETTING_MENU_ELEMENT_NUM ) { + s_csr=0; + } + } + if( pad.trg & PAD_KEY_UP ){ + if( --s_csr & 0x80 ) { + s_csr=SETTING_MENU_ELEMENT_NUM - 1; + } + } + tp_select = SelectMenuByTP( &s_csr, &s_settingParam ); + DrawMenu( s_csr, &s_settingParam ); + + if( ( pad.trg & PAD_BUTTON_A ) || ( tp_select ) ) { // j[ڂւ̕ + if( s_settingPos[ s_csr ].enable ) { + switch( s_csr ) { + case 0: + SelectLanguageInit(); + g_pNowProcess = SelectLanguageMain; + break; + case 1: + SetRTCInit(); + g_pNowProcess = SetRTCMain; + break; + case 2: +// SetOwnerInfoInit(); +// g_pNowProcess = SetOwnerInfoMain; + break; + case 3: + TP_CalibrationInit(); + g_pNowProcess = TP_CalibrationMain; + break; + } + } + } + +#ifdef __NCD_CLEAR_ENABLE + if( pad.trg & PAD_BUTTON_START ) { + SVC_CpuClearFast( 0x0000, GetNCDWork(), sizeof(NitroConfigData) ); + (void)SPI_NvramWriteEnable(); + SVC_WaitVBlankIntr(); + (void)SPI_NvramPageErase( 0x3fe00 ); + SVC_WaitVBlankIntr(); + (void)SPI_NvramWriteEnable(); + SVC_WaitVBlankIntr(); + (void)SPI_NvramPageErase( 0x3ff00 ); + SVC_WaitVBlankIntr(); + (void)SPI_NvramWriteDisable(); + OS_TPrintf("NitroConfigData zero clear!!\n"); + } +#endif /* __NCD_CLEAR_ENABLE */ + + return 0; +} + + +// OK / CANCEL{^̕` +void DrawOKCancelButton(void) +{ + (void)PutStringUTF16( CANCEL_BUTTON_TOP_X, CANCEL_BUTTON_TOP_Y, TXT_COLOR_CYAN, (const u16 *)L"CANCEL"); + (void)PutStringUTF16( OK_BUTTON_TOP_X, OK_BUTTON_TOP_Y, TXT_COLOR_CYAN, (const u16 *)L"OK"); +} + + +// OK or CANCEL{^`FbN +void CheckOKCancelButton(BOOL *tp_ok, BOOL *tp_cancel) +{ + *tp_cancel = WithinRangeTP( CANCEL_BUTTON_TOP_X, CANCEL_BUTTON_TOP_Y, + CANCEL_BUTTON_BOTTOM_X, CANCEL_BUTTON_BOTTOM_Y, &tpd.disp ); + *tp_ok = WithinRangeTP( OK_BUTTON_TOP_X, OK_BUTTON_TOP_Y, + OK_BUTTON_BOTTOM_X, OK_BUTTON_BOTTOM_Y, &tpd.disp ); +} + + +//--------------------------------------------------------- +// +// ݒI +// +//--------------------------------------------------------- + +// NV[PX +static BOOL InitialSetting( void ) +{ +#if 0 + if(GetNCDWork()->option.input_language == 0) { // ݒ肪܂B + g_initialSet = TRUE; + s_csr = 2; + SelectLangageInit(); + g_pNowProcess = SelectLanguageMain; + return TRUE; + }else if(GetNCDWork()->option.input_tp == 0) { // TPLu[V܂B + g_initialSet = TRUE; + s_csr = 3; + TP_CalibrationInit(); + g_pNowProcess = TP_CalibrationMain; + return TRUE; + }else if(GetNCDWork()->option.input_rtc == 0) { // RTCݒ肪܂B + ClearRTC(); + g_initialSet = TRUE; + s_csr = 1; + SetRTCInit(); + g_pNowProcess = SetRTCMain; + return TRUE; + }else if( (GetNCDWork()->option.input_nickname == 0) // jbNl[܂͍DȐF͂܂B + || (GetNCDWork()->option.input_favoriteColor == 0) ) { +/* g_initialSet = TRUE; + s_csr = 0; + SetOwnerInfoInit(); + g_pNowProcess = SetOwnerInfoMain; + return TRUE; +*/ } + + if( g_initialSet ) { + InitialSettingFinalizeInit(); + g_pNowProcess = InitialSettingFinalizeMain(); + return TRUE; + } +#endif + return FALSE; +} + + +static void InitialSettingFinalizeInit( void ) +{ + NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_WHITE ); + (void)PutStringUTF16( 6 * 8, 10 * 8, TXT_COLOR_BLACK, (const u16 *)L" Initial setting completed."); + (void)PutStringUTF16( 6 * 8, 12 * 8, TXT_COLOR_BLACK, (const u16 *)L" Please reboot."); +} + + +static int InitialSettingFinalizeMain( void ) +{ + return 0; +} + diff --git a/build/systemMenu_RED/MachineSettings/ARM9/src/MachineSetting.h b/build/systemMenu_RED/MachineSettings/ARM9/src/MachineSetting.h new file mode 100644 index 0000000..da904fc --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/src/MachineSetting.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: MachineSetting.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef __MACHINE_SETTING_H__ +#define __MACHINE_SETTING_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include + + +// define data---------------------------------------------------------- +#define TP_CSR_TOUCH_COUNT 2 // TPJ[\̃`^Oẑ߂̃JEgl +#define TP_CSR_DETACH_COUNT 2 // TPJ[\uIvƔ肷TPf^b`̃JEgl + +#define HANDLE_MENU 48 +#define HANDLE_RTC_VIEW 240 +#define HANDLE_OK_BUTTON 255 +#define HANDLE_CANCEL_BUTTON 256 + +// l̓C^[tF[Xp[Nivoid InputDecimal()Ŏgpj +typedef struct InputNumParam { + u16 pos_x; // ͒l̕\Xʒu + u16 pos_y; // V@@@@ Yʒu + int up_count; + int down_count; + int keta_max; // ő包 + int value_min; // ͒l̍ŏ + int value_max; // ͒l̍ő + int y_offset; // ^b`pl͂̊ʒuYItZbg +}InputNumParam; + +// global variable------------------------------------------------------ +extern NNSFndAllocator g_allocator; +extern BOOL g_initialSet; +extern int (*g_pNowProcess)( void ); + +// function------------------------------------------------------------- +extern void MachineSettingInit( void ); +extern int MachineSettingMain( void ); +extern void SetOwnerInfoInit( void ); +extern int SetOwnerInfoMain( void ); +extern void SetRTCInit( void ); +extern int SetRTCMain( void ); +extern void SelectLanguageInit( void ); +extern int SelectLanguageMain( void ); +extern void TP_CalibrationInit( void ); +extern int TP_CalibrationMain( void ); + +extern void DrawOKCancelButton( void ); +extern void CheckOKCancelButton(BOOL *tp_ok, BOOL *tp_cancel); +extern void InputDecimal(int *tgtp, InputNumParam *inpp); + +extern void ClearRTC( void ); + +#ifdef __cplusplus +} +#endif + +#endif // __MACHINE_SETTING_H__ diff --git a/build/systemMenu_RED/MachineSettings/ARM9/src/calibrationTP.c b/build/systemMenu_RED/MachineSettings/ARM9/src/calibrationTP.c new file mode 100644 index 0000000..8cd7d8b --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/src/calibrationTP.c @@ -0,0 +1,524 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: calibrationTP.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "misc.h" +#include "MachineSetting.h" + +// define data------------------------------------------ + // OK{^LCD̈ +#define OK_BUTTON_TOP_X ( 2 * 8 ) +#define OK_BUTTON_TOP_Y ( 20 * 8 ) +#define OK_BUTTON_BOTTOM_X ( OK_BUTTON_TOP_X + 8 * 8 ) +#define OK_BUTTON_BOTTOM_Y ( OK_BUTTON_TOP_Y + 4 * 8 ) + + // LZ{^LCD̈ +#define CANCEL_BUTTON_TOP_X ( 11 * 8 ) +#define CANCEL_BUTTON_TOP_Y ( 20 * 8 ) +#define CANCEL_BUTTON_BOTTOM_X ( CANCEL_BUTTON_TOP_X + 8 * 8 ) +#define CANCEL_BUTTON_BOTTOM_Y ( CANCEL_BUTTON_TOP_Y + 4 * 8 ) + + // gC{^LCD̈ +#define RETRY_BUTTON_TOP_X ( 20 * 8 ) +#define RETRY_BUTTON_TOP_Y ( 20 * 8 ) +#define RETRY_BUTTON_BOTTOM_X ( RETRY_BUTTON_TOP_X + 8 * 8 ) +#define RETRY_BUTTON_BOTTOM_Y ( RETRY_BUTTON_TOP_Y + 4 * 8 ) + + // Lu[VpOBJf[^ +const u16 bitmapOBJPoint[8 * 8 * 5]; + + // eLN^f[^TCY +#define IMAGE_DATA (bitmapOBJPoint) +#define IMAGE_DATA_SIZE (sizeof(bitmapOBJPoint)) +#define MY_CHAR_SIZE (sizeof(myChar)) + + // NITRO-LCDTCY +#define DISP_X_SIZE 256 +#define DISP_Y_SIZE 192 + +enum { + INIT=0, + INTERVAL_0, + CALIBRATE_1, + INTERVAL_1, + CALIBRATE_2, + INTERVAL_2, + CHECK_PARAM, + INTERVAL_3, + GET_POINT +}; + + // Lu[Vݒ胏[N +typedef struct CalibWork { + u32 seq; + u16 release_count; + u16 touch_count; + u16 last_x; + u16 last_y; + TPData sample[2]; + TPCalibrateParam calibrate; +}CalibWork; + +// extern data------------------------------------------ + +// function's prototype declaration--------------------- +static void DisplayInit(); +static BOOL GetSamplePointNow(TPData *data); +static BOOL WaitPanelReleaseNow( void ); +static void ReturnMenu(void); + +// global variable ------------------------------------- + +// static variable ------------------------------------- +static CalibWork *s_pCw; +static GXOamAttr s_oamBak[ 128 ] ATTRIBUTE_ALIGN(32); // OAM obNAbv + +// const data ----------------------------------------- + +//====================================================== +// function's description +//====================================================== + +/*---------------------------------------------------------------------------* + Name: SetPoint8x8 + + Description: Display a 8x8 OBJ on indicated point. + + Arguments: x - position X. + y - position Y. + + Returns: None. + *---------------------------------------------------------------------------*/ +static inline void SetPoint8x8(u16 pos_x, u16 pos_y) +{ + G2_SetOBJAttr( &s_oamBak[0], // OAM number + pos_x - 4, // X position + pos_y - 4, // Y position + 0, // Priority + GX_OAM_MODE_BITMAPOBJ, // Bitmap mode + FALSE, // mosaic off + GX_OAM_EFFECT_NONE, // affine off + GX_OAM_SHAPE_8x8, // 8x8 size + GX_OAM_COLOR_16, // 16 color + 0x60, // charactor + 15, // alpha + 0); +} + + +/*---------------------------------------------------------------------------* + Name: SetPoint16x16 + + Description: Display a 16x16 OBJ on indicated point. + + Arguments: x - position X. + y - position Y. + + Returns: None. + *---------------------------------------------------------------------------*/ +static inline void SetPoint16x16(u16 pos_x, u16 pos_y) +{ + G2_SetOBJAttr( &s_oamBak[0], // OAM number + pos_x - 8, // X position + pos_y - 8, // Y position + 0, // Priority + GX_OAM_MODE_BITMAPOBJ, // Bitmap mode + FALSE, // mosaic off + GX_OAM_EFFECT_NONE, // affine off + GX_OAM_SHAPE_16x16, // 16x16 size + GX_OAM_COLOR_16, // 16 color + 0x61, // charactor + 15, // alpha + 0); +} + + +/*---------------------------------------------------------------------------* + Name: DisplayInit + + Description: Graphics Initialization + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +static void DisplayInit() +{ + MI_CpuClearFast( (void *)HW_OAM, 0x20 ); + MI_CpuClearFast( s_oamBak, sizeof(s_oamBak) ); + GX_SetOBJVRamModeBmp( GX_OBJVRAMMODE_BMP_1D_128K ); // 2D mapping OBJ + /* Load charactor bitmap data */ + GX_LoadOBJ( (const void *)IMAGE_DATA, 0x3000 /* 0 */, IMAGE_DATA_SIZE ); // Transfer OBJ bitmap data to VRAM +} + + +/*---------------------------------------------------------------------------* + Name: GetSamplePointNow + + Description: Get touched point by OneTime Sampling. + This function use TP_RequestSampling() and TP_WaitRawResult() + + Arguments: None. + + Returns: data - getton TouchPanel data. + BOOL - if touched and got point this function returns TRUE. + else FALSE. + *---------------------------------------------------------------------------*/ +static BOOL GetSamplePointNow(TPData *data) +{ + TPData temp; + + enum { + OK_COUNT = 4, OK_RANGE = 50 + }; + + // Detect a point pushed during definite time. + while (TP_RequestRawSampling( &temp )) { }; + + if (! temp.touch ) { + s_pCw->touch_count = 0; + return FALSE; + } + + if ( temp.validity != TP_VALIDITY_VALID ) { + s_pCw->touch_count = 0; + return FALSE; + } + + OS_Printf("( %d, %d )\n", temp.x, temp.y); + + s_pCw->touch_count++; + if ( s_pCw->touch_count == 1 ) { + s_pCw->last_x = temp.x; + s_pCw->last_y = temp.y; + return FALSE; + } + + // if jump point from last frame, reset count. + if ( (s32)(s_pCw->last_x - temp.x) < - OK_RANGE || + (s32)(s_pCw->last_x - temp.x) > OK_RANGE ) + { + s_pCw->touch_count = 1; + s_pCw->last_x = temp.x; + s_pCw->last_y = temp.y; + return FALSE; + } + + if ( (s32)(s_pCw->last_y - temp.y) < - OK_RANGE || + (s32)(s_pCw->last_y - temp.y) > OK_RANGE ) + { + s_pCw->touch_count = 1; + s_pCw->last_x = temp.x; + s_pCw->last_y = temp.y; + return FALSE; + } + + // if the point pressed during OK_COUNT, detect finish. + if ( s_pCw->touch_count == OK_COUNT ) { + data->x = (u16) ( (temp.x + s_pCw->last_x) / 2 ); + data->y = (u16) ( (temp.y + s_pCw->last_y) / 2 ); + data->touch = TP_TOUCH_ON; + data->validity = TP_VALIDITY_VALID; + s_pCw->touch_count=0; + return TRUE; + } + + s_pCw->last_x = temp.x; + s_pCw->last_y = temp.y; + return FALSE; +} + + +/*---------------------------------------------------------------------------* + Name: WaitPanelReleaseNow + + Description: Wait to released TouchPanel, using OneTime Sampling. + This function is using TP_RequestSampling() and TP_WaitRawResult(). + + Arguments: None. + + Returns: BOOL - if TouchPanel is released , this returns TRUE. + else FALSE. + + *---------------------------------------------------------------------------*/ +static BOOL WaitPanelReleaseNow( void ) +{ + TPData temp; + + enum { + INTERVAL_CNT = 10 + }; + + while (TP_RequestRawSampling( &temp )) { + SVC_WaitByLoop(0x400); + }; + + if ( temp.touch ) { + s_pCw->release_count = 0; + return FALSE; + } + + s_pCw->release_count++; + if ( s_pCw->release_count >= INTERVAL_CNT ) { + s_pCw->release_count = 0; + return TRUE; + } else { + return FALSE; + } +} + + +/*---------------------------------------------------------------------------* + Name: TP_Calibration + + Description: Initialization and main loop + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +int TP_CalibrationMain( void ) +{ + BOOL tp_ok = FALSE; + BOOL tp_cancel = FALSE; + BOOL tp_retry = FALSE; + + switch (s_pCw->seq) { + case INIT: + NNS_G2dCharCanvasClearArea( &gCanvas, TXT_COLOR_WHITE, + 0 * 8 , 20 * 8, 32 * 8, 4 * 8 ); + s_pCw->seq = INTERVAL_0; + PutStringUTF16( 2 * 8, 21 * 8, TXT_COLOR_CYAN, (const u16 *)L"[B]:CANCEL" ); + break; + + case INTERVAL_0: + // wait release TouchPanel + if ( WaitPanelReleaseNow() ) { + s_pCw->seq = CALIBRATE_1; + } + break; + + case CALIBRATE_1: + // detect first point. + SetPoint8x8( 32, 32 ); + if ( GetSamplePointNow( &s_pCw->sample[ 0 ] ) ) { + OS_Printf( "OK! ( %d, %d )\n", s_pCw->sample[0].x, s_pCw->sample[0].y ); + s_pCw->seq = INTERVAL_1; + } + break; + + case INTERVAL_1: + // wait release TouchPanel + if ( WaitPanelReleaseNow() ) { + s_pCw->seq = CALIBRATE_2; + } + break; + + case CALIBRATE_2: + // detect second point. + SetPoint8x8( DISP_X_SIZE - 32, DISP_Y_SIZE - 32 ); + if ( GetSamplePointNow( &s_pCw->sample[ 1 ] ) ) { + OS_Printf( "OK! ( %d, %d )\n", s_pCw->sample[1].x, s_pCw->sample[1].y ); + // Calculate and set calibration parameter from two detected point. + (void)TP_CalcCalibrateParam( + &s_pCw->calibrate, + s_pCw->sample[0].x, s_pCw->sample[0].y, 32, 32, + s_pCw->sample[1].x, s_pCw->sample[1].y, DISP_X_SIZE - 32, DISP_Y_SIZE - 32 ); + TP_SetCalibrateParam( &s_pCw->calibrate ); + + OS_Printf( "Calibrate param: \n" ); + OS_Printf( "\tx = %d, xDotSize = %d\n", s_pCw->calibrate.x0, s_pCw->calibrate.xDotSize / 0x100 ); + OS_Printf( "\ty = %d, yDotSize = %d\n", s_pCw->calibrate.y0, s_pCw->calibrate.yDotSize / 0x100 ); + OS_Printf( "Check calibrate param\n" ); + + s_pCw->seq = INTERVAL_2; + } + break; + + case INTERVAL_2: + // Wait release TouchPanel + if ( WaitPanelReleaseNow() ) { + s_pCw->seq = CHECK_PARAM; + } + break; + + case CHECK_PARAM: + // Verify Calibrattion Parameter. + SetPoint8x8( DISP_X_SIZE / 2, DISP_Y_SIZE / 2 ); + if ( GetSamplePointNow( &tpd.raw ) ) { + TP_GetUnCalibratedPoint( &tpd.disp.x, &tpd.disp.y, DISP_X_SIZE / 2, DISP_Y_SIZE / 2 ); + s_pCw->seq = GET_POINT; + + NNS_G2dCharCanvasClearArea( &gCanvas, TXT_COLOR_WHITE, + 2 * 8 , 21 * 8, 10 * 8, 2 * 8 ); + PutStringUTF16( OK_BUTTON_TOP_X, OK_BUTTON_TOP_Y, TXT_COLOR_CYAN, (const u16 *)L" OK "); + PutStringUTF16( CANCEL_BUTTON_TOP_X, CANCEL_BUTTON_TOP_Y, TXT_COLOR_CYAN, (const u16 *)L" CANCEL "); + PutStringUTF16( RETRY_BUTTON_TOP_X, RETRY_BUTTON_TOP_Y, TXT_COLOR_CYAN, (const u16 *)L" RETRY "); + PutStringUTF16( OK_BUTTON_TOP_X + 2 * 8, OK_BUTTON_TOP_Y + 2 * 8, TXT_COLOR_CYAN, (const u16 *)L"[A]"); + PutStringUTF16( CANCEL_BUTTON_TOP_X + 2 * 8, CANCEL_BUTTON_TOP_Y + 2 * 8, TXT_COLOR_CYAN, (const u16 *)L"[B]"); + PutStringUTF16( RETRY_BUTTON_TOP_X, RETRY_BUTTON_TOP_Y + 2 * 8, TXT_COLOR_CYAN, (const u16 *)L"[START]"); + { + s32 xRange, yRange; + xRange = tpd.raw.x - tpd.disp.x; + yRange = tpd.raw.y - tpd.disp.y; + OS_TPrintf( "OK! ( %d, %d )\n", tpd.raw.x, tpd.raw.y ); + OS_TPrintf( "Raw ( %d, %d )\n", tpd.disp.x, tpd.disp.y ); + OS_TPrintf( "\txRange = %d, yRange = %d\n", xRange, yRange ); + } + } + break; + + case GET_POINT: + // Draw Marker by calibrated point. + while ( TP_RequestRawSampling( &tpd.raw ) ) { + SVC_WaitByLoop( 0x400 ); + } + TP_GetCalibratedPoint( &tpd.disp, &tpd.raw ); + + if ( tpd.raw.touch ) { + SetPoint16x16( tpd.disp.x, tpd.disp.y ); + + // [OK] [CANCEL] [RETRY]{^`FbN + tp_ok = WithinRangeTP( OK_BUTTON_TOP_X, OK_BUTTON_TOP_Y, + OK_BUTTON_BOTTOM_X, OK_BUTTON_BOTTOM_Y, &tpd.disp ); + tp_cancel = WithinRangeTP( CANCEL_BUTTON_TOP_X, CANCEL_BUTTON_TOP_Y, + CANCEL_BUTTON_BOTTOM_X, CANCEL_BUTTON_BOTTOM_Y, &tpd.disp ); + tp_retry = WithinRangeTP( RETRY_BUTTON_TOP_X, RETRY_BUTTON_TOP_Y, + RETRY_BUTTON_BOTTOM_X, RETRY_BUTTON_BOTTOM_Y, &tpd.disp ); + + if( tpd.raw.validity==TP_VALIDITY_VALID ) { + OS_TPrintf( "( %3d, %3d ) -> ( %4d, %4d )\n", tpd.disp.x, tpd.disp.y, tpd.raw.x, tpd.raw.y ); + } + } + + if( ( pad.trg & PAD_BUTTON_A ) || tp_ok ) { + GetSYSMWork()->ncd_invalid = 0; + GetNCDWork()->option.input_tp = 1; // ^b`pl̓tO𗧂ĂB + GetNCDWork()->tp.raw_x1 = s_pCw->sample[0].x; + GetNCDWork()->tp.raw_y1 = s_pCw->sample[0].y; + GetNCDWork()->tp.dx1 = 32; + GetNCDWork()->tp.dy1 = 32; + GetNCDWork()->tp.raw_x2 = s_pCw->sample[1].x; + GetNCDWork()->tp.raw_y2 = s_pCw->sample[1].y; + GetNCDWork()->tp.dx2 = DISP_X_SIZE - 32; + GetNCDWork()->tp.dy2 = DISP_Y_SIZE - 32; + // :::::::::::::::::::::::::::::::::::::::::::::: + // NVRAMւ̏ + // :::::::::::::::::::::::::::::::::::::::::::::: + (void)NVRAMm_WriteNitroConfigData( GetNCDWork() ); + + ReturnMenu(); + return 0; + }else if( ( pad.trg & PAD_BUTTON_START ) || tp_retry ) { + s_pCw->seq = INIT; + } + break; + } + + /* flush cache of OAM buffers to main memory */ + DC_FlushRange( s_oamBak, sizeof(s_oamBak) ); + GX_LoadOAM( s_oamBak, 0, sizeof(s_oamBak) ); + MI_DmaFill32( 3, s_oamBak, 192, sizeof(s_oamBak) ); // Clear OAM buffer + + // B{^LZ + if( ( pad.trg & PAD_BUTTON_B ) || tp_cancel ){ + (void)TP_CalcCalibrateParam( + &s_pCw->calibrate, + GetNCDWork()->tp.raw_x1, GetNCDWork()->tp.raw_y1, (u16)GetNCDWork()->tp.dx1, (u16)GetNCDWork()->tp.dy1, + GetNCDWork()->tp.raw_x2, GetNCDWork()->tp.raw_y2, (u16)GetNCDWork()->tp.dx2, (u16)GetNCDWork()->tp.dy2 ); + TP_SetCalibrateParam( &s_pCw->calibrate ); + ReturnMenu(); + return 0; + } + + return 0; +} + + +// j[ɖ߂ +static void ReturnMenu( void ) +{ + NNS_FndFreeToAllocator( &g_allocator, s_pCw ); // Lu[Vpϐ̊J + s_pCw = NULL; + OS_Printf("Free :CalibWork\n"); + MachineSettingInit(); +} + + +// Lu[Vݒ̏ +void TP_CalibrationInit( void ) +{ + GX_DispOff(); + GXS_DispOff(); + NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_WHITE ); + + PutStringUTF16( 0, 0, TXT_COLOR_BLUE, (const u16 *)L"TOUCH PANEL CALIBRATION" ); + + if( g_initialSet ) { + PutStringUTF16( 8 * 8, 18 * 8, TXT_COLOR_RED, (const u16 *)L"Calibrate touch panel." ); + } + + DisplayInit(); + + s_pCw = NNS_FndAllocFromAllocator( &g_allocator, sizeof(CalibWork) ); // Lu[Vpϐ̊m + if( s_pCw == NULL ) { + OS_Panic("ARM9- Fail to allocate memory...\n"); + } + SVC_CpuClear( 0x0000, s_pCw, sizeof(CalibWork), 16 ); + SVC_CpuClear( 0x0000, &tpd, sizeof(TpWork), 16 ); + + GX_SetVisiblePlane ( GX_PLANEMASK_BG0 | GX_PLANEMASK_OBJ ); + GXS_SetVisiblePlane( GX_PLANEMASK_BG0 ); + GX_DispOn(); + GXS_DispOn(); + + s_pCw->seq = INIT; +} + + +// ^b`plݒ|Cg@Lf[^ +const u16 bitmapOBJPoint[8 * 8 * 5] = { + 0x0000, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0x0000, // 0 char + 0xFC00, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0xFC00, // 0 char + 0xFC00, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0xFC00, // 0 char + 0xFC00, 0xFC00, 0xFC00, 0x801F, 0x801F, 0xFC00, 0xFC00, 0xFC00, // 0 char + 0xFC00, 0xFC00, 0xFC00, 0x801F, 0x801F, 0xFC00, 0xFC00, 0xFC00, // 0 char + 0xFC00, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0xFC00, // 0 char + 0xFC00, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0xFC00, // 0 char + 0x0000, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0x0000, // 0 char + + 0x0000, 0x0000, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0x0000, 0x0000, // 1 char + 0x0000, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0x0000, // 1 char + 0xFC00, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0xFC00, // 1 char + 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, // 1 char + + 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, // 2 char + 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, // 2 char + 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, // 2 char + 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0x801F, 0x801F, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, // 2 char + + 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0x801F, 0x801F, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, // 3 char + 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, // 3 char + 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, // 3 char + 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, // 3 char + + 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, // 4 char + 0xFC00, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0x0000, 0x0000, 0x0000, 0x0000, 0xFC00, 0xFC00, 0xFC00, // 4 char + 0x0000, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0x0000, // 4 char + 0x0000, 0x0000, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0x0000, 0x0000, // 4 char +}; + diff --git a/build/systemMenu_RED/MachineSettings/ARM9/src/main.c b/build/systemMenu_RED/MachineSettings/ARM9/src/main.c new file mode 100644 index 0000000..a0e8631 --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/src/main.c @@ -0,0 +1,117 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "misc.h" +#include "MachineSetting.h" + +// extern data----------------------------------------------------------------- + +// define data----------------------------------------------------------------- + +// function's prototype------------------------------------------------------- +static void InitAllocator( NNSFndAllocator* pAllocator ); +static void InitAllocSystem( void ); +static void INTR_VBlank( void ); + +// global variable------------------------------------------------------------- +NNSFndAllocator g_allocator; +int (*g_pNowProcess)( void ); +RTCDrawProperty g_rtcDraw = { + TRUE, RTC_DATE_TOP_X, RTC_DATE_TOP_Y, RTC_TIME_TOP_X, RTC_TIME_TOP_Y +}; + +// static variable------------------------------------------------------------- + +// const data------------------------------------------------------------------ + + +// ============================================================================ +// function's description +// ============================================================================ +void TwlMain(void) +{ + + // ---------------------------------- + OS_Init(); + + (void)OS_EnableIrq(); + (void)OS_EnableInterrupts(); + + GX_Init(); + GX_SetPower(GX_POWER_ALL); // eWbN p[ON + + // 荞݋---------------------------- + (void)OS_SetIrqFunction(OS_IE_V_BLANK, INTR_VBlank); + (void)OS_EnableIrqMask(OS_IE_V_BLANK); + (void)GX_VBlankIntr(TRUE); + + // foCX------------------------------- + TP_Init(); + (void)RTC_Init(); + + // VXȅ------------------ + InitAllocator( &g_allocator ); + CMN_InitFileSystem( &g_allocator ); + + // NitroConfigDatã[h + (void)NVRAMm_ReadNitroConfigData( GetNCDWork() ); + SYSM_CaribrateTP(); + + InitBG(); + GetAndDrawRTCData( &g_rtcDraw, TRUE ); + MachineSettingInit(); + // C[v---------------------------- + while ( 1 ) { + OS_WaitIrq( 1, OS_IE_V_BLANK ); // VuN荞ݑ҂ + + ReadKeyPad(); // L[͂̎擾 + + (void)g_pNowProcess(); + + GetAndDrawRTCData( &g_rtcDraw, FALSE ); + } +} + + +// AP[^̏ +static void InitAllocator( NNSFndAllocator* pAllocator ) +{ + u32 arenaLow = MATH_ROUNDUP ( (u32)OS_GetMainArenaLo(), 16 ); + u32 arenaHigh = MATH_ROUNDDOWN( (u32)OS_GetMainArenaHi(), 16 ); + u32 heapSize = arenaHigh - arenaLow; + void* heapMemory = OS_AllocFromMainArenaLo( heapSize, 16 ); + NNSFndHeapHandle heapHandle; + SDK_NULL_ASSERT( pAllocator ); + + heapHandle = NNS_FndCreateExpHeap( heapMemory, heapSize ); + SDK_ASSERT( heapHandle != NNS_FND_HEAP_INVALID_HANDLE ); + + NNS_FndInitAllocatorForExpHeap( pAllocator, heapHandle, 4 ); +} + + +// ============================================================================ +// 荞ݏ +// ============================================================================ + +// VuN荞 +static void INTR_VBlank(void) +{ + OS_SetIrqCheckFlag(OS_IE_V_BLANK); // VuN`FbÑZbg +} + diff --git a/build/systemMenu_RED/MachineSettings/ARM9/src/misc.c b/build/systemMenu_RED/MachineSettings/ARM9/src/misc.c new file mode 100644 index 0000000..03f8c50 --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/src/misc.c @@ -0,0 +1,601 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: misc.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "misc.h" + +// define data----------------------------------------------------------------- +#define NTR_IPL_FONT_DATA "data/NTR_IPL_font_m.NFTR" + +#define STRING_LENGTH_MAX 256 + +#define GRAY(x) GX_RGB(x, x, x) + +enum +{ + TXT_CPALETTE_MAIN, + TXT_CPALETTE_USERCOLOR, + TXT_CPALETTE_4BPP, + TXT_NUM_CPALEETE +}; + +// fʂ̃J[pbg +GXRgb TXTColorPalette[TXT_NUM_CPALEETE * 16] = +{ + GX_RGB(31, 31, 31), GX_RGB(31, 31, 31), GX_RGB( 0, 0, 0), GX_RGB(31, 0, 0), + GX_RGB( 0, 31, 0), GX_RGB( 0, 0, 31), GX_RGB( 0, 31, 31), GX_RGB(31, 0, 31), + GX_RGB(31, 31, 0), GX_RGB( 0, 0, 0), GX_RGB( 0, 0, 0), GX_RGB( 0, 0, 0), + GX_RGB( 0, 0, 0), GX_RGB( 0, 0, 0), GX_RGB( 0, 0, 0), GX_RGB( 0, 0, 0), + + GX_RGB( 0, 0, 0), GX_RGB(12, 16, 19), GX_RGB(23, 9, 0), GX_RGB(31, 0, 3), + GX_RGB(31, 17, 31), GX_RGB(31, 18, 0), GX_RGB(30, 28, 0), GX_RGB(21, 31, 0), + GX_RGB( 0, 20, 7), GX_RGB( 9, 27, 17), GX_RGB( 6, 23, 30), GX_RGB( 0, 11, 30), + GX_RGB( 0, 0, 18), GX_RGB(17, 0, 26), GX_RGB(26, 0, 29), GX_RGB(31, 0, 18), + + GRAY(31), GRAY(29), GRAY(27), GRAY(25), + GRAY(23), GRAY(21), GRAY(19), GRAY(17), + GRAY(15), GRAY(14), GRAY(12), GRAY(10), + GRAY( 8), GRAY( 6), GRAY( 3), GRAY( 0), +}; + +// extern data----------------------------------------------------------------- + +// define data----------------------------------------------------------------- +#define CANVAS_WIDTH 32 // `̕ (LN^P) +#define CANVAS_HEIGHT 24 // `̍ (LN^P) +#define CANVAS_LEFT 0 // `̈ʒuX (LN^P) +#define CANVAS_TOP 0 // `̈ʒuY (LN^P) + +#define TEXT_HSPACE 1 // `掞̕ (sNZP) +#define TEXT_VSPACE 1 // `掞̍s (sNZP) + +#define CHARACTER_OFFSET 0 // gpLN^̊Jnԍ + +// RTCf[^\ʒu[N +typedef struct RtcDrawPos{ + int date_x; + int date_y; + int time_x; + int time_y; +}RtcDrawPos; + +// function's prototype------------------------------------------------------- +static BOOL WaitDetachTP( void ); +static void StartDetachTP( void ); +static void InitScreen( void ); +static void InitCanvas( void ); + +// global variable------------------------------------------------------------- +KeyWork pad; // L[pbh̓f[^ +TpWork tpd; // ^b`pl̓f[^ + +NNSG2dFont gFont; // tHg +NNSG2dCharCanvas gCanvas; // CharCanvas +NNSG2dTextCanvas gTextCanvas; // TextCanvas +NNSG2dCharCanvas gCanvasSub; // CharCanvas +NNSG2dTextCanvas gTextCanvasSub; // TextCanvas + +// static variable------------------------------------------------------------- +static int s_detach_count; +static RtcDrawPos s_rtcPos; +static RTCDate s_rtcDate; +static RTCTime s_rtcTime; +static u16 s_vcount; + +static char s_strBuffer[ STRING_LENGTH_MAX * 2 ] ATTRIBUTE_ALIGN(2); +static u16 s_strBufferUTF16[ STRING_LENGTH_MAX ]; + +// const data------------------------------------------------------------------ + +// jf[^\pR[h +const u8 *const g_strWeek[] ATTRIBUTE_ALIGN(2) = { + (const u8 *)"SUN", + (const u8 *)"MON", + (const u8 *)"TUE", + (const u8 *)"WED", + (const u8 *)"THU", + (const u8 *)"FRI", + (const u8 *)"SAT", +}; + +// ============================================================================ +// function's description +// ============================================================================ + +// BG +void InitBG(void) +{ + // OFF + GX_DispOff(); + GXS_DispOff(); + + // VRAM̊蓖ĂSĉ + GX_DisableBankForBG(); + GX_DisableBankForOBJ(); + GX_DisableBankForSubBG(); + GX_DisableBankForSubOBJ(); + + // C2DGW̏o͂ʂ + GX_SetDispSelect( GX_DISP_SELECT_SUB_MAIN ); + + // CLCD + { + // VRAM蓖 + GX_SetBankForBG ( GX_VRAM_BG_128_A ); + GX_SetBankForOBJ( GX_VRAM_OBJ_128_B ); + + MI_CpuClearFast( (void *)HW_BG_VRAM, 0x20000 ); // BG -VRAM NA + MI_CpuClearFast( (void *)HW_OBJ_VRAM, 0x20000 ); // OBJ-VRAM NA + + // J[pbgݒ + GX_LoadBGPltt( TXTColorPalette, 0, sizeof(TXTColorPalette) ); + + // BG[hݒ + GX_SetGraphicsMode( GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_2D ); + + GX_SetBGScrOffset ( GX_BGSCROFFSET_0x10000 ); + GX_SetBGCharOffset( GX_BGCHAROFFSET_0x00000 ); + } + // TuLCD + { + // VRAM蓖 + GX_SetBankForSubBG ( GX_VRAM_SUB_BG_128_C ); // VRAM-C for BGs + GX_SetBankForSubOBJ( GX_VRAM_SUB_OBJ_128_D ); // VRAM-D for BGs + + MI_CpuClearFast( (void *)HW_DB_BG_VRAM, 0x20000 ); // BG -VRAM NA + MI_CpuClearFast( (void *)HW_DB_OBJ_VRAM, 0x20000 ); // OBJ -VRAM NA + + // J[pbgݒ + GXS_LoadBGPltt( TXTColorPalette, 0, sizeof(TXTColorPalette) ); + + // BG[hݒ + GXS_SetGraphicsMode( GX_BGMODE_0 ); // BGMODE is 0 + } + InitScreen(); + InitCanvas(); +} + + +// XN[ +static void InitScreen( void ) +{ + // C BG 0 ݒ + G2_SetBG0Control( + GX_BG_SCRSIZE_TEXT_256x256, // XN[TCY 256x256 + GX_BG_COLORMODE_16, // J[[h 16F + GX_BG_SCRBASE_0xf800, // XN[x[X + GX_BG_CHARBASE_0x00000, // LN^x[X + GX_BG_EXTPLTT_01 // gpbgXbg + ); + GX_SetVisiblePlane( GX_PLANEMASK_BG0 ); + + // Tu BG 0 ݒ + G2S_SetBG0Control( + GX_BG_SCRSIZE_TEXT_256x256, // 256pix x 256pix text + GX_BG_COLORMODE_16, // use 256 colors mode + GX_BG_SCRBASE_0xf800, // screen base offset + 0x0000 is the address for BG #0 screen + GX_BG_CHARBASE_0x00000, // character base offset + 0x04000 is the address for BG #0 characters + GX_BG_EXTPLTT_01 // use BGExtPltt slot #0 if BGExtPltt is enabled + ); + GXS_SetVisiblePlane( GX_PLANEMASK_BG0 ); // display only BG #0 +} + + +// `̏ +static void InitCanvas( void ) +{ + // tHgǂݍ݂܂ + { + void* pFontFile; + u32 size = CMN_LoadFile( &pFontFile, NTR_IPL_FONT_DATA, &g_allocator); + NNS_G2D_ASSERT( size > 0 ); + NNS_G2dFontInitUTF16(&gFont, pFontFile); +// NNS_G2dPrintFont(&gFont); + } + + { + // CharCanvas ̏ + NNS_G2dCharCanvasInitForBG( + &gCanvas, + (GXCharFmt16*)G2_GetBG0CharPtr() + CHARACTER_OFFSET, + CANVAS_WIDTH, + CANVAS_HEIGHT, + NNS_G2D_CHARA_COLORMODE_16 + ); + + // TextCanvas̏ + NNS_G2dTextCanvasInit( + &gTextCanvas, + &gCanvas, + &gFont, + TEXT_HSPACE, + TEXT_VSPACE + ); + + // XN[ݒ + NNS_G2dMapScrToCharText( + G2_GetBG0ScrPtr(), + CANVAS_WIDTH, + CANVAS_HEIGHT, + CANVAS_LEFT, + CANVAS_TOP, + NNS_G2D_TEXT_BG_WIDTH_256, + CHARACTER_OFFSET, + TXT_CPALETTE_MAIN + ); + } + { + // CharCanvas ̏ + NNS_G2dCharCanvasInitForBG( + &gCanvasSub, + (GXCharFmt16*)G2S_GetBG0CharPtr() + CHARACTER_OFFSET, + CANVAS_WIDTH, + CANVAS_HEIGHT, + NNS_G2D_CHARA_COLORMODE_16 + ); + + // TextCanvas̏ + NNS_G2dTextCanvasInit( + &gTextCanvasSub, + &gCanvasSub, + &gFont, + TEXT_HSPACE, + TEXT_VSPACE + ); + + // XN[ݒ + NNS_G2dMapScrToCharText( + G2S_GetBG0ScrPtr(), + CANVAS_WIDTH, + CANVAS_HEIGHT, + CANVAS_LEFT, + CANVAS_TOP, + NNS_G2D_TEXT_BG_WIDTH_256, + CHARACTER_OFFSET, + TXT_CPALETTE_MAIN + ); + } +} + + +// UTF16ł̒ڕ\ +void PutStringUTF16( int x, int y, int color, const u16 *strUTF16 ) +{ + NNS_G2dTextCanvasDrawText( &gTextCanvas, x, y, color, TXT_DRAWTEXT_FLAG_DEFAULT, + strUTF16 ); +} + +void PutStringUTF16Sub( int x, int y, int color, const u16 *strUTF16 ) +{ + NNS_G2dTextCanvasDrawText( &gTextCanvasSub, x, y, color, TXT_DRAWTEXT_FLAG_DEFAULT, + strUTF16 ); +} + + +// tō쐬\ꍇ̕擾 +int GetPrintfWidth( const NNSG2dTextCanvas *pCanvas, const char *fmt, ... ) +{ + int srcLen; + int dstLen = sizeof(s_strBufferUTF16); + va_list vlist; + va_start(vlist, fmt); + srcLen = STD_TVSNPrintf( s_strBuffer, sizeof(s_strBuffer), fmt, vlist); + va_end(vlist); + s_strBuffer[ srcLen ] = 0; + + (void)STD_ConvertStringSjisToUnicode( s_strBufferUTF16, &dstLen, s_strBuffer, &srcLen, NULL ); + s_strBufferUTF16[ dstLen ] = 0; + + return NNS_G2dTextCanvasGetTextWidth( pCanvas, s_strBufferUTF16 ); +} + + +// SJISPrintf`ŕ\iUTF16ɕϊ) +void PrintfSJIS( int x, int y, int color, const char *fmt, ... ) +{ + int srcLen; + int dstLen = sizeof(s_strBufferUTF16); + va_list vlist; + va_start(vlist, fmt); + srcLen = STD_TVSNPrintf( s_strBuffer, sizeof(s_strBuffer), fmt, vlist); + va_end(vlist); + s_strBuffer[ srcLen ] = 0; + + (void)STD_ConvertStringSjisToUnicode( s_strBufferUTF16, &dstLen, s_strBuffer, &srcLen, NULL ); + s_strBufferUTF16[ dstLen ] = 0; + + NNS_G2dTextCanvasDrawText(&gTextCanvas, x, y, color, TXT_DRAWTEXT_FLAG_DEFAULT, + s_strBufferUTF16 ); +} + +void PrintfSJISSub( int x, int y, int color, const char *fmt, ... ) +{ + int srcLen; + int dstLen = sizeof(s_strBufferUTF16); + va_list vlist; + va_start(vlist, fmt); + srcLen = STD_TVSNPrintf( s_strBuffer, sizeof(s_strBuffer), fmt, vlist); + va_end(vlist); + s_strBuffer[ srcLen ] = 0; + + (void)STD_ConvertStringSjisToUnicode( s_strBufferUTF16, &dstLen, s_strBuffer, &srcLen, NULL ); + s_strBufferUTF16[ dstLen ] = 0; + + NNS_G2dTextCanvasDrawText(&gTextCanvasSub, x, y, color, TXT_DRAWTEXT_FLAG_DEFAULT, + s_strBufferUTF16 ); +} + + +// L[͓ǂݏo-------------------------------- +void ReadKeyPad(void) +{ + u16 readData = PAD_Read(); + pad.trg = (u16)(readData & (readData ^ pad.cont)); // gK + pad.cont = readData; // x^ +} + + +// ^b`plf[^̎擾----------------------- +void ReadTP(void) +{ + TP_GetCalibratedPoint( &tpd.last, &tpd.raw ); // OTPf[^ޔ + + if( TP_RequestRawSampling(&tpd.raw) ) { // ^b`pl̃TvO + SVC_CpuClear(0x0000, &tpd.raw, sizeof(tpd.raw), 16); // SPI-busyŃf[^擾Ɏśhf[^ȂhŃ^[B + return; + } + TP_GetCalibratedPoint( &tpd.disp, &tpd.raw ); // TPWLCDWɕϊB + + if( !WaitDetachTP() ) { // TPf^b`҂sB + SVC_CpuClear(0x0000, &tpd.disp, sizeof(tpd.disp), 16); // SPI-busyŃf[^擾Ɏśhf[^ȂhŃ^[B + return; + } +#if 1 + if(tpd.disp.touch) { // ݂TPf[^\ + switch ( tpd.disp.validity ) { + case TP_VALIDITY_VALID: + OS_Printf("( %3d, %3d ) -> ( %3d, %3d )\n", tpd.raw.x, tpd.raw.y, tpd.disp.x, tpd.disp.y); + break; + case TP_VALIDITY_INVALID_X: + OS_Printf("( *%3d, %3d ) -> ( *%3d, %3d )\n", tpd.raw.x, tpd.raw.y, tpd.disp.x, tpd.disp.y); + break; + case TP_VALIDITY_INVALID_Y: + OS_Printf("( %3d, *%3d ) -> ( %3d, *%3d )\n", tpd.raw.x, tpd.raw.y, tpd.disp.x, tpd.disp.y); + break; + case TP_VALIDITY_INVALID_XY: + OS_Printf("( *%3d, *%3d ) -> ( *%3d, *%3d )\n", tpd.raw.x, tpd.raw.y, tpd.disp.x, tpd.disp.y); + break; + } + } +#endif +} + + +// TPf^b`҂ +static BOOL WaitDetachTP( void ) +{ + // s_detach_countnĂAJEgB + if(s_detach_count > 0) { + if(tpd.disp.touch == 0) { // TPĂȂ΁AJEgisKlōē͂󂯕tB + s_detach_count--; + }else { + s_detach_count = TP_CSR_DETACH_COUNT; + } + return FALSE; + } + return TRUE; +} + + +// TPf^b`҂̊Jn +static void StartDetachTP( void ) +{ + s_detach_count = TP_CSR_DETACH_COUNT; +} + + +//====================================================== +// j[ +//====================================================== + +// j[` +void DrawMenu( u16 nowCsr, const MenuParam *pMenu ) +{ + int i; + int color; + + for( i = 0; i < pMenu->num; i++ ) { + if(i == nowCsr) { + if( !pMenu->pos[ i ].enable ) { + color = pMenu->disable_color; + }else { + color = pMenu->select_color; + } + }else { + color = pMenu->normal_color; + } + PutStringUTF16( pMenu->pos[ i ].x, pMenu->pos[ i ].y, color, (pMenu->str_elem)[ i ] ); + } +} + + +// ^b`plɂ郁j[I +BOOL SelectMenuByTP( u16 *nowCsr, const MenuParam *pMenu ) +{ + u16 i; + TPData *target; + static u16 detach_count = 0; + static u16 csr_old = 0xff; + static u16 same_csr_count = 0; + + // detach_countnĂAJEgB + if( detach_count > 0 ) { + if( tpd.disp.touch == 0 ) { // TPĂȂ΁AJEgisAPOJEgŃj[I + if( ++detach_count == TP_CSR_DETACH_COUNT ) { + detach_count = 0; + return TRUE; + }else { + return FALSE; + } + } + } + detach_count=0; // detachJEgl̃NA + + // ʏ́ATPf[^j[ɂ邩ǂ𔻒B + if( tpd.disp.touch ) target = &tpd.disp; + else target = &tpd.last; + + for( i = 0; i < pMenu->num; i++ ) { + if( tpd.disp.touch ) { // ^b`plj[̗vfŃ^b`ĂȂA + NNSG2dTextRect rect = NNS_G2dTextCanvasGetTextRect( &gTextCanvas, (pMenu->str_elem)[ i ] ); + u16 top_x = (u16)( pMenu->pos[ i ].x ); // j[vfLCDWZo + u16 top_y = (u16)( pMenu->pos[ i ].y ); + u16 bottom_x = (u16)( top_x + rect.width ); + u16 bottom_y = (u16)( top_y + rect.height ); + + OS_TPrintf( "MENU[ %d ] : top_x = %02d top_y = %02d bot_x = %02d bot_y = %02d : ", + i, top_x, top_y, bottom_x, bottom_y ); + + if( WithinRangeTP( top_x, top_y, bottom_x, bottom_y, target ) ) { + OS_TPrintf( "InRange\n" ); + if( tpd.disp.validity == TP_VALIDITY_VALID ) { // J[\̗vfɈړ + if( csr_old == i ) { + if( same_csr_count < TP_CSR_TOUCH_COUNT ) { + same_csr_count++; + }else { + *nowCsr = i; + } + return FALSE; + }else { + csr_old = i; + } + break; + } + }else { + OS_TPrintf( "OutRange\n" ); + } + }else { // touch==0 + if( same_csr_count == TP_CSR_TOUCH_COUNT ) { + detach_count = 1; + break; + } + } + } + same_csr_count = 0; + return FALSE; +} + + +// ݂̃^b`plWẅɂ邩ǂԂB +BOOL WithinRangeTP( int top_x, int top_y, int bottom_x, int bottom_y, TPData *tgt ) +{ + if( ( tgt->x >= top_x ) && + ( tgt->x <= bottom_x ) && + ( tgt->y >= top_y ) && + ( tgt->y <= bottom_y ) ) { + OS_TPrintf( "\nRANGE : tx=%3d ty=%3d bx=%3d by=%3d : x=%3d y=%3d\n", + top_x, top_y, bottom_x, bottom_y, tgt->x, tgt->y ); + return TRUE; + }else { + return FALSE; + } +} + + +// oi[ACROBJ̃[h +void SetBannerIconOBJ( GXOamAttr *pDstOAM, BannerFileV1 *bannerp ) +{ + GXS_LoadOBJPltt( bannerp->pltt, 15, BNR_PLTT_SIZE ); + MI_CpuCopyFast( bannerp->image, (void *)(HW_DB_OBJ_VRAM + 0x20), BNR_IMAGE_SIZE ); + G2_SetOBJAttr( pDstOAM, // OAM pointer + 32, // X position + 32, // Y position + 0, // Priority + GX_OAM_MODE_NORMAL, // Bitmap mode + FALSE, // mosaic off + GX_OAM_EFFECT_NONE, // affine off + GX_OAM_SHAPE_32x32, // 16x16 size + GX_OAM_COLOR_16, // 16 color + 1, // charactor + 15, // palette + 0); // affine +} + + +//=============================================== +// RTCANZX[` +//=============================================== + +// RTCf[^̎擾 +BOOL GetRTCData( RTCDrawProperty *pRTCDraw, BOOL forceGetFlag ) +{ + if( forceGetFlag || ( pRTCDraw->vcount++ == 59 ) ) { + pRTCDraw->vcount = 0; + MI_CpuCopy16( &pRTCDraw->date, &pRTCDraw->date_old, sizeof(RTCDate) ); + MI_CpuCopy16( &pRTCDraw->time, &pRTCDraw->time_old, sizeof(RTCTime) ); + (void)RTC_GetDateTime( &pRTCDraw->date, &pRTCDraw->time ); + return TRUE; + } + return FALSE; +} + + +// RTCf[^̕\ +void DrawRTCData( RTCDrawProperty *pRTCDraw ) +{ + void (*pPrintFunc)( int x, int y, int color, const char *fmt, ... ) = + ( pRTCDraw->isTopLCD ) ? PrintfSJISSub : PrintfSJIS; + + // ORTC̏ + { + u32 year = pRTCDraw->date_old.year + 2000; + pPrintFunc( pRTCDraw->date_x, pRTCDraw->date_y, TXT_COLOR_WHITE, "%04d/%02d/%02d[%3s]", + year, + pRTCDraw->date_old.month, + pRTCDraw->date_old.day, + g_strWeek[ pRTCDraw->date_old.week ] + ); + pPrintFunc( pRTCDraw->time_x, pRTCDraw->time_y, TXT_COLOR_WHITE, "%02d:%02d:%02d", + pRTCDraw->time_old.hour, + pRTCDraw->time_old.minute, + pRTCDraw->time_old.second + ); + } + // RTC̕\ + { + u32 year = pRTCDraw->date.year + 2000; + pPrintFunc( pRTCDraw->date_x, pRTCDraw->date_y, TXT_COLOR_BLACK, "%d/%02d/%02d[%3s]", + year, + pRTCDraw->date.month, + pRTCDraw->date.day, + g_strWeek[ pRTCDraw->date.week ] + ); + pPrintFunc( pRTCDraw->time_x, pRTCDraw->time_y, TXT_COLOR_BLACK, "%02d:%02d:%02d", + pRTCDraw->time.hour, + pRTCDraw->time.minute, + pRTCDraw->time.second + ); + } +} + +// RTCf[^̎擾&\ +void GetAndDrawRTCData( RTCDrawProperty *pRTCDraw, BOOL forceGetFlag ) +{ + if( GetRTCData( pRTCDraw, forceGetFlag ) ) { + DrawRTCData( pRTCDraw ); + } +} diff --git a/build/systemMenu_RED/MachineSettings/ARM9/src/misc.h b/build/systemMenu_RED/MachineSettings/ARM9/src/misc.h new file mode 100644 index 0000000..e0f0a40 --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/src/misc.h @@ -0,0 +1,168 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: misc.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef __MISC_H__ +#define __MISC_H__ + +#include +#include + +#define NNS_G2D_UNICODE +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// define data---------------------------------------------------------- +#define TP_CSR_TOUCH_COUNT 2 // TPJ[\̃`^Oẑ߂̃JEgl +#define TP_CSR_DETACH_COUNT 2 // TPJ[\uIvƔ肷TPf^b`̃JEgl + +// DrawText ł̍ +#define TXT_DRAWTEXT_FLAG_DEFAULT (NNS_G2D_VERTICALORIGIN_TOP | NNS_G2D_HORIZONTALORIGIN_LEFT | NNS_G2D_HORIZONTALALIGN_LEFT) + +// TXTColorPalette ̐F 16Fpbgւ̃[hz +enum +{ + // pbg0 TXT_CPALETTE_MAIN + TXT_COLOR_NULL=0, + TXT_COLOR_WHITE, + TXT_COLOR_BLACK, + TXT_COLOR_RED, + TXT_COLOR_GREEN, + TXT_COLOR_BLUE, + TXT_COLOR_CYAN, + TXT_COLOR_MAGENTA, + TXT_COLOR_YELLOW, + + // pbg1 TXT_CPALETTE_USERCOLOR + TXT_UCOLOR_NULL=0, + TXT_UCOLOR_GRAY, + TXT_UCOLOR_BROWN, + TXT_UCOLOR_RED, + TXT_UCOLOR_PINK, + TXT_UCOLOR_ORANGE, + TXT_UCOLOR_YELLOW, + TXT_UCOLOR_LIMEGREEN, + TXT_UCOLOR_DARKGREEN, + TXT_UCOLOR_SEAGREEN, + TXT_UCOLOR_TURQUOISE, + TXT_UCOLOR_BLUE, + TXT_UCOLOR_DARKBLUE, + TXT_UCOLOR_PURPLE, + TXT_UCOLOR_VIOLET, + TXT_UCOLOR_MAGENTA, + + // pbg TXT_CPALETTE_4BPP + TXT_COLOR_4BPP_NULL=0, + TXT_COLOR_4BPP_BG=1, + TXT_COLOR_4BPP_TEXT=1 +}; + + +// v\ꏊ +#define RTC_DATE_TOP_X ( 9 * 8 ) +#define RTC_DATE_TOP_Y ( 10 * 8 ) +#define RTC_TIME_TOP_X ( 12 * 8 ) +#define RTC_TIME_TOP_Y ( 12 * 8 ) + + +// L[f[^[N +typedef struct { + u16 trg; // gK + u16 cont; // x^ +}KeyWork; + + +// ^b`pl[N +typedef struct { + int detached; // ̃f[^͂Ń^b`ꂽƂB + TPData disp; // ̓͒liLCDWj + TPData raw; // ̓͒liTP Wj + TPData last; // O̓͒liLCDWj +}TpWork; + + +// j[vfW +typedef struct MenuPos { + BOOL enable; + int x; + int y; +}MenuPos; + + +// j[\p[^\ +typedef struct MenuParam { + int num; + int normal_color; + int select_color; + int disable_color; + MenuPos *pos; + const u16 **str_elem; +}MenuParam; + + +// RTCf[^\ʒu[N +typedef struct RTCDrawProperty { + BOOL isTopLCD; + int date_x; + int date_y; + int time_x; + int time_y; + int vcount; + RTCDate date; + RTCTime time; + RTCDate date_old; + RTCTime time_old; +}RTCDrawProperty; + +// global variables-------------------------------------------------- +extern TpWork tpd; // ^b`plf[^ +extern KeyWork pad; // L[pbh̓f[^ +extern const u8 *const g_strWeek[ 7 ]; // j +extern RTCDrawProperty g_rtcDraw; + +extern NNSFndAllocator g_allocator; // AP[^ +extern NNSG2dFont gFont; // tHg +extern NNSG2dCharCanvas gCanvas; // CharCanvas +extern NNSG2dTextCanvas gTextCanvas; // TextCanvas + +// function------------------------------------------------------------- +void InitBG( void ); +int GetPrintfWidth( const NNSG2dTextCanvas *pCanvas, const char *fmt, ... ); +void PutStringUTF16 ( int x, int y, int color, const u16 *strUTF16 ); +void PutStringUTF16Sub( int x, int y, int color, const u16 *strUTF16 ); +void PrintfSJIS ( int x, int y, int color, const char *fmt, ... ); +void PrintfSJISSub( int x, int y, int color, const char *fmt, ... ); +void ReadKeyPad( void ); +void ReadTP( void ); +void DrawMenu( u16 nowCsr, const MenuParam *pMenu ); +BOOL SelectMenuByTP( u16 *nowCsr, const MenuParam *pMenu ); +BOOL WithinRangeTP( int top_x, int top_y, int bottom_x, int bottom_y, TPData *tgt ); +void SetBannerIconOBJ( GXOamAttr *pDstOAM, BannerFileV1 *bannerp ); +BOOL GetRTCData( RTCDrawProperty *pRTCDraw, BOOL forceGetFlag ); +void DrawRTCData( RTCDrawProperty *pRTCDraw ); +void GetAndDrawRTCData( RTCDrawProperty *pRTCDraw, BOOL forceGetFlag ); + +#ifdef __cplusplus +} +#endif + +#endif // __MISC_H__ diff --git a/build/systemMenu_RED/MachineSettings/ARM9/src/selectLanguage.c b/build/systemMenu_RED/MachineSettings/ARM9/src/selectLanguage.c new file mode 100644 index 0000000..49b3f64 --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/src/selectLanguage.c @@ -0,0 +1,148 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: SelectLanguage.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "misc.h" +#include "MachineSetting.h" + +// define data------------------------------------------ +#define CANCEL_BUTTON_TOP_X ( 2 * 8 ) +#define CANCEL_BUTTON_TOP_Y ( 21 * 8 ) +#define CANCEL_BUTTON_BOTTOM_X ( (CANCEL_BUTTON_TOP_X + 8 ) * 8 ) +#define CANCEL_BUTTON_BOTTOM_Y ( (CANCEL_BUTTON_TOP_Y + 2 ) * 8 ) + +// extern data------------------------------------------ + +// function's prototype declaration--------------------- + +// global variable ------------------------------------- + +// static variable ------------------------------------- +static NvLangCode s_langCode; // R[h + +// const data ----------------------------------------- +static const u16 *const s_pStrLanguage[] = { + (const u16 *)L"{", + (const u16 *)L"English ", + (const u16 *)L"Francais", + (const u16 *)L"Deutsch ", + (const u16 *)L"Italiano", + (const u16 *)L"Espanol ", +}; + +static MenuPos s_languagePos[] = { + { TRUE, 4 * 8, 6 * 8 }, + { TRUE, 4 * 8, 8 * 8 }, + { TRUE, 4 * 8, 10 * 8 }, + { TRUE, 4 * 8, 12 * 8 }, + { TRUE, 4 * 8, 14 * 8 }, + { TRUE, 4 * 8, 16 * 8 }, +}; + +static const MenuParam langSel = { + 6, + TXT_COLOR_BLACK, + TXT_COLOR_GREEN, + TXT_COLOR_RED, + &s_languagePos[ 0 ], + (const u16 **)&s_pStrLanguage, +}; + + +//====================================================== +// function's description +//====================================================== + +// ݒ̏ +void SelectLanguageInit( void ) +{ + GX_DispOff(); + GXS_DispOff(); + NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_WHITE ); + + PutStringUTF16( 0, 0, TXT_COLOR_BLUE, (const u16 *)L"LANGUAGE SELECT" ); + PutStringUTF16( CANCEL_BUTTON_TOP_X, CANCEL_BUTTON_TOP_Y, TXT_COLOR_CYAN, (const u16 *)L"CANCEL" ); + if( g_initialSet ) { + PutStringUTF16( 8 * 8, 18 * 8, TXT_COLOR_RED, (const u16 *)L"Select language." ); + } + + if( ( GetSYSMWork()->ncd_invalid ) || + ( GetNCDWork()->option.language >= LANG_CODE_MAX ) ) { + s_langCode = LANG_ENGLISH; + }else { + s_langCode = (NvLangCode)GetNCDWork()->option.language; + } + + DrawMenu( (u16)s_langCode, &langSel ); + + SVC_CpuClear( 0x0000, &tpd, sizeof(TpWork), 16 ); + + GX_SetVisiblePlane ( GX_PLANEMASK_BG0 ); + GXS_SetVisiblePlane( GX_PLANEMASK_BG0 ); + GX_DispOn(); + GXS_DispOn(); +} + + +// I +int SelectLanguageMain( void ) +{ + BOOL tp_select,tp_cancel = FALSE; + + ReadTP(); // TP͂̎擾 + + //-------------------------------------- + // L[͏ + //-------------------------------------- + if( pad.trg & PAD_KEY_DOWN ) { // J[\̈ړ + if( ++s_langCode == LANG_CODE_MAX ) { + s_langCode = (NvLangCode)0; + } + } + if( pad.trg & PAD_KEY_UP ) { + if( --s_langCode < 0 ) { + s_langCode = (NvLangCode)( LANG_CODE_MAX - 1 ); + } + } + tp_select = SelectMenuByTP( (u16 *)&s_langCode, &langSel ); + DrawMenu( (u16)s_langCode, &langSel ); + + // [CANCEL]{^`FbN + if( tpd.disp.touch ) { + tp_cancel = WithinRangeTP( CANCEL_BUTTON_TOP_X, CANCEL_BUTTON_TOP_Y, + CANCEL_BUTTON_BOTTOM_X, CANCEL_BUTTON_BOTTOM_Y, &tpd.disp ); + } + + if( ( pad.trg & PAD_BUTTON_A ) || tp_select ) { // j[ڂւ̕ + GetSYSMWork()->ncd_invalid = 0; + GetNCDWork()->option.input_language = 1; // ̓tO𗧂Ă + GetNCDWork()->option.language = s_langCode; + // :::::::::::::::::::::::::::::::::::::::::::::: + // NVRAMւ̏ + // :::::::::::::::::::::::::::::::::::::::::::::: + (void)NVRAMm_WriteNitroConfigData( GetNCDWork() ); + MachineSettingInit(); + return 0; + }else if( ( pad.trg & PAD_BUTTON_B ) || tp_cancel ) { + MachineSettingInit(); + return 0; + } + + return 0; +} + + diff --git a/build/systemMenu_RED/MachineSettings/ARM9/src/setOwnerInfo.c b/build/systemMenu_RED/MachineSettings/ARM9/src/setOwnerInfo.c new file mode 100644 index 0000000..20f9457 --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/src/setOwnerInfo.c @@ -0,0 +1,1077 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: ownerInfo.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include "misc.h" +#include "DS_Setting.h" +#include "myFontequ.h" + +/* + + jbNl[́ASJISŕۑĂ܂ANVRAMɂ͊eR[hHi/Lot]`Ŋi[Ă܂B + +*/ + +// define data---------------------------------- + +#define OWNER_INFO_ELEM_NUM 3 + + // RETURN{^LCD̈ +#define RETURN_BUTTON_LT_X 2 +#define RETURN_BUTTON_LT_Y 21 +#define RETURN_BUTTON_RB_X (RETURN_BUTTON_LT_X + 8) +#define RETURN_BUTTON_RB_Y (RETURN_BUTTON_LT_Y + 2) + + // I[i[J[\LCD̈ +#define OWNER_INFO_CSR_LT_X 2 +#define OWNER_INFO_CSR_LT_Y 5 +#define OWNER_INFO_CSR_NEXT_Y_NUM 3 + + // NJ[\LCD̈ +#define DAY_LT_X (OWNER_INFO_CSR_LT_X + 13) +#define DAY_LT_Y (OWNER_INFO_CSR_LT_Y + OWNER_INFO_CSR_NEXT_Y_NUM * 1) + + // DȐFJ[\LCD̈ +#define FCOLOR_LT_X (OWNER_INFO_CSR_LT_X + 13) +#define FCOLOR_LT_Y (OWNER_INFO_CSR_LT_Y + OWNER_INFO_CSR_NEXT_Y_NUM * 2) + + // \tgEFAL[{[hLCD̈ +#define CLIST_LT_X 4 +#define CLIST_LT_Y 7 +#define CLIST_RB_X (CLIST_LT_X + 24) +#define CLIST_RB_Y (CLIST_LT_Y + 12) + // {^擪LCD̈ +#define BUTTON_TOP_LT_X (CLIST_LT_X + 18) +#define BUTTON_TOP_LT_Y (CLIST_LT_Y + 2) +#define BUTTON_TOP_RB_X (BUTTON_TOP_LT_X + 8) +#define BUTTON_TOP_RB_Y (BUTTON_TOP_LT_Y + 2) + // ̓l[LCD̈ +#define INPUT_NAME_LT_X 11 +#define INPUT_NAME_LT_Y 3 + // LN^R[h +#define CHAR_MODE_HKANA 0 +#define CHAR_MODE_KKANA 1 +#define CHAR_MODE_EISUU 2 +#define CHAR_MODE_MAX CHAR_MODE_EISUU + + // jbNl[̓L +#define CHAR_USCORE 0x5181 // 'Q' (0x8151)t]́B + +#define CHAR_LIST_CHAR_NUM 120 + + // jbNl[͍\ +typedef struct Nickname { + u8 input_flag; // ̓tO + u8 change_flag; // ύXtO + u8 length; // + u8 pad; + u16 str[NCD_NICKNAME_LENGTH + 1]; // jbNl[R[h +}Nickname; + + // J[\X,YʒuiLPʁj +typedef struct CsrPos { + u16 x; // x + u16 y; // y +}CsrPos; + + // a +typedef struct Birthday { + int year; // N(1900-2099) + int month; // (1-12) + int day; // (1-31) +}Birthday; + + // vtB[ҏW[N +typedef struct OwnerWork { + u16 sel; + Nickname nickname; // jbNl[ + Birthday birthday; // N + int favoriteColor; // DȐF + + // [U[J[N̓[N + int seq; // V[PXԍ + int *tgtp; // ̓^[Qbgւ̃|C^ + InputNumParam inp; // l͊֐InputDecimalpp[^ + + // jbNl[̓[N + u16 char_mode; // ̓LN^[hiȁAJiApj + u16 rsv; // \CsrPos̃ACĝ߂̃pfBO + CsrPos tpcsr; // TPɂĎZoJ[\ʒu + CsrPos csr_now; // ݂̃J[\ʒuiL[TP̗ZoLȒlj + CsrPos csr_old; // Ot[̃J[\ʒu + u16 detach_count; // TPLȃJ[\ʒu痣ẴJEgl + u16 touch_count; // TPLȃJ[\ʒuŃ^b`ĂԂ̃JEgl + u16 handleTbl[CHAR_LIST_CHAR_NUM]; // LN^Xgpnhi[z +}OwnerWork; + +// extern data---------------------------------- + + +// function's prototype------------------------- +void SEQ_OwnerInfo_init(void); +int SEQ_OwnerInfo(void); + +static void SEQ_InputBirthday_init(void); +static int SEQ_InputBirthday(void); +static void SEQ_InputFavoriteColor_init(void); +static int SEQ_InputFavoriteColor(void); +static void DrawBirthday(u16 x, u16 y, u16 color, NvDate *birthp); +static void SEQ_InputNickname_init(void); +static int SEQ_InputNickname(void); +static void ReturnMenu(int save_flag); +static u16 CalcTblIndex(CsrPos *csrp); +static void DeleteName1Char(void); +static void MoveCharCursor(int force_flag); +static BOOL MoveCharCursorTp(CsrPos *csrp); +static void DrawTargetCsrChar(CsrPos *csrp, u16 color); +static void DrawCharacterList(void); +static void SetSoftKeyboardButton(u16 char_mode); +static void SJISCodeExchangeCopy(u16 *srcp, u16 *dstp, u16 length); + +// static variable------------------------------ +static OwnerWork *ow; + +// const data----------------------------------- +static const u16 char_tbl[3][CHAR_LIST_CHAR_NUM]; + +static const u8 *const str_ownerInfoSel[] ATTRIBUTE_ALIGN(2) = { + (const u8 *)"NICKNAME ", + (const u8 *)"BIRTHDAY ", + (const u8 *)"USER COLOR", +}; + +const MenuComponent ownerInfoSel={ + OWNER_INFO_ELEM_NUM, + OWNER_INFO_CSR_LT_X, + OWNER_INFO_CSR_LT_Y, + 0, + OWNER_INFO_CSR_NEXT_Y_NUM, + 23, + WHITE, + HIGHLIGHT_Y, + (const u8 **)&str_ownerInfoSel, +}; + +static const u8 str_button_hkana[] ATTRIBUTE_ALIGN(2) = " "; +static const u8 str_button_kkana[] ATTRIBUTE_ALIGN(2) = " Ji "; +static const u8 str_button_eisuu[] ATTRIBUTE_ALIGN(2) = " ABC "; +static const u8 str_button_del[] ATTRIBUTE_ALIGN(2) = " DEL "; +static const u8 str_button_cancel[] ATTRIBUTE_ALIGN(2) = "CANCEL"; +static const u8 str_button_ok[] ATTRIBUTE_ALIGN(2) = " OK "; +static const u16 *str_button[] = { NULL, + NULL, + (const u16 *)str_button_del, + (const u16 *)str_button_cancel, + (const u16 *)str_button_ok, + }; +//static const u16 str_uscore[] = { uscore_, uscore_, uscore_, uscore_, uscore_, uscore_, uscore_, uscore_, EOM_}; + +//====================================================== +// I[i[ҏW +//====================================================== + +// I[i[ҏW̏ +void SEQ_OwnerInfo_init(void) +{ + u16 x,y; + u16 temp[NCD_NICKNAME_LENGTH + 1]; + + GXS_SetVisiblePlane(GX_PLANEMASK_NONE); + + MI_CpuClearFast(bgBakS,sizeof(bgBakS)); + SVC_CpuClearFast(0xc0, oamBakS, sizeof(oamBakS)); + + ClearAllStringSJIS(); + + (void)DrawStringSJIS( 1, 0, YELLOW, (const u8 *)"USER INFO SET"); + (void)DrawStringSJIS( RETURN_BUTTON_LT_X, RETURN_BUTTON_LT_Y,HIGHLIGHT_C, (const u8 *)" RETURN "); + + if(ow == NULL) { + ow = NNS_FndAllocFromAllocator( &g_allocator, sizeof(OwnerWork) ); // I[i[ҏWp[N̊m +#ifdef __SYSM_DEBUG + if(ow == NULL) OS_Panic("ARM9- Fail to allocate memory...\n"); +#endif /* __SYSM_DEBUG */ + OS_Printf("Alloc :OwnerWork\n"); + SVC_CpuClear(0x0000, ow, sizeof(OwnerWork), 16); + } + + // I[i[̃`FbN + { + u32 dayNum; + + if(GetNCDWork()->owner.nickname.length > NCD_NICKNAME_LENGTH) { + GetNCDWork()->owner.nickname.length = 0; + SVC_CpuClear(0x0000, GetNCDWork()->owner.nickname.str, NCD_NICKNAME_LENGTH * 2, 16); + } + if((GetNCDWork()->owner.birthday.month == 0) || (GetNCDWork()->owner.birthday.month > 12)) { + GetNCDWork()->owner.birthday.month = 1; + } + dayNum = SYSM_GetDayNum( 0, (u32)GetNCDWork()->owner.birthday.month ); + if((GetNCDWork()->owner.birthday.day == 0) || (GetNCDWork()->owner.birthday.day > dayNum)) { + GetNCDWork()->owner.birthday.day = 1; + } + if( GetNCDWork()->owner.favoriteColor >= NCD_FAVORITE_COLOR_MAX_NUM ) { + GetNCDWork()->owner.favoriteColor = 0; + } + } + + // I[i[̕\ + x = (u16)(ownerInfoSel.pos_x+13); + y = (u16)ownerInfoSel.pos_y; + SVC_CpuClear(0x0000, temp, sizeof(temp), 16); + ExUTF16_LEtoSJIS_BE( (u8 *)temp, GetNCDWork()->owner.nickname.str, GetNCDWork()->owner.nickname.length); + (void)DrawStringSJIS ( x, y, LIGHTGREEN, temp); + DrawBirthday ( x, (u16)(y + OWNER_INFO_CSR_NEXT_Y_NUM * 1), LIGHTGREEN, &GetNCDWork()->owner.birthday); + ow->favoriteColor = GetNCDWork()->owner.favoriteColor; + (void)DrawDecimalSJIS( x, (u16)(y + OWNER_INFO_CSR_NEXT_Y_NUM * 2), LIGHTGREEN, &ow->favoriteColor, 2, 1); + + DrawMenu(ow->sel, &ownerInfoSel); + SVC_CpuClear(0x0000, &tpd, sizeof(TpWork), 16); + + GXS_SetVisiblePlane(GX_PLANEMASK_OBJ | GX_PLANEMASK_BG1); +} + + +// I[i[ҏW +int SEQ_OwnerInfo(void) +{ + BOOL tp_select; + BOOL tp_return = FALSE; + + ReadTP(); // ^b`pl͂̎擾 + + if(tpd.disp.touch) { // [RETURN]{^`FbN + tp_return = WithinRangeTP(RETURN_BUTTON_LT_X*8, RETURN_BUTTON_LT_Y*8-4, + RETURN_BUTTON_RB_X*8, RETURN_BUTTON_RB_Y*8-4, &tpd.disp); + } + + // I[i[̏NV[PX + if(g_initialSet) { + + pad.trg = 0; + + if(GetNCDWork()->option.input_nickname == 0) { + ow->sel = 0; + pad.trg |= PAD_BUTTON_A; + }else if(GetNCDWork()->option.input_favoriteColor == 0) { + ow->sel = 2; + pad.trg |= PAD_BUTTON_A; + }else if(GetNCDWork()->option.input_birthday == 0) { + ow->sel = 1; + pad.trg |= PAD_BUTTON_A; + }else if ( GetNCDWork()->option.input_nickname + || GetNCDWork()->option.input_favoriteColor + || GetNCDWork()->option.input_birthday ) { + pad.trg |= PAD_BUTTON_B; // j[ɖ߂炷 + } + } + + //-------------------------------------- + // L[͏ + //-------------------------------------- + if(pad.trg & PAD_KEY_DOWN){ // J[\̈ړ + if(++ow->sel == OWNER_INFO_ELEM_NUM) ow->sel= 0; + } + if(pad.trg & PAD_KEY_UP){ + if(--ow->sel & 0x80) ow->sel = OWNER_INFO_ELEM_NUM - 1; + } + tp_select=SelectMenuByTp(&ow->sel, &ownerInfoSel); + DrawMenu(ow->sel, &ownerInfoSel); + + if((pad.trg & PAD_BUTTON_A) || (tp_select)) { // j[ڂւ̕ + + mf_clearRect( RETURN_BUTTON_LT_X, RETURN_BUTTON_LT_Y, 2, 8); + DrawOKCancelButton(); + + switch(ow->sel) { + case 0: + SEQ_InputNickname_init(); + g_pNowProcess = SEQ_InputNickname; + break; + case 1: + SEQ_InputBirthday_init(); + g_pNowProcess = SEQ_InputBirthday; + break; + case 2: + SEQ_InputFavoriteColor_init(); + g_pNowProcess = SEQ_InputFavoriteColor; + break; + } + }else if((pad.trg & PAD_BUTTON_B) || (tp_return)) { // j[ɖ߂ + NNS_FndFreeToAllocator( &g_allocator, ow ); // [N̉ + ow = NULL; + OS_Printf("Free :OwnerWork\n"); + SEQ_MainMenu_init(); + } + + return 0; +} + + +//====================================================== +// N +//====================================================== + +// N͂̏ +static void SEQ_InputBirthday_init(void) +{ + // N̕\ + DrawBirthday((u16)(ownerInfoSel.pos_x + 13), (u16)(ownerInfoSel.pos_y + OWNER_INFO_CSR_NEXT_Y_NUM * 1), WHITE, &GetNCDWork()->owner.birthday); + // Ñ[h + ow->birthday.month = (int)GetNCDWork()->owner.birthday.month; + ow->birthday.day = (int)GetNCDWork()->owner.birthday.day; + SVC_CpuClear(0x0000, &tpd, sizeof(TpWork), 16); + ow->seq = 0; +} + + +// N +static int SEQ_InputBirthday(void) +{ + BOOL tp_ok = FALSE; + BOOL tp_cancel = FALSE; + int x_base, y_base, abs_y_offset, new_seq; + + enum { // t̓V[PXԍ + SEQ_INIT = 0, + SEQ_MONTH_INIT = 2, SEQ_MONTH_SET, + SEQ_DAY_INIT, SEQ_DAY_SET, + SEQ_END, + SEQ_RETURN=64 + }; + + + ReadTP(); // ^b`pl͂̎擾 + + ow->inp.y_offset = 0; + + CheckOKCancelButton(&tp_ok, &tp_cancel); + + if(tpd.disp.touch) { // [CANCEL]{^`FbN + if((ow->seq & 0x01) && (ow->seq < SEQ_END)) { // SEQ_**_SET̎̂ݗL + new_seq = ow->seq; + x_base = (ownerInfoSel.pos_x + 13) * 8; + y_base = (ownerInfoSel.pos_y + OWNER_INFO_CSR_NEXT_Y_NUM * 1) * 8 + 6; + // ͍ڈړ̃`FbN + if( WithinRangeTP( x_base, (y_base - 6), (x_base + 80), (y_base + 6), &tpd.disp) ) { + if(tpd.disp.x < x_base + 2 * 8) { + new_seq = SEQ_MONTH_SET; + }else if((tpd.disp.x >= x_base + 3 * 8) && (tpd.disp.x < x_base + 5 * 8)) { + new_seq = SEQ_DAY_SET; + }else if(tpd.disp.x >= x_base + 7 * 8) { + } + } + if(ow->seq != new_seq) { + ow->seq = new_seq - 1; + }else { + // ͒l̑ + if(WithinRangeTP( ow->inp.pos_x * 8, (y_base - 30), (ow->inp.pos_x + ow->inp.keta_max) * 8, (y_base + 30), &tpd.disp)) { + ow->inp.y_offset = tpd.disp.y - y_base; + abs_y_offset = (ow->inp.y_offset >= 0) ? ow->inp.y_offset : -ow->inp.y_offset; + if(abs_y_offset <= 6) { + ow->inp.y_offset = 0; + }else if(abs_y_offset <= 14){ + ow->inp.y_offset >>= 2; + }else if(abs_y_offset <= 22){ + ow->inp.y_offset >>= 1; + } + } + } + } + } + + // ^b`pl or L[͂ɂāAJ[\ʒuɁÄʒũJ[\B + if((ow->seq > 0) && ((ow->seq & 0x01) == 0)) { // SEQ_INIT͎̎sȂ + (void)DrawDecimalSJIS( ow->inp.pos_x, ow->inp.pos_y, WHITE, ow->tgtp, (u8)ow->inp.keta_max, 4); + } + + // eV[PXɂ鏈 + switch(ow->seq){ + case SEQ_INIT: + ow->seq = SEQ_MONTH_INIT; + // ̂܂SEQ_MONTH_INIT + + case SEQ_MONTH_INIT: + ow->inp.pos_x = DAY_LT_X; + ow->inp.pos_y = DAY_LT_Y; + ow->inp.keta_max = 2; + ow->inp.value_max = 12; + ow->inp.value_min = 1; + ow->inp.y_offset = 0; + ow->tgtp = (int *)&ow->birthday.month; + break; + + case SEQ_DAY_INIT: + ow->inp.pos_x = DAY_LT_X + 3; + ow->inp.keta_max = 2; + ow->inp.value_min = 1; + ow->inp.value_max = (int)SYSM_GetDayNum( 0, (u32)ow->birthday.month ); + // NEƂɂ̌̓ZoB + if(ow->birthday.day > ow->inp.value_max) { + ow->birthday.day = ow->inp.value_max; + } + ow->inp.y_offset = 0; + ow->tgtp = (int *)&ow->birthday.day; + break; + + case SEQ_MONTH_SET: + case SEQ_DAY_SET: + InputDecimal(ow->tgtp, &ow->inp); + + // ͂Ȃ΁AZoāA݂͓̓𒴂ĂCB + if(ow->seq == SEQ_MONTH_SET) { + u32 dayNum = SYSM_GetDayNum( 0, (u32)ow->birthday.month ); + if( dayNum < ow->birthday.day) { + ow->birthday.day = (u8)dayNum; + (void)DrawDecimalSJIS( DAY_LT_X + 3, DAY_LT_Y, WHITE, &ow->birthday.day, 2, 4); + } + } + break; + + case SEQ_END: + GetNCDWork()->owner.birthday.month = (u8 )ow->birthday.month; + GetNCDWork()->owner.birthday.day = (u8 )ow->birthday.day; + GetNCDWork()->option.input_birthday = 1; + GetSYSMWork()->ncd_invalid = 0; + + if ( GetNCDWork()->option.destroyFlashFlag ) { + GetNCDWork()->option.destroyFlashFlag = 0; + } + // :::::::::::::::::::::::::::::::::::::::::::::: + // NVRAMւ̏ + // :::::::::::::::::::::::::::::::::::::::::::::: + (void)NVRAMm_WriteNitroConfigData (GetNCDWork()); + + // SEQ_END̎͂̂܂܃^[B + + case SEQ_RETURN: + SEQ_OwnerInfo_init(); + g_pNowProcess = SEQ_OwnerInfo; + return 0; + } + + if(ow->seq & 0x01) { // SEQ_**_SET̎̂ݗL + if((pad.trg & PAD_BUTTON_A) || (tp_ok)) { + ow->seq = SEQ_END; // A{^Ō + }else if((pad.trg & PAD_BUTTON_B) || (tp_cancel)) { // B{^ŃLZ + ow->seq = SEQ_RETURN; + }else if(pad.trg & PAD_KEY_LEFT) { + if(ow->seq == SEQ_MONTH_SET) ow->seq = SEQ_DAY_INIT; + else ow->seq -= 3; + }else if(pad.trg & PAD_KEY_RIGHT) { + if(ow->seq == SEQ_DAY_SET) ow->seq = SEQ_MONTH_INIT; + else ow->seq++; + } + }else { // SEQ_**_INIT̎̂ݗL + ow->seq++; + } + return 0; +} + + +// N̕` +static void DrawBirthday(u16 x, u16 y, u16 color, NvDate *birthp) +{ + (void)DrawStringSJIS ( (u16)(x + 2), y, color, (const u8 *)"/"); + (void)DrawDecimalSJIS( x, y, color, &birthp->month, 2, 1); + (void)DrawDecimalSJIS( (u16)(x + 3), y, color, &birthp->day, 2, 1); +} + + +//====================================================== +// DȐF +//====================================================== + +// DȐF͂̏ +static void SEQ_InputFavoriteColor_init(void) +{ + // DȐF̃[h + ow->favoriteColor = (int)GetNCDWork()->owner.favoriteColor; + // DȐF̕\ + SVC_CpuClear(0x0000, &tpd, sizeof(TpWork), 16); + ow->seq = 0; + + if( g_initialSet ) { + (void)DrawStringSJIS( 8, 18, RED, (const u8 *)"Select user color."); + } +} + + +// DȐF +static int SEQ_InputFavoriteColor(void) +{ + BOOL tp_ok = FALSE; + BOOL tp_cancel = FALSE; + int x_base, y_base, abs_y_offset, new_seq; + + enum { // t̓V[PXԍ + SEQ_INIT = 0, SEQ_SET, + SEQ_END, + SEQ_RETURN=64 + }; + + + ReadTP(); // ^b`pl͂̎擾 + + ow->inp.y_offset = 0; + + CheckOKCancelButton(&tp_ok, &tp_cancel); + + if(tpd.disp.touch) { // [CANCEL]{^`FbN + if((ow->seq & 0x01) && (ow->seq < SEQ_END)) { // SEQ_**_SET̎̂ݗL + new_seq = ow->seq; + x_base = FCOLOR_LT_X * 8; + y_base = FCOLOR_LT_Y * 8 + 6; + // ͒l̑ + if(WithinRangeTP( ow->inp.pos_x * 8, (y_base - 30), (ow->inp.pos_x + ow->inp.keta_max) * 8, (y_base + 30), &tpd.disp)) { + ow->inp.y_offset = tpd.disp.y - y_base; + abs_y_offset = (ow->inp.y_offset >= 0) ? ow->inp.y_offset : -ow->inp.y_offset; + if(abs_y_offset <= 6) { + ow->inp.y_offset = 0; + }else if(abs_y_offset <= 14){ + ow->inp.y_offset >>= 2; + }else if(abs_y_offset <= 22){ + ow->inp.y_offset >>= 1; + } + } + } + } + + // eV[PXɂ鏈 + switch(ow->seq){ + case SEQ_INIT: + ow->inp.pos_x = FCOLOR_LT_X; + ow->inp.pos_y = FCOLOR_LT_Y; + ow->inp.keta_max = 2; + ow->inp.value_max = NCD_FAVORITE_COLOR_MAX_NUM - 1; + ow->inp.value_min = 0; + ow->inp.y_offset = 0; + ow->tgtp = (int *)&ow->favoriteColor; + break; + + case SEQ_SET: + InputDecimal(ow->tgtp, &ow->inp); + break; + + case SEQ_END: + GetNCDWork()->option.input_favoriteColor = 1; + GetNCDWork()->owner.favoriteColor = (u8 )ow->favoriteColor; + GetSYSMWork()->ncd_invalid = 0; + + // :::::::::::::::::::::::::::::::::::::::::::::: + // NVRAMւ̏ + // :::::::::::::::::::::::::::::::::::::::::::::: + (void)NVRAMm_WriteNitroConfigData (GetNCDWork()); + + // SEQ_END̎͂̂܂܃^[B + + case SEQ_RETURN: + SEQ_OwnerInfo_init(); + g_pNowProcess = SEQ_OwnerInfo; + return 0; + } + + if(ow->seq & 0x01) { // SEQ_**_SET̎̂ݗL + if((pad.trg & PAD_BUTTON_A) || (tp_ok)) { + ow->seq = SEQ_END; // A{^Ō + }else if((pad.trg & PAD_BUTTON_B) || (tp_cancel)) { // B{^ŃLZ + ow->seq = SEQ_RETURN; + } + }else { // SEQ_**_INIT̎̂ݗL + ow->seq++; + } + return 0; +} + + +//====================================================== +// jbNl[̓ +//====================================================== + +// jbNl[͂̏ +static void SEQ_InputNickname_init(void) +{ + GXS_SetVisiblePlane(GX_PLANEMASK_NONE); + + MI_CpuClearFast(bgBakS, sizeof(bgBakS)); + + ClearAllStringSJIS(); + + (void)DrawStringSJIS( 1, 0, YELLOW, (const u8 *)"INPUT NICKNAME"); +// (void)DrawStringSJIS( INPUT_NAME_LT_Y, WHITE, (const u16 *)str_uscore); + if( g_initialSet ) { + (void)DrawStringSJIS( 8, 20, RED, (const u8 *)"Input nickname."); + } + + // jbNl[UTF16SJISɕϊăRs[ + SVC_CpuClear(CHAR_USCORE, ow->nickname.str, NCD_NICKNAME_LENGTH * 2, 16); + if(GetSYSMWork()->ncd_invalid == 0) { + ExUTF16_LEtoSJIS_BE( (u8 *)ow->nickname.str, GetNCDWork()->owner.nickname.str, GetNCDWork()->owner.nickname.length); + ow->nickname.length = GetNCDWork()->owner.nickname.length; + ow->nickname.input_flag = 1; + } + ow->nickname.change_flag = 0; + (void)DrawStringSJIS( INPUT_NAME_LT_X, INPUT_NAME_LT_Y, WHITE, (const u16 *)ow->nickname.str); + + ow->char_mode = CHAR_MODE_HKANA; // uЂ炪ȁv͂Zbg + SetSoftKeyboardButton(ow->char_mode); // {^̃Zbg + ow->detach_count = 0; + ow->touch_count = 0; + ow->tpcsr.x = 0; + ow->tpcsr.y = 0; + ow->csr_now.x = 0; + ow->csr_now.y = 0; + ow->csr_now.x = 15; + ow->csr_now.y = 5; + DrawCharacterList(); // ̓Lꗗ̕` + MoveCharCursor(1); // J[\\ + + SVC_CpuClear(0x0000, &tpd, sizeof(TpWork), 16); + + GXS_SetVisiblePlane(GX_PLANEMASK_BG1); +} + + +// jbNl[̓ +static int SEQ_InputNickname(void) +{ + BOOL tp_input = FALSE; + u16 tbl_index, charCode; + const u16 *char_listp; + + ow->csr_old = ow->csr_now; // Ot[̃J[\ʒuۑ + + ReadTP(); // ^b`pl͂̎擾 + + tp_input = MoveCharCursorTp(&ow->csr_now); // TP͂ɂJ[\ړ + + // J[\ړ + char_listp = char_tbl[ow->char_mode]; + if(pad.trg & PAD_KEY_UP) { + while(1) { + if(--ow->csr_now.y & 0x8000) ow->csr_now.y = 5; + tbl_index = CalcTblIndex(&ow->csr_now); + if(char_listp[tbl_index]) { + break; + }else if(ow->csr_now.x > 15) { + ow->csr_now.x = 15; + ow->csr_now.y = 6; // ̃[v-15ɂȂB + } + } + }else if(pad.trg & PAD_KEY_DOWN) { + while(1) { + if(++ow->csr_now.y > 5) ow->csr_now.y = 0; + tbl_index = CalcTblIndex(&ow->csr_now); + if(char_listp[tbl_index]) { + break; + }else if(ow->csr_now.x > 15) { + ow->csr_now.x--; + ow->csr_now.y--; + } + } + } + + if(pad.trg & PAD_KEY_LEFT) { + while(1) { + if(--ow->csr_now.x & 0x8000) ow->csr_now.x = 18; + tbl_index = CalcTblIndex(&ow->csr_now); + if(char_listp[tbl_index]) { + break; + } + } + }else if(pad.trg & PAD_KEY_RIGHT) { + while(1) { + if(++ow->csr_now.x > 18) ow->csr_now.x = 0; + tbl_index = CalcTblIndex(&ow->csr_now); + if(char_listp[tbl_index]) { + break; + } + } + } + + if(pad.trg & PAD_BUTTON_START) { + ow->csr_now.x = 15; + ow->csr_now.y = 5; + } + + // ͕؂ւ + if(pad.trg & (PAD_BUTTON_R | PAD_BUTTON_L)) { + if(pad.trg & PAD_BUTTON_R) { + if(++ow->char_mode > CHAR_MODE_MAX) ow->char_mode = 0; + }else { + if(--ow->char_mode & 0x8000) ow->char_mode = CHAR_MODE_MAX; + } + SetSoftKeyboardButton(ow->char_mode); + while(1) { + tbl_index = CalcTblIndex(&ow->csr_now); + if(char_tbl[ow->char_mode][tbl_index]) { + break; + } + ow->csr_now.x--; + } + DrawCharacterList(); + } + + charCode = (u16)char_listp[CalcTblIndex(&ow->csr_now)]; + MoveCharCursor(0); + + if((pad.trg & PAD_BUTTON_A)||(tp_input)) { + // E[R}h + if((charCode == VAR_BUTTON1_)||(charCode == VAR_BUTTON2_)) {// ͕؂ւ + ow->char_mode = (u16)(ow->char_mode + 1 + charCode - CODE_BUTTON_TOP_); + if(ow->char_mode > CHAR_MODE_MAX) ow->char_mode -= CHAR_MODE_MAX+1; + SetSoftKeyboardButton(ow->char_mode); + DrawCharacterList(); + }else if(charCode == OK_BUTTON_) { // + ReturnMenu(1); + }else if(charCode == CANCEL_BUTTON_){ // LZ + ReturnMenu(0); + }else if(charCode == DEL_BUTTON_) { // P폜 + DeleteName1Char(); + }else { + if(ow->nickname.length < NCD_NICKNAME_LENGTH) { // ꕶ + ow->nickname.str[ow->nickname.length] = (u16)((charCode >> 8) | (charCode << 8)); + // SJISASCIIڕ̍ۂɂ𔻕ʂł悤ASJISHi,LȍŊi[B + ow->nickname.length++; + ow->nickname.change_flag = 1; + (void)DrawStringSJIS( INPUT_NAME_LT_X, INPUT_NAME_LT_Y, WHITE, ow->nickname.str); + } + } + }else if(pad.trg & PAD_BUTTON_B) { + if(!( (charCode >= CODE_BUTTON_TOP_)&&(charCode < CODE_BUTTON_BOTTOM_) )) { + DeleteName1Char(); // P폜 + }else if(charCode == OK_BUTTON_) { + ReturnMenu(0); // [OK]{^B{^Ȃ烊^[ + } + } + + return 0; +} + + +// Cj[ɖ߂ +static void ReturnMenu(int save_flag) +{ + int i; + + if((save_flag)&&(ow->nickname.change_flag)) { + GetSYSMWork()->ncd_invalid = 0; + GetNCDWork()->option.input_nickname = 1; // jbNl[̓tO𗧂ĂB + + ExSJIS_BEtoUTF16_LE( (u8 *)ow->nickname.str, GetNCDWork()->owner.nickname.str, ow->nickname.length); + // ͂ꂽl[SJISUTF16֕ϊB + GetNCDWork()->owner.nickname.length = ow->nickname.length; + for(i = ow->nickname.length; i < NCD_NICKNAME_LENGTH; i++) {// ͂ꂽOȍ~0x0000Ŗ߂B + GetNCDWork()->owner.nickname.str[i] = 0x0000; + } + // :::::::::::::::::::::::::::::::::::::::::::::: + // NVRAMւ̏ + // :::::::::::::::::::::::::::::::::::::::::::::: + (void)NVRAMm_WriteNitroConfigData(GetNCDWork()); + } + SEQ_OwnerInfo_init(); + g_pNowProcess = SEQ_OwnerInfo; // I[i[ҏWɖ߂ +} + +// P폜 +static void DeleteName1Char(void) +{ + if(ow->nickname.length == 0) return; + + ow->nickname.change_flag = 1; + ow->nickname.length--; + ow->nickname.str[ow->nickname.length] = CHAR_USCORE; + (void)DrawStringSJIS( INPUT_NAME_LT_X, INPUT_NAME_LT_Y, WHITE, ow->nickname.str); +} + + +// J[\ʒuΉLԍ擾 +static u16 CalcTblIndex(CsrPos *csrp) +{ + u16 tbl_index = 0; + u16 x_bak = csrp->x; + + while(x_bak >= 5) { + x_bak -= 5; + tbl_index += 30; + } + tbl_index += x_bak + (csrp->y * 5); + + return tbl_index; +} + + +// J[\ړ +static void MoveCharCursor(int force_flag) +{ + if((*(u32 *)&ow->csr_now != *(u32 *)&ow->csr_old) || (force_flag)) { + DrawTargetCsrChar(&ow->csr_old, WHITE); + DrawTargetCsrChar(&ow->csr_now, HIGHLIGHT_Y); + } +} + + +// J[\ʒũLN^` +static void DrawTargetCsrChar(CsrPos *csrp, u16 color) +{ + u16 index = CalcTblIndex(csrp); + u16 charCode = (u16)char_tbl[ ow->char_mode ][ index ]; + + if( (charCode >= CODE_BUTTON_TOP_) && (charCode < CODE_BUTTON_BOTTOM_) ) { + if(color == WHITE) { + color = HIGHLIGHT_C; + } + } + + if(ChangeColorSJIS(ow->handleTbl[ index ], color) == 0) { + OS_Printf("this handle is not found. %x\n", ow->handleTbl[ index ]); + } +} + + +// TPɂJ[\ړ +static BOOL MoveCharCursorTp(CsrPos *csrp) +{ + int x_bak; + BOOL active = FALSE; + CsrPos temp; + + if(ow->detach_count) { + if(tpd.disp.touch == 0) { + if(++ow->detach_count == TP_CSR_DETACH_COUNT) { + ow->detach_count = 0; + return TRUE; + }else { + return FALSE; + } + } + } + ow->detach_count = 0; + + if(tpd.disp.touch) { + if(WithinRangeTP(CLIST_LT_X*8, CLIST_LT_Y*8-4, CLIST_RB_X*8-1, CLIST_RB_Y*8-4, &tpd.disp)) { + // }[WB + temp.x = (u16)((tpd.disp.x - CLIST_LT_X * 8) / 8); + temp.y = (u16)((tpd.disp.y - (CLIST_LT_Y * 8)) / 16); + x_bak = temp.x; // TƂɂ󔒗̕␳ + while(x_bak >= 5) { + x_bak -= 6; + temp.x--; + } + + if(temp.y == 0) { // E[]̕␳ + if(temp.x > 18) temp.x = 18; + }else if(temp.x > 15) { + temp.x = 15; + } + if(*(u32 *)&temp == *(u32 *)&ow->tpcsr) { // TPJ[\ʒuOƓȂAJEgi߂āA + if(ow->touch_count < TP_CSR_TOUCH_COUNT) { // KlɒBLȈʒuƂB + ow->touch_count++; + }else { + csrp->x = temp.x; + csrp->y = temp.y; + } + return FALSE; + } + } + }else { // touch == 0 + if(ow->touch_count == TP_CSR_TOUCH_COUNT) { + ow->detach_count = 1; + } + } + ow->tpcsr.x = temp.x; + ow->tpcsr.y = temp.y; + ow->touch_count = 0; + return FALSE; +} + + +// ݂charmodẽLN^ꗗ` +static void DrawCharacterList(void) +{ + u16 i, j, k, x, y, index, button; + const u16 *code; + u16 str[2]; + + // LXg̍폜 + for( i = 0; i < CHAR_LIST_CHAR_NUM; i++ ) { + if( ow->handleTbl[ i ] ) { + ClearStringSJIS_handle( ow->handleTbl[ i ] ); + } + } + + // LN^Xg̕` + code = char_tbl[ow->char_mode]; + str[1] = 0x0000; + index = 0; + button = 0; + for(i = 0; i < 4; i++) { +// buffp = bgBakS + CLIST_LT_X + (CLIST_LT_Y << 5) + (6 * i); + for(j = 0; j < 6; j++) { + x = (u16)(CLIST_LT_X + (i * 6)); + y = (u16)(CLIST_LT_Y + (j * 2)); + for(k = 0; k < 5; k++) { + if(*code != EOM_) { + if( (*code >= CODE_BUTTON_TOP_) && (*code < CODE_BUTTON_BOTTOM_) ) { // {^ + ow->handleTbl[ index ] = DrawStringSJIS( x, y, HIGHLIGHT_C, str_button[ button++ ]); + }else { // LN^ + str[0] = (u16)( (*code >> 8) | ( *code << 8) ); + ow->handleTbl[ index ] = DrawStringSJISEx( x, y, WHITE, str, index ); + } + } + index++; + code++; + x++; + } + } + } + MoveCharCursor(1); +} + + +// \tgL[{[h̃{^ݒ +static void SetSoftKeyboardButton(u16 char_mode) +{ + if(char_mode == 0) { + str_button[0] = (const u16 *)str_button_kkana; // 1 + str_button[1] = (const u16 *)str_button_eisuu; // 2 + }else if(char_mode == 1) { + str_button[0] = (const u16 *)str_button_eisuu; // 2 + str_button[1] = (const u16 *)str_button_hkana; // 0 + }else { + str_button[0] = (const u16 *)str_button_hkana; // 0 + str_button[1] = (const u16 *)str_button_kkana; // 1 + } +} + + +// SJISR[hR[hHi/Lot]ȂRs[ +static void SJISCodeExchangeCopy(u16 *srcp, u16 *dstp, u16 length) +{ + while(length--) { + *dstp++ = (u16)( (*srcp >> 8) | (*srcp << 8) ); + srcp++; + } +} + + +//====================================================== +// jbNl[͗pLe[u +//====================================================== + +/* + SJIS𕶎萔ƂċLqꍇAȉ̂QʂŏʁEʃR[h̊i[ +@@@tɂȂĂ܂̂ŁAӂ邱ƁB + + u8 str[] = ""; 0x82,0xa0,0x82,0xa2...ƏʃR[hʃoCgɊi[B + u16 code = ''; 0xa0,0x82 ƏʁEʃR[ĥ܂܊i[B + +*/ + +static const u16 char_tbl[3][CHAR_LIST_CHAR_NUM] = { + { // Ђ炪 + '', '', '', '', '', + '', '', '', '', '', + '', '', '', '', '', + '', '', '', '', '', + '', '', '', '', '', + '', '', '', '', '', + + '', '', '', '', '', + '', '@', '', '@', '', + '', '', '', '', '', + '', '@', '', '@', '', + '', '', '', '', '', + '', '@', '', '@', '', + + '', '', '', '', '', + '', '', '', '', '', + '', '', '', '', '', + '', '', '', '', '', + '', '', '', '', '', + '', 'A', 'B', 'I', '[', + + 'u', 'v', '`', 'E', '@', + VAR_BUTTON1_, EOM_, EOM_, EOM_, EOM_, + VAR_BUTTON2_, EOM_, EOM_, EOM_, EOM_, + DEL_BUTTON_, EOM_, EOM_, EOM_, EOM_, + CANCEL_BUTTON_, EOM_, EOM_, EOM_, EOM_, + OK_BUTTON_, EOM_, EOM_, EOM_, EOM_, + }, + + { // J^Ji + 'A', 'C', 'E', 'G', 'I', + 'J', 'L', 'N', 'P', 'R', + 'T', 'V', 'X', 'Z', '\', + '^', '`', 'c', 'e', 'g', + 'i', 'j', 'k', 'l', 'm', + 'n', 'q', 't', 'w', 'z', + + '}', '~', '', '', '', + '', '@', '', '@', '', + '', '', '', '', '', + '', '@', '', '@', '', + '@', 'B', 'D', 'F', 'H', + '', '@', '', '@', '', + + 'K', 'M', 'O', 'Q', 'S', + 'U', 'W', 'Y', '[', ']', + '_', 'a', 'd', 'f', 'h', + 'o', 'r', 'u', 'x', '{', + 'p', 's', 'v', 'y', '|', + 'b', 'A', 'B', 'I', '[', + + 'u', 'v', '`', 'E', '@', + VAR_BUTTON1_, EOM_, EOM_, EOM_, EOM_, + VAR_BUTTON2_, EOM_, EOM_, EOM_, EOM_, + DEL_BUTTON_, EOM_, EOM_, EOM_, EOM_, + CANCEL_BUTTON_, EOM_, EOM_, EOM_, EOM_, + OK_BUTTON_, EOM_, EOM_, EOM_, EOM_, + }, + + { // p + '`', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', + 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', + 'y', '@', '@', '@', '@', + + '', '', '', '', '', + '', '', '', '', '', + '', '', '', '', '', + '', '', '', '', '', + '', '', '', '', '', + '', '@', '@', '@', '@', + + 'O', 'P', 'Q', 'R', 'S', + 'T', 'U', 'V', 'W', 'X', + 'I', '@', '', '@', '^', + 'C', '@', 'D', '@', '|', + 'f', '@', 'h', '@', '@', + '', '@', 'i', '@', 'j', + + EOM_, EOM_, EOM_, EOM_, EOM_, + VAR_BUTTON1_, EOM_, EOM_, EOM_, EOM_, + VAR_BUTTON2_, EOM_, EOM_, EOM_, EOM_, + DEL_BUTTON_, EOM_, EOM_, EOM_, EOM_, + CANCEL_BUTTON_, EOM_, EOM_, EOM_, EOM_, + OK_BUTTON_, EOM_, EOM_, EOM_, EOM_, + }, +}; + diff --git a/build/systemMenu_RED/MachineSettings/ARM9/src/setRTC.c b/build/systemMenu_RED/MachineSettings/ARM9/src/setRTC.c new file mode 100644 index 0000000..3c6ffe3 --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/ARM9/src/setRTC.c @@ -0,0 +1,557 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: setRTC.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "misc.h" +#include "MachineSetting.h" + +// define data------------------------------------------ + +//#define __RTC_MINUTE_OFFSET // ̒`LȏꍇrtcOffset͕ItZbgŎZo܂B܂Aȏꍇ͕bItZbgƂȂ܂B + + // RETURN{^LCD̈ +#define RETURN_BUTTON_TOP_X ( 2 * 8 ) +#define RETURN_BUTTON_TOP_Y ( 21 * 8 ) +#define RETURN_BUTTON_BOTTOM_X ( RETURN_BUTTON_TOP_X + 6 * 8 ) +#define RETURN_BUTTON_BOTTOM_Y ( RETURN_BUTTON_TOP_Y + 2 * 8 ) + + // tf[^LCD̈ +#define DATE_TOP_Y ( 10 * 8 ) +#define YEAR_TOP_X ( 5 * 8 ) +#define MONTH_TOP_X ( YEAR_TOP_X + 5 * 8 ) +#define DAY_TOP_X ( MONTH_TOP_X + 3 * 8 ) + + // f[^LCD̈ +#define TIME_TOP_Y ( DATE_TOP_Y ) +#define HOUR_TOP_X ( DAY_TOP_X + 5 * 8 ) +#define MINUTE_TOP_X ( HOUR_TOP_X + 3 * 8 ) +#define SECOND_TOP_X ( MINUTE_TOP_X + 3 * 8 ) + + // ̓^b`plpJE^ +#define S_UPDOWN_COUNT_MAX 16 + // l̓^b`plpJE^ +#define D_DOWN_COUNT_MAX -50 +#define D_UP_COUNT_MAX 50 + + + // t̓V[PXp[N +typedef struct DateTimeParam { + int seq; // V[PXԍ + int *pTgt; // ͑Ώۂ̕ϐւ̃|C^ + RTCDate Date; + RTCTime Time; + RTCDate Date_old; + RTCTime Time_old; +}DateTimeParam; + + + // RTCݒV[PXp[N +typedef struct SetRtcWork { + int csr; // J[\ʒu + s64 rtcOffset[ 2 ]; // RTCItZbgli[0]:ݒύXO̒lA[1]:ύX̒lj + DateTimeParam dtp; // t̓V[PXp[N + InputNumParam inp; // l̓C^[tF[Xp[N +}SetRtcWork; + + +typedef struct DateTimeWidth { + int year; + int month; + int day; + int hour; + int minute; + int second; +}DateTimeWidth; + +// extern data------------------------------------------ + +// function's prototype declaration--------------------- +RTCWeek CalcWeekFromDate( u32 year, u32 month, u32 day ); +void InputDecimal(int *pTgt, InputNumParam *inpp); + +static void InputRtcDateTimeInit( int start ); +static int InputRtcDateTimeMain( void ); + +static void TransmitRtcData(DateTimeParam *dtpp, RtcDateTime *rtcp); +static void SelectString( int *pTgt, const u8 **const pStrp, InputNumParam *inpp); +static void BcdToHex(int *bcdp); +static void HexToBcd(int *hexp); +static BOOL CheckLeapYear( u32 year ); +static void DrawDateTime( RTCDate *pDate, RTCTime *pTime, int color ); + +// global variable ------------------------------------- + +// static variable ------------------------------------- +static SetRtcWork *s_pWork; // RTCݒp[N +// const data ----------------------------------------- + +//====================================================== +// tݒ +//====================================================== + +// RTCݒV[PX̏ +void SetRTCInit( void ) +{ + GX_DispOff(); + GXS_DispOff(); + NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_WHITE ); + + PutStringUTF16( 0, 0, TXT_COLOR_BLUE, (const u16 *)L"DATE & TIME SET" ); + PutStringUTF16( RETURN_BUTTON_TOP_X, RETURN_BUTTON_TOP_Y, TXT_COLOR_CYAN, (const u16 *)L" RETURN " ); + + if( g_initialSet ) { + if( GetSYSMWork()->rtcStatus & 0x01) { + PutStringUTF16( 8 * 8, 18 * 8, TXT_COLOR_RED, (const u16 *)L"RTC reset is detected!" ); + }else { + PutStringUTF16( 8 * 8, 18 * 8, TXT_COLOR_RED, (const u16 *)L"Set RTC." ); + } + } + + s_pWork = NNS_FndAllocFromAllocator( &g_allocator, sizeof(SetRtcWork) ); // RTCݒp[N̊m + if( s_pWork == NULL ) { + OS_Panic( "ARM9- Fail to allocate memory...\n" ); + } + + SVC_CpuClear( 0x0000, s_pWork, sizeof(SetRtcWork), 16 ); + SVC_CpuClear( 0x0000, &tpd, sizeof(TpWork), 16 ); + + RTC_GetDateTime( &s_pWork->dtp.Date, &s_pWork->dtp.Time ); + s_pWork->dtp.Date.year += 2000; + + PrintfSJIS ( YEAR_TOP_X, DATE_TOP_Y, TXT_COLOR_BLACK, "%04d", s_pWork->dtp.Date.year ); + PrintfSJIS ( MONTH_TOP_X, DATE_TOP_Y, TXT_COLOR_BLACK, "%02d", s_pWork->dtp.Date.month ); + PrintfSJIS ( DAY_TOP_X, DATE_TOP_Y, TXT_COLOR_BLACK, "%02d", s_pWork->dtp.Date.day ); + PrintfSJIS ( HOUR_TOP_X, TIME_TOP_Y, TXT_COLOR_BLACK, "%02d", s_pWork->dtp.Time.hour ); + PrintfSJIS ( MINUTE_TOP_X, TIME_TOP_Y, TXT_COLOR_BLACK, "%02d", s_pWork->dtp.Time.minute ); + + DrawDateTime( &s_pWork->dtp.Date, &s_pWork->dtp.Time, TXT_COLOR_BLACK ); + + GX_SetVisiblePlane ( GX_PLANEMASK_BG0 ); + GXS_SetVisiblePlane( GX_PLANEMASK_BG0 ); + GX_DispOn(); + GXS_DispOn(); +} + + +// w肵tE̕\ +static void DrawDateTime( RTCDate *pDate, RTCTime *pTime, int color ) +{ + PrintfSJIS( YEAR_TOP_X, DATE_TOP_Y, color, "%04d", pDate->year ); + PrintfSJIS( MONTH_TOP_X, DATE_TOP_Y, color, "%02d", pDate->month ); + PrintfSJIS( DAY_TOP_X, DATE_TOP_Y, color, "%02d", pDate->day ); + PrintfSJIS( HOUR_TOP_X, TIME_TOP_Y, color, "%02d", pTime->hour ); + PrintfSJIS( MINUTE_TOP_X, TIME_TOP_Y, color, "%02d", pTime->minute ); + PutStringUTF16( YEAR_TOP_X + 4 * 8, DATE_TOP_Y, color, L"/" ); + PutStringUTF16( MONTH_TOP_X + 2 * 8, DATE_TOP_Y, color, L"/" ); + PutStringUTF16( HOUR_TOP_X + 2 * 8, TIME_TOP_Y, color, L":" ); +} + + +// RTCݒV[PX +int SetRTCMain( void ) +{ + BOOL tp_set = FALSE; + BOOL tp_return = FALSE; + + ReadTP(); // TP͂̎擾 + + if(tpd.disp.touch) { + tp_set = WithinRangeTP( YEAR_TOP_X, DATE_TOP_Y, // [RTCݒ]̈扟`FbN + SECOND_TOP_X, DATE_TOP_Y + 16, &tpd.disp ); + // [RETURN]{^`FbN + tp_return = WithinRangeTP( RETURN_BUTTON_TOP_X, RETURN_BUTTON_TOP_Y, + RETURN_BUTTON_BOTTOM_X, RETURN_BUTTON_BOTTOM_Y, &tpd.disp ); + } + if( g_initialSet && !GetNCDWork()->option.input_rtc ) { + tp_set = TRUE; + } + //-------------------------------------- + // L[͏ + //-------------------------------------- + if( ( pad.trg & PAD_BUTTON_A ) || tp_set ) { // RTCݒJn + InputRtcDateTimeInit( 1 ); + g_pNowProcess = InputRtcDateTimeMain; + }else if( ( pad.trg & PAD_BUTTON_B ) || tp_return ) { // j[ɖ߂ + NNS_FndFreeToAllocator( &g_allocator, s_pWork ); // RTCݒp[N̉ + s_pWork = NULL; + MachineSettingInit(); + } +#ifdef __SYSM_DEBUG + else if( pad.trg & PAD_BUTTON_START ) { + ClearRTC(); + OS_Printf( "RTC offset in NVRAM is ZERO clear!\n" ); + } +#endif /* __SYSM_DEBUG */ + + return 0; +} + + +//====================================================== +// t͏ +//====================================================== + +// t͏ +static void InputRtcDateTimeInit( int start ) +{ + NNS_G2dCharCanvasClearArea( &gCanvas, TXT_COLOR_WHITE, + RETURN_BUTTON_TOP_X, RETURN_BUTTON_TOP_Y, 256 - RETURN_BUTTON_TOP_X, 2 * 8 ); + if( start ) { + DrawOKCancelButton(); + s_pWork->dtp.seq = 0; + }else { + PutStringUTF16( RETURN_BUTTON_TOP_X, RETURN_BUTTON_TOP_Y, TXT_COLOR_CYAN, (const u16 *)L"RETURN" ); + } + SVC_CpuClear( 0x0000, &tpd, sizeof(TpWork), 16 ); +} + + +// t +static int InputRtcDateTimeMain( void ) +{ + BOOL tp_ok = FALSE; + BOOL tp_cancel = FALSE; + int new_seq, y_base, abs_y_offset; + + enum { // t̓V[PXԍ + SEQ_INIT=0, + SEQ_YEAR_INIT=2, SEQ_YEAR_SET, + SEQ_MONTH_INIT, SEQ_MONTH_SET, + SEQ_DAY_INIT, SEQ_DAY_SET, + SEQ_HOUR_INIT, SEQ_HOUR_SET, + SEQ_MINUTE_INIT, SEQ_MINUTE_SET, + SEQ_END, + SEQ_CANCEL=64 + }; + + ReadTP(); // ^b`pl͂̎擾 + CheckOKCancelButton( &tp_ok, &tp_cancel ); // [OK],[CANCEL]{^`FbN + + s_pWork->inp.y_offset = 0; + + if( tpd.disp.touch ) { // [CANCEL]{^`FbN + if( ( s_pWork->dtp.seq & 0x01 ) && ( s_pWork->dtp.seq < SEQ_END ) ) { // SEQ_**_SET̎̂ݗL + new_seq = s_pWork->dtp.seq; + y_base = DATE_TOP_Y + 6; + + // ͍ڈړ̃`FbN + if( WithinRangeTP( YEAR_TOP_X, DATE_TOP_Y, SECOND_TOP_X, DATE_TOP_Y + 12, &tpd.disp ) ) { + if( tpd.disp.x < YEAR_TOP_X + 32 ) { + new_seq = SEQ_YEAR_SET; + }else if( ( tpd.disp.x >= MONTH_TOP_X ) && ( tpd.disp.x < MONTH_TOP_X + 16 ) ) { + new_seq = SEQ_MONTH_SET; + }else if( ( tpd.disp.x >= DAY_TOP_X ) && ( tpd.disp.x < DAY_TOP_X + 16 ) ) { + new_seq = SEQ_DAY_SET; + }else if( ( tpd.disp.x >= HOUR_TOP_X ) && ( tpd.disp.x < HOUR_TOP_X + 16 ) ) { + new_seq = SEQ_HOUR_SET; + }else if( ( tpd.disp.x >= MINUTE_TOP_X ) && ( tpd.disp.x < MINUTE_TOP_X + 16 ) ) { + new_seq = SEQ_MINUTE_SET; + } + } + if( s_pWork->dtp.seq != new_seq ) { + s_pWork->dtp.seq = new_seq - 1; + }else if( WithinRangeTP( s_pWork->inp.pos_x, y_base - 40, + s_pWork->inp.pos_x + s_pWork->inp.keta_max * 8, y_base + 60, &tpd.disp ) ) { + // ͒l̑ + s_pWork->inp.y_offset = tpd.disp.y - y_base; + abs_y_offset = ( s_pWork->inp.y_offset >= 0 ) ? s_pWork->inp.y_offset : -s_pWork->inp.y_offset; + if( abs_y_offset <= 6 ) { + s_pWork->inp.y_offset = 0; + }else if( abs_y_offset <= 20 ){ + s_pWork->inp.y_offset >>= 2; + }else if( abs_y_offset <= 40 ){ + s_pWork->inp.y_offset >>= 1; + } + } + } + } + + // ^b`pl or L[͂ɂāAJ[\ʒuɁÄʒũJ[\B + if( ( s_pWork->dtp.seq > 0 ) && ( ( s_pWork->dtp.seq & 0x01 ) == 0 ) ) { // SEQ_INIT͎̎sȂ + PrintfSJIS( s_pWork->inp.pos_x, s_pWork->inp.pos_y, TXT_COLOR_BLACK, "%02d", *s_pWork->dtp.pTgt ); + } + + // eV[PX̏ + switch(s_pWork->dtp.seq){ + + case SEQ_INIT: + MI_CpuCopy32( &s_pWork->dtp.Date, &s_pWork->dtp.Date_old, sizeof(RTCDate) ); + MI_CpuCopy32( &s_pWork->dtp.Time, &s_pWork->dtp.Time_old, sizeof(RTCTime) ); + + s_pWork->dtp.seq = SEQ_YEAR_INIT; + // SEQ_INIT͒ʂSEQ_YEAR_INIT + + case SEQ_YEAR_INIT: + s_pWork->inp.pos_x = YEAR_TOP_X; + s_pWork->inp.pos_y = DATE_TOP_Y; + s_pWork->inp.keta_max = 4; + s_pWork->inp.value_max = 2099; + s_pWork->inp.value_min = 2000; +// s_pWork->inp.value_min = 2004; +// if(s_pWork->dtp.Date.year < 2004) { +// s_pWork->dtp.Date.year = 2004; +// } + s_pWork->dtp.pTgt = (int *)&s_pWork->dtp.Date.year; + break; + + case SEQ_MONTH_INIT: + s_pWork->inp.pos_x = MONTH_TOP_X; + s_pWork->inp.keta_max = 2; + s_pWork->inp.value_max = 12; + s_pWork->inp.value_min = 1; + s_pWork->dtp.pTgt = (int *)&s_pWork->dtp.Date.month; + break; + + case SEQ_DAY_INIT: + s_pWork->inp.pos_x = DAY_TOP_X; + s_pWork->inp.keta_max = 2; + s_pWork->inp.value_max = (int)SYSM_GetDayNum( s_pWork->dtp.Date.year, s_pWork->dtp.Date.month ); + // NEƂɂ̌̓ZoB + s_pWork->inp.value_min = 1; + if(s_pWork->dtp.Date.day > s_pWork->inp.value_max) { + s_pWork->dtp.Date.day = (u32)s_pWork->inp.value_max; + } + s_pWork->dtp.pTgt = (int *)&s_pWork->dtp.Date.day; + break; + + case SEQ_HOUR_INIT: + s_pWork->inp.pos_x = HOUR_TOP_X; + s_pWork->inp.keta_max = 2; + s_pWork->inp.value_max = 23; + s_pWork->inp.value_min = 0; + s_pWork->dtp.pTgt = (int *)&s_pWork->dtp.Time.hour; + break; + + case SEQ_MINUTE_INIT: + s_pWork->inp.pos_x = MINUTE_TOP_X; + s_pWork->inp.keta_max = 2; + s_pWork->inp.value_max = 59; + s_pWork->inp.value_min = 0; + s_pWork->dtp.pTgt = (int *)&s_pWork->dtp.Time.minute; + break; + + case SEQ_YEAR_SET: + case SEQ_MONTH_SET: + case SEQ_DAY_SET: + case SEQ_HOUR_SET: + case SEQ_MINUTE_SET: + InputDecimal( s_pWork->dtp.pTgt, &s_pWork->inp ); + + // N͂Ȃ΁AjČvZ + if( ( s_pWork->dtp.seq == SEQ_YEAR_SET ) || + ( s_pWork->dtp.seq == SEQ_MONTH_SET ) || + ( s_pWork->dtp.seq == SEQ_DAY_SET ) ) { + s_pWork->dtp.Date.week = CalcWeekFromDate( s_pWork->dtp.Date.year, s_pWork->dtp.Date.month, s_pWork->dtp.Date.day ); + } + + // NE͂Ȃ΁AZoāA݂͓̓𒴂ĂCB + if( ( s_pWork->dtp.seq == SEQ_YEAR_SET ) || + ( s_pWork->dtp.seq == SEQ_MONTH_SET ) ) { + u32 dayNum = SYSM_GetDayNum( s_pWork->dtp.Date.year, s_pWork->dtp.Date.month ); + if( dayNum < s_pWork->dtp.Date.day ) { + PrintfSJIS( DAY_TOP_X, DATE_TOP_Y, TXT_COLOR_WHITE, "%02d", s_pWork->dtp.Date.day ); + PrintfSJIS( DAY_TOP_X, DATE_TOP_Y, TXT_COLOR_BLACK, "%02d", dayNum ); + s_pWork->dtp.Date.day = dayNum; + } + } + break; + + case SEQ_END: + s_pWork->dtp.Time.second = 0; + { + RTCDate date; // +-2000̂ʓ|Ȃ̂ŁAʃobt@ɃRs[ď + MI_CpuCopy32( &s_pWork->dtp.Date, &date, sizeof(RTCDate) ); + date.year -= 2000; + (void)RTC_SetDateTime( &date, &s_pWork->dtp.Time ); + NCD_SetRtcOffset( SYSM_CalcRtcOffsetAndSetDateTime( &date, &s_pWork->dtp.Time ) ); + } + + GetSYSMWork()->ncd_invalid = 0; + GetNCDWork()->option.input_rtc = 1; // RTC̓tO𗧂ĂB + // :::::::::::::::::::::::::::::::::::::::::::::: + // NVRAMւ̏ + // :::::::::::::::::::::::::::::::::::::::::::::: + (void)NVRAMm_WriteNitroConfigData( GetNCDWork() ); + + // ʂ̕\XV + GetAndDrawRTCData( &g_rtcDraw, TRUE ); + + g_pNowProcess = SetRTCMain; + InputRtcDateTimeInit( 0 ); // t͉ʂ̃NA + return 0; + + case SEQ_CANCEL: + // tE\̒lɖ߂ĕ\XV + DrawDateTime( &s_pWork->dtp.Date, &s_pWork->dtp.Time, TXT_COLOR_WHITE ); + DrawDateTime( &s_pWork->dtp.Date_old, &s_pWork->dtp.Time_old, TXT_COLOR_BLACK ); + MI_CpuCopy32( &s_pWork->dtp.Date_old, &s_pWork->dtp.Date, sizeof(RTCDate) ); + MI_CpuCopy32( &s_pWork->dtp.Time_old, &s_pWork->dtp.Time, sizeof(RTCTime) ); + g_pNowProcess = SetRTCMain; + InputRtcDateTimeInit( 0 ); // t͉ʂ̃NA + return 0; + } + + if( s_pWork->dtp.seq & 0x01 ) { // SEQ_**_SET̎̂ݗL + if( ( pad.trg & PAD_BUTTON_A ) || tp_ok ) { + s_pWork->dtp.seq = SEQ_END; // A{^Ō + }else if( ( pad.trg & PAD_BUTTON_B ) || tp_cancel ) { // B{^ŃLZ + s_pWork->dtp.seq = SEQ_CANCEL; + }else if( pad.trg & PAD_KEY_LEFT ) { + if( s_pWork->dtp.seq == SEQ_YEAR_SET ) { + s_pWork->dtp.seq = SEQ_MINUTE_INIT; + }else { + s_pWork->dtp.seq -= 3; + } + }else if( pad.trg & PAD_KEY_RIGHT ) { + if( s_pWork->dtp.seq == SEQ_MINUTE_SET ) { + s_pWork->dtp.seq = SEQ_YEAR_INIT; + }else { + s_pWork->dtp.seq++; + } + } + }else { // SEQ_**_INIT̎̂ݗL + s_pWork->dtp.seq++; + } + return 0; +} + + +/* +// 邤N̔ (邤NFPAʏ̔NFO^[j +BOOL CheckLeapYear( u32 year) +{ + if((year & 0x03) == 0) { // 邤ŃAu4Ŋ؂@@100Ŋ؂ȂNv + CP_SetDiv32_32(year, 100); // u400Ŋ؂Nv + if(CP_GetDivRemainder32() != 0) { + return TRUE; + }else { + CP_SetDiv32_32(year, 400); + if(CP_GetDivRemainder32() == 0) { + return TRUE; + } + } + } + return FALSE; +} +*/ + +// tj߂B +RTCWeek CalcWeekFromDate( u32 year, u32 month, u32 day ) +{ + if( month == 1 || month == 2 ){ + year--; + month += 12; + } + return (RTCWeek)( ( year + year/4 - year/100 + year/400 + (13*month + 8)/5 + day) % 7 ); +} + + +/* +// ɂp[^I +static void SelectString(int *pTgt, const u8 **const ppStr, InputNumParam *pInp ) +{ + BOOL value_up = FALSE; + BOOL value_down = FALSE; + const u8 *pStr_old = *pTgt; + + if( pInp->y_offset == 0 ) { + pInp->up_count = S_UPDOWN_COUNT_MAX; + }else { + pInp->up_count ++; + if( pInp->up_count > S_UPDOWN_COUNT_MAX ) { + pInp->up_count = 0; + if( pInp->y_offset < 0 ) value_up = TRUE; + else value_down = TRUE; + } + } + + if( ( pad.trg & PAD_KEY_DOWN ) || value_down ) { // \؂ւ + if( ++ *pTgt > pInp->value_max ) { + *pTgt = 0; + } + }else if( ( pad.trg & PAD_KEY_UP ) || value_up ) { + if( -- *pTgt & 0x8000 ) { + *pTgt = pInp->value_max; + } + } + + PutStringUTF16( pInp->pos_x, pInp->pos_y, TXT_COLOR_WHITE, pStr_old ); // + PutStringUTF16( pInp->pos_x, pInp->pos_y, TXT_COLOR_BLACK, ppStr[ *pTgt ] ); // ݑIĂ镶\ +} +*/ + +// POil +void InputDecimal( int *pTgt, InputNumParam *pInp ) +{ + BOOL value_up = FALSE; + BOOL value_down = FALSE; + int old = *pTgt; + + if( pInp->y_offset == 0 ) { + pInp->up_count = D_UP_COUNT_MAX; + pInp->down_count = D_DOWN_COUNT_MAX; + }else if( pInp->y_offset < 0 ) { + pInp->down_count += pInp->y_offset; + if( pInp->down_count < D_DOWN_COUNT_MAX ) { + pInp->down_count = 0; + value_down = TRUE; + } + }else { // y_offset > 0 + pInp->up_count += pInp->y_offset; + if( pInp->up_count > D_UP_COUNT_MAX ) { + pInp->up_count = 0; + value_up = TRUE; + } + } + + // L[͂ɉđΏےl𑝌 + if( value_down || + ( pad.trg & PAD_KEY_UP ) || + ( ( pad.cont & PAD_KEY_UP ) && ( pad.cont & PAD_BUTTON_R ) ) ) { + if( --*pTgt < pInp->value_min ) { + *pTgt = pInp->value_max; + } + }else if( value_up || + ( pad.trg & PAD_KEY_DOWN ) || + ( ( pad.cont & PAD_KEY_DOWN ) && ( pad.cont & PAD_BUTTON_R ) ) ) { + if( ++*pTgt > pInp->value_max ) { + *pTgt = pInp->value_min; + } + } + + PrintfSJIS( pInp->pos_x, pInp->pos_y, TXT_COLOR_WHITE, "%02d", old ); + PrintfSJIS( pInp->pos_x, pInp->pos_y, TXT_COLOR_GREEN, "%02d", *pTgt ); + // ΏےlnCCg\ +} + + +// RTCݒ̃NA +void ClearRTC( void ) +{ + SVC_CpuClear( 0x0000, &GetSYSMWork()->rtc[0].Time, sizeof(RTCTime), 16 ); + GetSYSMWork()->rtc[0].Date.year = 0; + GetSYSMWork()->rtc[0].Date.month = 1; + GetSYSMWork()->rtc[0].Date.day = 1; + (void)RTC_SetDateTime( &GetSYSMWork()->rtc[0].Date, &GetSYSMWork()->rtc[0].Time ); + GetNCDWork()->option.input_rtc = 0; + GetNCDWork()->option.rtcOffset = 0; + NCD_SetRtcLastSetYear( 0 ); + // :::::::::::::::::::::::::::::::::::::::::::::: + // NVRAMւ̏ + // :::::::::::::::::::::::::::::::::::::::::::::: + (void)NVRAMm_WriteNitroConfigData( GetNCDWork() ); +} diff --git a/build/systemMenu_RED/MachineSettings/Makefile b/build/systemMenu_RED/MachineSettings/Makefile new file mode 100644 index 0000000..9cf34e1 --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/Makefile @@ -0,0 +1,30 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +SUBDIRS = banner ARM9 + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/systemMenu_RED/MachineSettings/banner/Makefile b/build/systemMenu_RED/MachineSettings/banner/Makefile new file mode 100644 index 0000000..efdcadf --- /dev/null +++ b/build/systemMenu_RED/MachineSettings/banner/Makefile @@ -0,0 +1,52 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +ICON_DIR = ./icon +TOOLS_DIR = $(TWLIPL_ROOT)/tools/bin +NTEXCONV = $(TOOLS_DIR)/ntexconv.exe +MAKEBANNER = $(TOOLS_DIR)/makebanner.exe + +BANNER_ICON = $(ICON_DIR)/gameIcon.bmp +BANNER_SPEC = banner_v3.bsf + +TARGETS = banner.bnr +INSTALL_DIR = ./ +INSTALL_TARGETS = $(TARGETS) + +BANNER_ICON_NAME = $(basename $(BANNER_ICON)) + +LDIRT_CLEAN = $(TARGETS) \ + $(BANNER_ICON_NAME).nbfs \ + $(BANNER_ICON_NAME).nbfc \ + $(BANNER_ICON_NAME).nbfp \ + $(TARGETS:.bnr=.srl) + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + +#---------------------------------------------------------------------------- +# build +#---------------------------------------------------------------------------- +do-build: $(TARGETS) + +$(TARGETS): $(BANNER_SPEC) $(BANNER_ICON) + $(NTEXCONV) -no -bg -bgb -bgnc $(BANNER_ICON) >/dev/null && \ + $(MAKEBANNER) -d -N $(BANNER_ICON_NAME) $(BANNER_SPEC) $(TARGETS) + +# diff --git a/build/systemMenu_RED/MachineSettings/banner/banner_v3.bsf b/build/systemMenu_RED/MachineSettings/banner/banner_v3.bsf new file mode 100644 index 0000000000000000000000000000000000000000..c5a4f1d1c271275342d60fa886aa4707d04ada47 GIT binary patch literal 768 zcmc(dy-EW?6opT#U}--POOqgiMM^_fBcj1o8>`JGZWiJuY*vFlg1&*zVJU*0g%4tH zW2Js~cAh~QGTfgtcfK>5pYMit6)Tcc(=SJ!s9=p%QjIkyN{J%nni8*RRgIvo&-~3^ z-|KX$2_y@ME(4L%m9D8&)P@i`En&~eE3$$-_j}68gwBGhY0sDy;bcoYI#lmpote9H zxQs5>4Bife+n&jK2O3aW(PkDOH}4-Wtk%l^-37|rYvMrH_2l+lGNzR1QsU1r zsT+7-9%}ymkbgZty*u1)ysp0)yZstrcb?k*kqgKY&p1Lm)Ghmjyn?EuHfzc4C908H WD5rE1-Eehc@*xO#cOIC~b5A literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/MachineSettings/banner/icon/gameIcon.bmp b/build/systemMenu_RED/MachineSettings/banner/icon/gameIcon.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1a7a401223d3d978740e5f1e25d08cc5d757db78 GIT binary patch literal 630 zcmY+BF-yZh6vv+;II4RGQ#uHpY(hUkb6JWOikGbxiZ+8_=}>ag$))IC!Dennn%yN? zwNSiIV4G12t>zP$)OSf5^bdEJ-+RAYj$G-~+=eJ7&PO;7ld%Om_=HLNF~oC-OD2;tDUl0V=>U`aVTOT*iiMc(gj+yWAolN1jH{{0P7^_rl)yfJ!0!n`m8GoU$5c3u*yIXB+mt4|}ZXi%#W2 z$3Fh9nczArM?Cp@nK?F|d0}2OX*lPtx0P!@6H;cE1`Rzv`CPfK&Dag=2%dAp|HkX` tIDZw4f`P$%qQn$D=lmUCu&u!zqamuCa~BI^>z>g)KTfj4t+@0*fnPik4Ql`Z literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/Makefile b/build/systemMenu_RED/Makefile new file mode 100644 index 0000000..bcccad8 --- /dev/null +++ b/build/systemMenu_RED/Makefile @@ -0,0 +1,31 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +SUBDIRS = launcher MachineSettings PictoChat \ + #DS_DownloadPlay + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/systemMenu_RED/PictoChat/ARM9/Makefile b/build/systemMenu_RED/PictoChat/ARM9/Makefile new file mode 100644 index 0000000..af75337 --- /dev/null +++ b/build/systemMenu_RED/PictoChat/ARM9/Makefile @@ -0,0 +1,53 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlSDK - demos - simpleShoot-1 +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev: $ +# $Author: $ +#---------------------------------------------------------------------------- + +SUBDIRS = + +#---------------------------------------------------------------------------- + +TARGET_FIRM = SYSTEMMENU +TARGET_PLATFORM = TWL +TWL_ARCHGEN = LIMITED + +TARGET_BIN = main.srl + +#LCFILE_SPEC = +ROM_SPEC = main.rsf + +MISC_DIR = ../../MachineSettings/ARM9/src + +SRCS = main.c PictoChat.c $(MISC_DIR)/misc.c +#SRCS_OVERLAY = + +LINCLUDES = $(MISC_DIR) +#LLIBRARY_DIRS = +#LLIBRARIES = +#LDEPENDS_NEF = + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +do-build : $(FONT_OBJS) $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + +#---------------------------------------------------------------------------- + +#===== End of Makefile ===== diff --git a/build/systemMenu_RED/PictoChat/ARM9/main.rsf b/build/systemMenu_RED/PictoChat/ARM9/main.rsf new file mode 100644 index 0000000..f7b7ea4 --- /dev/null +++ b/build/systemMenu_RED/PictoChat/ARM9/main.rsf @@ -0,0 +1,146 @@ +#---------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ROM-BB.rsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TWL ROM SPEC FILE +# + +Arm9 +{ + Static "$(MAKEROM_ARM9:r).FLX.TWL.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.FLX.TWL.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.FLX.TWL.sbin$(COMPSUFFIX9)" + Elf "$(MAKEROM_ARM9:r).tef" +} + +Arm7 +{ + Static "$(MAKEROM_ARM7_BASE:r).FLX.TWL.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.FLX.TWL.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.FLX.TWL.sbin$(COMPSUFFIX7)" + Elf "$(MAKEROM_ARM7_BASE:r).tef" +} + +Arm9.Ltd +{ + Static "$(MAKEROM_ARM9:r).LTD.TWL.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.LTD.TWL.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.LTD.TWL.sbin$(COMPSUFFIX9)" +} + +Arm7.Ltd +{ + Static "$(MAKEROM_ARM7_BASE:r).LTD.TWL.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.LTD.TWL.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.LTD.TWL.sbin$(COMPSUFFIX7)" +} + +Property +{ + ### + ### Settings for FinalROM + ### + #### BEGIN + # + # TITLE NAME: Your product name within 12bytes + # + #TitleName "YourAppName" + + # + # MAKER CODE: Your company ID# in 2 ascii words + # issued by NINTENDO + # + #MakerCode "00" + + # + # REMASTER VERSION: Mastering version + # + #RomVersion 0 + + # + # ROM SPEED TYPE: [MROM/1TROM/UNDEFINED] + # + RomSpeedType $(MAKEROM_ROMSPEED) + + # + # ROM SIZE: in bit [64M/128M/256M/512M/1G/2G] + # + #RomSize 128M + #RomSize 256M + + # + # ROM PADDING: TRUE if finalrom + # + #RomFootPadding TRUE + + # + # ROM HEADER TEMPLATE: Provided to every product by NINTENDO + # + #RomHeaderTemplate ./etc/rom_header.template.sbin + + # + # BANNER FILE: generated from Banner Spec File + # + BannerFile ../banner/banner.bnr + + ### + ### Setting for TWL + ### + # + # BANNER FILE: + # + BannerTWLFile $(TWLSDK_ROOT)/include/twl/specfiles/default.bnr + + # + # Boot allowed Media: [GameCard/NAND/SDCard/DownloadPlay] + # possible to choose one or more. + # + BootMedia GameCard NAND SDCard DownloadPlay + + # + # Certification FILE: + # + Certificate $(TWLSDK_ROOT)/include/twl/specfiles/default_sgn.sbin + + # + # Digest parameters: + # + DigestParam 1024 32 + + # + # WRAM mapping: [MAP_BB_HYB/MAP_BB_LTD/MAP_TS_HYB/MAP_TS_LTD] + # don't have to edit + # + WramMapping $(MAKEROM_WRAM_MAPPING) + + # + # Codec mode: + # don't have to edit + # + CodecMode $(MAKEROM_CODEC_MODE) + + ### + #### END +} + +RomSpec +{ + Offset 0x00000000 + Segment ALL + HostRoot ../../data + Root /data + File NTR_IPL_font_m.NFTR +} diff --git a/build/systemMenu_RED/PictoChat/ARM9/src/PictoChat.c b/build/systemMenu_RED/PictoChat/ARM9/src/PictoChat.c new file mode 100644 index 0000000..e2c466e --- /dev/null +++ b/build/systemMenu_RED/PictoChat/ARM9/src/PictoChat.c @@ -0,0 +1,83 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: DS_Chat.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include "misc.h" +#include "PictoChat.h" + +// define data------------------------------------------ +#define RETURN_BUTTON_TOP_X 2 +#define RETURN_BUTTON_TOP_Y 21 +#define RETURN_BUTTON_BOTTOM_X ( RETURN_BUTTON_TOP_X + 8 ) +#define RETURN_BUTTON_BOTTOM_Y ( RETURN_BUTTON_TOP_Y + 2 ) + +// extern data------------------------------------------ + +// function's prototype declaration--------------------- + +// global variable ------------------------------------- +RTCDrawProperty g_rtcDraw = { + TRUE, RTC_DATE_TOP_X, RTC_DATE_TOP_Y, RTC_TIME_TOP_X, RTC_TIME_TOP_Y +}; + +// static variable ------------------------------------- + +// const data ----------------------------------------- + +//====================================================== +// sNg`bg +//====================================================== + +// sNg`bg̏ +void PictoChatInit( void ) +{ + GX_DispOff(); + GXS_DispOff(); + NNS_G2dCharCanvasClear( &gCanvas, TXT_COLOR_WHITE ); + + PutStringUTF16( 1 * 8, 0 * 8, TXT_COLOR_BLUE, (const u16 *)L"PictoChat"); + PutStringUTF16( 4 * 8, 8 * 8, TXT_COLOR_BLACK, (const u16 *)L"Under Construction..."); + GetAndDrawRTCData( &g_rtcDraw, TRUE ); + + GXS_SetVisiblePlane( GX_PLANEMASK_BG0 ); + GX_DispOn(); + GXS_DispOn(); +} + + +// sNg`bg̃C[v +void PictoChatMain(void) +{ + BOOL tp_cancel = FALSE; + + ReadTP(); // ^b`pl͂̎擾 + + // [RETURN]{^`FbN + if(tpd.disp.touch) { + tp_cancel = WithinRangeTP( RETURN_BUTTON_TOP_X * 8, RETURN_BUTTON_TOP_Y * 8 - 4, + RETURN_BUTTON_BOTTOM_X * 8, RETURN_BUTTON_BOTTOM_Y * 8 - 4, &tpd.disp ); + } + + if( ( pad.trg & PAD_BUTTON_B ) || tp_cancel ) { +// SYSM_RebootLauncher(); + } + + GetAndDrawRTCData( &g_rtcDraw, FALSE ); +} + + diff --git a/build/systemMenu_RED/PictoChat/ARM9/src/PictoChat.h b/build/systemMenu_RED/PictoChat/ARM9/src/PictoChat.h new file mode 100644 index 0000000..eaea919 --- /dev/null +++ b/build/systemMenu_RED/PictoChat/ARM9/src/PictoChat.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: DS_Chat.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef __DS_CHAT_H__ +#define __DS_CHAT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include + +// define data---------------------------------------------------------- + +void PictoChatInit( void ); +void PictoChatMain( void ); + +#ifdef __cplusplus +} +#endif + +#endif // __DS_CHAT_H__ diff --git a/build/systemMenu_RED/PictoChat/ARM9/src/main.c b/build/systemMenu_RED/PictoChat/ARM9/src/main.c new file mode 100644 index 0000000..c432558 --- /dev/null +++ b/build/systemMenu_RED/PictoChat/ARM9/src/main.c @@ -0,0 +1,107 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: main.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include "misc.h" +#include "PictoChat.h" + +// extern data----------------------------------------------------------------- + +// define data----------------------------------------------------------------- + +// function's prototype------------------------------------------------------- +static void InitAllocator( NNSFndAllocator* pAllocator ); +static void InitAllocSystem( void ); +static void INTR_VBlank( void ); + +// global variable------------------------------------------------------------- +NNSFndAllocator g_allocator; + +// static variable------------------------------------------------------------- + +// const data------------------------------------------------------------------ + + +// ============================================================================ +// function's description +// ============================================================================ +void TwlMain(void) +{ + + // ---------------------------------- + OS_Init(); + + (void)OS_EnableIrq(); + (void)OS_EnableInterrupts(); + + GX_Init(); + GX_SetPower(GX_POWER_ALL); // eWbN p[ON + + // 荞݋---------------------------- + (void)OS_SetIrqFunction(OS_IE_V_BLANK, INTR_VBlank); + (void)OS_EnableIrqMask(OS_IE_V_BLANK); + (void)GX_VBlankIntr(TRUE); + + // foCX------------------------------- + TP_Init(); + (void)RTC_Init(); + + // VXȅ------------------ + InitAllocator( &g_allocator ); + CMN_InitFileSystem( &g_allocator ); + + InitBG(); + PictoChatInit(); + // C[v---------------------------- + while(1){ + OS_WaitIrq(1, OS_IE_V_BLANK); // VuN荞ݑ҂ + + ReadKeyPad(); // L[͂̎擾 + ReadTP(); // TP͂̎擾 + + PictoChatMain(); + } +} + + +// AP[^̏ +static void InitAllocator( NNSFndAllocator* pAllocator ) +{ + u32 arenaLow = MATH_ROUNDUP ((u32)OS_GetMainArenaLo(), 16); + u32 arenaHigh = MATH_ROUNDDOWN((u32)OS_GetMainArenaHi(), 16); + u32 heapSize = arenaHigh - arenaLow; + void* heapMemory = OS_AllocFromMainArenaLo(heapSize, 16); + NNSFndHeapHandle heapHandle; + SDK_NULL_ASSERT( pAllocator ); + + heapHandle = NNS_FndCreateExpHeap(heapMemory, heapSize); + SDK_ASSERT( heapHandle != NNS_FND_HEAP_INVALID_HANDLE ); + + NNS_FndInitAllocatorForExpHeap(pAllocator, heapHandle, 4); +} + + +// ============================================================================ +// 荞ݏ +// ============================================================================ + +// VuN荞 +static void INTR_VBlank(void) +{ + OS_SetIrqCheckFlag(OS_IE_V_BLANK); // VuN`FbÑZbg +} + diff --git a/build/systemMenu_RED/PictoChat/Makefile b/build/systemMenu_RED/PictoChat/Makefile new file mode 100644 index 0000000..9cf34e1 --- /dev/null +++ b/build/systemMenu_RED/PictoChat/Makefile @@ -0,0 +1,30 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +SUBDIRS = banner ARM9 + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/systemMenu_RED/PictoChat/banner/Makefile b/build/systemMenu_RED/PictoChat/banner/Makefile new file mode 100644 index 0000000..efdcadf --- /dev/null +++ b/build/systemMenu_RED/PictoChat/banner/Makefile @@ -0,0 +1,52 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-10-03#$ +# $Rev: 1319 $ +# $Author: kitase_hirotake $ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +ICON_DIR = ./icon +TOOLS_DIR = $(TWLIPL_ROOT)/tools/bin +NTEXCONV = $(TOOLS_DIR)/ntexconv.exe +MAKEBANNER = $(TOOLS_DIR)/makebanner.exe + +BANNER_ICON = $(ICON_DIR)/gameIcon.bmp +BANNER_SPEC = banner_v3.bsf + +TARGETS = banner.bnr +INSTALL_DIR = ./ +INSTALL_TARGETS = $(TARGETS) + +BANNER_ICON_NAME = $(basename $(BANNER_ICON)) + +LDIRT_CLEAN = $(TARGETS) \ + $(BANNER_ICON_NAME).nbfs \ + $(BANNER_ICON_NAME).nbfc \ + $(BANNER_ICON_NAME).nbfp \ + $(TARGETS:.bnr=.srl) + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + +#---------------------------------------------------------------------------- +# build +#---------------------------------------------------------------------------- +do-build: $(TARGETS) + +$(TARGETS): $(BANNER_SPEC) $(BANNER_ICON) + $(NTEXCONV) -no -bg -bgb -bgnc $(BANNER_ICON) >/dev/null && \ + $(MAKEBANNER) -d -N $(BANNER_ICON_NAME) $(BANNER_SPEC) $(TARGETS) + +# diff --git a/build/systemMenu_RED/PictoChat/banner/banner_v3.bsf b/build/systemMenu_RED/PictoChat/banner/banner_v3.bsf new file mode 100644 index 0000000000000000000000000000000000000000..d595b6d35b72e52619f29b85a7cea0a85f471335 GIT binary patch literal 762 zcmc(dK}!QM5QX2hg8v~<5IkrR!9$Ohu3Abdt_mL0tb9)y>^dE zV93mSJNw>be!jc9Rjy1%7x5T!s}<)>71dmy+zM`)oR-{Ab)s&=PT%}ZO#d}{(gGzl ziryPVMy1wNJhd4LjkaiaMXc>L03@c^nuYz(jhut!^0RvH$F0knzW#q9$U~moFDJ}z>JQgd8?{HqiSEC9Y(wJ*Wly6 zRcU(T6b&w`xQjJ=XX9JWnaNCF#09x$H~Z>ww#=h~HP(I-nf#Th!L($%5DJTha5`L6s@6ybjn%yN? zRVW_*0osgCYX1V0`n@z_{lZ=Hx%bU`@A8@_&L(AYupeOU!w*rG$gwV8ui2t-`7iaqoEDpxIr^P)f#UzZs0(QsSQt*9@9H z*U3v5MlA`>$3ypd0Ws4kX6(5P%~hCrn6d8-ZIr0!CTmG}KJ`8Ox(K$a)mjo=1^(DR zlKT~IHO*QIp87UQG{g@FzWx6i%$v+YJPf8_r_m8j%SxZFq9Ev^d_#&;uyeTxf$IPUVA8!~?UxO+tjABKw#Pv@%p@SbJx+)K&RSUtYI zM^R?D(L7gj@riN8O5JOQK|)+$ERN>6Qcw6G>w%}RDy5=41OJE4wek$NdgyDSZ$-Qi AC;$Ke literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/data/CardBanner.bnr b/build/systemMenu_RED/data/CardBanner.bnr new file mode 100644 index 0000000000000000000000000000000000000000..3e87abc4614784ccfd77f8e01eda7f62ef614060 GIT binary patch literal 2624 zcmd^`YEW5V>TI6T^W-XYn|r*zAFFme~bK zWwVE*vzf!j#$u8*$p(eFT$Oa26O>fPteuT;zC9Ze@(*MOe)F;O&AyK}JM096!RL*M z4LECzMx&ov>+~c^(j@62DouKbYNkDPiuMR?t(1~VZObOdp-+!vA)eHaTsxIN^FZ1ZFh`ixwd7x_GP4Cx>lj!ngwHi5XOE# z*w5ho7IFGM=Y5Y?U*I_cA%x?BVhlwgHWol}u)d9!gW!xAxQ=3)reUBM78bT`+sy1N zqhJ{G#(&`E3uptpUc30=%E8si>x3{l~f(5ALy8klXfINTyyRee$ T{+Ho?uKRa${{Op^>;C@$S=}%| literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/data/DownloadBanner.bnr b/build/systemMenu_RED/data/DownloadBanner.bnr new file mode 100644 index 0000000000000000000000000000000000000000..f14caef20710f04b5e0de104af7171b1283006b4 GIT binary patch literal 2624 zcmd^SO*(@adV|t1>BvgGBL&Jh)G7P zfKO7&%apRRP4gPvoaTO`8}COT91*pGZq)J{4>ymZ-HkrV^aI};1fDB=PgEfs!mp#o zwOWq>nsc?*vs(*2o71lrqXUDMEoX#bIF_M1)&)?~9ivoo^pZBy4O?C(_>dzyKD9fZ z5FJ-kpJE*erBq-+QHDXNg#-|rGit%I0cOjfh(mN;*EEP`AhBgxdT!@6N}4vK{RbXC z1DlZb<#Vqte!MhxWqxAw#@=*x>-`=7%JDDwW_ XA@>X2|02HeBJaOb@c-ZKLihg%8rDS= literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/data/EmptyBanner.bnr b/build/systemMenu_RED/data/EmptyBanner.bnr new file mode 100644 index 0000000000000000000000000000000000000000..35bb2e40d4f126bf3a919da6fbc8240e7b9c4bd7 GIT binary patch literal 2624 zcmd^9zi-n(7(K+&fdRJ}m@3t&P`gAzb}Dr!LwuJ)g(4KVEHqv~7eRi|0m*4WVznhk z7H4OOZMIe#OssHvi87-NfR`!difTa_$->XFOkW=BBLY9dp*Gq`{Fl^1n_Y zMty3J(EA9zZ($z^rBq-;QHFu2Wfe`3&0!451~6Milrcf3X&MH|D8ksXEORPPYs?x( z#rO|+_y%M`-aWtdsqpR2%)-X`+D+zXXm;PCm;8h2qQJJ vjJZp;$Q!bqkJ$fGE|Ds!=Q{s7&OXoQ|ByV*b^a&hajx?_IsgAX$aVg|aiky4 literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/data/NTR_IPL_font_l.NFTR b/build/systemMenu_RED/data/NTR_IPL_font_l.NFTR new file mode 100644 index 0000000000000000000000000000000000000000..b6fe11e03f0ed48c6d3f22b2cee630b6cab3ef14 GIT binary patch literal 181128 zcmb@v4}25Xl`np0G?vC7(8xF-Ck`IT0t}@^h9q^`G#c9iWJ1HAl3mi*w}?MYvRiiR zX8ZQBEkz?+fK1#V8`6+nHaL`Q|Gr;I|83r9yG1rGF@3a2^LF<~cl%icanq!)yD?7E z2x2t9@0pRTJF*OZzxReV)<|d0z4zR6&OQI`oy}X;JZR(vA$3+{3Y){$JlL_Op5eL; z|Mz%=yYOdM48J`ovW@H4wukW9b6XRe=Mf0%f9H~zj3!j3FyI zZ!Dmu+3G7b*P{0IW?2<^&zhV5mY!kF`PU1&#$ zx-;dPY|>?v=4A?0A;6-tur3J`F&Q0v}j^1m?(34>yLn#0f2$6AHZ7FjkJqyeA1N{R3qz0mL6WUxA4;zDz8m7x{pM zg)W74f`v-ggln$P*?8(_KWjeJTHCc$`h@R$f8O|`80+i|>m?`#e$uPhEaUG?-YHmtQ=Efm|neGa64=Ra%9|@5a2McMZKXiO+U*nFdJM6 zpD0RFkzJC zYyAAWr4VjQ6tLkd@C)^45?xgPSN1FLO9;;tt`a_r|8y^wx^_%YdH*K)PZx9{3lWbo z@aa_k%h?#zK7YkV@wdnzw*FPXM;siASsc?#Yq_M&(Pyz*D0h`Z$K;e(378Y`_rezO z>s1?P4cw-ER1YwSpAAm&#T0!N3$i^JK}OJt7gn)0;edTUXnqx~83=Y`70FIJ4o}vm zb-4x1&MzLFn<$P|!B<&Z|DdfDbAmu$XjP&%qovo$Z2aP>Bp4=M8$M{EIeIhX?f?H} zUk9!AS(`Dsy+SVpEF@&-Y9VyvfN)%RgMYXvZ$A<)INT+Dbym0_+VooSnfurUhg_oH zP`UmC@l;Y9A7eka;bT8%?-X(He+i%2ZbKH&P332pd?38c$b1A^J9G1h3ZHH5Zr2}W zUl85SkSkLJ<;N>a3e-|b9Ts7%zcdh5-lEw7JDjyp74epOD5}nkYZA2hdlwX5NXpD+ z^=vs?&w9)CU%?WYI#wXAbiF71y%>-pCGqo$fl6>Rzc(MR_0;5im}X9e`6wW-#4j{Y z<(F+fXnu(gh!|zpi^4@%YxZTQ48*)O`I+nz2p~w(MMe}4S6npmb_$Xj>Ez*xpUri! z#0OL4gM)MU?AlK&{>J}JB`^Wb-%YFkim=pi#SwGpBAZJ_iYcbWAGyEi-;{O*eJ%%K zeawS&@P9Z1)UN-844I>*aFPW^+RVCz<-{W^@@a{WOM=J4&9$M3QM(pK42g&1KEsvU zEt5I!v+=bT=n|;Pp2PL-I`CoSNflI zt6mTJTCxrN^R&J#Bp-^z%a!4OvVVR|I4!~?Kny`R?aVkc5*EBUdNsR)-EIf8-Ffn? z$bi;l*nTbDz^$6*GRN`Z*P}F!-ge)_z4EJdcg>$V4nv;?f&FV2Iy|kCu!Dj!V0OXC z6qY*r)yUdm7~&f+fj{NHRJ`Z(TC*NE z&3%*NlfXHTdcU?;zb1?eqlo{c1y$527*qq(tm1`va%D)$|2HpE(n70}z(0kDB-E23PRUIhp#B`yiNPGOK^?R?~|9^ueJ1~ zwq2)X#0(|?Fa!0-JlTRYl5ke`r%n3J08V8CGs4Ga1_y!7Fwz)yCC}Yr40OdD_z(BB zsb=_xOeoB(sLu$F%@mICIwmBy>@L{DYcrGTBcx@D!9|l_X5deUXkDFwKkcS@n*p53 zS2KWH$&SqkpUKZNz(-_(pFA^v6`{Pld@ax}nFEPBaYt2huIxi7DVy1eu&{NRay|pU z+vL+3z?pQJ0h~GB8NiwIF;l;r43=<4vjS?8+cU25Gm&^i z++$x#+{}q5Zso5sCg|=N!HKYmW`fVD&6^P%*;u#6C$K8W@U7thVqRYyJU&F(jW*9j zGec^{e|+$*;&1$4o8P^ik^WO@IVoLEMt4PXR+-M9W-LQ=zBL?;WF~NIhHySCeGHw} zrufwOn!B9layS)A;9%&Z%$o4uTf?y#!3k+8!&rm9ovb_I9cPPAQDYPbF7q#8nV9@? zYk#_IKBo7l?ej4$T-kg~3upCja(<_UE1S2Qz|rb87xcyjyB*i$E#26!h1#Qu17f}O zSao{7+M;bwye{ssLs)c~TwtvDO9j8%a?frJXUX}k;Vk*RHJqhi0C!WroAlp`Y-cQE zh0@(py>CUfz>N0sPPThfd=3Nog<@P@YDg90QWRe^GUW(yZ|aStUv5(-pge4PqZVC5 zv>Z09j}oUk4Dboa9xQK7$;1YciRCUqBe@E*vx39H96FrJES6>DL%Q)0cL^F~SEb>e zgHL#x(#R!~#)323EjV_R&_#=-KM11QJTXxh&8I9s&<2;|nq`!+7WINv9)DdyH3kzRJRW%SybmS$c zTnr@*7OkcNtZjj`8F?Hs`Z%>+pIenRuVJ@~OZiJO-8d_;yxj@>Rv>RF`vw(kn+<5w zV#ixqw}I49=~lOQaLm=>^C6kj%mM~t`-0D@$f3}^nT2*Rk`D}JimoSa<1g5pAvM#E zKxjzJxDYu&{zGro6A75jwo7GML33tgil$Qp#_d$3m>UkOeLiG%%n@>S)(Za z>getBHtuLk9;}wi;3S{iqHI)8w}!g>(hhl-@)*+CS$&Y%+x3*BK;Q+ZoPLa>3%dzj zJQMbq^K^8^{DR6>Y}(M&;B0hWBP2z)du}JiE#9`{D?W6;daj*}ant^dWp-xv+Tkec zteSe)Ep|#F*r$-@jr#Y5`z-xb#8dp6$-IP`7AO!aEnzWv@kjh6zd}LOXCXUBI%Bfk zNiTqdrH}h4@#SPL-ACer_;`umOh_st@ac^dzAnagRm3O1gvq?W43&9%iM=Ltl`@Xd zOPD+E;`|=yt6TT4jA=3~!y)57B4KXjH5MWivj%x4GBUZ##VCnJJVjL@1CE%a5#a}? z$a&!zTVAqN|BdiP+b||ETQ0}}ik^vDm0mDYCVxhY3SyIp!U;~t9*0iF8K5(JnY|5$ ztZ>~w!+DDjo;1bW%!neo46RiG8^a{o_~12RZ{=}>Gd8%A*I0%%KA7S)D@F1vUKz~1 zm3lU{^(q+r6|YtL&$_(@$&+`4{!8ZmGKE@rDjVCbn-y3Ts6tAUopsn3V9nAm!$`p+ z140?8y3p;J26JVq&~hl2*$zG#QPZtz*LL@#p)Y1^P@>u}MiXW7pDS0=e`V_%%_dn0 zGgzn1i3dJ2)M4raO-m$rrH&r_UtiC2R??gj5IYzu=dfI&AVEtQT>?MgnXc!u(xP5$ zSCY-Xm9e|^Wh^gz-nrh_yM0a@iaYP;AhD<$4GUy-)4b2D)3_U0!KN zb#lJkq;#sV^Yjujd~(F*rO@wecdOJ@M{qUr@=9>rdhWDAM%=a_`a;uucW5uLTS zJM;B?a$TLV{c_WFI%gGn6{V=aFSxalh0S!Go?N%Q1vTgsE80ynU8iNy=e8;{c48P8 z*#KGOlpx63`$tUwe|4QM5yHxXS!9Bb0?Fd8sgoNDWy7XCb5O85O$7j^s+MYCM?@!Y z%k16h;c_;G#n)w&;!~3BYslK$Es160M8ut{R%+Cs7ESc!RXbcs+ul@f6z5kDF|~n+ zp-f{JFI0Zh=!l5NT&gSMMgV*jyCSS{9=z9)v9;@(@D*zlx&=p`R&+!prpl%D5czK+ zt9QHso`C&A_JIu>29c#YM$^wL&RZzftXH%l5T0kZ?6e19$Bj-)rx?HMIY;BQF~PcV+A@}_TSC;V2b*y zjBgvP&O%n4l+x$)AKR3{gB~fq;XM;eW?x)81S7 zqem|soGsNuhC*s*>vKboUiiWog=wc;RPaZoi>8$W*I$@s=D0P>^!}0VuV~nn;9||0 z`=KK%LNNqzN*<8;sbbWp5?mHm($s5=LGeR6b0TVAp-D2~sW9}7>H0{bXIL2_)q9{d zr&k0tdoD3gwpbrq=BE@Ng1swJaS3TUYfyq0m*tQ2Z-tkfRyujlwgovEsuw|LdA&63U-)l`U4~zZdUs0!NNX2$8p2U2bS` z#Bpu~HvR9W<68WgDmN&5zPtFvw14NogRcQxdRmBE{4fA>kOwI+lw7R3A;~DNBOILd zbx|L%vRe)iA02u_CY~|6je~|K@5wccHDpSK2X;`pb2yySI8Reyxo@V_*9mi-_xK{Q zU+S-8ZeqfFuD`!M@W{U(?Bt%Ik5=WTUiR(OTM3j7-kQ!DS@wmRFRPx5N-L<;Ug2>T zzry+lu0edLut9-7*e~DqW9NK6U#zZs;XS_C9^sf1cRTA2`0QXghtKW9>Vjw(rqBZ| z3f~Mmzih2WoONN~H=lKU9@VFoCIWP~!*N{5+VIKPpb^qP$4-83^>=?7JlfH8WK-be z+Q@;PIp3{*g@g3`gVZJ`y>dW_sHxU^#O%!5lgg-im`^Zxez)V!;SZ%c6hLr~PyLt? zH3<}?3|CY*Mw^?EG1D@GWqwb|@#OeZv& zmWQi06=PIB)~vLt$(?dUN%>FHwi}md8y9WM3i(v5L9`N@ISVHQjp877J}4NtgJ}?^ z-ADABlbj{j!ktt#u3>qpvROUV8aJ+0{Unilu3nV0|m-;p!<%Sc744Rw?JBQ7My+`--R= za;9d1ePB=@plDb;Tl|sxi!bRnjUBc+;bYs&@(@_db40e{Kj0;=7JnS}$PX+Lw3MNF zv4VOTKO}BB9#pvo3m+HGeWdxokV~5DzQ=ve zlgLG~mDEEeQ-M@|X#mzZ%IItr+(qs6cZFNNRg5ZIDgQCm@3HtLh8WYNZCrt0P*gXD z;M3Hh4nHx2cwawnA!qMSrx`@5IG%$EuA$jr|^XK1Qm zJ1Yu1tFPbvr->&~23Q~aQ}DwST-Fz4i!s5RP!F-O56oBbA{i^zi#AMH(pM1>g`_$B zVA-AFve0DliFzTs5FW}NJBg3*DgeJ_drh#LRV5yJQ>E<72 ztn{x8UmYr1OaDp_m4V^bGl7I-Nnw&GhsUOZ(U3I1GMZPV1(KzjJHC|W@|-b(`vi|K8mN+!Z?5cCfT_R2qlR!neljuJ=W5g3qFhvPSLQ>HEUX#_L%A`1!x9 zSsYv+J=WJ8c>GUKJzkN1KF4y_pK9y`$Ndwl!z*KYy0 z)|Y5*d;DjoD$g6*tr>aLdv0;>!@iTv`)<S$zD<)8nK5nQ+e) z+Z`+04@>;#_~7-C1mN=E0yR4I^v&X7Z-AFvCEwi~1xCeIOl9em52o z2jty$YXjtO_wja## zPA*^edE=Q1`1o5JKK_TB%&+Yk$j7w(;{i?in5KVrxG}yP{7<&eCceu2XQxY*jW%_xb%BH(YGU_tQIH{yv zjIw|%otuz#WL=qtOc?1F!-bewI3K@J32uNZ$8b7iG33;$%HTZ4TgC~aVIrIhXXBYT z_T%P+F(E@9q3!Y*Z=eFJqUXrNQ5i_ik@MujIpcl&d(G(1J93U}IX;5BND(J_uBtTWQ6a)}OJ(XeZAthCPY7h5?Oe0%kmPBz-_(*}N`#d=#aT&fIIgSfm z6YIMp6fxe8hdoK^Z~ zbNOd{zDfWa?L%&K3V$Tcohkj3b*_st=i}8OYg_X3M3n<$)10TkgK(eA3^4Q7k>voG zC!^>qs4@(Er_%mXhF3 zDt@v8TiBQ#4sj_f{sc#nmjNd6{jxrXNokav_p;jpyzW9HT6r8Pi!rM_Mj2&lbJ0jy zn=Ocs@L;U42iNx9jBk+Gp^cN}@FI)nh$`{!p8ejx+8*qBK&I(D_vAWAy9?txX@%m8)6=5SJkz$)PER!(VF0@FY`8g&Jw3zGr zkT5Jxfun7qLKZpx?m-p^@KirIb(^e327#Zr_=(tbn1(du`1WI zIBSeD^4-+PC?6wQNu(UND^9b&dcIph?xGx4)$G zV5oIIa}AMu%rG`ZzOL=jx3i%N^wR~0=x|-hJ)%ZXV&|ZO5EN%%gGJXu9v#C;H*HSW z>$zR(dce(_77h#rj#gPK7J6Mk4_!V{WkjQRhDRt5c(>(e07r)sbUJh#PeqlnZcqs& zpE}fE7AU!^1ou@TGCiDJ$fF=oY^rGUHipBz5*b@KP8LsB#SotaTrobW$`t(UMptZ? z88#|@Lz-GO#SfM6+2XhKSJ;r(`FpTRML1I=<3vF$1pB%V_6j5_becjq!#^(#RBOtu z;mYLO96s2O%8hMo1-M$Z33613uMu4;!I3zG4IO>*XmtLJnHzGvLg8pTzlZ}>@fpAg zs0SjJGx92OO*$CxK1(T;#r6d8WK{&kU&e$9hTspj`O)CY;2^zue3v0DIQX9VaguLr z^dq>H`cG~JN8||Ssi7DSBYsJrrr!u6E#-=1A287o9Lg%gF z8Vub>)n9Ufkr@?YI~k27awzXV)Pt7OJB7c#X>idON?W9e($GkjXf=-`Pr4+E!HdyP%v475?8NdnM$uIYK-8aVv&0-9g zd9a4OmAH~B&l@{!(0Zi%Zw2>CKIYEMzZD$udV_T^O}CLVS>H1jYSFe19<$Fc@_D2y zC_}fm@x=PZ^x$RZIr(BJ3-!TYkl*m@*r?_lbE)L@c-aqy7Ey7BLiTlQQjSi}iOfpf znQo5lNSqZfxYMD*Oc_4diLi;WOu7uAunLpM-e7~HXF!%E*}sgn?M!|=k#IU%tW(u& z{*1X1?f$yg7q00%_#7&}GMN+B`D-Ne0X>*09Z+w70tV9(k*8z-#)^DRVuiRjk~O zHORQNT+Fytq?owu+##>`jWy_8|In-Zl>aS($Bm6yO_D#l`uX=n+CFLIdsgV$KEeKSr2`xP3luJjXT%s9H7e#tvYgb z?j3V_XDRj2GdtPv$1Wx>yKM*4nf=Q+ChFZ;&q8cW*`LWf*qmpZUq=GX#t0yBL!RaW zHGp+puX}u-7g8v_#^@Ss4k6~&+Oh>c74|re1(mJpKx?L3c+z%&n8@a{yD-JKx~%hQ zc#7Wai5QlA^PfY*s-aH@s_oEr%mfb4!)V2b8llRM2{9)o2)2|RZG(Z91Q=j4wzXyE znaTlb60>fHGw;A~#9J*$Edy}P}+92%WdvqMNak+sdD+b*34G|3P*EbAB!nX0#A+&(c@m9X(2m`&4X0!L&G zm-Gv!(QJZ-#$P7B8Ngv+*jtWZT&!B3kGVIe(KNjG@aV{IY@ZPvbp&NTa?GnQroNI? zRhT#OLuUeqPK0fTfmw4{o@Zx>3!Rw(oaLv)jbi;f+!nB{$=Bvf*CL^2C0Rdj9ZF(8|j?hkURav={RE$pTLfcP)YoHz3#Go1S0IUEv zmfy}*x{AjqFJW6=p8;Hf<3%X8oItjM~}}5LU8Zo?_i$D2t6ae*wQAyTRv%IvaHx93%slGeuo6 z32wH}@wNNfb((B+!hTubnKH?9pDC>zB4ZgyB)OTMl)O!_|q_TLEENm19m{y;-Y#K48X`BL=rbv=IarNeK=4=!v z3>;9**1803}XNrRbNHPa8vg ze@1X9DRkD%_uT@YN!K_W53#t1#@DV=nU!R3SQ+qZ+Dzaw0WD&2ePK^dWqim76u6S) zyfu;dITnPB`A;WO6fW#X94o9SP$+v@A$XaCx$4Lkf#`2xt}Nw(%3X6?lPmTOiac>}gh!4y zbd9-HB^GPfd##YW1(+k3OD^(#qiOmUZs+0A(&e(UI8%yfC-|{RqEtx!`ewE~YA^K&kDr z;R72~9xp?`Ktak@SbQS-cjG00Vft~H&j1+;VpS{d?L-KG&Y1D==&a8)zHoL>fWq<>mg{o+rSuTh zht1>?v7%>g1!!rCsrsVqIel0kHgyU?>SaIDt;8OduWTHC?#$b@2mJ20{&n>3`W<_J z^50VJ=`Uk!rAuO4ak|Z=8@)Ik$M~6c%xD&OP7GJ4R;7Pd4wt^%bgtuA_kVr;q&wnE zH7h$-4&R;nX!?UTI5Usk?H7k!u5;M)Z@y$9@ttYvBB78ky%$&GXeXnsy6tiaTC6v@-d*>aSL)$7Bs4 z>^!!70!yWn6?4x^**`mMawM{bmq*fl{y^LC!R8z@YvNBl2NeUKxI|@U>YOl1I}(K| zRA57q3+ZheJm5y@JBRh=_z*ZhbjM)U#H6rY!g0s%crc_~eBnf+xZbUIzO6G?hIAZl zhl|=5sk|VIH5%YV<|0n6pBRV31_DvgoL=Uu6SC6Dl6gz)s9SoK!qR zB5HaxJVF&_iCz=ND(wI|$=|S}#u@z3#((Zsf2Z+q;#|+~L+4tZkTiCMxw?9)R?fQZ zAAQSWf0%fYhf|#c3-w3Bbbt)u+vpxp*>;A|ggsqB=|u+8W0K4)BLc3Z2(2D+_~y#( z%8Pi>6syW8u?&+o_dH)SYtcVOKOp~sH^jl=Bf?e-nQ!7TQpn;gsn*?8zj67g_N~2H z4$jo`%i6Zk2Aj*khb>gTrk0IcPjx@+=HXz6Wz?rympKVAOB959Zed$#8Ma?11|#9~ zk^Y|NZ~Nr3uWg!j=ARl~o)+MSXUnTgoV%F|H~iz)woKwBrf^oH0}jX!3gILMqjaDxn62lFi!w0y+!tBh{XCK>{-V5`jNG1-Bs79O5 zV))I-f|4hUOo5WF38;8Rv8g_B2S!-hl4XS8^oj1=0 zC;Dk4YTU5)rP8j`eZ|SM!7<0d$wSBPS1u4 z+j0IuE@*RU@a&!>{2O`DD zWNUK5J1-E3oa?EYKdTA1_WoJRLfk+BKye>S+|VsPnUjg=E?Lmseg{f@){Lb3LV?U$Tj7Jl0BOe5%^BQM2|`OYtMoO_h7;y;*RacjYbZXgnPIV?<#B_LcGv+LC%RaKnHUmPOMp3 z+8j}3S6=+Qp=1d{<-|*9rpz13V1qG00Yb`I0BZ|kqC{sf2H&nJTgtQk(Lb6!YHssh z0)`M&Q7eO6*)VL1t3MB=hA9k>#-f=%SV(IpZ1_IXFwCMI>2+{DCv-D@AAZByKc3~` z1gT*}YA|A53CVHo9lXo%(phZJYR(V&rB+^_I_>UP`w0-wn-#1B~NthqBauU(&7+8LERW_%3@v5djL zz+uexlfgh|bRukdg!7D1)PkgiFo^=XTk0M@H9&L7*j215>#_04og9>}D7)}YS-VNR z%5vVTA%7>I&Trzb%q7LcsRvw8wmfEfyfN~A#FL6-N&)}B={m>zgk)d<9r{Sv-9HtTa(F&v4_}Rk8 zSbV~aTr2_qiBb2l=DMN!3UJoEneC3T&*pWr-TIsMZ;WkMx>R>t=fQ++emMfylQ(0X zFpA>^cVZ#nE-dGC^d2}baprxP_ofoDVjUb5gJ2mcbD}bWUIi&D&fB&L-3A99khKLl zzcS=cu9k6jULYFj>j}VCJzX|$osJjl>$7tkGI*ZE3c9oq-sTY^?SdERU~hHyqv|md zBp4|b_?~jAv}T3$?LwQFtfrG3TIH^J&fw>_r8s=%IB*D=>dS0T>=#92lx!Sxyazcj zM$K41T)L5{;_VXs1W#v}NjTEcyC5+BZ>v*Z2Ir5`t(guvY=eWTloI9{DypiIx48o{ zLI`xk1@R-VPs!|(Q+?h*VA#S(l0>(Whz%d6!lX;fy_tH5V%8F&3h}1>iRuGhSzVIX z5($T67O56@x>~(mtJf8Nz`$qCM>vbGAL++h-UoiUcvA^|k?Fx5X8SRk!y}`i9>hzcW zI9emw@z{~Rza=`8K|rQ%xDe8`>pvkrWWH-|MLyG$xJ?Yihlzb+l=bel zwHv=u%()0B-Yp#4LgsOse8$Ev;J?{M8jP7qoOqW7)Zv}-ZiIABKiG2GMn6fcmggw} zw2N`L$Ug^Ms?oRJXNQ9*ru>SwB0nf}-R9h3o&9^S|6d-o^MS?p3k?6pq38CmzI_PO zQGH~7V^bT93Vs|Vx?K7dz6ZbPc#od!^Z9?7=lKeBDJb|$H@d1YC~2j{a$arF=`17rPuvL9M1rXflk8>V72;R0l=fXy#Y~kxr@=hVB}uoM zr0?Mn3emQ7Pcs(4T_YXoyVW)=`9yWF=2uIWZ@tiMlMg&8AAI`Fz~WkFJn_FUxfh6&*fVSzr*K zlAg5q-qfddd=Q;#Bdz&$6!BLnVt9DC8mH_KVEOz)aG)pkLE%7^OlE9{b~NF~o`{2G zd;mC}PtW&w=f6LNPifxBFlihe?npgl>QNXd<5To*iJvp|ivFMB+GKn)c7^z*5y#ig-Hb2>1e!Sv6xkzp^M$H578s+s$ zTIK0%=>z6h&NUyq`?2qOrF)ReR#9!%`C`jdI5c$W#&dJpYM}qBLtf3FS(AOy#;5Ts zdI#$lg5t|J^eR*B%Kh`egAP*_SY6`WDS-yW@CAn*X5s-=haE8-Z#`-A5? zQa|vbG;(NG((4Y4to0r9@%RdK4n)truzxk_`)TwaRKSRNj_RQQ#EoEoN9lid`6$q3 zNq)qeUbMVzJ!)Wu`9n>wZ``G8e7mZMGcWpKS-pI%@3ug|7&Yx)EVHuS$-_bar3AAL!+LKvm4XN}zb&>XPW+2Cp_xA2zgA&S${BSGeZO2FUza%HUcLx4s_3;;N>w+wX zQZF63rl!v>I{qcd`S9QqYbuS`EAE6Dw|M#MgRKXC;v0&+q@OqFY{aO1VvKLMtbfMn zGWnmq!Nu#h_Lh$W>k-Wdf<0B?E3jj$Z-$TNgWw>)mFEq5O^zQ;F1z^3<*$DF;g!j% z=2`CAt4(gL^PtZ6uUf3B{!KcnrU(7ce#t!6mu~%#fRx6=Ne**CL%XJ3GE2HE`m?8J z1$?WI9WUd1g432v47Mg$$H&#=`JOM;`WtiQdI zv+M(Z4BpvLn)eEr`R2 z?EFXi0M>t_Z^%#jk4c8bKIQXf>X#!O!B_w7`Q*pR5WF6Z;EXk~efUR}^b7dP+xuy` z%e3p}<)`Z129meij3)M~@Uo2ZX9SGv(wL%4;tV|^@(>?s^v&Q4E)NPkX;WI z+HK4c{}I2WdJOAqx^g%JZjUKP>DyG;yAtFGVqa#r)A|cNX|6Nrsukl81;5#`rQi7A z=FO*`-^!1J_?{K}2W9gP%KU`ad|aIeO|e4=0Hxode1+>_oq4yq?5#!))9zk>!B&0zS3mazoBeXASt+0`T+8*V4B^k7K<0 zJR{iuiCsy)f8vQ>BNw@7-@4>8vm3`F!Ncb__CJSP_BYQseOw0xFWQYLY{|q(Pap6} z64pygzntOuO7!i&EO)JVt8Lbqr#qJA9}0f!+QzQ${JQP-gU|2T$m3JRcy$;0XYzq0 z-nIHE`NI6W{NMi6`fd)4nSQ8Bg80(a7e5B&Wv=Hp7R`F#opcKaD9jR%roKsb6X^}& zgK5?y(nC!(hXV4;*G@yA2rmhe7Etg^-ZVorfkRR-k$Gylj@ZINg`ea^@2Lo9yxwK_9{bs zvU2|@$LBHdCN=>}Ir6pBjRVIb`rT{jB_}o7&Ed@WE&`meH|X8U8;k^8t0{3z$_n|! zm>i!l--JN@qv)MHCEjV~g_vG~OFQTQ?L*sL-Tb^&8?UlcLR5rLJ4>t8mm06gW;C#T z-bAG<5H_&(I^ypX@|cc&_y8x6;~2YDIxpu%{hUQXr0IuZqq6miDto+%=9hd?iXWQ$m>uR@l|uB6bzhO= z=&uzp#mU66=F~knN)};OH#R)Fx4(tmzT9Q!Mwdff_Oqe@^TALtkima2ABcQ1#g&Z8%i3tr>nJj*aXGHiJqj_ zgYfDu3X?Pj*Nr^i{9s#;i;4zp{9@LZm}5mj)pH$f{reZqT37pn?X$Y(V{%HD%Ygc8 zQ;}8Z_bxeUx{L^7?LR*|{LeNxcCcq@&F1ha){##Ojn^Z!sih6CdKax+_o1i9`T1Z_ zrjNMKc@OM#9&owczI#IFc3N^?#(#w!ZHgBs6xdGJv%`5_8bg8+Ik0y50K!(jNGMm( z2X;7UL==FSdILW|%J|#Ta4EnJ!D$t~JMW%H7WK+LrFr=y>o4{kz}Zwb`Ct&7OhMtA zZ_4rOZLHU<-@p=7x(J_!Sb-p(lirX!@ye>x?V+UKM=xjL;aCI-Zn<#ISRJyLumHM5 z$t{PxXEP;qObWjtZ^T}L^=;XMuvJkcnBJtG9Q+crq1?&AF=aW9AMNS8Jy08IK|IExTMOqP`aMR2Acs@YDS>9JDglnxnS<|~b{l^ru5fSgS(M4~ref+UgeR88g z2k$Fg;djh~_o;t8K5R-4QXz&B&?0)zwVIk>Fd9AG*XrnUw($L9q42PY0QkP%v#I90 z9}I4ej`pRd;L8QX^$3vcJaQu#h-&Esxl+(=VuK5suyjfKQZYV?82dcqlp57eTx+h` z5kv^Qdx5=wu8F2u8*9(J*;bQ;X6b)w(Xw@0j(%h5=Jw|g*ytxJ2X;!ya9+}sb|Z(X zxi8;1-IJg^s`gr`ReaL@Qrs*k$(ycp|I%G+<)^%#aU8L?3pg?UPO92l^T?889ix5E zEDmfPeyw^=SM&Zs+c?x{P(Nv$$AFx3`E~_Cpna|w&_s20P0fQ##C_L88cRqk7~!C`QVN=>8YMS?(UOp{Nl-}FfKrd zBLa=X;uqt5s@rQH2MetjqO}UKfF=2L(W8Cg@pZ|ksw>Pd5n{L_UZWrehIv!PZNmdS ztzuWz1m8cVwzL@TUNRmHo;a`87*%bvChT-xG2Rw5-jw?d#1`^Ldsd8Z z4xTxWy^aTSc6|Qph%LMs-JDB)pmAHYPqpYm47_`&cfyt6HFuVYy9@#BE^ z#BgwhpE#)pj0JVDG5wsstzF9VV5mb818$tJ^3q~+iyF>Kf!mi5FuAS_->&P5Os~L* z?+c*X;*fX2l_nG4+P44hI>#eKo&Kd%qA~FK-7TFL*UpQ%V_F!4a!Z}FZTT676#foFI)QH9=! z#0}jcIgyZnJFF!V)3h5NW#K^0xg|~n?zRWI)K{~exVGl8B~Sx> zF9g~?p8Br$=Ye~YKjGUoMrt+33O&4dbFDh2v%lHv06{ zMQ!U+Kj`ad#LGWTbaMTpS4M@-wAI9|{L+%&x25(s-@ZO5 zj@a#DwgczW$nm(+II$*r_-b7sJZ$yvW3C|^K5xS~UhQ%wPO;>5@=Ycm7~YL8gip0KuUC)cGGE!b^%1Ey{&jD9hkyS$9?o^DXBk8?A5CBNhY@Q3{>vk; z?gJB^KT@+h!;Ql#Fe85p{yFS%4fSS{FL^01DOY(oLGq-eeeq!A{PL&X{`&rHuV~;a zhsjroEQe3@H;l_kX3_b9oVjkvXZqy8!h@Ij{z-!8N>Gx+Mt@|H^1#IL))nKM&05c?h2{FV)!3VCTyHDn%J&5qO}kEdl5f9Y)SN!i&p|HFbq|HJ`jYwAfag?`|XHe5kFom~H{-l^i5Vbkx& zyBS?D7Aw?&VhwVrQmb;n-*WbBa*ipbWS`*eHaQNT6+h@|ocNTSMSO^E9m-$%N67}^ z;au=N8%73>v@VB!I(UPjhU0-Zj(Ydpf81V2Oa7Y*ixM&5S#7n+rSfLwlt20)ibm{l z3lolM3r}2DX}!57k*1^*M=HYM%sI%rC>d|aFpSl0RNP$wA70S*W6G&jz5NCp@|T4lGt z_rbZ9;iPRw(u*8e|3M8xS__Hn>zL9^5!5kFvRCvU+B{DpJs8nPyw8Hbw| zu8v)4kP5|o#d>}>sEB%6jl*a0AI0^$M667fn^8c|fnhze;(CbJ-G zr@38X45Ab8_szla2+?t}uV`AcukGBuJ4UxO{IcmG_TniV?57QArLjViFhd~>bhBN_ouPM9=?J8z^- z87~AyI8X#|P@zq=WIOW%LJS2umqwDfUC=(Jb71T@Z^18vfzgHl&8(W*;0H$brn{F& znoqyXgR!>^RI6oL$#5NaW7lWMyq$QKW`w(}c&sX)$x}zeLmF8-D?b)-q?|TC-u0U| zOhaU!)$W4PCV3Nee;4z^~T;dw*T!zix&K}>4%qA2cCS8j~5F{ ztC#jKY*SNT%J)C9=-qW6czUSm$^UuV7yhh@&x;fB8VZH^ln*G>%ZJ`HeE5mGG~s~L z8U8)aN19L*$)ATV56=w=!wW-Y=YmoE6!MJ>03Bvpcq=JRq%DsZQyfGWu=_{e8EU%; zoXfK8eTs?zjWVz^hIh*C4t2J^@Z`!)o-QPnVIv96*Dw}S2L@ZkbMA{uc4zGP<1rr2 z^Hvu2#dH2OYf?QgywKX#)g{iIJHIv(Nj@>##|@Y0Z0T;}npzXv)tWM^ea>#Lf86Gm zVJSL;GDvc2>uLgvhhgL|kU!Egd~r77ksLmVY4{*=L8!R6y4+>h^FjRaB@Y^xt{l2W$*F~`dja#vli*K5$JBX<}B4yW4{a%Ae? zw)anWocNjk!gGV?_NM&l*3Vu~RLx4>eY|6-l6sAAS7;a?xLaGMKRgk5;)Zg_KYwUZ z_~&wJUQ6)e12#A`oD||G6OlcKKK;U?wO5Y8Q1;jFYfARK&%-&Ep1=l(Fiv5?dgL4plBqz=hWRIwo{ zZWUaja^ot#wcCH5m&elE)uGm8HxBD?2Yt~HZu70IT%Ym{nQ?De6BY9=Y@2e@AAvW4 z+K1XmQ)&}#hyUpPQCf?+fnWhgbpHT20f8+KOw9%(Yvm#AaYDeEYi-!F4aw~DT)`NC z&1Rp{dQ?al{jWTUY-vTZQ&4VD0{-DO*hzP#QTh~2SS6qix8|@+IdWY8i0Mh)nF}tA zLB$<&>NvPE)A^ddhlf+C<>Cpl8He$6_I(Tr(Y3PuoMHoNc*q4_kcZVL(}n}w=FG=A ze8qi>Vd{*_pb5j4N18R+mF3_-7c^{KGk=8C>*iPlkX z)4-MZirZ&slKnorJ;}D=1gzCYs!GB8EZ2jtd?&pT(X{dSagf~}W0!7FLMwhje@0j- z?n3Fs)clr)BeR_?KD;j#hvS3<^sd7jQ?P?8LBAKGk!b5nFW z+^t1?WeWdE3+rKvTs%^@{PzF)E7CFs(#uYqzlB4tCOd}@(!%QCylCJAHpjJ_rr15f zNJsCu8CvJyz<&yzVc_X}{G&-9R@`akm-vP1c;5OCMtqRL-kGAJv&&`tS%0uC+KZgy z{cGI4_ttLy(^F4&$iHuqFE;wPc0p$q#Tbbv8fzbHI@&59G}X-R9J17I8=SgO1K)Ri z<;c>-o7X3wsav^tSM+?}_zs*g(8=M$#wo~ec*68RmY7|t*gqF14tOJOX|$#?EFql2 z&)Kg#wp#nBZ2Vk=i%;NL*c;%ng852TmDa{yD7&1~y1!BT+BFJ<#(#@KfTj7((y8i~-)8oFG7JBk zb}E6A`>Noq4ewZ?!d=mxw@JUr{Mi$;8d$@T%FXDE}e%{Sk6_y$J0PU==hBp_Vx$b_8zCzg1<=r#m^7)w=VD6 zG%-|7etg4-YMrOV!^Ij-pbETI>AoSgRS(ZgElY11I8X7235^G1>a#n8kq7cLj#k>M zIbIvw9ZkJ$zT$=lBsn*LvBUe_53OJOV%MfQCs#%;ynh$o-@)6bEdFo$^WJrVr`~Nk zw5j&w(g!z_o&PWI*2=Ouv`LiQem`P4q`Mxhe&=@Cx4@U<`M$_kh*_9iP)hF|yh>k8 zUhs!b`~q5{)xfEnc+p>UQTjo(C;k!kD~B=(M65Yt)-#~WW3t{BdHX5+#{&278tsTu zC8IOyK5c?<$U8R(x<&^ z6@Ah`vh%aWe|d}l(o5CN+9_iXLvSfnZ);ax*c^QMf$={7;x$|0BQ^AIUvwaPaV+by z=evpTAxA8p?-LqtZ{PjBBZJ&FOKu>F$9RRQ+J=clb^N*%l(8F!Ey+(^7mU1_N_*NM zJ#^}sj+OnNHb$ajX+gD(mtpHP_AnV=@h%U1c7k5sY-W?j720IZU$*h;qGlQ*N-8aY{_vM?V9cI~4ncncc z0~0QMrmg)#@`c=x_Fuiu z?D13RN#l88o%qzds<>e^-J$l!gIyic+nC!jenCUp{XbqEIn?v+7~)~0s=QO#9f)l$ zJNIMBjq%5lzo`Dsk;o%Ye))5MBGt+tFkabs`SjeDP8(flU4R`ctMRwBtyp1b{aA6G zQm(f368)Zvm2INkJg@eQ{5atl|H{}{I06g3wb^eRa;#e>S;*A&F$W{`31jd zG2Qq}gp!=!`Wf<#;a8Dw{L61Twm5w}K8A@OjYQegHz?8ARULnI#`7`E;^BaG>{E#m zigj~mu4CaFh0B~~anvovQPyMYAI9q$RUR;owm1F$52ce!*S@MRI{MRZyt_pi*nl}H zUGlTWXdudt7y*>PpSeaQ@QAIvheIHkUV>s&X7>(e#P@spr>y0d>Q_)wUR47yr<>EDH+D^7y<9jbAH2^*?Pi9oXbPgBry+ zmg79_6UDnGxl3BO;S|{E1cdCNEhm?5+njp--gV!6CsMY~xZWBu^L+bA-g33VOZCE~ zGgegY{W5&UDWxNL!U)!EduL#2{8jyVW1aZkgrtOQ<3Q#42Szt7{O0oyt^4M?4=wxF zKW+Keo0}G1(W{!~rnv4g^-J%4Bf2^Lynow1?8jMleM{sU=RdLex2J+5)%<$I)W3P} zjjm17$?ACi=tCd;)_?koZ~ps3uO9mMyK17#PxJW9jd6&JRvCHkoWWNj4aOi|E6Yrxm0YSZ4dg!W;+0$Pni9w4s^L(ekbJ;%v~s+&Xm%kv+}}!)OSxi=+1DqW8pK6|q2IkF^?T9j<^6eh=;8dw45%#nS7 zQ~+XU34z~@T^>KB$Ibd@q~c?E-A?#Fq`PD@IfOF0A~O10X84!gPC_EwLix4@*T)}3 z#VF=(6t{N@S72Xxczj4Yqte#P-k+c}d+m;<$9;nd987kwy+?* z0IuR`6FwDAWTSDKkLzsh1S$bV6tCEAWZwLB zA|leND#nrU=5g4Leci|WQYo%MbV>D?H3715+&tIbHeRVpuAYZ*V^mA`e5~eyVE_3= zH4g@R{&>}Qw|tz}rvlQJ;WOV{_6J)|ed~cwCHuV7_@N?pg!bSdgPgh{+TXV*@P*+j z`OoI1T0WYw`wOr`O^@|Gvp7esffGK0(09;175K&T)~oDHU+XKS%o<&NIyF3!MR;yc$=Nymbx3~}Il@KJTLc7++!Y^W<5;oQ# zj0pLtR&KxlKeYL}Egvtc5n}}V_urqOa57@2t6@yntozuVBW3ay#~KjdXBLAzeKmlh zrM~LFSlIIGU&(ejcGwt0dF)z4Up?_JsplKs-(J(T1e^1Zdv^zT`@ocQY$$sl?)aH& z*q1;0>I1>_FF)FNVb~Gk#tS}(N0oGAZapF9sJU!=?D*$C`(0-36Q08NIMKVF{l}xOojInTxh6Vy{qk64K7d@FXJ4RV zxaf&%h^U|@kKLaCcdXh=#<>2GykSGUsjn!lKxEqY?EYV0mnEfzhoc`@Up^OWXU}*Y zZFflLu*)Pq8yPPf*=~mJD<2pp-S2}mR{9(A=1hBuTtHT z?CZVs`*J;`B#rY*zaRP(ryD>Ip?m=A!bhrxWt)BPN%h6A$k82NUFtu%e00sXnnP|@ zsedItrMNu#jj7YA3VcedZ(8vO-^wRZ*+tZY6s;6rnquF-bxBE{`B2+C$vbmDeeka5 zzJC0n?$1@g=emq^HwsfVLl5LuFBtc`hAQ??l4c{Wvc&l9tfRNB_^noJyisTuo)b?$ zQ9?=@`}p3$M&lDWkI@)iDgWfJpZs@Oyg1j#^8vvH7r=DcFp>0!#}$Z6P`U8o*+UiJ zu&?(WX+utjWrzI>(dKzS4E^_?f2xd63x*-`zh)Mya9d1sOg3GxBPbk6`Q%CSvXBlb z!qN7Ypz@fyQ9Cn%Kt5F;*5VYqG&a9%D6gJ!t|U2FHH&wxJ(k=F zni$=V+uaW2Vefk_vxn=T2PJwQyp0+Ab`;|>YsVq?C}efJJ3ZZF{QSZ!GtQxeEabd6 zyFTRB=IFB!P70X^5OU}kRb9D8WW2Vv?Q<7?_>0gPdMlMcsl|V&Ciwo!skRD>3-GTFrLh9JsmKS;cE6O>}GsuxErmr$S<-|+xfZjG-%m1+Qy4Kr~FQR$?$BC8g z2Lt^u>twVNBhgEiE5lXBce?KM<&WC;-IWY=lTVw9C$N?8S2N*MGvsxkS)#ks!BPAQhKM9movH*ioEhle?tY{kA4VHC4k&e@9jg%kYg2HJD=GoP z*UQdrH2HME5v%`P_CC;g3ShjdUG z`|fo0pm9}@{2#ty>NTve{AI#HAP`57oz;Jrk6~+*pyB+#%b89NPVgAR5&6f>O54W{ zQeiKN-$12$5c7w*Em!|P!oCGAit}oJW*J}>SD9Tfq7s>1mTOHw6I0UI?Ci4Wf+iwj zu6_lTB%0bUByGQ%6x?B1bwQNnVqy~-&|rcz{bDX{(|&DOa8)oS8f#i}X+c90W77sr zY!H{7|MSj*%q-ad_V;Tt@%6o)_nh;d%X8+*{Fz2Lo<;JIcsR%#MSrA&LkR?z4*6=N zRu>#puwZel^@bn+U*+9dY69Sj`rl znRBf5x{OiIPnj8b>80~$a^pnB{Lo))F9NNh;2_>?VZ435r+}-23-b7Ot@2_b$Q)c~ ziw1hJw&{{N$`Q%UfSV}Y^+B{szbEH$QkDf0I5hl&XOVoA1pXHmhr&?37LKg|`}RWZ zEeW_{5M;*@;0jxsYFzpK8w5ZBf`$$AA9ie=I|B{V%RhMih8)#8{1z6OKxW=yZ5=U2 z*&=7mh-a}aAH>Bg`5MFw!{t}NrqWn2zh!0OzRnvHfu~rw;9yUhqC0{O4O=$tT3ff4 z69k;?*=1JrG-8f-%=Z>pTHr-o z8TndF)}-^rxgm+gO6auYFh6yFL_Kg+NXz(UTRIXKTaR6%7gc{Dd|;;(Da`Se9c9b0 zFFjH7awgLsmQffCBs-RS8!Z8A-L{y7k3WywTv+{TRI+k@4?KHTr@mn^f)ZIP3=^P&=L|$i~E$4+om&q2|8&9&Da5OShe#=IiVLs`f^FWsIx=migi$o$hJytFzf|ujE&Z`k-n7pyKmAi zxns@`KAm)ruFM_#K_ zvcjJXZa>Ja0H_1(=-Ek!29)O(rHPU*vabgtnSA}LN7j@J#9cU#n@oSyc_-(oBq?L2 z^i4mg7$|VI;5}0m`9@5Z>K-NaQeJ0;CO_cCz7*nKT3UeTv@+$j2UPbGNqkJ9qvHAe zw&oygYk{^*=f`8~NY7F33+Iqdl6x6wMEuZ-FI_Rx$C=z;R;GmU7lzEw5%|c_{7le@ z{yZ_3mhL!v;p4Bqrm~-cZ#YkiqcrAcOOF4qP1Ut?5YY$|F(J7q2xNn`!OEO<3^ui=c4H-qN-gr?pZtR%SBLL-DcM)QXGZ(TF*CAbLo2zmO{`_L*XnkR!RxrgZ}c zG`rdQ&ht<=fMkd`)sL0?Lh(yS#cgzg6eM`zmP5W4;4oX{K;n7I?#9+zO4FftBY4jk z{KF1B3=}{4-8jz2smCR3QfcT}pw>?*$*F0aZZF|+; z*#pg&r~|R8b&R(IE{Xh3zTSC^ottQ&lI5-d4{@7_aFm9Msj1_y6!bzyiIoP3b$&8#N_c-1;C*#0I~l)3UPlit$Awci+O0`o z_=Mv|-I2!t*P!@~uNUF=2%tmIs#Hf$6|bk*ztH@6#-32OcDhTarh~Emy5Pqa2`&jq z`yy_JN$>s8xm9WKu0XC-$bKL{=hXVRVqBaX_Qb*niQ-MvyAjb-oo}0_Vz?&GkkY=g zw`x|@WZa&KeIA>in-N__+6K5p(2I{JYF=zM>@;eQx1F=3(k1Ti!g}swQ>*&_ktXuhu|D9LfRCOaFJou^Z5uumYu27`_hlw-@K;#<>x-ET11KiN|?BmQ4Hz-2;P<5#;mjpNk*xRN53$p^DEmWjsID_V55HxLqk43hnuWBlq}ILobZ@;~ zMOQ>JGERx`eM<0&-BgcUl?`;27)jV){)q7D5aZyOs6Tmy65vP*wF9Ob$_vWHDn-g6o_ z+h*$g+It>;@jg2W*E>I>n%8bv=e2{AE60rVWZ_QWd zd4=NoT)Y!?IM!Z*8qo{KES$DMp5q4;^a6%Ql|Wa-K1W;~cI!7-T74Q~=gL;M)A2ju z4~Pg3!hR3*l+T3+r77Eyb0r2uYI?tC1oX0%SX-T~Ei&=a1*Ibodvm2~Zs1Pa!C6I#e5*EzZHZCw?UUrI2c)ok5YLOGL`n*klAuC#04t*P(2O zdEJ`Z8_-Xck2pTA1p-yHX1i{$o6SW$5>f4v~ZWn54ix-_B_oTN601zhi zLqw?bl8JVZ9)`9yA*_fp8aZ8Y= z>G0GTotI`t_Vx0!q`mCXvk~hyXNUDyBJE>Kf_o#KBkq|X3!te296l@`hs+QCiTT0b zYL|YUZtm~nZg4Jg^?tye%Tm%Q;RhDk(jSUUBYcw31aT`V_b((5fC&=9%}ao*X95mO zF+Yt)4m{>MjH^c4W-fo!vwLo4Vlmh8_(eqAD%!YVsK%j@` zSHS+vcUp^G2O?LEw9j;8dRJRQpO@Gq<@^|8QI-`JqPUjQVl>XzF*y&7jy-1>E7%wu zuix0!$HHd-ai^FcRTB}%m=acG4f$MEHFP6A2)_Z5HsSJjtS%nzFM&WH?0QOlh|CWR z9zWt|r-<_wdB>q5ZpvZtYGX5#iun#J;A%&O7;&ca0#`i0Q!ooU5+9nW1{GlNsKV{xEP z$xS5@{MBobM#Xh)SoK_mQy z;F5rE;8g}yLhnwN{3?A7>rLof`~GN0!>ZJmEA27$?`L-&!a5%R`b|~d?D+o4@?$z& z4HQMl_V(Mu{8pe_=LKxUft~lvXu}N=SKry0S6q7lG2$w{eY`)y$BFkGkpL$tUYHd3 z5ZV`!B8rlB+SlJ8hpeQP-~esi_B|y%kN0O87EZne;Tj}(c(X3AEvWuWg;%jJEN8*S zLca>-lMrok01)@yILl|MJOT}8*OQHv@6lGW&uk`N9Q>6&z())#`osP?JF8X)J0tHM z>4+@BokORJfr`tIt-w3V4L){)clRNjKpGO*Qjm2O?*KB@qX1U+Haf>=%Ttk`V8yC6~3}Ra4&r+8d4Y@t>qp473$>M##eyE_J`Ii|B zfs(Ta$wR(KRXd$_{%yVa^lvqe>903hZ|k|uZ}$8M8h+zIgj2O%#MLJu&InRHgj?YQ z`*OA2_;^?yK;Qt83oRRZlV$h4Wjk)`n`^_^YaMp`%0e!A$0} zLOqElFJ%V=BODA&7+&9yJQ8j>fsaimOgJ=;uyJKvQxOxA-}~SjA_18!N0m5>a=ma1 zk1qm#Vk)$hHo(w`k&?RINoXbHKV#fkVE%-m`AGUCobD6HfonK4&bXtPSp3m-+R-%e zA7RNvzp{!w!MezU+IqlMhUN7}=&K)wMKOdocSSrxeH8RDNyB`&{U!Eo`}aG>M%962Rzad<-DxlO9MG>a?awQy-96KkX+K@_e<(EM-K-dx?)LqQDvy41I1$zt$Qe(x z)MDH~6zUv}qM00*f&E3~k{NYbp1G2~u&@mIbWcyh_W`5zhx~NVi$P&vo1xUY9MyVh zTy%@Gr(tVy%+hb_v@9QUoxbQFnL=WxGHD~BcWoE0j92WZIiNC)_uDKqc%uHUn^GrJNL4X@>=TovL) z^4_QLK*XsrF7>{U_|q-Y`*df-y}>rZ{}wqfi0?~((Ad@WsL&2K9OFh7#k_P`z_|8D zJ!pq8;(F!%AoF|68PYe}w&rKn?k3`7!<&t{<~k)EjK{Ue@(q4i5yuE9*|RfjVf#Y) zoos$ZG30O2i@(Xw?79pvyW-&QK^5DF6zkQRV%!WY;*EJfU3H(mAz#MXk@LV4Rr{>s zYq00Y*JYeTDEb3K!8m`vG) zJymJdR~SvXq8(90b*#Zzmb@pgt)?5eGfY1Bn(^-3%S?>29mN^UWsVPjvwztGzk6wU z-!BZe{d!~3=+)|Ijhg>y^wU#+`(S$Wf`n5)eE&RKFP-CoScF_K!uzPxBp}CTy{6DqqQpq>6e=e)Sn5V8HDtRo=rDwGw$g=JL3s8PR!VOkQz4MJGVOTtzM#!PsRZn-{%roV=d

Mx%KrV)@@{qzl*L#lI=*I}eeFh5kI`pk0x!O&*=iK}#! zO0OGR2iA+~GbY}StPYMs7Q^orr1m(J=P|Yp%ug$gFe!Lf%t}kX&sTNh6QAXTx5EMj zw={}w!y?+KE|Tk&0T@2ZHVN4@U~i z_G!plrQQ_|I1B-NjWWhgn7iG5p z^}qPe-20UM5kDgCwh^*ra2P1na}l+22O>*{BGmMZynKQ&0oBl&bhVpAs+!phDF^A| zv8wZBlAJC*Yf1}>HD|e!^X@ojGl%|!A(y&8sMt2KrqWcqb>@Zi;`?6tKcQIs{S@Om zC7?8;o@SAIKfqGG2QCT^iw7o;OA|&3CM5+4qa{z#YdlL1^SicWfp$kRT!r*9^mW`$ z7yKUtIwL$@G$b&tIe19-V{v$DT)N3}i^7WpcGfWbItq>*QSX!}B3dG@LWgDmKG_#L zXDAUWsNxq{--mP|UJ4Qs6cK$6@<~@!Gh=R8yK%kPNpK+uM$CZRGyau{7*cdc)(=Pg|SJ5z515L%FoptH!c}v(jgyxENnd#PXjrVbEmx?kT5w|zHc0V{^}vYfbbGJDbVa$fStJRwZz~GRa@IqlvYp(C zhac*u4T)vC`e`_g1*mN}FY9wr`F@L~&N)d=DaD$fz-SoLi`3p^ZCedRe%9$>5DZRy)v%a#4L8_hik zni~PmY-~WEw9kk_u#ieY&gv5t?Pf@W6voS*p}zkHb+tk!edvrE{_p^Q=LCuU#^O~p{e8{e}v^r zhwb_4r3>x;VH8@+HMjIdEQ~s;oF8z-+4uBWFWT?(Y^|JwFweLD5ntHxLP?(ZY;>t& zVAvyopz8e6xX?EJ-MBT6E^7YYjU;eSXUlf`6zwRnImmlv;z(}-+z>U(}{W&a20?4Ez2kQ+z~&#v8i-G(TpPRGR|HK7rS}!Nt%kXoTfa; z^XJQR54Pke8j{= zbfVaSM|3Io1twjDoRvbm!1-0_{|ziJI2&Y1tZGN<=6b3Z)O8<3p#0hL{{g;$cB=ZJ zn4Z&%Am(T|cm!kDC92Mv-ZMqrO|+A|`chL;koR=!EuS&*a&!&^x4Nz`7}IR_NcNfD z!CQ1CUx*M*mJY;eP1+Z?3Ag$BHGg-qv+WBvUGJFSR z{EWca5tRoFlSOskH@~gvgBH}E&pxfc^$)01Sd;P>gr5q^^W_=o&(zwWfk_+g)hB(% z#iMN34W7w$H|2V`3%S1r(}j~&S^qAa-}QxnI(C{O<|XAiG{(px!%LqQ#Jo}B5dU1! zzVZyRFHO7hil6(D*`pkniG;$uJ{aGg;W*U*Bb_cGW2*XeMHbC@>GNZZxxn$KRa|@i z{TIBhl)DR>_y34hwnGRF{s)fQ>)7Mf^9zOf;!4fANI+8IJ}K6LR_mxT>OPkDt~9=8 zGuJ(tz0P-3tK-U(yOixha#i*VMN-pXq^C+_*2m{=i1V5)VeLSXcWR>j3Fil9(Y|at z8|6YGdgBmVplk=>KIUH_aTzElLubb%$45-+FVwD07UE;=47W_tA5lbRIy<2(9iWS% z+DYkSn4~~ds9B>tUp&6#cNyLvbcDuWZ|@TttM+R@j5DVKqh0Zn=O;h3!MO34C@SVq z{Gkm^Ve7^9U^As+Q%7E5?cSN1Oy@UK*RMqf<9J^rmfS~)8jU0V$cAUa`-7b51z`J< z^{o3A_BcoTN)7AHxs&!!BjdpvO%HF{P+o3*{lDjzUVnbykxmO8dy8zZj4qh7ZV^e7 z)|*WBHKKC8xaTu6Z!13XN;Ld4kwT1X5)9R>* zgr7?;tTq%sBnnfnH<-Yba?Sun60y>-GgI%ghC$J~V(C}LVp|97-bts&UfzPxsytuF z*%NyjjHVau>3bGXJ+q>ROJml>+cwM!-)Ea1Q}ci`2PJ-a?Ff9iVtndr+iotYf* zya?M`VOvfBvw}X9HYl(PatYC?i$`^kUo^~H$JJf$ezd}5R>Zww%(NAMnU!5mf$ndK zPo6~gkTX;!MeO&*FYF7U-rX7oWG7eOs&;Lx)d?%A7+OvBr?ACVjvdH=%iB}qiR ziG6_kP0F%@#^0nA*y49-;|-h4o(B_NPEf2Pwg-5Zc*1Nh^j4u%M_Tj7^rBPyQ|`+@ z={4f8ul-2gamc?AnxFaB<-I##Rz#iK=av0|UMR0MYsBW>S@XDDpN=wE&4+rM!uY|& zLxNA1P@lwDXMJt|&P@w9`5ige1||Q(Q!uHKKr{q|{U^F&n8eKV;xoURy=LA^pAy}j zqUVr*M&FTqZ?I$Q z${5Qx@s17NhGf(7`_%W1hd)ZZhdMA?RM5U#3%&u^0#sHa^`}cGW=GyF5*&T}uSQn_ zyU9X4@_>J!P2qM-lH3>Le8bgQxANfL?j=1r1C(Z}`4N4R_(O@m3-g|~OJAI1&@CWrIU?Z>vIfU>x+G&=;I?|s$nPyS8i@g?4O-1Q+ zy4m>)tAC_9HFNtXR1~G29}|0lTP+dbq*q1@=kT{WdttFl3$Jra^eeOrc34Y@y%_h6 z&`Xfeiziz#Kd=Kh(#HD}aK5xhhq5716stu=J1UaW!eGif?XC|3ZM64)q&=cIbKAyA ze2CBi3dy|OwCdsZoe$12pQc#7;q{v`!|L1;dwYg-+I>JnOp90@4s3Q?>5GEPdzRr z8z5kN4rWu*x0DI7WFj?lTShn?P(4Xz_eS=fU`NN<`gT$5s2I`MyA1XSBHu!B zS~RsXvh8N4vOgj(Tj8LPaoPgxo}}NMEv4OJdh<#3xKu>{DC=T9lEg%{|Ik_ny&n0$ zs7@MNt;Q$RtU&%k)+u3r*Gk(t_b;y=oL)QSJ(vB6UT(w2hK99k_rCbBvqYdG#f+Cv zu298YYs?!S>nfy-@MF_g=EQwI$U0WFioW#YVeE3&wuFLIRe;N8l0q4R}4N#X#;{3OiG;t%gBYfDfZ z2dvDHGtz3!uSN?st)u2=o!{UYj)3$%)`90YD;nZm;rW&Hq3L&{rJB~ue5Ug>@CBx- z?@TB4`x(@2(T@g%TxkGxOGShuWH9fk&qMR`!RB9QJW%wzU*{J!?oS)p+)RL=>ry)J zDt=Y94uL|dHgFO&T^G3+=`xG>A!Amsrz*a4g^CUk|JV9eo2JApZVVRjHx(8)RZ|(7 z_hyCjKhV`R+y%r(9Qe+bW?^sO-31XY1nN%wGrTAq~dp;*-9D{GCc4C))i0!ZoTi&LM`xH4}g`OHfNSWUB8u zncuZ>$LM8>I>s8>F8z~v@WLB2SN!4ksP6rzpHLnS)!oARGX=Z{mn92Y*!1B?SB&93 zR8im2h4UA@8^7cp48E~Hzo7N9CPw-O_zaE6e+&0>8mAX6eCe4Fd2|0p?f+ERjeY+< z$?kS-41X^~4180PRkQN8w?42xd^JGTUoNO^Zx_Xkx-fdC^i(p1_zkNFf6Brrd!%Ou zicMtrK8l`~pgcF~nmrazCoVVbQg@_ghEB_Uuk_<;RXbMXTBSB(Le*=MKeOj~YGKUM z+kag1+yBYFMg{nnpVrp^ga>w8^yjsf{$cyk?=j4c?4xnN98mR#Ji{)?OZZ(0{>)

+`3}KD#uex1orifycHwv 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 literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/data/NTR_IPL_font_m.NFTR b/build/systemMenu_RED/data/NTR_IPL_font_m.NFTR new file mode 100644 index 0000000000000000000000000000000000000000..03ba3a4885cba7b2cd38400a749425587ae911cd GIT binary patch literal 107180 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%0DL@U>Kf~S+EhCEWuce3@ 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%0DTZOf#X>Myiij zB6d-7aDl^jQj260d8n&t+PYMb2a%-Xj;>ZlE{gbjB*cT)PBNa@VOcMvu%v%7Bj4IN z@MgqF!uHD;COt{v(4?E@H%*^8S0T@elX4mR`>55-XGaV{w-r&s`8YQj^Lw#*P)y1^ zNfnvWN6`B=3It2219^iGnV9oqU`u^%Amv7B25 zeq2T3YgAMYV$?3d0Hy$0?+_$O&K_OtV9bkKi+rX7IS}2dBZ6rTX9?#xU+s+1=3C}% zQx1$I<(d(g;jgv-7yNW(nB)xWhhcF{A59#um{la__db97%$ZztL?FeTWGl0{xB8h0 z5^8-TTHy!p<8ENGBT?2B#}PWgP290$N4h7yCEwbl^Y1%7{iwjJDTK7GFBo9eLy^eZ z50Mn(%-0LCA1#?}N)^ZryT1^SY8TZ~@@+x9zUU6~E4Lo((CueSMv#6ow!HG;YW@D4 zwM|N!g6WB|gVjHNJ-74MuXfh+{T&LHJ}w1t4_ehGJ;$Mj&@Z1tfe9~FVoKXK2*c7I z*~lfIPzGHVQm%Y66=*=C9m#yh^u!TZlZ!<_ za4fj$I{67-+V;n64dn-~Vu9@K2v#uXM9@7kW^gT-(7)XBlU7}rTW{?XO@_*cs`ZD4 zEy2x7nJZ0L#I&ChzxIw=6H^=glcUJeY{P8Y6Y4GWKRT2@?0Kg7;af4yLkv+cJn5Bj ztcA<5_C!LSr1z@s+}!=QmPQ^UH8$k258u4E=F*+s=-cal733*wqDw4idc=L~hs)oi zh>ARgYgbkj9?LsSfkMf$X52$reyPOMJmf!RWx%+!l0{AsrbxtCtV2;l&7~WBUAM`| z)$C@N_Tit?-ZA!`!FsNrdnPpY;m}@7isXqr=?SBHdXL7rlaWi0Ex1-{+ur`_natCV z)_*{On2z*utd6F8pSvLuBteM*Vglj4vTK!U$=I)y7S&uLRWx#w=-|B@wv@^hiwb;Q zt#XG>0p@M7A#a9r*wtx0!-|x|uTB`?nD`JC=owTNmv6A?{w+Uz{MO%o^xdED;&&V% z&mq0VKHj+h+TYwKpJy7Py?iXMC#P;)Y(qWR$>*7dXorQbIwLPxzUEhJ9pXz4xjtRC zw&DJR6870wY3r$4G_k3x)psDVALTwVR=uh_4aazSx28S9q?GrVO|JgY9nSr^@!+El zHk)LMo$@I-W_igr1qgWpN^3gw)wJIYmvezYZFZD(r7i2M8f)HS;y~hqecrnE4Y+WP z(n&rYv%b1#)rN<@@iTQtFf3W|?||;`5yNobvs7ZD#*x)^M^@+C;kfP+`W$c85QbClvd_Jr~M=9U7N-g zaVJz2iK67FLYzb%o1N{eUESEYc;1}krjL$*`6$9uk_vcJwhtG>d)}HCQ~_^(rl|JL z4}(h{JgNdxa&ynGZ;Y#eU%RHi|AvX+;#X9_qrbSOf8>7>fy7VOFd=K@6Ti5Y;~Q`M zVsORQz69_n$RGJfW80Fye4L1C(o+CAw!mRfb_C)9nh;5&1zn1t4DSisBd*>)GEBeY zLPl7QY!m7YMbue?`#xR=+x?KaeSn(_(cY=6KTD4e-d7$nyC}IxDs@g(HZ?j53qt3V zGpxRN*x6^$*b&QWA5a1>aGyNUmqRIKS|TvTSoS%D2Xi|vR5BYP>gEscJ-v1eJ4ZoJ zzv2ZUvDa{xwBa4~*NR*fk;~b8qJrd$&E$q08xh^(j-&W0xR)#`3M7%eyH{H!Nc#^0n(GPDMzzC8Hsqf_96XWqusicjx>jcGydBcecaJk@mBwvY?l%B^M`kwMGnMMG!cA+FIZ7Ce>mgg z(@iy{MPNxW)S>N~C$Hvo{Q6pO?WIVioAC+JH5{Ks6RG<*nV4M?MIS1N!n0&ks41?D zoygO0%wUuq-irr*&_0Ke+dFgQQ^siZs*8r`#R@)lB?&?-n4(MC%ct^QHXbg>95W?> z2v51?(>J<&-i(RPO$Kf>X%?4tLT2NXlSXTq3&^`k)BSm(Nn1`9iLk+k>3seNOprl^h#gqc}`JU=Qp zHfv0(IiAsz5D0=9GIS}&?R~a+qbaB!dsFGEi$#Yn?B~-V6UV#le`%LI|7>FHqEvjo zKyHb|OFVDy8{m->v24OF9?KTbQLK3!&j`n53qzp8ov9X^c-_SI)#yL(_?s&n)@nkHfVTh>dU5 zCg0EVh{C@F_%`kQGBlP5YVIRj-tc}dS-9simHo;{tpYY+vjde8;_VvI-Fa%#N-;N8bB-SNb0AZV^nH<2!2TP0yOk zn0I8I(>YplHsP&E$-4u=xqh}vsXXhEcFY9Xap5`i@NhBEwThu~ErIXi!hw`o6LCGU+yQ^C2lsPhOFH7aGYr<3PBt0+^3hBgtwz&)1R8w8zxhdda^I zp>A6NA7-AVm}bZrFwRG0+C$QNp%lzabJ?=)97}NR03=_+^iw2O&-U%5M4kiMtd}@> z{#j$kzOhi{ropbF++|E4P+I*K@sIDB^CpUBzyCLeY2Tk^>e_b+@*IKWdGC20Wu8N4 z@DFWR$0IhSBb~X-{hKOHD)aWvx$IcoUA^R^n;E&rH2;bPuPbxN1F$wHr?KAC?8DMK zm8(#n*Ie2A?k0s#DrA33?~ptZ$l^6IId1>Z0le+)(FP7iEw` z{UOu=p1y}|Jz{aeB2v*)*Y2GVDs5at@;dVBx~j+g>jr{t$lo!RB;-)!4`Bpq#*?b3 zn>7+?3q*G9^o=L%rSx+YUq+P<-`+>Y57;z7G9pQTYiz9Z;LVp%&NM6}_MAJXo@r zVQTVaM|9Rx(W;W)HQTC76Kxjud=!-{4~#c0cp%Dvy7_T>VC*h>+;-+ab}B%bWHAp{ zHjF2=j$l^*Xd(xqv;TW3-{b7J#Aj~g z_IZ$5F!i)I%18Y1&k&HR7y8+VQ2FkZkKnJY(V~K4uC#O^WX!v!5q2c1;qM~1JWaKoJ`N)M7mb7OZMO;yHMlN@nT63Obvk7B0qSe;;muIyJI190kC{U>3 z2_R)e1XFZi(c>S!5)?}dpa$XnAeMbH7)~(t&U85!feR&GN89u{P*{FWRjQ<53hHn) zZ_{DaIGQc%hvb}o3T+GVR< zo0q7GQ=&q-KPMNTB&*mNQ#*m+kLccReI*eYAi5UWbE&PkAKeap3x8+LELZK>M# zKC&YZ zb%2OzZ02pUFa=VA;{m<04C|%h!=|7yVs;lft%WZ#OcLdQTP#b!+~k7gRjFfVYWIC%Hfr@%2qlIA)?OUJe&2IsT5YPMhv$BSMK<$!rHrVJBQoq_7=Mxqng$#;PmB zziNhyv*aR6VrfI3m?JnYBks^kb6K0gZS6i7i`ApS%IKN9xD!Qg5#oq}>IJh-dA}G* z8Q=!J##BQO4(u?Z03Du-S5z5Wkjr69?~0J&{^f;6+7U2k#p`DsHP!Uh`&_f@6d-L= zx~KbYl)Z72PKy}x#zYc2SCUF1yV$rxcB%45v`xQ}hG?w4&$DGnfx%fr$Wx7CqZn5@ zniWTY-G%CXRT3F20T|k_@ZYN3FED{n@<>G`3DKDTI1)&bH|LGHeV3dio>lK9futj( zo8=Gh`Clqv_9bJ@g+`yNa9a}C*)~>HRW@N!O8#g^&9lauYc7@edJ9#2cHK0#aoq>r zyFJGfYZEWUhnr6BGzAi88S?KE()WKNNyoF6LZEsK_cbP*(c5et+jzPJ@z0yGa~}DJ zIpwP69uy~_EV1(78B}MR_;gUaV;@OPsO>p(&%x@4C&<0sLwF4o9g*P8&@B42(3xhc z#eSq1D{`e&4hJOIVAfZj2|DDx03- zNjl-3%6q&uC{%yt?WX3ZHlL>C8c80aRh0R% zVx8ldcbvJBx&)R6g)dL9I_WLG!`k`6D@vQgy2H&z+hJyVH4M)#Kq_w`*#7rerQ4hV(K?)z4;4F@*q>AA1 z=&^ZIHpz`t^nvvWGp35A&&G>EQHm_7WB#N**+ck z9SaO#&8eKY5{=QG)ED28Q#TUw9nDW9Qc-Kf?<_CgnT;?86CG3yrFk%xkf)`e1Bv(R z$-Bx#UCV*H4Q057b^tYZcOiJojp`rMv*y5oY`4GP)NEA9QSZG6w^C}Nx2?F4sNLeJ zH#1@v1`BUfL|WWu+rGM}Vc9EHCwiDqE80hpEB}3!?P?|J=`M3e7kR^weA==NrV<8l zA!S}P_=er2q9FLK;fOKD`RpmTP0&+MFG_+haPmFPSv^(AsU5mnd8ygLuO38*|H*u? z1WN)+fO@JPovD4?*JO_Aj=o)YUg}_)j1qKGo`>qGnh8VA zX%FR7sNZ|?V9lk+s}HHjHJy_DcIDxM@4*Aa9mdscMDztb%CSXYBZ7YFFg+%AUz-C_ za4~GwWnGahd9-SWbtKvQopRqK2Qsj&BY)6>>b16Qfo(2sL&`$N<(|q6RCNZ!ujVac zz3U1ae3l>HnQ_0Z!2RdBZ}2uN?^)IK_=bYccMc_zHKNgWPgVE!twwpk(NMVlIfjWj zf_AgpxDH;wL=wI@a*&d>X0!W$oJ(Q?n3~o>L|4EavwaszGMvi4FGGNB5faJIebSM^wjR>EzpW+vDW~^hzMGeRah7o3aQcL!kC)#Q zppux*aj#-lkz&Hy)Oc2T3*3df61`JZMAe6R`SG0zpn%*;HS|-T2uG7P<&Pqy0A61+ zVoGAZ+ia=1H`Kh&ol%znI^@$G@rS#w=$*5>C zR}wgJ#&+I)Ja?@3$&dqP(&0>V;R6Kq2wkE}~^hU64udN|W7=5IL?Ym$Pl_Ldu&l!W(ugZTGz#!*@m44+dv3TF>hoHn^Jb6uU`-HSQ-tRZvn{+t|e z)o4`OtlxXI`o#V!g4vq$>01mFm3TY8>VNvI{@a^6&Nnml*0x1(s>GrE@<2EeS;Sci z87lo(9@vj{yShUOdPV0&b zM+z^nHbc$DBX0dO?>yKF-_%mbfDYO6!nk4jxspA8hiqo29&xZ^{wJY4eIOpH9}E?& zrI`rPgCbupS+EWDDg<7a{5?B>9>;??L|~i!ua9BHU0OV_}G2zO_B@6dB;g5 zpc3k|TWp0cspI=c^yCI5$JEciWOC0M)0|aZPe$tPg4Nd-iMzfwN(>KUNpH6Gt;jY` z9Mz9LYCiTJ1M1AB?(&Ku{mBbv+{R^60-vym*<_wi)O2>VHqR0 zTW#azdxwOx7Yx2mHy6nAL-&+=*F_8d5^eq78+>u0NMn(3JRjj&)**eNn&FN_M$qUXL<-(w7DJVU>9qGlsgU8MD ztC)mzrh56%f@&(vw0P6bFjD^zt7FE5D+{UmvW zK_Ms8i*z|_QwU^_VZAk!qoN5`fQ_B+N3O!E(uT^@>$ftN5NDt-lMyl-Jqhw)_NCU! zu4>y_2vqNC9I$G1=dERON^;l@^2sB5!p5GdxAy<3}#<5mlRD@ zcXU=YHE&^7QP^o%uzY1#n(!*hzQb=xv?GyMvf;?4B6mo|W8{XK8YspcD{(l&Ep9bt zFsDhb#CvcL4ZyYqAS^thaL2%bs^G5-f9O}W*<-YIR~8=l{(i*#6-+o0&un)UmSF6r zM#C-Kg@gMFgS7eu^@y~Gt?m=8_q_3R${h8Cr*Hou)UDGUYLhgqcj4)Hq_XKA@9|@w zi3!mOJuTB4t5L<>)lhgKH`_w_)DD30bGfD6kE8s3>wf0>BWSXK)WW$A9g{j*^N+F- z$(Dj))MPgKVq!%RR~vy`Y;?j)_f%IMuRkH4fkUUZ_M$0ya zNe+ZO!eg>2ZPH5SV@_-D{VL|04W+W{M-!ey1Dje}_{0hAv#yE6c|SDJ)tWuTx3ivb z)Amg$T5H#hBs&Tju0GJ&vhiP1v<_(qH;e3z7>e%Zn!MjwI#G^8TqoXM6{+OjT36&3 z)ehV1)!lgeRf~}cSt~cBkGHf9mg5ASSVw|;>lMRadspr;=#oIC63-l1GOgpx`oFQU z2c@y*vWqw1e&aYfpmN}>F~cKWB``lD%_zH3fY(Y$fn0kKyNq&iEWbn7${+!X3y)!z!P5L4mz9IF2%p zI*O?Y|7`H8rj1GFg^_e@me zpHq?Jz}PJJit+xHBS}7Qd9q@`Xinvch*>qoOK1Q2e+l;0MH7p6nGz!k8cP4TvM}xO z=z))-`;4!!5lQ60h}uFZn4yqQ99A*vLwd%G4*zOKxk8TcXql|9sv6a6uN+m9@)NBpyf_{6CWP3G$A7RG#=alv-a!HMca19~KKnIj>z8KZLP!3pP~^SYjh zVgOO9l<`#`QX9Cjk}!ZzL|;D>eY;XdvA|t#e7uOYX%D8y!|P}mO{!YYG+BFPxqM91 zQ`Pj*T}w^n-(z;3l$Rj>xmT_(yt3uUGapcL(dzor(rmYsK4lUTqN84=zh~TBvG!_G zbQn9ULd3i$R&lG;B>!N+2K^f)+sf3X+$*vMI*(Q8Q*5E}?QqqQGe-3gg4Gf z($40)dKo5Gu?cyyma(P+_wl>A+N9zA^J4~7m^lh>8BuDUNg6kjjdyx@i=tK1H2rH*V1__Z`vWr8oSgVF=f) zX=+~kFK!a`d36KZCXh#n-G6*~_dNV-s@q*sjJ1h`uM{wRsp<8gGKZI}h&sy~RZWpq z-ap_zpm`U^w0FLQEoT+Iu+lk)?J{E4D-`HGUQ}?~YrD9|GS{-k(^&ak;bdQi(fll5 z#d>7x{D!|;$p+hbFJp;>Xb{vJ?Hs^%ma`(nSdxn4aMQlD^m;3-1$VBXK$xInL}RWH z%;ubV%m;&~8jnP>zjVD1%%VHlY{L7MH7}K~$~al{b-Y7}^QoP`I~>Wr<~dH@zqF8< zAVN;YuKz>m(Om0`oOv?Lw$rOHBIKZz5fLF{?B0_XQN8>kZ_{pF6l{xRyZXr6pKf44 zoQwC6+Ry!eCqufijx!(0qm`$BhhNux;~F+hd*@6)CpTGVaPqb=)sVKoS$n&bTscM* z542Z&UeJr9UHhDwj9h1hE;2 z=|opWW(U_gQfVJ|&icqq-ua-sD32;bq+%^jXR39iw=5ciDta*X$*bdYA`oZ@n>ds= z&m0eDU#mKSLX@I!aM3+#`5?4^)-~%#P0jPIijYyAq9+PQJ5pH6Bda+38d0$19HEK^ zFIUGDXWVgX(X(@zK(^v)^Y1Gclzc$K!e4)o0n?z#XwwI!g)*>BAFDWC-h_!e=6ygk zz2BdZCsA)7m^YZ;S8NC&KlQTjnD=qr{Bgbzbmlcx`^uO5VtPbM7j9$ZU@0Cp=GVZm z6nB4p83PuXXO1_{y5{IN$!6+Sx~n15#<>j-=b=*UTq z>IpvcOfx&0!dhrZin*9u*s%7y(Q8j#p=11JG+!3pv^#9sB|0nN%Ct`S@GL z<-X$?6IQFDOE8t5mVMVMF?PF|r(AK?j)TuhIxpqN1HsCJhLc_AZTsgeV!gvIjfeMs zY5L>EhI>2it>eJXx$nS&Z8-i=!6KDqnCpHz`)hitb+0iWjC3TtSb6aA6WwQQ2j;xO z$PM%3Za?&sDOfzwCf*eUmM)lQb?iEv=snnTI=c>5(R}D1%rc|TzD^AD<1aOz6uux>6cYqYH)9^B*#Fu| zr9^@cp?4#eFCIQfV$`)vbfkCe2z7m{CT3XfWSFAwz$=aYKj`*;yWrj^Yt!=Tn!~RfU$!0dmIw(TS%z&Nu3dJ_qgF+b zzgxZl^M1T&zC!LOmaC%su0_w3O$fF(Dp{M@5vo8=jg@*gBvV}e!NrpAyuOgj^Sk@! ze$kx$ZVqf+Qu4O_YvN>e{ISn$->4Q%|ZIUaFbQE0sZsEz#&Gt@Z9buS(XHOrr{HaT{cPQ4T?2Wvff0M=< z{tIuyDflzri;1xU^WD8okKdwrEC?mxEz5a>8mT^6rlsx6xMD5*eNI&%Y(cRAb2$Y4 z_93gM(NJXxnl5co(#@gm!`5J1C9c8XwnKLZWuCmjW3D^Ydip?>F>vo276yb{_!82q zw$Tb?SPwBwQM1f56IGFT{YYblz5E2j>;&cth&_l^74UdkY` zNlq?w`T{TQY^%ac@tRL-_Mf9HA(Fr6rGaR(%~^wgpy2fc`PHhi-Il1_4;M#C&f@iJ zWfPnJd?xan((VoGA7&$}@-^Hy*1GqSp{ChlRis2Bd(KH$-AUwGnls};EgVppyh5Km zxbRY=ujwnuc^S0|XZ~Y=waGAlAfrgkVC(8-Kqd51ke95{)$Z*m7!Lk6vJS3g_XB3; zSqU1wBa|`Q6cj%D@@V3WQD1FqaU5>W-2BfsKZ{#Stj+qO!j^uLL3#Y<*QI$JxO2N@ z`EbX&qfIClnotVQ=$&OrE8~qW_@9Z9^NY;Lh#i^fEaX7-z(mtoHw(XB#oV z8`}UiGug(FUnSM8Pg=>w9I=fQ7@L@-^LDM&?!Bq$r(enjjvUw(n2_cz`O!$2SE)XE zD@#URDxhv57pmLs26FKVRPrMbn6T&jKF>MNv(f$TFMRtx=e*C)=bZPC*BcXIC2I`WP4Xdw`Dik1~w*0tv*Wu%aKN1XPhzG749CZq8)ytybubS(9`b4us5`cq1_ zPFnK9guCoJ7c9m(jUh#gi6iwY_XK!9J==Cu#$A8Lp9%2w(}$tBPkRtH1@YmLVXz9a zzy#{n#RnvhF0esbBHn{YK!5b*N0bdR=%Qsq+)JQ1)K~orunrb_7hb_j&{N$zyQz>_XvBBoZ$pJat@ismj#LYku_wK4aoWBhY z&9=eQE)4?h@dc8Koqi=s^_bdzbo|8}AMrKfM+wxDv3G`%iv${_!bSZrSxw3N;3>}z z2#FSFAo#7cWT$*-@OX}?Vi0QgtIJp-s5(V%3s@L~rx=_@P;_$>_!@0~laE=3K>NaM zwwsWkU{r(~f&gJ~7tc1Zea|_JiJ#ae{;N(-csVl|7VvCD1Crg4$%ei@-G?_9#|hEm znGopQjD<(&B|c+;e4d=BxbYMN@Yw#+T{&Oi*6*8K^7^LX(9APu7rwtoUW$w3wKS+? z1|k^F=Y)bNY;YGpXmdyV8lP?X4=xUM!k%PU7`ELcqKYb;TjDhrAV;Y+Qx&H5q)vCH zzhcqT76gjLLDf;2Oz~!qHwU~B16wB8#o|Ct9(h5Ng!fCUYFSxOQbQ4^S#jxMe#BqlJ zl?YP|%0|EZ;Ap^v4M1cJ*mf23IDfbD#~YX`({4x~AJ_<3|EVku<|KXhX=Dh9xMvb+&I&d*(d&;@#ik8dIeU~k7wYlcAcdhJe+ z$$08fwnu{0#@M>d;Xme{V&LY$fv^p_-OXbVg9ES^@%)t|v$@iA{bJToI@IYo@i-pO zvbpFq$L47TY(wNA&k<#DQ~hNZ4?&%CHdodncf>f8v>drQrszxtkH=Nl(R?$KlP?Y9P#3l(eNi{t%f^8ZhOmr zf#;9q817h%4i@wU!XhEJVU6?GrQ6N=3cgNEjB;%^Ck7gV9yRL?5f$6-Qo+aTMqC`+ zv;e_3&b^~D$05~z!V{gDZE=ommCzq8={q(*fuq8OpojoQa@(;5H#{K>cBMmCBP?eN z__%Si30_G!-$W1q2&lLjxYGQ)^3lqiQqG->!YNwTlsoS-g?X&!1f`!%6CCm8KXRD zA;&K$23z!D*WJIX1jV4%iAM?My#RpToWB9#D~K-~DBQA})5URzw|AR)ktpDV8}$*- zb~DIXN3I-v^l0#a6iJbu_IlxtyApX$${F=#Lx%p;Ne~`PT4aHN@LdK&O5N|wu)+lR zU_lLmN5LBB6Wsy3Asx9Na8KTt54}P;qL>SM{edG-Rw4&nJjFDtn(N9obTqEL-5vcR z?xs`9)ES*|r919|ES?w0N2(CI31FxdPfoyo=ZfQaZAg{@ewDj-YVdSOl`H(tibcv# zK}W;E1=Hn`pX;UO`@v-;u$BOuqUATtg|fGUi^F0-8ps3HJMIDvB-aque`cc>A9T&n zO$R&jWHFE)MZB>YT!EV`pgnl9R;S0Dx-*w0=k`52zja$O(m>`jpn(KU7CybvO3rQX z1-mx-^rVu8@cMlHC~O(P<}4ts!%EhM{p^9YR3+;tIxBVjipuh%jH%rarsiN{!95MF zx-|`tO}Hzoh>6*CkeWp&q@)CnLbtRrq!U4;|78 zP)=8*l2uRX$kvAOl)##=ePRL>!ZJ>HS=m0Lc#UmW^vpGFD~YPwewQBLu<%NT9>s!^`MP`SJCzl(x_&$$PU(owB3@JZyFEe1FAPwlan5BX znc6O@Fz1oVNVz`Zg}SX~v}n18qDJ5$a@{_!@3Q30pO;7zRG)WL$y9v)4%_qrrd6|Z ztnUC*dUzdMC(^AI9W_O6>R{2@@k*u{$m#V_v(IpQ`$?XY@|H*L)0adwL+b&T0O%$p zEB@IYypJenbhSzEJYaj&>^v?Z(ItQx4jPH7{2d?b8&lo!cz4j@saKJU6LUeFbmNLj za?+x=j9&kh#XnVd4TO1KP!YR~`eqBPi>E+tnn=hHn1OjHZJOvbVf!ADm0JEzyBF!a$?u zmk!KZOH#!;e^DNz|8nrLX!kp0d9zw~*-1-pBPc~Jck&|-8r|$opEaK5_a>SSP<2k} zK_qnp$tD002Yz{V=RsSmVNQ{xB0Yi~7sBL1x2%CP1P;Iv9TNUGF)&J;KSKpDA>vlc ztetm*K@(?fd)@Y!Wsf6@+lKemgKiDB%ojtjvpIBe*d3sw&bEOHF-GZj;iZVbTsMiX z4@f_?n8*hO)IRd+@|T$lS)illy{AB#Q&zDk4b**sV-0C|>``7zhv#46N;CO(Adxb{ z0FuSh*0_lK=mQau2&3wr=mxO5y0>xb@ct6#cO2^7fiPl;;{;@Q$u2NN#Cf+?27C{Y z`3V;7&-SM#MG$p^&m~qRYnNswwSNZ6#>x}8PIQLk>(|&|f$`sW`X1Gp%Hv(3e`qr# z-Fd5yC|=kB={$+1gYOY;=+O0=CnmuH=XwKAahmFj!K$b$<}X3ZQE%CU8*;+QkX^dQ zyA>7~?~H-*LmDWiuQ*m2LFB|EA8Gll5p=(mWX+=mRvg7xK1X`RXv|4@SV%oK5HIjS zQM=dqD`d<(&oPQy46s5D%j)oK(x67u{IRoXZ-=2h{PhshdJLF0N?qCF3qe^A1d^s& zNm{gdX5N~A#?#ade(p?Xkn;eoO!e>hqlvM653oPrMTGkf`v@I?aH#6vl3u_kEsZt0 z@9u@T+mw?T4S4AIL2iFcT}M_OJ8|BN%b5);zWMF85KFpcxlm zrb_jfADIHRB(3Hmd{N&e*-n7>iBZAneLF6WRvo)L%mEh*I^oQT6Rv!lp*?9e?1bgG z&hS*f2RJ2((@jt5gx(#y7a{k+qS2x8+L3*TZ0#dxO*o2jJDJ zJTH6^_NwZ;$s5-5{I$~t>$nMGF{a#2~X*y2=ck$n}BdYQ(A4_`e#QuAaH6p)v-Qlx-LWSaiE~|jMzFXCsOlHm`=6o ztII=F4UghEawdtJ2S9fSXJYYEULB2cy=j_SscK0v7knz55FM^IKi|+gTNqVu<{R2S z88^A3sa0N`Se&$&Gz2Q{*a>q}Yfc$pik`$oP&Ojh%W)J3&ZnaSA0Bv%AfTrpA_b^V zfKl+MGdDb5ccyw77XC8w42K#vg)6jYtmH~8iR#zr0cAy}FTJzyU<=C$Ne}6Nw0#6V zBEgzx;7n&)1Re;IwcPmxdB?%E&@ZU=i6Mf&(ee;E6&a!r(L2+#4dnb3qCm89lj*@m z0YqU}Vv#_XUZmRd_hHQ`iW2=N_Jyk+rL<4&5-T_;MR2Wo z3Gl<`$JB#{Tn>)$pf*>C{=Au7_HguQ5d_UCL~oGA03r=i3Te2NT2V-@O=bZGo-E4)F;9 zm<%GxIk;ev1c*`7V(_4VtX$+ikK)_KQmINLDt9T9F0ic&(o~ufX_VX?4zJyYhwus! zNa9A~STzKc^w z6)Je;$F@P1SS|)f@_dEa@M~7_!t3hyA#UfYL)mfB}E_1ZtJMSaM`k9~K57jL8DbN&4;&hd?KU--><$rbZreKZqpD zYKK9_S|fohbu=q1f7%^82-z{7!@HOlDH6SlkC8zZE2xa9d?yt<3@R=X=p?Y!O5()p zS5lG4GlyGCGNr~KaY+gzk;e;(+ZEUn6(RCUi9ZB}&P_sz!7-8zKJ|;1xh-7$yFjF% z7+9a_^Xe4KYhpyM8cRfS#*%o$O57t@A#-RtL=X<9BH>^Nk43mFM;{i69HlssM5$v@ z%0;7f(Z+f6K1zd}N|-oM=WrXLK`K;tQ{}Q9yYxv*(nv!vM`(9M!rp{n3zoV+_MIZFF7BUXs}FsCfFFI`;$N*S>se8n+*ehTQ5ErqcV zRwO<&NAW8;Og*YV!pk7;EQv&A3RDSW=m?s>z{IJSLe#L9q{&IzloWC@*kH>*akS%X z3i6E;&`lr3$&OCnKqKfCa;yntD#fp1K(vyipg~6a-3GH5E}x^0P8UX^ zjCkCRQ`OZ-W4j==5X8T`x%3}4<(50t-A+c9GN*66X*uq@tp+sb`O|hOq`V0_ZJ?W- zc1Dynr$|mD10qI!F9+_#+Gr&SuM^lB;9^;+VI<*z&``>4!_?8-h%UWliJ?)cB7w{T zC{DwG6hYr%jvmFWixNf;P;h#OK@3iE30cWX)fz@BlV82*Zx*FW@5G!5DtV90mFp89 z%8lo&)$Bf!m)>KG4goXP8Jw+Gfq}+haEQ;_)LgTcE*RmmI-Yyu__6g zfgmJxOnR?bKOAGM_}|8jI$Wo%A#Aqh;JCdyNWUb2b16gJBWadE?wF(wGM=^uDI*79 zrhJbAaL0)7aL%8PhNZX&uKK6`K@I_Klwv_Ym3)eDKHCURmHF`UKh+~>T(S_i4(Gff zY|*rK5prhZPDL2HbhS&tEP5~_O`o1T*=8*hPgNY##Gr?P?aDQUeXx$<} z-%s}7S0oM7TkgG(ZZk+{(QOX5{!Bw|MDqGq?C_0K^WQi$O0d9~aP)$nc3{qQv}K~D z^t?e9tH*^gF*&;1pA0%Gr!Gj=yfBzPBD(7hQ`akB;Nl_j3P!o8(-V_*(R6xaG$tyQ z2N)_^UVnEZB%^uwdrah}m|dSFKp1W95^3zTD;8yz%58F7T#QC( z5VB|7eXWikrL;tilpLy5vL_jH+UnAor2J_Lz6dsV}ccGk2JbFx95uE4O=l0 z)~7+;lL%AXlb5oQ^a!Fr004PLoI1JuFFohJCB7DumnWJd+m_=Qc;}=7I z1C<_ISJ9Qj5bKf@h><@Scc@AeMl)hz)xj55UCSLTj;u@4$lBcIm^{ds#%%<4%~#JP zsRzT9aeQ{L;6s3GJ+4<%vVR!zDncs5-VH7+CtMHE8DhH$xh9fNxgg<8&Y@MN4HF^a z_JVqY3Uew~^p)6pa;33gMCQMSPd7-vgd<%O`(ud3^9nf?r@D^x8lQTOPJQQr=8H?P z!=WIqH|Nm)!Ny7D6lxtCyWy&NDc;r%=2moAadPfW&M8jKp$f#{aji6vHUG3H_sgXG zmFJ@&lA7P|*DvP%kiMgkNq+Ylc8Niixt+u`D#3l88A=vhf;Aq{P-qkqzLBZiv{v@YeUXU{2;EA!FG>GjP_yA+R13 zpHJR3lo+#el!|~fM%-yLRTtGOwmz$my$T7rxJy*r*UGZ}kFK(af3QT4;Lz->Q2ezKMO@FjQ)t%=s@hFdynpGkgYGvC{84Hdblhn2s>q#f;14|VaF>;Aj8S1 zT>|GMN@Bz1RH7xa$Z2WlXpwsG22WM=VYVURXwA{C(jEGC2|#vnoFq0-$YQ*B9$G<0 z385lGFbQpMxt-^9O0TccGy;UV>b%)=439j8wXcmLN1~G-5O|pmH(1m&=H#+~NR$(B zB$!Tk*aDagS0^p_5cC1jxup;SZBQM<+Ys!AKY)M8j52iq24n*k9z`latk7CpQar5B z2EwVcO*kf8N4ktzi}^YMu))ae-ErEc2$|C*au;$GBZk7kfVhq;F6;#q^dAR6y`2^i z35+#|Z2IkUiiCk;Yh$9842ZYJz+7O1<_cqf#I4h|nqM(}&-m<{f3Q5%v+;4v>5NAa zYDFkQEg+I(k?(-svo`wHt&ot5+yubAgvAiPDtp`!#JR6%^>}5Ead&H3A2&)=-BF|W z_sR93+RD(xZ@^odIxgLDO7HoJN@y*yCh76XK)GEIw&q!@O})H*Q!@ETu`!{xm8xw-hvPASZ*j61l9* z!5o$BZE${t`%ZgXk*OAA<}AiT$42}qZ9eS_Lt&RysSjdKfJG45-Fjy@W#^X-^~tt3 zFa5hEbi|OFr1HO6PDUQm78r74;*AzF4}>dZT-ko-pWgQTp`-Bw9?}G9Czwt^NPs^y z1Yv{rMGY>YCMi^ANU?n8Z0ML;`!WLoH3yZFb2yok&RiF3jGcW!Y(*Y2dD|H zgX!WsmV)M_h)f)W*9rC6{c^Al@O9F<#Dl#mN2h1iMx+;2;yTMskv4E#i@EbdWZT6b zQ>xNbW`k$36L1d#bvp7HDZqpjjSM(Tc()BOKS`PX6rU<|hQIKzXj+bC=O|OejFZO? zDTU(MfcSOSYqPGSN<4HFtKp#$HX7hvJV-v})pbiC*e4>vEwYz)MHgT>i*sIPah@N2 z$y8w?5tITiLLLAsa4l$!avZqtg2Iy>5E6dG{@9nNUV(nl#y`7w#&V*qA8Hg%qj8CjH$M@sn(062) zQ9#tNJy)eAM7a@6gliT<@-0t~g> zs(rY4MS@SKiMVcPjGuLPbG`>fv!<}A{^hMRmXynuo9YNBz$RowT(|rgoTb2J5fhaS zR%fO^UiS}3Ims!*1-g`eN$-$U`9ycl@gCJ~%=vzeYD9CWLhuK(_*{>97!!}4)HUXR zb}Hix-0^$NgDjCY+4I|)dX;X!J!w*TlJq?{bzI*I-}Y@)vlY3mpRkERp9}a}M$w0V~641f5zg<$QR8hylkQp;IxSbDmQ|Dh5UAqg)1}YUIj$ zpAURxa!dPj$T#jK$T?fKQh;*KIxpQWXImF~YgD3FAr{1FXy?(iDBJVUKXAr?z0|X# z7QeNH1K^*Oo|b;6+_Cl2&Xz5>xI^jK=US1o%ppY^g?0CUWbz= z6p}g}2@`VX2g4LxQ2?p_My^M?+h2Khcl3j8tB(IjlFkTS$_#(WDrLdijw;uq8a?J5 zDF>I8v}yUxOCgfNE}uta)zP&?9W5lB6iNZyLR_lAUEDleGLsy?Zph-foP$@0ury&J zv1rveq;;ALOoto1WMDcVF*@RW5jXTMZ0xERHd5I`@!o-Q(xZw5@XCJ=l4FYJ>b7YL zFeh{~(e*rwKkvSrgKbijdeRJGEQ~Uy`?H8RY}xH9Md)swfLb>z#&by7i}o|rWc z;Z-M`t{QyZ&>ko($>Prnv<1ByYk?4NE&*a<)p21 z;k8rAC%-ct&NViEy_F>*=PNeHG(f!aE|esT1PjKcO1wfu+P+I!paX~LxL#vYM(T&S zPRQBKfVOmAQV-ZNkS!?IS8n}0pq_%Wu4%s!P@1L&RL)nHt;5B6WDM|h(k7CRsf-70 zK-SeqSWZ6iwBz<5ghOzZV-V~io12USy@B@=z@J0zC`eicJBlq10zwN2L>{?}6C$=^ z0RAU@q~ynzF2fB?8)o8F-bxfG3qhevN$W*$d~LsNjzvu*4RJ;gr~LS>0YrV`qDCQr zuZ5ZTg96xS2sQDv6)rd6ZnthEdN;drjmVQ!xXO4~5dOtwX?z@2_Uh6J3A4 z`}xNGoHwsvKSGRTTChl1PRM!yiT?mD158Dzb8KQ zpXO6fwKTyCdQQF(7w2KnhHEF2^YL{Hj!FQR0&o{FCYG-g7qFbdR)A_l5FGDzD-Ulx zgRe1&DA%9*i8>1>-o`U{Z_=snfj5HW`sMPnSB){c&7_;^3A$RA{Ao+X3=g)6Lbs&e zZlkleqr|8$y~=YcN@a0JK6ffsY4oE!kuHxKFTVhKuwZaA+S^&gbS2k6+D3HLs7@L% z+$0ympM#ILpD(WPmLFhR4$UdG`o%nvMjj}gSu+_OSy*_sxVKz@h?Fji6bCE?+FPOY zcl`pLjD9sYd9t;!=gyAB58yh1QvquhaR$06QBTqzd}}oP3!XR~#{&bR@K&tJ=>1zv zT6!2c1jOpe5Y##pr#O^UB$DD!w|v{*lhv4)VZ<+eR?hche8U&B=1dRIwBgnVLo%Wv zX+lnT+2^O< zS}1RgJsxLu_50=vJ}aS4-)$ZJ3@01F`{K3^4CHnywYJEpO+Ss#>wl^ z$JD?>j)M)F&j!d7DRi@E9E)z84^A#o4rX+fD*gl-1P-yBLLF9$l>%lcP$x1Gy0jAa zZ-a|dVE{Na;WB+(_*4M!98y@us#RN=3Q;g|LSNRqKrJeprGgsDOmqKlgW8v5zF5z< z&W77?4(sR@&HfOo5{5K^cx`Uz(9n?YNnsA>s|oOob(w9y@Ka@KA!20_WK#`}GH@vq zyB0)FLDUXtwBxvw0o?gvBNSSPLu@=qpkDw<57jdQ8`6CfPRMn`g1!p8o$vs9kXy;< z@JBe1`ami}A@ZLexeQsy0D;7pGr)F8SZdk$`;Qar|7Z9eQ|UN&Uqauek^1PmsV?9o zdD-A)3Uz{ATb?;nm_u3@9>^<|_CoTz%fZR-Mk-<})06Y0^A;G2@32mvexmjkza!@` z-kUu9-8@bBYaNoRsJJOXOJFOJQ(tIE*VPutl#>7^eYm#s5IUP@5K>)gk1 zLxNaeczSlpqJEWbCMTI3s&wRs;gD>ntXD3|$WV!!aq-xdrG9D9sscJB`Is6A(5u+U(4O*;VRR)@|SUO;MA1d0>si< z%e`;niU&J=1t&1)YuD=XJ93Th=is}I@S;-XDqi|V-3EvXy_baWked}8R>R@`hIG6)h0st@ z`KD{&Ftf^hubqrMsnc#94zrz;^Y{7j8ybolZ-a?LJ<_bs@nB+C>V&?!D#hMA z9G{K3Wb5CR$k{EquC2qnBP+!Ao7HB2J97Xb+^p zk-Y$D8;St%plD}Nffn3Oz8=Z|`#)}oj@=D87%HNaU&A$&_gho%fs|24epW%`0o)94 z#H|7T)kt-c#?89H)I0I-K7Fq}9s(&|xx zKL;TXAe$7?3DENVy;-kW?sd--UOistvUX+t{yKgsxcXO$1g?*b*6 zDt(c>k6L#lEp@tW*8)=j%y8Q-fqF7b5wrXB`qFYOxoWoU>d%-IuX%I(gsw`W-H99e z$LNJ8#=~Z!pZRHh0Jo48$w}LG{R$wcI3?c2UE2K+Cz}R+hfpJY2crgdX+ND33!Ar@ zB|HQi?R)|!fa^O}VXNU%T($4g+J+(&>OC*{c?dY#@x+9*x6|`P|KjKFP;fey-kn9v zaLHKmGoLG~`PLzJJ7qNNxum_fHN$IcGZwz}nehW7&h)!?eg5r>N3>YaK$ko*VYvAB z{`8S)U_G6yN~?Vx8(3y5C5Y&dp>c1M&4}-H~NzzjK->RJ`sA>vF1ROzxW0u5bpCO|G;fXkS0al{$f zrvU7xRPTcnCP*USxW`zqt|M3q88i5FfJh@u(dXKYX zi~TBT9dV*0Q`vz*7LK%`T$!p;pZoyhEW_QTRTJf4M4l5jUA81o5>*mdnkHkWT0#Mp zZhywDjmz0O!D%Ygn-nicx)@N@uO!6PKE2#d!I2LCCc@KVAX2gO5TF+N+%JE8^6%K%-eh z;4(eSwLYVFM9iYZO*NdyAS$l6gF7xt5K~Sp4!Aga^*~Z2Se0CHXnpXux!{aWfrjP} zollQeGD`8SRDI4D*HdB4rG%@+UdZCf5oh#bYbWS}0uktJom0r{m~9A)e`*WI35!AP zgJ6c!W*ad8A>j?|D>8Dfve&nssLIdp1BC) z2{u#C)J~6dWcz=)4LOm%Uzh#ds(96pf#OFQkNJh6%-Q;FrT`HV9QZS`=VG#lgNULg zpR2k<&(smc3ld(hdu>Mc%s|%2s^kxGaj8tHhd0;!J41E%ahJBBJ#5$M^>E!=$8u7I zJsr;UG)3%Ah?arfiHVSnQv$)fajNQ|*sEdyan%*jvAb3*cUQ$c^^5@i}LUSuw92BP%opB?~_2odtOxDkfM z(|s zo9mVm;fo&jX$-5;_s9joyv?LX4-ZSSKTNmndC(UKUpn&b#$m%;Qv4r&S`Xe^Siw$t zzYA}+6wFv&_(=vi@JMl}Q=iQwsrQ`mAA_WTxX!Oo%5OMSA?3Huc5MMBmRfxttG|(L zhzA9Q7j(I`IoGy*tWSNn>LiDMEN-1q z!hF;?Y!5_**GPVUYif<0+;Wjo_6;dMFORa2ZgC)Y)vtW>`2sxrNeuQ4=z z>Th~OOoCVSvdh(F8en?_aZtDE4LxOV#jp3c%yo5`7!KIxPETZ-_K~bGrRr7OcXT?V z1u zO}@8QA&akcXD@2syYM&=OmUG0etTK5nn(()0dtKpx+Bq{%E##MK-G}CU>s(6I?tjX>Gwn?5gv3@pY=Zmw2j&vkhzaH$gzw zit-{P>s0vpkLF0LiD8_Ih0T?DMJI@yagdRB z@Z=NPr7zsU$C-*#e$r)EEoxT8_y@X4=&Nw#Vr)!$+Bf<;gI98R!t;s6Dc)%9YrWwL z66#LFvN4;?N6*U_DxDUBaZSU#@6$k{D*u}6KTIU}1iSAPcCCLfqjdOX)@vUbt zXJ)*|`Qp_CtNt|`WTy+Pr6Ok%qkDKRGqpatnbZl#T6QI*R9^3^$Rpv3w7|Ca;W)v-r~ng7t^Eu z!KdgV!IUpz%(*IGIC+)Ru-_}IJ^41{rl!=yV%&Ft=EBNbq@Log*+K^3Zm2Ks ze>zC8DTGXWtX~lei7GC{jEl1e+16Q36!GBg4re(1JWHfv#UcKhnDM$rUtl?z_yovl z3HQ2wF|$p9@1HEEGZt{7+6o!_EqFj!qRw^Yt*jBliq&K~SYqSdGh6fh<<;MkLx8nn zpzI8yU~eDDoWgz)f?pGqc(%?v6Q0nkDT_*VXFBm5aawnsh*4D#O%$(+msw{s3iAF3 zcXPzCxXxuvOoy}qs*j@%lj6~97w)G*Q92cQ<)*)IoJ-%%-QD(AXq`7I2}j(nLoYwD z7`hp-3L#?Y+aH0>zw{Ju^b|g&`jx%P}sl zdiwUoFj`Kj9~0#`<82Ew0C8@d$yK5*N1PhjTw&wx#R z7J0-YeRSgQaGl@+ZJTf&?Mk?62;jm2)?Ce==0@4u5=ATt?O7!qq- zpdqfaLQn_W`rOfVkR3N&pMrZtkGOTtF^trt)EV%a7ebv`7Y9QM2FxZ$E{VAlw!#~` zKYpTU!er7JvOdABd%KSx>DsZ@HVC*#Tz+j1v7A`h@Z|&*R{-jC_4u6+=sRx4(*Ym@ zpa?+G1Zd5x$RM||obJkTm&;=OfGDy+%Mrqme7g{W#x#K4btfe#EOJ2m|S(ATVc=5^KTYfsbu(@*yUh|a0J(44^?UT>l z{=tOy*!P(8;%Dt^1|OTXPj!`AjVb%^fWZ66@f*N7VFrV`2|$@lC#2IGwrp&$+?pzG_y|BH!*Uw0h%8c;olK-XwK?jm*W-dWoNX$SkRj1~bzBj!BPweg4c z?YHe6IJ^GT*G59@Y)`TcKDNLM=1pV!!(_)bbRD;}B%ihn-M!w!uaI7_zYfOF)&ORt zsUu|^*EynZs#2u=bKb}!Ym1}lJK4+D;m1tvuNW~WO!29Y6Hh0~q$34okou%aT zF8_K-#=o}xYWHx}C-$D?LB2RZFK5^;Tl^IOUC0wp!MOx`)9>j?*^P;gykW4|LPKD& z?IGF&VMV?#t9Q75|Ipdt#{6@om=iE;(ouvnN?o9ZZHj)vafo__5IohK3Ea$L@z7C{ z7XZxge01|@%=exi>s6MM+5%e*Z6L_Gi@`Awne%7RSOZEtFwW9qjdu_-ZU$)}A%I;~ zc|JE>4zd3{Ai$PgpgP_X*=xT&C@to`m6y%`uF5-;YXu}mqKN`;AG-!!IfAut*xEva z7A{CRMin(qgIi`}tgprfA5*+xDM!lmg^{+S-z#IE4>*a@s{ywO9;GtvEZ~%qBS^^9 zffg=Y@WPm(G2$8~g0b7z$aI`!G-UA= z-_(pp9_o|~R4sx!A)$2A^O#t&TIKFO64{dVH}K_1`VbS}d;c-rV3oJalx@iKMBw7| z{dfVW<=KP?cf}CqA{fdCX-GVT zi&F>ZmK0A7H}#Zy_v<P#aJQCt9e;YAc|IuO}u~mJ`s1uLFvyLeysu)G1xCXl~w0#v+Y_g*KoJCw-q5fHySn z2S|D}t&xOY=iMPV;`}Xx>J+PIX=F$h1kaH~I1Rzo0VOjojxxyxZEZ}f_Q|!N&HiXZ zYe0C78t!T;@NjwM`v8%lH4^5MuI-Y%FNo;S?7ZXHOMcz}1R_b93kUp0<91%fjT(}Q zrPGSAL_i+kqIFo|Z}>C;9V{}=GlwnCCPkW|nLe_M5hv@elO53Hv%*tqaHvv)|M23& z0g*JH^^4PQhVW!Z@LGZuq6QnO>=CkyQJpAZnPP#0*Rim5Y9f4s?1z$8a~B>Uj!J68 zYYdIIf+dvmb%)})BzH4!@MVkR^s<5TlO>8lZ9Y$Vi;IWN$`4KlPw^xqvJN*St0x); zI)i!yerrBm*3hbCqVtD3A+;{{Ddlylq;)vKMneHPIH>Qm_k#A9txIeYz?;vWHcFSK z1%?iGv6Jb8$GOROKLUvofZTob8b^e^dH-z1&*Kkd&qyBNh@jc~I5R;ED%qgoW713FrXJ-PX}y^PD&a<+ zg=5VQ>ZUVnV(S{=Yicgc9|mMn%5=ps@Qw=}rAbAs)5TmcK)fZ%!-$41he^MOSulUc zK|B}0Ajy-LKkKaEg@+#XADT0yUIzc&mpS3b7VlHfsMHQX3LxKNT&Ey`k(bSgZKHCY z6H=cX{N9+hPs^ELkem|6UEx}*UCbwMLdB(%vRp^+7CCRD%?9xynWb)n7#=A(g!<#w=4Y=Uzl!{WP zUA-L!rj~m+pgONZa0;V|pQwAc6N{v^jfoMouc&M;Jn`5cI62Y0FJdax0R(tqwf8-sZp&?iyqbLk;4z5kEKtp2iMy3R^%C0}X$`MBkna^1Z zV@9ewuo$FMuU9_k)4e#7OPuQ29x=n2Bd&XojO#s0uK1WV))if#Uo!`Q06{&n$4;7= z%Xv&=VxaYCZ^wf+gJQNYb^0Z~xCEU`xmiQ^1szsn632-*I3*WW4~9?mW%m9pHjR@L;>z3CjtD~Mcq9jw^WW}- z-iE6CuFxBu9OoEhMl0)e+;h$RDYw9In!J7pjiFV#KP|(Y9ML*V+w|NWj3rtTXKiK2 zDSt4h&t-+(ap7k2m5D71^*i&%-Bx&jw-Ur2iVu9~1IV6Ua*47_88++}kWcHDu4~41 zLVO2<5~un^nuc3$3=q92N&JisIM39voER%!ygUwt9ta>eDf)q>Dt9PHZMC8R`V# z=QPufeZj&vRhf6})m$IYHN3Wr2wzs7U1IY51R4H?sB)yYn>{su$Dl0vegIP znN_imvvN}BWLAT9C_esL{V~_^%{YXdIw)-_Sw9?aMRnfdCsSN5vt5U%jr~6GRDGGr z!Nozp{y7%a-~IeK+&bYj`W&jJSJ&ZPO!u}`pR}aSZUyKBeu^nT`GdH~4BJHUtgCv3 zk#ti8xkp{BGjG5F9-b}kO7FBp_v;3k>{czy3C0C61s5}s<`{CWA+8|N$`?lU(tACu z=}h$?=8S48)fm3+Quc!P?+W5@NXt{7uPKQ3kHaM@SM4U8_ti!CcO32V0Ox*XJpM@0 zFI*Ikp8EPL4@#gBA5U)nFz+?dI%nw}MwvDup@;}ibkyMH6o|nAPDne*exx!+xsMbO z+5E7;nGwF`MJ%UimljNKLh9?bFz6B1gHiVV<8_sfPlKbBJn)UnSaeOAu3s!?`ZJ3q znfSv;ga4=Bv_8wwI}{JmbADW>;OTLrA?CW`tHef`%8hp%EqWS~&X|9uz8*}EuBza8vc*~&p_rI4KZ?0kb*YMpG=u*cdkKT=ttC2{!M@XH*T}s=x z{gucm-K}(G#6+cIm(+b&&X8xuCDyO9Z2v%M$T*-;k*vY|vR?VDBX*YWJFT8@xq#Eq z%ld!fZlX+H5$V}|$enB+C-M|^jtn<~-4KtbK+EJt%xyi!%E`q^L7g&x&cZnBHz+q* zOd1wR^7MFXc2!hbmpI@tNQ3L_Y|hc2<-J28E8UgXSWe{7r7L?=`(!$;3$!kJX1r+Q z*Vmu?CK1p!I6JKLncccgJyEt!l*Nog;LL0;s>Vv@S$>ot|3RUYRmI<>rnsv+=VYs4 z`X#O0l~~BsC(PzV&0a_}Tz@pK7@yuOkqUodNSb=y%#6u!k2nRh?E;_?zPbzx5BRjR z`jV;sgjP^!5R?GiP2@V;26$`4Ls-}wp1Lpb`~)cE^E$%v@FBpCybTwlg1|Q$F5K|ahlI}jvxV-pXFKUM zxoFxBh_~7A;nw>p_+l=b7Cmd1_N$2fNZ3rR(}%5+?-{Tkb#-rcu$;n=sMG@LLy2-+ zll7546(0h^wnA%i$i9Y{@tXXO4l6#FgdZLFQX;s2!~J7aTx(l39%SK&J+_D{n3njc z%t0=xhp?SaRf*1v#lQ*a+VGhyY!!|~3qH(Ik5PFY##DT;2wTCPB)Wf82CcUnQy;-1 zeJ{v1N@uCG2~A$BAscTlVH+Kp7PeY0`nfOaf<9Y}Ij`8O0d`&=Iim>#G9x)P;?>it z3H$&3-AK-P;U{#emcGA5Flzs8OIs>FRE2HelP9=eBc5uBYt@(eah))pV*37?MdS9o z4nuYUCZfB&?EYt=M{3~2I}Qn76ur+L^|O6VTRXY%2z%|-GSU8()KuTW&W>18+-pDV z3V$v~Jkl2j!6~G8uRV4*wZAQCQhxHgw%8kSLoZP`?i75mA^EcAl)L-H?U>kkU_>L{ zKaJ|_IvJ-b+5;G>x>UywAiRHXVXQS~< zgL!A#f<`G(+&oB4wXFG)TVSxc#>4DiLS~Y?n2Vk@z9Mu*^U`zW&kz6gvsX5)_#GDBYroM<-G>%K9PD?} z_YaCUKOXbkH_<#j}_b8q&eU8GzHkVr8v zOv9Q-J;J+~R;A7D84`Xof6H{herH!mA=C9`D!!?*69>hkNBZ)-e_!_((t4!dsrEs3 zp+cr2_X~0+16r_N?dxO))34X&j|f;!+PM0sZBvye=bJXb9P&W4C|$%11cKs`aTZME zQOG-5$Gc%8zYDk$Q(&`UAn22fQfKL<3)^~rcd2s6*_`8BSR&<@XG2z_(cg@x|KHzk zs3t_Xm?2;yrt;Qrez$993+CMR+(g~BJ%)_7*F`l0QTU{#^iN;T__AbSv+Tt@W665F zi`maAXC@MpC~OLzmXH|@fAl%C4(-=u{uhzhweJD%xU7p5(WSGYF~2NM6+QK)^9n_5 zyFcE5<;?xR4lNf_swPAT)r?GsyAHs2mdlI;tQZ2rQ~i+9i8Uf~BEfA9dy=sBVy<|9 z2J?D!fyjyyOC%B-AB|ibsv-4WFek!O&G@g@k!#I=315;rD=*5q4;vFX;dNkzWZJUl z)hUDJXKNM%h|{xg9RXM9_M4Wo4Ivat<)3av5z}Bm=LV!W-!C<;TKio6 zBMq|7Z?QT>_%Reuoz;0OmL&@G|9G4&jz)fe;%bq%YV)6CjIWTVB|KLJwmS^|mY_Nj z$W_=>cmDjoLyRrhpqcWcKj(K8J+u(_T?+Sk8|OU0iPW0SWW=i>x9|5(sWAy}SO|Qm z{-e@1e~N`g`J2P6(~#TowH!XTqj2P-NU!P_i$U0$H4>#fKkGc=Z-oI#!#zT_U8KyZ zH(##`^>OD?zW<2Tx7Ox)@wqbDc&apCY0vYgGYl!WvaNH)+Z=c>*P3#=Ef5<(i&rw`F}V*N{IBny?gqr zUhtUykd+?}+Fm^Jw#H?i>fBJ9>9+i|{`&|K852>`LzQSIXStY+(#Xf++9?PtJa-pF zY~DzSt@;w?vbf%I?(F)~jq5hx@dQtjq`}gksCT=yWgAv3#l$wl5X6XOM1Q!)SFw>C zzrv2S5B(mB|Iayyt^RiNVa)k)){JzdEkpfQbaK&#@3~di))+R@zE*wqE`Q~>C)SgO z)-~o2m;MbJDy`=0gw``IN6Z=C?FP^W?h6Y%vYFrz5S+7!^J-dV`GU+~;y^2u&bHHw|ZhbrWDT&!hEK!JI1G{9Lls|_1V1|1-{mG2{7 z$B-6toCVJZV(~uC2vRmHphuILRv>~h>0aDAlp*gU)DWH{SRt~QvE=-V4b}VL{|OP6 zB0cUY>u9tl7V&km&;Qm;pC!A|WXr{SlY+Gr2BzU&k9Qx`iO&$KtY;$_v58YZ&V<}AGXX~_g`^Vm|XJ;T-dLyFHBQ z4VIHWlKRGj%~g4R3uHblfA9v<&HdvkQ^RPK_CfkN(j%AcLeuqase3)=+Zt^o-vrS} zEMipE1)e!B;6-Zfu`oUBuY;Tc10{~q0*8bkBr)pIT`)>cIu>&9q_$=|u}Dk}eE4F0 zP5|N6W)Y}lfC6KQjt{p)G3A=YSWXovFPN?@012D}KY{}N&feCXriz1=siGTpl6<^91hjX5aeN(pJfv}KR zp3^S}N5RN9bo#~^1<$$Y&lNJ|9%G3m^)`|GkRQt_Ot9M}zxF}nQZ3J^c2oA)@zPv_ zQM#6|Q?7b?7?9#DM$e`VJSVg+5!_))HY6$*@ISmaNo)z5=F(#!3F<%^@k|nXD+NBwW_`oQM6Ts~WJ_!1xke~rkL8|Tl8_$K5%Fpo) zDV2q&PJc$2G@Y+AI=R*yem8)qiR+)>IRT&6FS-j9PXIN~CC3ri6heQ@f)le4hMmb5 zx7E_!p?7FMU!$+z8plnXEwRwAyvOIv?`S;AkEeL~UvG$o*0o`|4+V%1 zI05uqBDlu~h*CkLB#yh(8XCGxoEc<0L+H3{aZ@(N@%J1FT_2ZgDjUv8vfOPi9vxBVga)v)h!~kIDPa`xfNMJ-hX98vF&T{F` zr6%LB;bDH1n75>}s&~iH6!S5m0-GC_&98kH>kk$MFFarfe;EC)uP`5B#dCEckz!%u zz-vPhm?KyrQne2-?9zF&BP<(*AC{sxyBz?!50Tk?rcUFM{+|&P&z47dkzkPJHc(A! z#Y0bWR!c!%P2RAyqsapI4jnI&EeS&B??Esrv@MYvC3OvDhTUOH4~q|sJk*&3i{YFJ z@EKB0k=6l2*sMNl^6L?Xa26o~E-{t(uCFftbK1i<1l`oDCzC$~2o5xj8QISCav}I0l_-HUpNa1Asy-wZrtm~8ZC)Q8aIS4Tmti7dM zx{@;DRhgA9?IaCB;#6O5-cUMJ>N%Xl5`|YPtGi4ErZ5OBjCUU_=R~SBl^XMB=+yd{ zx`TY3P+XHY6sEj#*?B;MIe$G3ifhX~lV)%CnnT>D=f3)lr#6}1wwyU1ed?s4fzt#pTZ{TQSR~<8dF)^H+xI8_OLB7JLiP8!&P$S1Z;q$R_>bI(OS;ro zS)xE)t4WIOYOpMT(}s&k1(3iIh$nhY_f3Tj9zghG3Jo!hmXy^%jGae(-Q-!`QF_OH zmvv3JPT^pM6@i=CzI_Wh)z{(H`=uj?z)?2)+uS1~t=Y#gaTpB4$j0~2u^{d1fHW1X zZ0EQAV=VKsjwHts_D3E3!$589dnD|q96Vz!j{&Oq^gvZwy=sR;NfB3ZZ+lu@jGDt*#!0UR0(Rrtx z%y_=`<{97Gh3bjMZ!GTX;;@8Y7R>+m%OKmWZXfSnYl zBq73^nm>Zp`wFG9Y+NT*-Jo|~60?zsP<$m8{*&Lo33=*Q&7zwX&smg+I2jbf2%KWf z>4bDtgNE#n z2TDd-P@S)B#;*xl-7Wc`(==i+p3h(L&e9h#XJxX}KP=AlDql9iC>`eH9CTj}d!jAw z+9!c-mL_fZ@v`{jUy}b4#90gtjkINY6*0+0OUXlwI+&7p>_HU(jT=PGYLe1Z&J${?B!6!GV- z{a`UfF|Jz)~9Px6uir{(gIlKkfQ^}fSPh?1E?#rvIXP-hvx z>Z%hH_w^mZVSr1{U?npJi{X*sL(E4h5Rbrj6V{S>q&@$PYN5aK_#d#6nfl=LhO2!M zj2%KX%eXa9-(#++`W7-v>Nlm_dH;izSkBVrdgH$gsqPh3o~k8h9%YHNVEt&;XI-gJ z>0b5TspK3ys$qE#mrQvQzEV~%=0>R^VLEZ7t%*^d_5bOX&55MW27U7Y#NWd{Dtq;e z5)%(6C;A8fAA4^B9!1tIik3Uw!JP;R1RDZja3YWZK{{!POUK>aI_Y@Q3GOa~Td-jU z4emZLzyL#VnSlfkMEdRO>Q2J^=bZcB_uqHVdFM=jmCEi_%eU0-spM2NmJrCCLsg3oIj=@s6+I|nN zJNr6;1%p4{)3hH+k}q18JIufljR-#7V6Ews$CPCPU#=wwE%Y( zHy!V8xF4M|uIiA}U|O~7wBowQ#BX`78rmoO?2=F40Hv#}inC9371}3y=IknCv)qQV znM3PxG&N{U-3#VP*qNAn26$=oVoA+y*IFy7dp_@S(j; z@6LG(Ih`2?}vZ489XJHy*g&6j|>OT0KZJI3@@BB@A~+&$GX@EdV*CMRWAD$ zfF*D28V5`Llw-F1)hS0S$Fwya>gP|Y6B+{w)}a(BcXtH);`Ls8s^4*ee67OkwbXk1 znKd1?g?6QS>HLBhmxPZ{^4;{@&EJEBO9q}Notzx4BKQS%W;Y!c zTM0bRI(?a7vN?P6f}uxl9M^9gz>_;VS~o%)Z69~*tQ>X9 z+fP0%kn;<3Tz+b_tNiGG{&QjW&) ze<{=f`RCs3=c9ukK&uq_u5S8C6bRA>Y4&ydIOK~B?@$U`Hg{-#1_-vRu)L0uB-pjk zUTbPdWusk(FuaF)s;sI=geIto1!Xn9iX@UWj_m>ZAWIW8ah$s z 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 I_5TO;7YHZZ9smFU literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/data/NTR_IPL_font_s.NFTR b/build/systemMenu_RED/data/NTR_IPL_font_s.NFTR new file mode 100644 index 0000000000000000000000000000000000000000..59591f8be6def8fe4de486ab80d222c2a61cac62 GIT binary patch literal 79924 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 YoG(@VSs+#W>6gIILJ9sX`u`8=e>mHKZvX%Q literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/data/PictoChatBanner.bnr b/build/systemMenu_RED/data/PictoChatBanner.bnr new file mode 100644 index 0000000000000000000000000000000000000000..87072f9aa865cb681d87eee8b1656ef8b1351031 GIT binary patch literal 2624 zcmd^d8QBMy0 ziXSSK?Em%eE1*ivGSy30l}uMLMo2V{BN1W)N{=DSrqB$hK@+AtTnQMga5`t1(E#Dg zl=3>ItnSe=V_ecd>y6c!MB+Je5RK)a+mk8!r>|s`HluC|k?`EE_>qYaxPX9%m;vnx zv-yMuh;2_id|e)=p3A7~(7Nl-aU9=uY~Q_s)NJ3W)qJ~VwZ`#4jH2Tb7Y@QQkE1b49)d^Az;SH0ZCe&L%Ryt;b?s6vGisLAvi<>YzJf9# zZ+EVJym@kK;r7t?{KXZG6Rk*(Umb#}^4B z56BXENM4W~@|x@tpFAhe@T?lONY+Wa((~WI9Z==<-z1MKJ^x4e?N@pI{fhtp?p1pJ Fe*mGdGSdJ6 literal 0 HcmV?d00001 diff --git a/build/systemMenu_RED/data/SettingBanner.bnr b/build/systemMenu_RED/data/SettingBanner.bnr new file mode 100644 index 0000000000000000000000000000000000000000..e1f6218ecb8c07862ee762358d8f853af61e5582 GIT binary patch literal 2624 zcmd^W)7@vkPtQL2I@^BJXX_u?RaKVd zpFGct(=02pYzTCb4T0_!Lwydrgq>@xmDc;J8=~^lZ0%5~XNO8wJ|4}KlBtq1355_? zY8l6$-VyD=W|`JA$xh67H)75y;`(vOV;?MrywKgFLWiQz=Q&VQ_D@uyPI^GD9`vL* zkZJbwqJK}O31WPiZUzwH3$Yc5vp5i2esC63Fz`tTBEbRCB${90d-H-O6%Y6&MEwR) ztKm|WF|Ozxr(=1XfK9M8P6h$!AVwfYKsbaT6G$J@;Zw=`7pv(ebp*M{b|DTY$EJqk zO|fmyu`SQJ1x(AcP1CbXqdDFk{21;0ia|KqAa@jp;V24M*6|)0p(Y*CLfUsUcF+LX zReuMLTiJ-Q5o19t%Q6gzVWY9*I96p>8Kz-0jsL*S*I+aD;rWekw}0Q6x!aoia{p+d zczCnfZhdY4U0aCWzb?1$eNI=eIy!aOpJkjqVRLMmyXe8G3vv$7|(NS*p7^Fvhy_-RIC=G$*j!R zjc6M%1x$gzrT~At9Xg>IUC}vhf4|Y|9`Dvf% z+@J)-l!M6yor1@V=5z)|mz39bl=z^~BNc8+-MnmNsYKWK4pQbj*zhgDyHFVSo^QX3 zRXD4)71nBejd%Znd4H_1pb`qV>D+tT*CQ3qN?nDq65Ya=Ih*~w0ywkTx^Y1BrhqA6 z3TzbM{UJePOa-fee(QkqR{&syVQ=X3F9qi$f~jB?5Hm0rQh_1W$rZzebc`nwmkL$^ zLpnLRd^mZtlN*ZjZ%6&ahm%VKnl}YZfw}^_;c>|4|B-(GuP51)DPRixD+OGXO|mhT zBxh@5aeUS$Xvb)599ISODR6Qe`wkz)duZM;mv9G|3RVFz0<#|hFM~N#;8zuR2jgg> Af&c&j literal 0 HcmV?d00001 diff --git a/build/tools/Makefile b/build/tools/Makefile new file mode 100644 index 0000000..9246e82 --- /dev/null +++ b/build/tools/Makefile @@ -0,0 +1,35 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - firmware +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + + +#---------------------------------------------------------------------------- + +SUBDIRS = \ + makenorfirm \ + makegcdfirm \ + makenandfirm \ + + +#---------------------------------------------------------------------------- + +include $(TWLSDK_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/tools/acsign/Makefile b/build/tools/acsign/Makefile new file mode 100644 index 0000000..bba2b4a --- /dev/null +++ b/build/tools/acsign/Makefile @@ -0,0 +1,61 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: NitroSDK - libraries - acsign +# File: Makefile +# +# Copyright 2003,2004 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $NoKeywords: $ +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Codegen for sub processer +NITRO_PROC = ARM9 + +# build ARM & THUMB libraries +NITRO_CODEGEN_ALL = True + +#---------------------------------------------------------------------------- + +SUBDIRS = + + +#---------------------------------------------------------------------------- + +SRCDIR = ./src +INCDIR = ./include $(TWLSDK_ROOT)/build/libraries/mb/include + + +SRCS = acsign.c acmemory.c acsign_util.c + +TARGET_LIB = libacsign_x86.a + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +# CCFLAGS += -DOPT_32_BIT -DSTANDALONE -DNO_SPLIT -DNO_FP_API -DNO_R_DIAG -DNO_STDIO_H -DNO_STDLIB_H +CCFLAGS += -DSMALL_CODE_SIZE \ + -DSTANDALONE \ + -DOPT_32_BIT \ + -DNO_SPLIT \ + -DNO_FP_API \ + -DNO_R_DIAG \ + -DNO_STDIO_H \ + -DNO_STDLIB_H + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = . + + +do-build: $(TARGETS) + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/tools/acsign/acsign.c b/build/tools/acsign/acsign.c new file mode 100644 index 0000000..7b63142 --- /dev/null +++ b/build/tools/acsign/acsign.c @@ -0,0 +1,334 @@ +#include +#include "format_sign.h" +#include "acsign.h" + +// SHA1 +#include "sha1dgst.c" + +// RSA + +// BN +#include "bn.h" + +#include "bn_lib.c" +#include "bn_asm.c" +#include "bn_comba.c" +#include "bn_lsh.c" +#include "bn_rsh.c" +#include "bn_word.c" +#include "bn_add.c" +#include "bn_mul.c" +#include "bn_div.c" +#include "bn_exp.c" +#include "bn_sqr.c" +#include "bn_fm_w.c" +#include "bn_gcd.c" +#include "bn_ex_str.c" +#include "bn_ms_w.c" +//#include "bn_me.c" +#include "bn_rec.c" +#include "bn_mont.c" +#include "bn_recp.c" +#include "bn_wdiv.c" +#include "bn_r_exp.c" +#include "bn_m_exp.c" + + + +#define BER_NULL 5 +#define BER_OBJECT 6 +#define BER_SEQUENCE 16 +#define BER_OCTET_STRING 4 +#define BER_CONSTRUCTED 0x20 + + +/** + * Perform the EMSA-PKCS1_v1_5 padding + * + * @param random random context for seed data generation + * @param out destination buffer + * @param out_len length written to out + * @param in data to be padded + * @param in_len length of in + * @param flags mask of operation directives + * + * @pre out_len must contain length of data allocated to out + * @pre out must be the allocated the total length to be padded + * + * @note Method from PKCS#1 v2.1 standard 9.2.1 EMSA-PKCS1-v1_5 + * @li In: Hash is hash funtion, hLen denotes length of octets of hash output + * @li In: M is message to be encoded + * @li In: emLen is intended length of octets + * @li Out: EM encoded message of length emLen + * + * @li Apply the hash function to message M to produce a hash value H + * If hash output is message to long the output message too long and + * stop + * @li Encode the algorithm ID for the hash in function into an ASN1 value + * @li if emLen < 10 + BER encoded message T output message length too short + * and stop + * @li generate octet string PS consisting of emLen - Length(T) - 2 octets + * with value FF + * @li Concatenate PS, DER encoding T and other padding such that EM is: + * 01 || PS || 00 || T + * + * @note it is the out layers responsibility to DER encode the + * data prior to padding as described in the first 2 steps in method + */ +// +// rsa_padding_add_pkcs1_type_1֐ +// +static int add_padding(unsigned char *out, + int out_len, const unsigned char *in, int in_len) +{ + unsigned char *p; + int j,i; + + if ((in_len+11) > out_len) + return(1); + + /* First we copy data bytes to the output buffer, this + * way the input and output buffers can be the same + * and things will still work */ + p=out+out_len-in_len; + for (i=in_len-1; i>=0; i--) + p[i]=in[i]; + p=out; + *(p++)=0; + *(p++)=1; /* Private Key BT (Block Type) */ + + /* pad with 0xff data */ + j=out_len-3-in_len; + Memset(p,0xff,j); + p[j]='\0'; + return(0); +} + +static void debug_dump(const void* buf, int len, const char* str, int line_elms) +{ + const u8* bufp = (u8*)buf; + int i,ii; + + if (str) + { + debug_printf("%s :\n", str); + } + for (i=0; i<=len/line_elms; i++) + { + if (i*line_elms >= len) + { + break; + } + for (ii=0; ii= len) + { + break; + } + debug_printf("%02x ", bufp[i*line_elms+ii]); + } + debug_printf("\n"); + } +} + +// +// RSA +// +BOOL ACSign_Encrypto(void *sign, const void *key, const void *data, int length) +{ + BN_CTX *ctx; + BIGNUM src, dst, exp, mod; + u8* key_exp = &((u8*)key)[ACS_RSA_PRVEXP_OFFSET]; + u8* key_mod = &((u8*)key)[ACS_RSA_PRVMOD_OFFSET]; + u8 buf[ACS_ENCRYPTED_HASH_LEN]; + u32 len = length; + BOOL result = TRUE; + + if (NULL == sign || NULL == key || NULL == data || 0 > length) { + return FALSE; + } + + if ( add_padding( buf, ACS_ENCRYPTED_HASH_LEN, data, length ) ) { + debug_printf2("encode_padding was failed.\n"); + result = FALSE; + goto end; + } + + { + debug_dump(buf, ACS_ENCRYPTED_HASH_LEN, "padded hash", 16); + debug_dump(key_mod, ACS_RSA_PRVMOD_LEN, "key mod", 16); + debug_dump(key_exp, ACS_RSA_PRVEXP_LEN, "key exp", 16); + } + + ctx = BN_CTX_new(); + + BN_init(&src); + BN_init(&dst); + BN_init(&exp); + BN_init(&mod); + + BN_bin2bn((u8*)buf, ACS_ENCRYPTED_HASH_LEN, &src); + BN_bin2bn(key_exp, ACS_RSA_PRVEXP_LEN, &exp); + BN_bin2bn(key_mod, ACS_RSA_PRVMOD_LEN, &mod); + + BN_mod_exp( &dst, &src, &exp, &mod, ctx ); + + len = BN_bn2bin( &dst, sign ); + + BN_free(&src); + BN_free(&dst); + BN_free(&exp); + BN_free(&mod); + + if (ctx) { + BN_CTX_free(ctx); + } + + if ( len != ACS_DECRYPTED_HASH_LEN ) { + result = FALSE; + goto end; + } +end: + return result; +} + +BOOL ACSign_Decrypto(void *buf, const void *key, const void *sign, int length) +{ + BN_CTX *ctx; + BIGNUM src, dst, exp, mod; + u32 key_exp = ACS_RSA_EXP; + u8* key_mod = &((u8*)key)[ACS_RSA_PRVMOD_OFFSET]; + u8* bufp = (u8*)buf; + u32 len = length; + BOOL result = TRUE; + + if (NULL == buf || NULL == key || NULL == sign || 0 > length) { + return FALSE; + } + + ctx = BN_CTX_new(); + + BN_init(&src); + BN_init(&dst); + BN_init(&exp); + BN_init(&mod); + + BN_bin2bn((u8*)sign, ACS_ENCRYPTED_HASH_LEN, &src); + BN_bin2bn((u8*)&key_exp, ACS_RSA_PUBEXP_LEN, &exp); + BN_bin2bn(key_mod, ACS_RSA_PRVMOD_LEN, &mod); + + BN_mod_exp( &dst, &src, &exp, &mod, ctx ); + + len = BN_bn2bin( &dst, bufp ); + + BN_free(&src); + BN_free(&dst); + BN_free(&exp); + BN_free(&mod); + + if (ctx) { + BN_CTX_free(ctx); + } + + if ( len != ACS_DECRYPTED_HASH_LEN ) { + result = FALSE; + goto end; + } +end: + return result; +} + +// +int ACSign_DigestUnit( + void* buffer, // o͗̈ + const void* buf, // f[^ւ̃|C^ + unsigned int len // f[^̒ + ) +{ + HASHContext context; + unsigned char *bufferp = buffer; + + HASHReset( &context ); + HASHUpdate( &context, buf, len ); + HASHGetDigest( &context, bufferp ); + + return TRUE; +} + +// +int ACSign_CompareUnit( + const void* decedHash, // ACSign_Decryptȍo + const void* digest // ACSign_DigestUnit̏o + ) +{ + const unsigned char* dgt = digest; + const unsigned char* dgtCmp = decedHash; + int i; + int test = TRUE; + + if ( !decedHash ) return FALSE; + if ( !digest ) return FALSE; + + for ( i = 0; i < ACS_HASH_LEN; i++ ) + { + if ( *dgt++ != *dgtCmp++ ) + { + test = FALSE; + break; + } + } + return test; +} + +/* + CӃoCg̓̓f[^ + CӃoCg̏o̓f[^𓾂܂B + ΂Ă邩Ȃ͒llȒlɃ}bv邾łB + o̓ԂĂĂȂ +*/ +int ACSign_GetKey( + void* dest_ptr, // o̓f[^ւ̃|C^ + unsigned int dest_len, // o̓f[^̒ + const void* src_ptr, // ̓f[^ւ̃|C^ + unsigned int src_len // ̓f[^̒ + ) +{ + HASHContext ctx; + unsigned char *ptr; + unsigned char state[ACS_HASH_LEN]; + unsigned char output[ACS_HASH_LEN]; + int i; + + if (dest_ptr == NULL) + return 1; + if (src_ptr == NULL && src_len > 0) + return 0; + + HASHReset(&ctx); + + HASHUpdate(&ctx, src_ptr, src_len); + HASHGetDigest(&ctx, state); + + ptr = dest_ptr; + while (dest_len > 0) + { + unsigned int len = dest_len < ACS_HASH_LEN ? dest_len : ACS_HASH_LEN; + + // plus one + for (i = 0; i < ACS_HASH_LEN; i++) + { + if (state[ACS_HASH_LEN-1-i]++) + break; + } + + HASHUpdate(&ctx, state, ACS_HASH_LEN); + HASHGetDigest(&ctx, output); + memcpy(ptr, output, len); + ptr += len; + dest_len -= len; + } + memset(state, 0, ACS_HASH_LEN); + memset(output, 0, ACS_HASH_LEN); + return 1; +} + diff --git a/build/tools/acsign/acsign_gcd.c b/build/tools/acsign/acsign_gcd.c new file mode 100644 index 0000000..e8b4567 --- /dev/null +++ b/build/tools/acsign/acsign_gcd.c @@ -0,0 +1,74 @@ +#include +#include "acsign_gcd.h" + +static void debug_dump(void* buf, int len, char* str, int line_elms) +{ + u8* bufp = (u8*)buf; + int i,ii; + + if (str) + { + debug_printf("%s :\n", str); + } + for (i=0; i<=len/line_elms; i++) + { + if (i*line_elms >= len) + { + break; + } + for (ii=0; ii= len) + { + break; + } + debug_printf("%02x ", bufp[i*line_elms+ii]); + } + debug_printf("\n"); + } +} + +// +int ACSign_DigestHeader( + void* buffer, // o͗̈ + GCDHeader* header // wb_ւ̃|C^ + ) +{ + HASHContext context; + GCDHeader* nh = header; + unsigned char *bufferp = buffer; + + HASHReset( &context ); + HASHUpdate( &context, (void*)&nh->l, sizeof(GCDHeaderLow) ); + HASHUpdate( &context, (void*)&nh->h, sizeof(GCDHeaderHigh) ); + HASHGetDigest( &context, bufferp ); + + return TRUE; +} + +// +int ACSign_Final( + GCDHeader* header, // wb_ւ̃|C^ + void* buffer, // ͗̈ + const void* key + ) +{ + GCDHeader* nh = header; + FIRMSignedContext* sc = buffer; + + if (key) + { + unsigned char decSign[ACS_ENCRYPTED_HASH_LEN]; + + debug_dump(sc->hash, sizeof(sc->hash), "5 hashs of header, norfirms and total", 20); + + ACSign_Encrypto(&nh->sign, key, buffer, sizeof(FIRMSignedContext)); + ACSign_Decrypto(decSign, key, (void*)&nh->sign, ACS_ENCRYPTED_HASH_LEN); + + debug_dump(&nh->sign, ACS_ENCRYPTED_HASH_LEN, "encrypted sign", 16); + debug_dump(decSign, ACS_ENCRYPTED_HASH_LEN, "decrypted sign", 16); + } + + return TRUE; +} + diff --git a/build/tools/acsign/acsign_nand.c b/build/tools/acsign/acsign_nand.c new file mode 100644 index 0000000..8b0b719 --- /dev/null +++ b/build/tools/acsign/acsign_nand.c @@ -0,0 +1,75 @@ +#include +#include "acsign_nand.h" + +static void debug_dump(void* buf, int len, char* str, int line_elms) +{ + u8* bufp = (u8*)buf; + int i,ii; + + if (str) + { + debug_printf("%s :\n", str); + } + for (i=0; i<=len/line_elms; i++) + { + if (i*line_elms >= len) + { + break; + } + for (ii=0; ii= len) + { + break; + } + debug_printf("%02x ", bufp[i*line_elms+ii]); + } + debug_printf("\n"); + } +} + +// +int ACSign_DigestHeader( + void* buffer, // o͗̈ + NANDHeader* header // wb_ւ̃|C^ + ) +{ + HASHContext context; + NANDHeader* nh = header; + unsigned char *bufferp = buffer; + + HASHReset( &context ); + HASHUpdate( &context, (void*)&nh->d, sizeof(NORHeaderDS) ); + HASHUpdate( &context, (void*)&nh->l, sizeof(NANDHeaderLow) ); + HASHUpdate( &context, (void*)&nh->h, sizeof(NANDHeaderHigh) ); + HASHGetDigest( &context, bufferp ); + + return TRUE; +} + +// +int ACSign_Final( + NANDHeader* header, // wb_ւ̃|C^ + void* buffer, // ͗̈ + const void* key + ) +{ + NANDHeader* nh = header; + FIRMSignedContext* sc = buffer; + + if (key) + { + unsigned char decSign[ACS_ENCRYPTED_HASH_LEN]; + + debug_dump(sc->hash, sizeof(sc->hash), "5 hashs of header, nandfirms and total", 20); + + ACSign_Encrypto(&nh->sign, key, buffer, sizeof(FIRMSignedContext)); + ACSign_Decrypto(decSign, key, (void*)&nh->sign, ACS_ENCRYPTED_HASH_LEN); + + debug_dump(&nh->sign, ACS_ENCRYPTED_HASH_LEN, "encrypted sign", 16); + debug_dump(decSign, ACS_ENCRYPTED_HASH_LEN, "decrypted sign", 16); + } + + return TRUE; +} + diff --git a/build/tools/acsign/acsign_nor.c b/build/tools/acsign/acsign_nor.c new file mode 100644 index 0000000..0bb690c --- /dev/null +++ b/build/tools/acsign/acsign_nor.c @@ -0,0 +1,75 @@ +#include +#include "acsign_nor.h" + +static void debug_dump(void* buf, int len, char* str, int line_elms) +{ + u8* bufp = (u8*)buf; + int i,ii; + + if (str) + { + debug_printf("%s :\n", str); + } + for (i=0; i<=len/line_elms; i++) + { + if (i*line_elms >= len) + { + break; + } + for (ii=0; ii= len) + { + break; + } + debug_printf("%02x ", bufp[i*line_elms+ii]); + } + debug_printf("\n"); + } +} + +// +int ACSign_DigestHeader( + void* buffer, // o͗̈ + NORHeader* header // wb_ւ̃|C^ + ) +{ + HASHContext context; + NORHeader* nh = header; + unsigned char *bufferp = buffer; + + HASHReset( &context ); + HASHUpdate( &context, (void*)&nh->d, sizeof(NORHeaderDS) ); + HASHUpdate( &context, (void*)&nh->l, sizeof(NORHeaderLow) ); + HASHUpdate( &context, (void*)&nh->h, sizeof(NORHeaderHigh) ); + HASHGetDigest( &context, bufferp ); + + return TRUE; +} + +// +int ACSign_Final( + NORHeader* header, // wb_ւ̃|C^ + void* buffer, // ͗̈ + const void* key + ) +{ + NORHeader* nh = header; + FIRMSignedContext* sc = buffer; + + if (key) + { + unsigned char decSign[ACS_ENCRYPTED_HASH_LEN]; + + debug_dump(sc->hash, sizeof(sc->hash), "5 hashs of header, norfirms and total", 20); + + ACSign_Encrypto(&nh->sign, key, buffer, sizeof(FIRMSignedContext)); + ACSign_Decrypto(decSign, key, (void*)&nh->sign, ACS_ENCRYPTED_HASH_LEN); + + debug_dump(&nh->sign, ACS_ENCRYPTED_HASH_LEN, "encrypted sign", 16); + debug_dump(decSign, ACS_ENCRYPTED_HASH_LEN, "decrypted sign", 16); + } + + return TRUE; +} + diff --git a/build/tools/acsign/aes.h b/build/tools/acsign/aes.h new file mode 100644 index 0000000..a7a75d8 --- /dev/null +++ b/build/tools/acsign/aes.h @@ -0,0 +1,139 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2003 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + */ + +#ifndef HEADER_COMMON_AES_H +#define HEADER_COMMON_AES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define AES_ecb_encrypt(key, out, in) \ + AES_ecb_encrypt_com((key), (out), (in), AES_encrypt) +#define AES_ecb_encrypt_m(key, out, in) \ + AES_ecb_encrypt_com((key), (out), (in), AES_encrypt_m) +#define AES_ecb_encrypt_s(key, out, in) \ + AES_ecb_encrypt_com((key), (out), (in), AES_encrypt_s) + +#define AES_ecb_decrypt(key, out, in) \ + AES_ecb_decrypt_com((key), (out), (in), AES_decrypt) +#define AES_ecb_decrypt_m(key, out, in) \ + AES_ecb_decrypt_com((key), (out), (in), AES_decrypt_m) +#define AES_ecb_decrypt_s(key, out, in) \ + AES_ecb_decrypt_com((key), (out), (in), AES_decrypt_s) + +#define AES_cbc_encrypt(ctx, out, in, len, iv) \ + AES_cbc_encrypt_com((ctx), (out), (in), (len), (iv), AES_encrypt) +#define AES_cbc_encrypt_m(ctx, out, in, len, iv) \ + AES_cbc_encrypt_com((ctx), (out), (in), (len), (iv), AES_encrypt_m) +#define AES_cbc_encrypt_s(ctx, out, in, len, iv) \ + AES_cbc_encrypt_com((ctx), (out), (in), (len), (iv), AES_encrypt_s) + +#define AES_cbc_decrypt(ctx, out, in, len, iv) \ + AES_cbc_decrypt_com((ctx), (out), (in), (len), (iv), AES_decrypt) +#define AES_cbc_decrypt_m(ctx, out, in, len, iv) \ + AES_cbc_decrypt_com((ctx), (out), (in), (len), (iv), AES_decrypt_m) +#define AES_cbc_decrypt_s(ctx, out, in, len, iv) \ + AES_cbc_decrypt_com((ctx), (out), (in), (len), (iv), AES_decrypt_s) + +#define AES_cfb128_encrypt(ks, out, in, len, iv, num) \ + AES_cfb128_encrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_encrypt) +#define AES_cfb128_encrypt_m(ks, out, in, len, iv, num) \ + AES_cfb128_encrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_encrypt_m) +#define AES_cfb128_encrypt_s(ks, out, in, len, iv, num) \ + AES_cfb128_encrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_encrypt_s) + +#define AES_cfb128_decrypt(ks, out, in, len, iv, num) \ + AES_cfb128_decrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_decrypt) +#define AES_cfb128_decrypt_m(ks, out, in, len, iv, num) \ + AES_cfb128_decrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_decrypt_m) +#define AES_cfb128_decrypt_s(ks, out, in, len, iv, num) \ + AES_cfb128_decrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_decrypt_s) + +/** Note. OFB encryption is also used for decryption */ +#define AES_ofb128_encrypt(ks, out, in, len, iv, num) \ + AES_ofb128_encrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_encrypt) +#define AES_ofb128_encrypt_m(ks, out, in, len, iv, num) \ + AES_ofb128_encrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_encrypt_m) +#define AES_ofb128_encrypt_s(ks, out, in, len, iv, num) \ + AES_ofb128_encrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_encrypt_s) + +#define AES_ofb128_decrypt(ks, out, in, len, iv, num) \ + AES_ofb128_encrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_encrypt) +#define AES_ofb128_decrypt_m(ks, out, in, len, iv, num) \ + AES_ofb128_encrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_encrypt_m) +#define AES_ofb128_decrypt_s(ks, out, in, len, iv, num) \ + AES_ofb128_encrypt_com((ks), (out), (in), (len), (iv), (num), \ + AES_encrypt_s) + + +#define AES_MAXROUNDS 14 + +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +typedef unsigned int AES_INT4; + +typedef struct aes_key_st { + unsigned int rounds; + unsigned int key_size; + AES_INT4 ks[(AES_MAXROUNDS+1)*8]; + } AES_KEY; + +typedef void (* AES_ENC_DEC_FN)(AES_KEY *, AES_INT4 *); + +void AES_encrypt(AES_KEY *ctx,AES_INT4 *data); +void AES_encrypt_m(AES_KEY *ctx,AES_INT4 *data); +void AES_encrypt_s(AES_KEY *ctx,AES_INT4 *data); +void AES_decrypt(AES_KEY *ctx,AES_INT4 *data); +void AES_decrypt_m(AES_KEY *ctx,AES_INT4 *data); +void AES_decrypt_s(AES_KEY *ctx,AES_INT4 *data); + +void AES_ecb_encrypt_com(AES_KEY *key, unsigned char *out, + const unsigned char *in, AES_ENC_DEC_FN enc_fn); +void AES_ecb_decrypt_com(AES_KEY *key, unsigned char *out, + const unsigned char *in, AES_ENC_DEC_FN dec_fn); +void AES_cbc_encrypt_com(AES_KEY *ctx, unsigned char *out, + const unsigned char *in, long length, unsigned char *iv, + AES_ENC_DEC_FN enc_fn); +void AES_cbc_decrypt_com(AES_KEY *ctx, unsigned char *out, + const unsigned char *in, long length, unsigned char *iv, + AES_ENC_DEC_FN dec_fn); +void AES_ofb128_encrypt_com(AES_KEY *ks,const unsigned char *in, + unsigned char *out, long length, unsigned char *ivec, int *num, + AES_ENC_DEC_FN enc_fn); +void AES_cfb128_encrypt_com(AES_KEY *ks, const unsigned char *in, + unsigned char *out, long length, unsigned char *ivec, int *num, + AES_ENC_DEC_FN enc_fn); +void AES_cfb128_decrypt_com(AES_KEY *ks, const unsigned char *in, + unsigned char *out, long length, unsigned char *ivec, int *num, + AES_ENC_DEC_FN dec_fn); + +int AES_set_key(AES_KEY *ctx, const unsigned char *key, int len); +void AES_convert_key(AES_KEY *ctx); +AES_INT4 AES_rotate(AES_INT4 u); +unsigned char AES_xtime(AES_INT4 x); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_COMMON_AES_H */ diff --git a/build/tools/acsign/aes2.c b/build/tools/acsign/aes2.c new file mode 100644 index 0000000..778dc53 --- /dev/null +++ b/build/tools/acsign/aes2.c @@ -0,0 +1,133 @@ +#include +#include + +#include "aes2.h" + +#include "aes_e.c" +#include "aes_e_ecb.c" +#include "aes_skey.c" + +// +// swap with memory allocation +// +static unsigned char* AES_Swap(const unsigned char *src, int len, int unit) +{ + int i; + int j; + unsigned char *dest = malloc(len); + for (i = 0; i < len; i+=unit) + for (j = 0; j < unit; j++) + dest[i + j] = src[i + unit - j - 1]; + return dest; +} + +// +// set keys +// +void AES_SetKey(AES_KEY *key, const unsigned char seed[AES_BLOCK_SIZE], const unsigned char id[AES_BLOCK_SIZE]) +{ + static const unsigned char f[AES_BLOCK_SIZE] = {0xff, 0xfe, 0xfb, 0x4e, 0x29, 0x59, 0x02, 0x58, 0x2a, 0x68, 0x0f, 0x5f, 0x1a, 0x4f, 0x3e, 0x79}; + static const unsigned char s = 0x2a; + + unsigned char key1[AES_BLOCK_SIZE]; + unsigned char key2[AES_BLOCK_SIZE]; + int i; + int o = 0; + + for (i = 0; i < AES_BLOCK_SIZE; i++) { + key1[i] = seed[AES_BLOCK_SIZE-i-1] ^ id[AES_BLOCK_SIZE-i-1]; + } + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + int t = key1[i] + f[i] + o; + o = (t > 0xFF ? 1 : 0); + key1[i] = t & 0xFF; + } + for (i = 0; i < AES_BLOCK_SIZE; i++) { + int j1 = (i + s / 8) % AES_BLOCK_SIZE; + int j2 = (j1 + 1) % AES_BLOCK_SIZE; + int k = s % 8; + key2[i] = ((key1[j1] << k) & 0xFF) | ((key1[j2] >> (8 - k)) & 0xFF); + } + AES_set_key(key, key2, 16); + memset(key2, 0, 16); + memset(key1, 0, 16); +} + +// +// ctr mode +// +#define GETU32(pt) (((unsigned long)(pt)[0] << 24) ^ ((unsigned long)(pt)[1] << 16) ^ ((unsigned long)(pt)[2] << 8) ^ ((unsigned long)(pt)[3])) +#define PUTU32(ct, st) { (ct)[0] = (unsigned char)((st) >> 24); (ct)[1] = (unsigned char)((st) >> 16); (ct)[2] = (unsigned char)((st) >> 8); (ct)[3] = (unsigned char)(st); } + +/* increment counter as u128 */ +static void AES_ctr128_increment(unsigned char *counter) { + unsigned long c; + + c = GETU32(counter + 12); + c++; c &= 0xFFFFFFFF; + PUTU32(counter + 12, c); + if (c) return; // return unless overflow + + c = GETU32(counter + 8); + c++; c &= 0xFFFFFFFF; + PUTU32(counter + 8, c); + if (c) return; // return unless overflow + + c = GETU32(counter + 4); + c++; c &= 0xFFFFFFFF; + PUTU32(counter + 4, c); + if (c) return; // return unless overflow + + c = GETU32(counter + 0); + c++; c &= 0xFFFFFFFF; + PUTU32(counter + 0, c); +} +static void AES_ctr128(const unsigned char *in, unsigned char *out, const unsigned long length, AES_KEY *key, + unsigned char ivec[AES_BLOCK_SIZE], unsigned char ebuf[AES_BLOCK_SIZE], unsigned int *num) { + + unsigned int n; + unsigned long l=length; + + n = *num; + + while (l--) { // loop each byte + if (n == 0) { + AES_ecb_encrypt(key, ebuf, ivec); // encrypt counter + AES_ctr128_increment(ivec); // increment counter + } + *(out++) = *(in++) ^ ebuf[n]; + n = (n+1) % AES_BLOCK_SIZE; + } + + *num=n; +} + +void AES_Ctr(AES_KEY *key, unsigned char *outdata, const unsigned char *indata, int len, unsigned char iv[AES_BLOCK_SIZE]) +{ + unsigned char ebuf[AES_BLOCK_SIZE]; + unsigned char *tmp; + unsigned int nums; + + if (len <= 0 || len > 0xFFFF00 || (len % AES_BLOCK_SIZE) != 0 || indata == NULL || outdata == NULL) + { + return; + } + + // CTR + memset(ebuf, 0, AES_BLOCK_SIZE); + nums = 0; + + tmp = AES_Swap(iv, AES_BLOCK_SIZE, AES_BLOCK_SIZE); + memcpy(iv, tmp, AES_BLOCK_SIZE); + free(tmp); + + tmp = AES_Swap(indata, len, AES_BLOCK_SIZE); + AES_ctr128(tmp, outdata, len, key, iv, ebuf, &nums); + free(tmp); + + tmp = AES_Swap(outdata, len, AES_BLOCK_SIZE); + memcpy(outdata, tmp, len); + free(tmp); + return; +} + diff --git a/build/tools/acsign/aes2.h b/build/tools/acsign/aes2.h new file mode 100644 index 0000000..3e80799 --- /dev/null +++ b/build/tools/acsign/aes2.h @@ -0,0 +1,21 @@ +#ifndef __AES_2_H__ +#define __AES_2_H__ + +#include "aes.h" + +#define AES_BLOCK_SIZE 16 +#define AES_NONCE_SIZE 12 +#define AES_QUANTITY (AES_BLOCK_SIZE - AES_NONCE_SIZE - 1) + +#ifdef __cplusplus +extern "C" { +#endif + +void AES_SetKey(AES_KEY *key, const unsigned char seed[AES_BLOCK_SIZE], const unsigned char id[AES_BLOCK_SIZE]); +void AES_Ctr(AES_KEY *key, unsigned char *outdata, const unsigned char *indata, int len, unsigned char iv[AES_BLOCK_SIZE]); + +#ifdef __cplusplus +} +#endif + +#endif // __AES_2_H__ diff --git a/build/tools/acsign/aes_e.c b/build/tools/acsign/aes_e.c new file mode 100644 index 0000000..fab235c --- /dev/null +++ b/build/tools/acsign/aes_e.c @@ -0,0 +1,115 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2003 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + */ + +/** + * @file aes_e.c + * \brief Large code size (thus fast) AES Encryption + */ + +#ifndef NO_AES + +#include "aes.h" + +/* Include the Large aes_submix tables */ +#include "aes_e.h" + +/* AES ECB Encryption of 1 x 128 bit Block */ +void AES_encrypt(AES_KEY *ctx, AES_INT4 *data) +{ + int r; + int rounds; + AES_INT4 *k; + AES_INT4 o0,o1,o2,o3; + AES_INT4 tmp0,tmp1,tmp2,tmp3; + + rounds=ctx->rounds; + k= (AES_INT4 *)ctx->ks; + + /* Encrypt one block. + */ + tmp0=data[0]; + tmp1=data[1]; + tmp2=data[2]; + tmp3=data[3]; +/*printf("K %08X %08X %08X %08X\n",tmp0,tmp1,tmp2,tmp3); +printf("KS %08X %08X %08X %08X\n",k[0],k[1],k[2],k[3]); */ + tmp0^=k[0]; + tmp1^=k[1]; + tmp2^=k[2]; + tmp3^=k[3]; + k+=4; + + for(r = 1; r < rounds; r++) + { +/*printf("%2d %08X %08X %08X %08X\n",r,tmp0,tmp1,tmp2,tmp3); */ + o0 = aes_submix[3][(tmp3 )&0xff]^ + aes_submix[2][(tmp2>> 8)&0xff]^ + aes_submix[1][(tmp1>>16)&0xff]^ + aes_submix[0][(tmp0>>24)&0xff]; + + o1 = aes_submix[3][(tmp0 )&0xff]^ + aes_submix[2][(tmp3>> 8)&0xff]^ + aes_submix[1][(tmp2>>16)&0xff]^ + aes_submix[0][(tmp1>>24)&0xff]; + + o2 = + aes_submix[3][(tmp1 )&0xff]^ + aes_submix[2][(tmp0>> 8)&0xff]^ + aes_submix[1][(tmp3>>16)&0xff]^ + aes_submix[0][(tmp2>>24)&0xff]; + + o3 = + aes_submix[3][(tmp2 )&0xff]^ + aes_submix[2][(tmp1>> 8)&0xff]^ + aes_submix[1][(tmp0>>16)&0xff]^ + aes_submix[0][(tmp3>>24)&0xff]; + +/* +printf(" %08X %08X %08X %08X\n",o0,o1,o2,o3); +printf("KS %08X %08X %08X %08X\n",k[0],k[1],k[2],k[3]); */ + tmp0=o0^k[0]; + tmp1=o1^k[1]; + tmp2=o2^k[2]; + tmp3=o3^k[3]; + k+=4; + } +/*printf("O %08X %08X %08X %08X\n",o0,o1,o2,o3); */ + o0 = (aes_submix[0][(tmp3 )&0xff]>> 8)&0xFF; + o1 = (aes_submix[0][(tmp0 )&0xff]>> 8)&0xFF; + o2 = (aes_submix[0][(tmp1 )&0xff]>> 8)&0xFF; + o3 = (aes_submix[0][(tmp2 )&0xff]>> 8)&0xFF; + + o0|= (aes_submix[0][(tmp2>> 8)&0xff] )&0xFF00; + o1|= (aes_submix[0][(tmp3>> 8)&0xff] )&0xFF00; + o2|= (aes_submix[0][(tmp0>> 8)&0xff] )&0xFF00; + o3|= (aes_submix[0][(tmp1>> 8)&0xff] )&0xFF00; + + o0|= (aes_submix[0][(tmp1>>16)&0xff]<< 8)&0xFF0000; + o1|= (aes_submix[0][(tmp2>>16)&0xff]<< 8)&0xFF0000; + o2|= (aes_submix[0][(tmp3>>16)&0xff]<< 8)&0xFF0000; + o3|= (aes_submix[0][(tmp0>>16)&0xff]<< 8)&0xFF0000; + + o0|= (aes_submix[0][(tmp0>>24) ]<<16)&0xFF000000; + o1|= (aes_submix[0][(tmp1>>24) ]<<16)&0xFF000000; + o2|= (aes_submix[0][(tmp2>>24) ]<<16)&0xFF000000; + o3|= (aes_submix[0][(tmp3>>24) ]<<16)&0xFF000000; +/*printf("P %08X %08X %08X %08X\n",o0,o1,o2,o3); */ + o0^=k[0]; + o1^=k[1]; + o2^=k[2]; + o3^=k[3]; +/*printf("Q %08X %08X %08X %08X\n",o0,o1,o2,o3); */ + data[0]= o0; + data[1]= o1; + data[2]= o2; + data[3]= o3; + } + +#endif /* NO_AES */ diff --git a/build/tools/acsign/aes_e.h b/build/tools/acsign/aes_e.h new file mode 100644 index 0000000..74f6db7 --- /dev/null +++ b/build/tools/acsign/aes_e.h @@ -0,0 +1,284 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2003 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + */ + +#ifndef HEADER_COMMON_AES_E_H +#define HEADER_COMMON_AES_E_H + +#ifdef __cplusplus +extern "C" { +#endif + +const AES_INT4 aes_submix[4][256]={{ + 0xC66363A5,0xF87C7C84,0xEE777799,0xF67B7B8D, + 0xFFF2F20D,0xD66B6BBD,0xDE6F6FB1,0x91C5C554, + 0x60303050,0x02010103,0xCE6767A9,0x562B2B7D, + 0xE7FEFE19,0xB5D7D762,0x4DABABE6,0xEC76769A, + 0x8FCACA45,0x1F82829D,0x89C9C940,0xFA7D7D87, + 0xEFFAFA15,0xB25959EB,0x8E4747C9,0xFBF0F00B, + 0x41ADADEC,0xB3D4D467,0x5FA2A2FD,0x45AFAFEA, + 0x239C9CBF,0x53A4A4F7,0xE4727296,0x9BC0C05B, + 0x75B7B7C2,0xE1FDFD1C,0x3D9393AE,0x4C26266A, + 0x6C36365A,0x7E3F3F41,0xF5F7F702,0x83CCCC4F, + 0x6834345C,0x51A5A5F4,0xD1E5E534,0xF9F1F108, + 0xE2717193,0xABD8D873,0x62313153,0x2A15153F, + 0x0804040C,0x95C7C752,0x46232365,0x9DC3C35E, + 0x30181828,0x379696A1,0x0A05050F,0x2F9A9AB5, + 0x0E070709,0x24121236,0x1B80809B,0xDFE2E23D, + 0xCDEBEB26,0x4E272769,0x7FB2B2CD,0xEA75759F, + 0x1209091B,0x1D83839E,0x582C2C74,0x341A1A2E, + 0x361B1B2D,0xDC6E6EB2,0xB45A5AEE,0x5BA0A0FB, + 0xA45252F6,0x763B3B4D,0xB7D6D661,0x7DB3B3CE, + 0x5229297B,0xDDE3E33E,0x5E2F2F71,0x13848497, + 0xA65353F5,0xB9D1D168,0x00000000,0xC1EDED2C, + 0x40202060,0xE3FCFC1F,0x79B1B1C8,0xB65B5BED, + 0xD46A6ABE,0x8DCBCB46,0x67BEBED9,0x7239394B, + 0x944A4ADE,0x984C4CD4,0xB05858E8,0x85CFCF4A, + 0xBBD0D06B,0xC5EFEF2A,0x4FAAAAE5,0xEDFBFB16, + 0x864343C5,0x9A4D4DD7,0x66333355,0x11858594, + 0x8A4545CF,0xE9F9F910,0x04020206,0xFE7F7F81, + 0xA05050F0,0x783C3C44,0x259F9FBA,0x4BA8A8E3, + 0xA25151F3,0x5DA3A3FE,0x804040C0,0x058F8F8A, + 0x3F9292AD,0x219D9DBC,0x70383848,0xF1F5F504, + 0x63BCBCDF,0x77B6B6C1,0xAFDADA75,0x42212163, + 0x20101030,0xE5FFFF1A,0xFDF3F30E,0xBFD2D26D, + 0x81CDCD4C,0x180C0C14,0x26131335,0xC3ECEC2F, + 0xBE5F5FE1,0x359797A2,0x884444CC,0x2E171739, + 0x93C4C457,0x55A7A7F2,0xFC7E7E82,0x7A3D3D47, + 0xC86464AC,0xBA5D5DE7,0x3219192B,0xE6737395, + 0xC06060A0,0x19818198,0x9E4F4FD1,0xA3DCDC7F, + 0x44222266,0x542A2A7E,0x3B9090AB,0x0B888883, + 0x8C4646CA,0xC7EEEE29,0x6BB8B8D3,0x2814143C, + 0xA7DEDE79,0xBC5E5EE2,0x160B0B1D,0xADDBDB76, + 0xDBE0E03B,0x64323256,0x743A3A4E,0x140A0A1E, + 0x924949DB,0x0C06060A,0x4824246C,0xB85C5CE4, + 0x9FC2C25D,0xBDD3D36E,0x43ACACEF,0xC46262A6, + 0x399191A8,0x319595A4,0xD3E4E437,0xF279798B, + 0xD5E7E732,0x8BC8C843,0x6E373759,0xDA6D6DB7, + 0x018D8D8C,0xB1D5D564,0x9C4E4ED2,0x49A9A9E0, + 0xD86C6CB4,0xAC5656FA,0xF3F4F407,0xCFEAEA25, + 0xCA6565AF,0xF47A7A8E,0x47AEAEE9,0x10080818, + 0x6FBABAD5,0xF0787888,0x4A25256F,0x5C2E2E72, + 0x381C1C24,0x57A6A6F1,0x73B4B4C7,0x97C6C651, + 0xCBE8E823,0xA1DDDD7C,0xE874749C,0x3E1F1F21, + 0x964B4BDD,0x61BDBDDC,0x0D8B8B86,0x0F8A8A85, + 0xE0707090,0x7C3E3E42,0x71B5B5C4,0xCC6666AA, + 0x904848D8,0x06030305,0xF7F6F601,0x1C0E0E12, + 0xC26161A3,0x6A35355F,0xAE5757F9,0x69B9B9D0, + 0x17868691,0x99C1C158,0x3A1D1D27,0x279E9EB9, + 0xD9E1E138,0xEBF8F813,0x2B9898B3,0x22111133, + 0xD26969BB,0xA9D9D970,0x078E8E89,0x339494A7, + 0x2D9B9BB6,0x3C1E1E22,0x15878792,0xC9E9E920, + 0x87CECE49,0xAA5555FF,0x50282878,0xA5DFDF7A, + 0x038C8C8F,0x59A1A1F8,0x09898980,0x1A0D0D17, + 0x65BFBFDA,0xD7E6E631,0x844242C6,0xD06868B8, + 0x824141C3,0x299999B0,0x5A2D2D77,0x1E0F0F11, + 0x7BB0B0CB,0xA85454FC,0x6DBBBBD6,0x2C16163A, + },{ + 0xA5C66363,0x84F87C7C,0x99EE7777,0x8DF67B7B, + 0x0DFFF2F2,0xBDD66B6B,0xB1DE6F6F,0x5491C5C5, + 0x50603030,0x03020101,0xA9CE6767,0x7D562B2B, + 0x19E7FEFE,0x62B5D7D7,0xE64DABAB,0x9AEC7676, + 0x458FCACA,0x9D1F8282,0x4089C9C9,0x87FA7D7D, + 0x15EFFAFA,0xEBB25959,0xC98E4747,0x0BFBF0F0, + 0xEC41ADAD,0x67B3D4D4,0xFD5FA2A2,0xEA45AFAF, + 0xBF239C9C,0xF753A4A4,0x96E47272,0x5B9BC0C0, + 0xC275B7B7,0x1CE1FDFD,0xAE3D9393,0x6A4C2626, + 0x5A6C3636,0x417E3F3F,0x02F5F7F7,0x4F83CCCC, + 0x5C683434,0xF451A5A5,0x34D1E5E5,0x08F9F1F1, + 0x93E27171,0x73ABD8D8,0x53623131,0x3F2A1515, + 0x0C080404,0x5295C7C7,0x65462323,0x5E9DC3C3, + 0x28301818,0xA1379696,0x0F0A0505,0xB52F9A9A, + 0x090E0707,0x36241212,0x9B1B8080,0x3DDFE2E2, + 0x26CDEBEB,0x694E2727,0xCD7FB2B2,0x9FEA7575, + 0x1B120909,0x9E1D8383,0x74582C2C,0x2E341A1A, + 0x2D361B1B,0xB2DC6E6E,0xEEB45A5A,0xFB5BA0A0, + 0xF6A45252,0x4D763B3B,0x61B7D6D6,0xCE7DB3B3, + 0x7B522929,0x3EDDE3E3,0x715E2F2F,0x97138484, + 0xF5A65353,0x68B9D1D1,0x00000000,0x2CC1EDED, + 0x60402020,0x1FE3FCFC,0xC879B1B1,0xEDB65B5B, + 0xBED46A6A,0x468DCBCB,0xD967BEBE,0x4B723939, + 0xDE944A4A,0xD4984C4C,0xE8B05858,0x4A85CFCF, + 0x6BBBD0D0,0x2AC5EFEF,0xE54FAAAA,0x16EDFBFB, + 0xC5864343,0xD79A4D4D,0x55663333,0x94118585, + 0xCF8A4545,0x10E9F9F9,0x06040202,0x81FE7F7F, + 0xF0A05050,0x44783C3C,0xBA259F9F,0xE34BA8A8, + 0xF3A25151,0xFE5DA3A3,0xC0804040,0x8A058F8F, + 0xAD3F9292,0xBC219D9D,0x48703838,0x04F1F5F5, + 0xDF63BCBC,0xC177B6B6,0x75AFDADA,0x63422121, + 0x30201010,0x1AE5FFFF,0x0EFDF3F3,0x6DBFD2D2, + 0x4C81CDCD,0x14180C0C,0x35261313,0x2FC3ECEC, + 0xE1BE5F5F,0xA2359797,0xCC884444,0x392E1717, + 0x5793C4C4,0xF255A7A7,0x82FC7E7E,0x477A3D3D, + 0xACC86464,0xE7BA5D5D,0x2B321919,0x95E67373, + 0xA0C06060,0x98198181,0xD19E4F4F,0x7FA3DCDC, + 0x66442222,0x7E542A2A,0xAB3B9090,0x830B8888, + 0xCA8C4646,0x29C7EEEE,0xD36BB8B8,0x3C281414, + 0x79A7DEDE,0xE2BC5E5E,0x1D160B0B,0x76ADDBDB, + 0x3BDBE0E0,0x56643232,0x4E743A3A,0x1E140A0A, + 0xDB924949,0x0A0C0606,0x6C482424,0xE4B85C5C, + 0x5D9FC2C2,0x6EBDD3D3,0xEF43ACAC,0xA6C46262, + 0xA8399191,0xA4319595,0x37D3E4E4,0x8BF27979, + 0x32D5E7E7,0x438BC8C8,0x596E3737,0xB7DA6D6D, + 0x8C018D8D,0x64B1D5D5,0xD29C4E4E,0xE049A9A9, + 0xB4D86C6C,0xFAAC5656,0x07F3F4F4,0x25CFEAEA, + 0xAFCA6565,0x8EF47A7A,0xE947AEAE,0x18100808, + 0xD56FBABA,0x88F07878,0x6F4A2525,0x725C2E2E, + 0x24381C1C,0xF157A6A6,0xC773B4B4,0x5197C6C6, + 0x23CBE8E8,0x7CA1DDDD,0x9CE87474,0x213E1F1F, + 0xDD964B4B,0xDC61BDBD,0x860D8B8B,0x850F8A8A, + 0x90E07070,0x427C3E3E,0xC471B5B5,0xAACC6666, + 0xD8904848,0x05060303,0x01F7F6F6,0x121C0E0E, + 0xA3C26161,0x5F6A3535,0xF9AE5757,0xD069B9B9, + 0x91178686,0x5899C1C1,0x273A1D1D,0xB9279E9E, + 0x38D9E1E1,0x13EBF8F8,0xB32B9898,0x33221111, + 0xBBD26969,0x70A9D9D9,0x89078E8E,0xA7339494, + 0xB62D9B9B,0x223C1E1E,0x92158787,0x20C9E9E9, + 0x4987CECE,0xFFAA5555,0x78502828,0x7AA5DFDF, + 0x8F038C8C,0xF859A1A1,0x80098989,0x171A0D0D, + 0xDA65BFBF,0x31D7E6E6,0xC6844242,0xB8D06868, + 0xC3824141,0xB0299999,0x775A2D2D,0x111E0F0F, + 0xCB7BB0B0,0xFCA85454,0xD66DBBBB,0x3A2C1616, + },{ + 0x63A5C663,0x7C84F87C,0x7799EE77,0x7B8DF67B, + 0xF20DFFF2,0x6BBDD66B,0x6FB1DE6F,0xC55491C5, + 0x30506030,0x01030201,0x67A9CE67,0x2B7D562B, + 0xFE19E7FE,0xD762B5D7,0xABE64DAB,0x769AEC76, + 0xCA458FCA,0x829D1F82,0xC94089C9,0x7D87FA7D, + 0xFA15EFFA,0x59EBB259,0x47C98E47,0xF00BFBF0, + 0xADEC41AD,0xD467B3D4,0xA2FD5FA2,0xAFEA45AF, + 0x9CBF239C,0xA4F753A4,0x7296E472,0xC05B9BC0, + 0xB7C275B7,0xFD1CE1FD,0x93AE3D93,0x266A4C26, + 0x365A6C36,0x3F417E3F,0xF702F5F7,0xCC4F83CC, + 0x345C6834,0xA5F451A5,0xE534D1E5,0xF108F9F1, + 0x7193E271,0xD873ABD8,0x31536231,0x153F2A15, + 0x040C0804,0xC75295C7,0x23654623,0xC35E9DC3, + 0x18283018,0x96A13796,0x050F0A05,0x9AB52F9A, + 0x07090E07,0x12362412,0x809B1B80,0xE23DDFE2, + 0xEB26CDEB,0x27694E27,0xB2CD7FB2,0x759FEA75, + 0x091B1209,0x839E1D83,0x2C74582C,0x1A2E341A, + 0x1B2D361B,0x6EB2DC6E,0x5AEEB45A,0xA0FB5BA0, + 0x52F6A452,0x3B4D763B,0xD661B7D6,0xB3CE7DB3, + 0x297B5229,0xE33EDDE3,0x2F715E2F,0x84971384, + 0x53F5A653,0xD168B9D1,0x00000000,0xED2CC1ED, + 0x20604020,0xFC1FE3FC,0xB1C879B1,0x5BEDB65B, + 0x6ABED46A,0xCB468DCB,0xBED967BE,0x394B7239, + 0x4ADE944A,0x4CD4984C,0x58E8B058,0xCF4A85CF, + 0xD06BBBD0,0xEF2AC5EF,0xAAE54FAA,0xFB16EDFB, + 0x43C58643,0x4DD79A4D,0x33556633,0x85941185, + 0x45CF8A45,0xF910E9F9,0x02060402,0x7F81FE7F, + 0x50F0A050,0x3C44783C,0x9FBA259F,0xA8E34BA8, + 0x51F3A251,0xA3FE5DA3,0x40C08040,0x8F8A058F, + 0x92AD3F92,0x9DBC219D,0x38487038,0xF504F1F5, + 0xBCDF63BC,0xB6C177B6,0xDA75AFDA,0x21634221, + 0x10302010,0xFF1AE5FF,0xF30EFDF3,0xD26DBFD2, + 0xCD4C81CD,0x0C14180C,0x13352613,0xEC2FC3EC, + 0x5FE1BE5F,0x97A23597,0x44CC8844,0x17392E17, + 0xC45793C4,0xA7F255A7,0x7E82FC7E,0x3D477A3D, + 0x64ACC864,0x5DE7BA5D,0x192B3219,0x7395E673, + 0x60A0C060,0x81981981,0x4FD19E4F,0xDC7FA3DC, + 0x22664422,0x2A7E542A,0x90AB3B90,0x88830B88, + 0x46CA8C46,0xEE29C7EE,0xB8D36BB8,0x143C2814, + 0xDE79A7DE,0x5EE2BC5E,0x0B1D160B,0xDB76ADDB, + 0xE03BDBE0,0x32566432,0x3A4E743A,0x0A1E140A, + 0x49DB9249,0x060A0C06,0x246C4824,0x5CE4B85C, + 0xC25D9FC2,0xD36EBDD3,0xACEF43AC,0x62A6C462, + 0x91A83991,0x95A43195,0xE437D3E4,0x798BF279, + 0xE732D5E7,0xC8438BC8,0x37596E37,0x6DB7DA6D, + 0x8D8C018D,0xD564B1D5,0x4ED29C4E,0xA9E049A9, + 0x6CB4D86C,0x56FAAC56,0xF407F3F4,0xEA25CFEA, + 0x65AFCA65,0x7A8EF47A,0xAEE947AE,0x08181008, + 0xBAD56FBA,0x7888F078,0x256F4A25,0x2E725C2E, + 0x1C24381C,0xA6F157A6,0xB4C773B4,0xC65197C6, + 0xE823CBE8,0xDD7CA1DD,0x749CE874,0x1F213E1F, + 0x4BDD964B,0xBDDC61BD,0x8B860D8B,0x8A850F8A, + 0x7090E070,0x3E427C3E,0xB5C471B5,0x66AACC66, + 0x48D89048,0x03050603,0xF601F7F6,0x0E121C0E, + 0x61A3C261,0x355F6A35,0x57F9AE57,0xB9D069B9, + 0x86911786,0xC15899C1,0x1D273A1D,0x9EB9279E, + 0xE138D9E1,0xF813EBF8,0x98B32B98,0x11332211, + 0x69BBD269,0xD970A9D9,0x8E89078E,0x94A73394, + 0x9BB62D9B,0x1E223C1E,0x87921587,0xE920C9E9, + 0xCE4987CE,0x55FFAA55,0x28785028,0xDF7AA5DF, + 0x8C8F038C,0xA1F859A1,0x89800989,0x0D171A0D, + 0xBFDA65BF,0xE631D7E6,0x42C68442,0x68B8D068, + 0x41C38241,0x99B02999,0x2D775A2D,0x0F111E0F, + 0xB0CB7BB0,0x54FCA854,0xBBD66DBB,0x163A2C16, + },{ + 0x6363A5C6,0x7C7C84F8,0x777799EE,0x7B7B8DF6, + 0xF2F20DFF,0x6B6BBDD6,0x6F6FB1DE,0xC5C55491, + 0x30305060,0x01010302,0x6767A9CE,0x2B2B7D56, + 0xFEFE19E7,0xD7D762B5,0xABABE64D,0x76769AEC, + 0xCACA458F,0x82829D1F,0xC9C94089,0x7D7D87FA, + 0xFAFA15EF,0x5959EBB2,0x4747C98E,0xF0F00BFB, + 0xADADEC41,0xD4D467B3,0xA2A2FD5F,0xAFAFEA45, + 0x9C9CBF23,0xA4A4F753,0x727296E4,0xC0C05B9B, + 0xB7B7C275,0xFDFD1CE1,0x9393AE3D,0x26266A4C, + 0x36365A6C,0x3F3F417E,0xF7F702F5,0xCCCC4F83, + 0x34345C68,0xA5A5F451,0xE5E534D1,0xF1F108F9, + 0x717193E2,0xD8D873AB,0x31315362,0x15153F2A, + 0x04040C08,0xC7C75295,0x23236546,0xC3C35E9D, + 0x18182830,0x9696A137,0x05050F0A,0x9A9AB52F, + 0x0707090E,0x12123624,0x80809B1B,0xE2E23DDF, + 0xEBEB26CD,0x2727694E,0xB2B2CD7F,0x75759FEA, + 0x09091B12,0x83839E1D,0x2C2C7458,0x1A1A2E34, + 0x1B1B2D36,0x6E6EB2DC,0x5A5AEEB4,0xA0A0FB5B, + 0x5252F6A4,0x3B3B4D76,0xD6D661B7,0xB3B3CE7D, + 0x29297B52,0xE3E33EDD,0x2F2F715E,0x84849713, + 0x5353F5A6,0xD1D168B9,0x00000000,0xEDED2CC1, + 0x20206040,0xFCFC1FE3,0xB1B1C879,0x5B5BEDB6, + 0x6A6ABED4,0xCBCB468D,0xBEBED967,0x39394B72, + 0x4A4ADE94,0x4C4CD498,0x5858E8B0,0xCFCF4A85, + 0xD0D06BBB,0xEFEF2AC5,0xAAAAE54F,0xFBFB16ED, + 0x4343C586,0x4D4DD79A,0x33335566,0x85859411, + 0x4545CF8A,0xF9F910E9,0x02020604,0x7F7F81FE, + 0x5050F0A0,0x3C3C4478,0x9F9FBA25,0xA8A8E34B, + 0x5151F3A2,0xA3A3FE5D,0x4040C080,0x8F8F8A05, + 0x9292AD3F,0x9D9DBC21,0x38384870,0xF5F504F1, + 0xBCBCDF63,0xB6B6C177,0xDADA75AF,0x21216342, + 0x10103020,0xFFFF1AE5,0xF3F30EFD,0xD2D26DBF, + 0xCDCD4C81,0x0C0C1418,0x13133526,0xECEC2FC3, + 0x5F5FE1BE,0x9797A235,0x4444CC88,0x1717392E, + 0xC4C45793,0xA7A7F255,0x7E7E82FC,0x3D3D477A, + 0x6464ACC8,0x5D5DE7BA,0x19192B32,0x737395E6, + 0x6060A0C0,0x81819819,0x4F4FD19E,0xDCDC7FA3, + 0x22226644,0x2A2A7E54,0x9090AB3B,0x8888830B, + 0x4646CA8C,0xEEEE29C7,0xB8B8D36B,0x14143C28, + 0xDEDE79A7,0x5E5EE2BC,0x0B0B1D16,0xDBDB76AD, + 0xE0E03BDB,0x32325664,0x3A3A4E74,0x0A0A1E14, + 0x4949DB92,0x06060A0C,0x24246C48,0x5C5CE4B8, + 0xC2C25D9F,0xD3D36EBD,0xACACEF43,0x6262A6C4, + 0x9191A839,0x9595A431,0xE4E437D3,0x79798BF2, + 0xE7E732D5,0xC8C8438B,0x3737596E,0x6D6DB7DA, + 0x8D8D8C01,0xD5D564B1,0x4E4ED29C,0xA9A9E049, + 0x6C6CB4D8,0x5656FAAC,0xF4F407F3,0xEAEA25CF, + 0x6565AFCA,0x7A7A8EF4,0xAEAEE947,0x08081810, + 0xBABAD56F,0x787888F0,0x25256F4A,0x2E2E725C, + 0x1C1C2438,0xA6A6F157,0xB4B4C773,0xC6C65197, + 0xE8E823CB,0xDDDD7CA1,0x74749CE8,0x1F1F213E, + 0x4B4BDD96,0xBDBDDC61,0x8B8B860D,0x8A8A850F, + 0x707090E0,0x3E3E427C,0xB5B5C471,0x6666AACC, + 0x4848D890,0x03030506,0xF6F601F7,0x0E0E121C, + 0x6161A3C2,0x35355F6A,0x5757F9AE,0xB9B9D069, + 0x86869117,0xC1C15899,0x1D1D273A,0x9E9EB927, + 0xE1E138D9,0xF8F813EB,0x9898B32B,0x11113322, + 0x6969BBD2,0xD9D970A9,0x8E8E8907,0x9494A733, + 0x9B9BB62D,0x1E1E223C,0x87879215,0xE9E920C9, + 0xCECE4987,0x5555FFAA,0x28287850,0xDFDF7AA5, + 0x8C8C8F03,0xA1A1F859,0x89898009,0x0D0D171A, + 0xBFBFDA65,0xE6E631D7,0x4242C684,0x6868B8D0, + 0x4141C382,0x9999B029,0x2D2D775A,0x0F0F111E, + 0xB0B0CB7B,0x5454FCA8,0xBBBBD66D,0x16163A2C, + }}; + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_COMMON_AES_E_H */ diff --git a/build/tools/acsign/aes_e_ecb.c b/build/tools/acsign/aes_e_ecb.c new file mode 100644 index 0000000..55867bd --- /dev/null +++ b/build/tools/acsign/aes_e_ecb.c @@ -0,0 +1,48 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2003 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + */ + +#ifndef NO_AES + +#include "aes.h" + + +void AES_ecb_encrypt_com(AES_KEY *key, unsigned char *out, + const unsigned char *in, AES_ENC_DEC_FN enc_fn) + { + AES_INT4 data[4],w; + + data[0]=((in[ 0]<<24)|(in[ 1]<<16)|(in[ 2]<<8)|(in[ 3])); + data[1]=((in[ 4]<<24)|(in[ 5]<<16)|(in[ 6]<<8)|(in[ 7])); + data[2]=((in[ 8]<<24)|(in[ 9]<<16)|(in[10]<<8)|(in[11])); + data[3]=((in[12]<<24)|(in[13]<<16)|(in[14]<<8)|(in[15])); + enc_fn(key,&(data[0])); + w=data[0]; + out[ 0]=(w>>24)&0xff; + out[ 1]=(w>>16)&0xff; + out[ 2]=(w>> 8)&0xff; + out[ 3]=(w )&0xff; + w=data[1]; + out[ 4]=(w>>24)&0xff; + out[ 5]=(w>>16)&0xff; + out[ 6]=(w>> 8)&0xff; + out[ 7]=(w )&0xff; + w=data[2]; + out[ 8]=(w>>24)&0xff; + out[ 9]=(w>>16)&0xff; + out[10]=(w>> 8)&0xff; + out[11]=(w )&0xff; + w=data[3]; + out[12]=(w>>24)&0xff; + out[13]=(w>>16)&0xff; + out[14]=(w>> 8)&0xff; + out[15]=(w )&0xff; + } + +#endif /* NO_AES */ diff --git a/build/tools/acsign/aes_sbox.h b/build/tools/acsign/aes_sbox.h new file mode 100644 index 0000000..6a584f4 --- /dev/null +++ b/build/tools/acsign/aes_sbox.h @@ -0,0 +1,59 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2003 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + */ + +#ifndef HEADER_COMMON_AES_SBOX_H +#define HEADER_COMMON_AES_SBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern const unsigned char aes_sbox[256]; + +const unsigned char aes_sbox[256]={ + 0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5, + 0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76, + 0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0, + 0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0, + 0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC, + 0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15, + 0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A, + 0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75, + 0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0, + 0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84, + 0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B, + 0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF, + 0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85, + 0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8, + 0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5, + 0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2, + 0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17, + 0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73, + 0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88, + 0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB, + 0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C, + 0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79, + 0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9, + 0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08, + 0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6, + 0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A, + 0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E, + 0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E, + 0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94, + 0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF, + 0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68, + 0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16, + }; + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_COMMON_AES_SBOX_H */ diff --git a/build/tools/acsign/aes_skey.c b/build/tools/acsign/aes_skey.c new file mode 100644 index 0000000..682766e --- /dev/null +++ b/build/tools/acsign/aes_skey.c @@ -0,0 +1,143 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2003 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + */ + +#ifndef NO_AES + +#include "aes.h" +#include "aes_sbox.h" + +static const unsigned char Rcon[30]={ + 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80, + 0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f, + 0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4, + 0xb3,0x7d,0xfa,0xef,0xc5,0x91, + }; + +int AES_set_key(AES_KEY *ctx, const unsigned char *key, int len) + { + int i,ii; + AES_INT4 *W,tmp,tmp2; + const unsigned char *ip; + int words; + + if (len == 16) + { + i=10; + words=4; + } + else if (len == 24) + { + i=12; + words=6; + } + else if (len == 32) + { + i=14; + words=8; + } + else + return(1); + + ctx->rounds=i; + ctx->key_size=words; + W=(unsigned int *)ctx->ks; + for (i=0; irounds+1); + for (i=words; i> 8)&0xff]<<16; + tmp2|=(AES_INT4)aes_sbox[(tmp>>16)&0xff]<<24; + tmp2|=(AES_INT4)aes_sbox[(tmp>>24) ]; + tmp=tmp2^(((unsigned int)*ip)<<24); + ip++; + } + if ((words == 8) && ((i % words) == 4)) + { + tmp2 =(AES_INT4)aes_sbox[(tmp )&0xff] ; + tmp2|=(AES_INT4)aes_sbox[(tmp>> 8)&0xff]<< 8; + tmp2|=(AES_INT4)aes_sbox[(tmp>>16)&0xff]<<16; + tmp2|=(AES_INT4)aes_sbox[(tmp>>24) ]<<24; + tmp=tmp2; + } + W[i]=W[i-words]^tmp; + } + return(0); + } + +#define rot1(x) (((x) << 24) | ((x) >> 8)) +#define rot2(x) (((x) << 16) | ((x) >> 16)) +#define rot3(x) (((x) << 8) | ((x) >> 24)) + +/* This cute trick does 4 'mul by two' at once. Stolen from + * Dr B. R. Gladman but I'm sure the u-(u>>7) is + * a standard graphics trick + * The key to this is that we need to xor with 0x1b if the top bit is set. + * a 1xxx xxxx 0xxx 0xxx First we mask the 7bit, + * b 1000 0000 0000 0000 then we shift right by 7 puting the 7bit in 0bit, + * c 0000 0001 0000 0000 we then subtract (c) from (b) + * d 0111 1111 0000 0000 and now we and with our mask + * e 0001 1011 0000 0000 + */ +#define mt 0x80808080 +#define ml 0x7f7f7f7f +#define mh 0xfefefefe +#define mm 0x1b1b1b1b +#define mul2(x,t) ((t)=((x)&mt), \ + ((((x)+(x))&mh)^(((t)-((t)>>7))&mm))) + +#define mix_col(x,f2,f3) (\ + (f2)=mul2(x,f3), \ + (f3)=(x)^(f2), \ + (rot3(f3) ^ rot2(x) ^ rot1(x)^(f2))) + +#define inv_mix_col(x,f2,f4,f8,f9) (\ + (f2)=mul2(x,f2), \ + (f4)=mul2(f2,f4), \ + (f8)=mul2(f4,f8), \ + (f9)=(x)^(f8), \ + (f8)=((f2)^(f4)^(f8)), \ + (f2)^=(f9), \ + (f4)^=(f9), \ + (f8)^=rot3(f2), \ + (f8)^=rot2(f4), \ + (f8)^rot1(f9)) + +void AES_convert_key(AES_KEY *ctx) + { + int i; + AES_INT4 *k,w,t1,t2,t3,t4; + + k= ctx->ks; + k+=4; + for (i=ctx->rounds*4; i>4; i--) + { + w= *k; + w = inv_mix_col(w,t1,t2,t3,t4); + *k++ =w; + } + } +#endif /* NO_AES */ diff --git a/build/tools/acsign/bn_add.c b/build/tools/acsign/bn_add.c new file mode 100644 index 0000000..75820c6 --- /dev/null +++ b/build/tools/acsign/bn_add.c @@ -0,0 +1,304 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +/** + * @file bn_add.c + * @brief BIGNUM addition and subtraction functions + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_ADD +#define SPLIT_BN_UADD +#define SPLIT_BN_USUB +#define SPLIT_BN_SUB +#endif /* NO_SPLIT */ + +#ifdef SPLIT_BN_ADD +/* r can == a or b */ +int BN_add(r, a, b) +BIGNUM *r; +BIGNUM *a; +BIGNUM *b; + { + BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + /* a + b a+b + * a + -b a-b + * -a + b b-a + * -a + -b -(a+b) + */ + if (a->neg ^ b->neg) + { + /* only one is negative */ + if (a->neg) + { tmp=a; a=b; b=tmp; } + + /* we are now a - b */ + + if (BN_ucmp(a,b) < 0) + { + if (!BN_usub(r,b,a)) return(0); + r->neg=1; + } + else + { + if (!BN_usub(r,a,b)) return(0); + r->neg=0; + } + return(1); + } + + if (a->neg) /* both are neg */ + r->neg=1; + else + r->neg=0; + + if (!BN_uadd(r,a,b)) return(0); + return(1); + } +#endif + +#ifdef SPLIT_BN_UADD +/* unsigned add of b to a, r must be large enough */ +int BN_uadd(r,a,b) +BIGNUM *r; +BIGNUM *a; +BIGNUM *b; + { + register int i; + int max,min; + BN_ULONG *ap,*bp,*rp,carry,t1; + BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + if (a->top < b->top) + { tmp=a; a=b; b=tmp; } + max=a->top; + min=b->top; + + if (bn_wexpand(r,max+1) == NULL) + return(0); + + r->top=max; + + + ap=a->d; + bp=b->d; + rp=r->d; + carry=0; + + carry=bn_add_words(rp,ap,bp,min); + rp+=min; + ap+=min; + bp+=min; + i=min; + + if (carry) + { + while (i < max) + { + i++; + t1= *(ap++); + if ((*(rp++)=(t1+1)&BN_MASK2) >= t1) + { + carry=0; + break; + } + } + if ((i >= max) && carry) + { + *(rp++)=1; + r->top++; + } + } + if (rp != ap) + { + for (; ib from a + * @param r result of subtraction + * @param a pointer to a BIGNUM + * @param b pointer to a BIGNUM + * @pre a must be larger than b + * @return 1 on success, 0 on failure + * @todo On next IRIX port check the validity of IRIX_CC_BUG. + */ +#ifdef SPLIT_BN_USUB +int BN_usub(r, a, b) +BIGNUM *r; +BIGNUM *a; +BIGNUM *b; + { + int max,min; + register BN_ULONG t1,t2,*ap,*bp,*rp; + int i,carry; +#if defined(IRIX_CC_BUG) && !defined(LINT) + int dummy; +#endif + + bn_check_top(a); + bn_check_top(b); + + /* + * check for pre-condition violation + */ + if (a->top < b->top) + { +#ifndef NO_ERR + BNerr(BN_F_BN_USUB,BN_R_ARG2_LT_ARG3); +#endif + return(0); + } + + max=a->top; + min=b->top; + if (bn_wexpand(r,max) == NULL) return(0); + + ap=a->d; + bp=b->d; + rp=r->d; + + /* + * perform the subtraction and see if we + * have a (final) carry + */ + carry=0; + for (i=0; i t2) break; + } + } + + if (rp != ap) + { +#ifdef BN_LIBRARY_SMALL + Memcpy(rp,ap,sizeof(*rp)*(max-i)); +#else /* BN_LIBRARY_SMALL */ + for (;;) + { + if (i++ >= max) break; + rp[0]=ap[0]; + if (i++ >= max) break; + rp[1]=ap[1]; + if (i++ >= max) break; + rp[2]=ap[2]; + if (i++ >= max) break; + rp[3]=ap[3]; + rp+=4; + ap+=4; + } +#endif /* BN_LIBRARY_SMALL */ + } + + r->top=max; + bn_fix_top(r); + return(1); + } +#endif + +#ifdef SPLIT_BN_SUB +int BN_sub(r, a, b) +BIGNUM *r; +BIGNUM *a; +BIGNUM *b; + { + int max; + int add=0,neg=0; + BIGNUM *tmp; + + bn_check_top(a); + bn_check_top(b); + + /* a - b a-b + * a - -b a+b + * -a - b -(a+b) + * -a - -b b-a + */ + if (a->neg) + { + if (b->neg) + { tmp=a; a=b; b=tmp; } + else + { add=1; neg=1; } + } + else + { + if (b->neg) { add=1; neg=0; } + } + + if (add) + { + if (!BN_uadd(r,a,b)) return(0); + r->neg=neg; + return(1); + } + + /* We are actually doing a - b */ + + max=(a->top > b->top)?a->top:b->top; + if (bn_wexpand(r,max) == NULL) return(0); + if (BN_ucmp(a,b) < 0) + { + if (!BN_usub(r,b,a)) return(0); + r->neg=1; + } + else + { + if (!BN_usub(r,a,b)) return(0); + r->neg=0; + } + return(1); + } +#endif + +#endif diff --git a/build/tools/acsign/bn_asm.c b/build/tools/acsign/bn_asm.c new file mode 100644 index 0000000..59326c1 --- /dev/null +++ b/build/tools/acsign/bn_asm.c @@ -0,0 +1,509 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#ifndef OPT_BN_ASM + +#define BN_MUL_ADD_WORDS + +#ifndef BN_MUL_WORDS +#define BN_MUL_WORDS +#endif + +#ifndef BN_SQR_WORDS +#define BN_SQR_WORDS +#endif + +#ifndef BN_ADD_WORDS +#define BN_ADD_WORDS +#endif + +#ifndef BN_SUB_WORDS +#define BN_SUB_WORDS +#endif + +#endif + + +#include "bn_lcl.h" + +#ifdef BN_LLONG + +/* + * bn_mul_add_words + * + * for(i=0;i=0; i--) + fprintf(stderr,BN_HEX_FMT,ap[i]); + fprintf(stderr,"*"); + fprintf(stderr,BN_HEX_FMT,w); + fprintf(stderr,"+"); + for (i=num-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,rp[i]); +#endif + + for (;;) + { + mul_add(rp[0],ap[0],w,c1); + if (--num == 0) break; + mul_add(rp[1],ap[1],w,c1); + if (--num == 0) break; + mul_add(rp[2],ap[2],w,c1); + if (--num == 0) break; + mul_add(rp[3],ap[3],w,c1); + if (--num == 0) break; + ap+=4; + rp+=4; + } + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + fprintf(stderr,"-"); + fprintf(stderr,BN_HEX_FMT,c1); + for (i=nn-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,rp[i]); + fprintf(stderr,"\n"); + } +#endif + return(c1); + } +#endif + +#ifdef BN_MUL_WORDS +BN_ULONG bn_mul_words(rp,ap,num,w) +BN_ULONG *rp,*ap; +int num; +BN_ULONG w; + { + BN_ULONG c1=0; + + bn_check_num(num); + if (num <= 0) return(c1); + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + { + int i,nn=num; + + for (i=num-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,ap[i]); + fprintf(stderr,"*"); + fprintf(stderr,BN_HEX_FMT,w); +#endif + + for (;;) + { + mul(rp[0],ap[0],w,c1); + if (--num == 0) break; + mul(rp[1],ap[1],w,c1); + if (--num == 0) break; + mul(rp[2],ap[2],w,c1); + if (--num == 0) break; + mul(rp[3],ap[3],w,c1); + if (--num == 0) break; + ap+=4; + rp+=4; + } + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + fprintf(stderr,"-"); + fprintf(stderr,BN_HEX_FMT,c1); + for (i=nn-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,rp[i]); + fprintf(stderr,"\n"); + } +#endif + return(c1); + } +#endif + +#ifdef BN_SQR_WORDS +void bn_sqr_words(r,a,n) +BN_ULONG *r,*a; +int n; + { + bn_check_num(n); + if (n <= 0) return; + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + { + int i,nn=n; + + for (i=n-1; i>=0; i--) + { + fprintf(stderr,BN_HEX_FMT,a[i]); + if (i != 0) + fprintf(stderr,"^2*2^%X+",i*2*BN_BITS2); + else + fprintf(stderr,"^2"); + } +#endif + + for (;;) + { + BN_ULLONG t; + + t=(BN_ULLONG)(a[0])*(a[0]); + r[0]=Lw(t); r[1]=Hw(t); + if (--n == 0) break; + + t=(BN_ULLONG)(a[1])*(a[1]); + r[2]=Lw(t); r[3]=Hw(t); + if (--n == 0) break; + + t=(BN_ULLONG)(a[2])*(a[2]); + r[4]=Lw(t); r[5]=Hw(t); + if (--n == 0) break; + + t=(BN_ULLONG)(a[3])*(a[3]); + r[6]=Lw(t); r[7]=Hw(t); + if (--n == 0) break; + + a+=4; + r+=8; + } +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + + fprintf(stderr,"-"); + for (i=nn+nn-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,r[i]); + fprintf(stderr,"\n"); + } +#endif + } +#endif + +#else + +#ifdef BN_MUL_ADD_WORDS + +BN_ULONG bn_mul_add_words(rp,ap,num,w) +BN_ULONG *rp,*ap; +int num; +BN_ULONG w; + { + BN_ULONG c=0; + BN_ULONG bl,bh,b_hl; + + bn_check_num(num); + if (num <= 0) return((BN_ULONG)0); + + bl=LBITS(w); + bh=HBITS(w); + b_hl=bh-bl; +/* +{ int i,nnum=num; +BN_ULONG *rrp=rp; +for (i=num-1; i>=0; i--) printf("%02X",rp[i]); +printf("+"); +for (i=num-1; i>=0; i--) printf("%02X",ap[i]); +printf("*%02X - ",w); +*/ + for (;;) + { + mul_add(rp[0],ap[0],bl,bh,b_hl,c); + if (--num == 0) break; + mul_add(rp[1],ap[1],bl,bh,b_hl,c); + if (--num == 0) break; + mul_add(rp[2],ap[2],bl,bh,b_hl,c); + if (--num == 0) break; + mul_add(rp[3],ap[3],bl,bh,b_hl,c); + if (--num == 0) break; + ap+=4; + rp+=4; + } + +/* +printf("%02X",c); +for (i=nnum-1; i>=0; i--) printf("%02X",rrp[i]); +printf("\n"); +} +*/ + return(c); + } + +#endif + +#ifdef BN_MUL_WORDS +BN_ULONG bn_mul_words(rp,ap,num,w) +BN_ULONG *rp,*ap; +int num; +BN_ULONG w; + { + BN_ULONG carry=0; + BN_ULONG bl,bh; + + bn_check_num(num); + if (num <= 0) return((BN_ULONG)0); + + bl=LBITS(w); + bh=HBITS(w); + + for (;;) + { + mul(rp[0],ap[0],bl,bh,carry); + if (--num == 0) break; + mul(rp[1],ap[1],bl,bh,carry); + if (--num == 0) break; + mul(rp[2],ap[2],bl,bh,carry); + if (--num == 0) break; + mul(rp[3],ap[3],bl,bh,carry); + if (--num == 0) break; + ap+=4; + rp+=4; + } + return(carry); + } +#endif + +#ifdef BN_SQR_WORDS +void bn_sqr_words(r,a,n) +BN_ULONG *r,*a; +int n; + { + bn_check_num(n); + if (n <= 0) return; + for (;;) + { + sqr64(r[0],r[1],a[0]); + if (--n == 0) break; + + sqr64(r[2],r[3],a[1]); + if (--n == 0) break; + + sqr64(r[4],r[5],a[2]); + if (--n == 0) break; + + sqr64(r[6],r[7],a[3]); + if (--n == 0) break; + + a+=4; + r+=8; + } + } +#endif + +#endif + +#ifdef BN_ADD_WORDS +#ifdef BN_LLONG +BN_ULONG bn_add_words(r,a,b,n) +BN_ULONG *r,*a,*b; +int n; + { + BN_ULLONG ll=0; + + bn_check_num(n); + if (n <= 0) return((BN_ULONG)0); + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + { + int i,nn=n; + + for (i=n-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,a[i]); + fprintf(stderr,"+"); + for (i=n-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,b[i]); +#endif + + for (;;) + { + ll+=(BN_ULLONG)a[0]+b[0]; + r[0]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + ll+=(BN_ULLONG)a[1]+b[1]; + r[1]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + ll+=(BN_ULLONG)a[2]+b[2]; + r[2]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + ll+=(BN_ULLONG)a[3]+b[3]; + r[3]=(BN_ULONG)ll&BN_MASK2; + ll>>=BN_BITS2; + if (--n <= 0) break; + + a+=4; + b+=4; + r+=4; + } +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + fprintf(stderr,"-"); + fprintf(stderr,BN_HEX_FMT,(BN_ULONG)ll); + for (i=nn-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,r[i]); + fprintf(stderr,"\n"); + } +#endif + return((BN_ULONG)ll); + } +#else +BN_ULONG bn_add_words(r,a,b,n) +BN_ULONG *r,*a,*b; +int n; + { + BN_ULONG c,l,t; + + bn_check_num(n); + if (n <= 0) return((BN_ULONG)0); + + c=0; + for (;;) + { + t=a[0]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[0])&BN_MASK2; + c+=(l < t); + r[0]=l; + if (--n <= 0) break; + + t=a[1]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[1])&BN_MASK2; + c+=(l < t); + r[1]=l; + if (--n <= 0) break; + + t=a[2]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[2])&BN_MASK2; + c+=(l < t); + r[2]=l; + if (--n <= 0) break; + + t=a[3]; + t=(t+c)&BN_MASK2; + c=(t < c); + l=(t+b[3])&BN_MASK2; + c+=(l < t); + r[3]=l; + if (--n <= 0) break; + + a+=4; + b+=4; + r+=4; + } + + return((BN_ULONG)c); + } +#endif +#endif + +#ifdef BN_SUB_WORDS +BN_ULONG bn_sub_words(r,a,b,n) +BN_ULONG *r,*a,*b; +int n; + { + BN_ULONG c,t1,t2; + + bn_check_num(n); + if (n <= 0) return((BN_ULONG)0); + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + { + int i,nn=n; + + for (i=n-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,a[i]); + fprintf(stderr,"-"); + for (i=n-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,b[i]); +#endif + + c=0; + for (;;) + { + t1=a[0]; t2=b[0]; + r[0]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + t1=a[1]; t2=b[1]; + r[1]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + t1=a[2]; t2=b[2]; + r[2]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + t1=a[3]; t2=b[3]; + r[3]=(t1-t2-c)&BN_MASK2; + if (t1 != t2) c=(t1 < t2); + if (--n <= 0) break; + + a+=4; + b+=4; + r+=4; + } + +#if defined(BN_ASM_DEBUG) && !defined(NO_FP_API) + fprintf(stderr,"- "); + if (c) fprintf(stderr,"-"); + for (i=nn-1; i>=0; i--) + fprintf(stderr,BN_HEX_FMT,r[i]); + fprintf(stderr,"\n"); + } +#endif + return(c); + } +#endif + diff --git a/build/tools/acsign/bn_comba.c b/build/tools/acsign/bn_comba.c new file mode 100644 index 0000000..61dbc93 --- /dev/null +++ b/build/tools/acsign/bn_comba.c @@ -0,0 +1,434 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_MUL_COMBA8 +#define SPLIT_BN_MUL_COMBA4 +#define SPLIT_BN_SQR_COMBA8 +#define SPLIT_BN_SQR_COMBA4 +#endif /* NO_SPLIT */ + +#ifndef OPT_BN_ASM +/* #if 1 */ + +#ifdef BN_LLONG +#define mul_add_c(a,b,c0,c1,c2) \ + t=(BN_ULLONG)a*b; \ + t1=(BN_ULONG)Lw(t); \ + t2=(BN_ULONG)Hw(t); \ + c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define mul_add_c2(a,b,c0,c1,c2) \ + t=(BN_ULLONG)a*b; \ + tt=(t+t)&BN_MASK; \ + if (tt < t) c2++; \ + t1=(BN_ULONG)Lw(tt); \ + t2=(BN_ULONG)Hw(tt); \ + c0=(c0+t1)&BN_MASK2; \ + if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c(a,i,c0,c1,c2) \ + t=(BN_ULLONG)a[i]*a[i]; \ + t1=(BN_ULONG)Lw(t); \ + t2=(BN_ULONG)Hw(t); \ + c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c2(a,i,j,c0,c1,c2) \ + mul_add_c2((a)[i],(a)[j],c0,c1,c2) +#else +#define mul_add_c(a,b,c0,c1,c2) \ + t1=LBITS(a); t2=HBITS(a); \ + bl=LBITS(b); bh=HBITS(b); \ + mul64(t1,t2,bl,bh); \ + c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define mul_add_c2(a,b,c0,c1,c2) \ + t1=LBITS(a); t2=HBITS(a); \ + bl=LBITS(b); bh=HBITS(b); \ + mul64(t1,t2,bl,bh); \ + if (t2 & BN_TBIT) c2++; \ + t2=(t2+t2)&BN_MASK2; \ + if (t1 & BN_TBIT) t2++; \ + t1=(t1+t1)&BN_MASK2; \ + c0=(c0+t1)&BN_MASK2; \ + if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c(a,i,c0,c1,c2) \ + sqr64(t1,t2,(a)[i]); \ + c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \ + c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++; + +#define sqr_add_c2(a,i,j,c0,c1,c2) \ + mul_add_c2((a)[i],(a)[j],c0,c1,c2) +#endif + +#if defined(BN_MUL_COMBA) + +#ifdef SPLIT_BN_MUL_COMBA8 +#undef bn_mul_comba8 +void bn_mul_comba8(r,a,b) +BN_ULONG *r,*a,*b; + { +#ifdef BN_LLONG + BN_ULLONG t; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + mul_add_c(a[0],b[0],c1,c2,c3); + r[0]=c1; + c1=0; + mul_add_c(a[0],b[1],c2,c3,c1); + mul_add_c(a[1],b[0],c2,c3,c1); + r[1]=c2; + c2=0; + mul_add_c(a[2],b[0],c3,c1,c2); + mul_add_c(a[1],b[1],c3,c1,c2); + mul_add_c(a[0],b[2],c3,c1,c2); + r[2]=c3; + c3=0; + mul_add_c(a[0],b[3],c1,c2,c3); + mul_add_c(a[1],b[2],c1,c2,c3); + mul_add_c(a[2],b[1],c1,c2,c3); + mul_add_c(a[3],b[0],c1,c2,c3); + r[3]=c1; + c1=0; + mul_add_c(a[4],b[0],c2,c3,c1); + mul_add_c(a[3],b[1],c2,c3,c1); + mul_add_c(a[2],b[2],c2,c3,c1); + mul_add_c(a[1],b[3],c2,c3,c1); + mul_add_c(a[0],b[4],c2,c3,c1); + r[4]=c2; + c2=0; + mul_add_c(a[0],b[5],c3,c1,c2); + mul_add_c(a[1],b[4],c3,c1,c2); + mul_add_c(a[2],b[3],c3,c1,c2); + mul_add_c(a[3],b[2],c3,c1,c2); + mul_add_c(a[4],b[1],c3,c1,c2); + mul_add_c(a[5],b[0],c3,c1,c2); + r[5]=c3; + c3=0; + mul_add_c(a[6],b[0],c1,c2,c3); + mul_add_c(a[5],b[1],c1,c2,c3); + mul_add_c(a[4],b[2],c1,c2,c3); + mul_add_c(a[3],b[3],c1,c2,c3); + mul_add_c(a[2],b[4],c1,c2,c3); + mul_add_c(a[1],b[5],c1,c2,c3); + mul_add_c(a[0],b[6],c1,c2,c3); + r[6]=c1; + c1=0; + mul_add_c(a[0],b[7],c2,c3,c1); + mul_add_c(a[1],b[6],c2,c3,c1); + mul_add_c(a[2],b[5],c2,c3,c1); + mul_add_c(a[3],b[4],c2,c3,c1); + mul_add_c(a[4],b[3],c2,c3,c1); + mul_add_c(a[5],b[2],c2,c3,c1); + mul_add_c(a[6],b[1],c2,c3,c1); + mul_add_c(a[7],b[0],c2,c3,c1); + r[7]=c2; + c2=0; + mul_add_c(a[7],b[1],c3,c1,c2); + mul_add_c(a[6],b[2],c3,c1,c2); + mul_add_c(a[5],b[3],c3,c1,c2); + mul_add_c(a[4],b[4],c3,c1,c2); + mul_add_c(a[3],b[5],c3,c1,c2); + mul_add_c(a[2],b[6],c3,c1,c2); + mul_add_c(a[1],b[7],c3,c1,c2); + r[8]=c3; + c3=0; + mul_add_c(a[2],b[7],c1,c2,c3); + mul_add_c(a[3],b[6],c1,c2,c3); + mul_add_c(a[4],b[5],c1,c2,c3); + mul_add_c(a[5],b[4],c1,c2,c3); + mul_add_c(a[6],b[3],c1,c2,c3); + mul_add_c(a[7],b[2],c1,c2,c3); + r[9]=c1; + c1=0; + mul_add_c(a[7],b[3],c2,c3,c1); + mul_add_c(a[6],b[4],c2,c3,c1); + mul_add_c(a[5],b[5],c2,c3,c1); + mul_add_c(a[4],b[6],c2,c3,c1); + mul_add_c(a[3],b[7],c2,c3,c1); + r[10]=c2; + c2=0; + mul_add_c(a[4],b[7],c3,c1,c2); + mul_add_c(a[5],b[6],c3,c1,c2); + mul_add_c(a[6],b[5],c3,c1,c2); + mul_add_c(a[7],b[4],c3,c1,c2); + r[11]=c3; + c3=0; + mul_add_c(a[7],b[5],c1,c2,c3); + mul_add_c(a[6],b[6],c1,c2,c3); + mul_add_c(a[5],b[7],c1,c2,c3); + r[12]=c1; + c1=0; + mul_add_c(a[6],b[7],c2,c3,c1); + mul_add_c(a[7],b[6],c2,c3,c1); + r[13]=c2; + c2=0; + mul_add_c(a[7],b[7],c3,c1,c2); + r[14]=c3; + r[15]=c1; + } +#endif + +#ifdef SPLIT_BN_MUL_COMBA4 +#undef bn_mul_comba4 +void bn_mul_comba4(r,a,b) +BN_ULONG *r,*a,*b; + { +#ifdef BN_LLONG + BN_ULLONG t; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + mul_add_c(a[0],b[0],c1,c2,c3); + r[0]=c1; + c1=0; + mul_add_c(a[0],b[1],c2,c3,c1); + mul_add_c(a[1],b[0],c2,c3,c1); + r[1]=c2; + c2=0; + mul_add_c(a[2],b[0],c3,c1,c2); + mul_add_c(a[1],b[1],c3,c1,c2); + mul_add_c(a[0],b[2],c3,c1,c2); + r[2]=c3; + c3=0; + mul_add_c(a[0],b[3],c1,c2,c3); + mul_add_c(a[1],b[2],c1,c2,c3); + mul_add_c(a[2],b[1],c1,c2,c3); + mul_add_c(a[3],b[0],c1,c2,c3); + r[3]=c1; + c1=0; + mul_add_c(a[3],b[1],c2,c3,c1); + mul_add_c(a[2],b[2],c2,c3,c1); + mul_add_c(a[1],b[3],c2,c3,c1); + r[4]=c2; + c2=0; + mul_add_c(a[2],b[3],c3,c1,c2); + mul_add_c(a[3],b[2],c3,c1,c2); + r[5]=c3; + c3=0; + mul_add_c(a[3],b[3],c1,c2,c3); + r[6]=c1; + r[7]=c2; + } +#endif + +#else + +#ifdef SPLIT_BN_MUL_COMBA4 +#undef bn_mul_comba4 +void bn_mul_comba4(r,a,b) +BN_ULONG *r,*a,*b; + { + r[4]=bn_mul_words( &(r[0]),a,4,b[0]); + r[5]=bn_mul_add_words(&(r[1]),a,4,b[1]); + r[6]=bn_mul_add_words(&(r[2]),a,4,b[2]); + r[7]=bn_mul_add_words(&(r[3]),a,4,b[3]); + } +#endif + +#ifdef SPLIT_BN_MUL_COMBA8 +#undef bn_mul_comba8 +void bn_mul_comba8(r,a,b) +BN_ULONG *r,*a,*b; + { + r[ 8]=bn_mul_words( &(r[0]),a,8,b[0]); + r[ 9]=bn_mul_add_words(&(r[1]),a,8,b[1]); + r[10]=bn_mul_add_words(&(r[2]),a,8,b[2]); + r[11]=bn_mul_add_words(&(r[3]),a,8,b[3]); + r[12]=bn_mul_add_words(&(r[4]),a,8,b[4]); + r[13]=bn_mul_add_words(&(r[5]),a,8,b[5]); + r[14]=bn_mul_add_words(&(r[6]),a,8,b[6]); + r[15]=bn_mul_add_words(&(r[7]),a,8,b[7]); + } +#endif + +#endif /* BN_MUL_COMBA */ + +#ifdef BN_SQR_COMBA + +#ifdef SPLIT_BN_SQR_COMBA8 +#undef bn_sqr_comba8 +void bn_sqr_comba8(r,a) +BN_ULONG *r,*a; + { +#ifdef BN_LLONG + BN_ULLONG t,tt; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + sqr_add_c(a,0,c1,c2,c3); + r[0]=c1; + c1=0; + sqr_add_c2(a,1,0,c2,c3,c1); + r[1]=c2; + c2=0; + sqr_add_c(a,1,c3,c1,c2); + sqr_add_c2(a,2,0,c3,c1,c2); + r[2]=c3; + c3=0; + sqr_add_c2(a,3,0,c1,c2,c3); + sqr_add_c2(a,2,1,c1,c2,c3); + r[3]=c1; + c1=0; + sqr_add_c(a,2,c2,c3,c1); + sqr_add_c2(a,3,1,c2,c3,c1); + sqr_add_c2(a,4,0,c2,c3,c1); + r[4]=c2; + c2=0; + sqr_add_c2(a,5,0,c3,c1,c2); + sqr_add_c2(a,4,1,c3,c1,c2); + sqr_add_c2(a,3,2,c3,c1,c2); + r[5]=c3; + c3=0; + sqr_add_c(a,3,c1,c2,c3); + sqr_add_c2(a,4,2,c1,c2,c3); + sqr_add_c2(a,5,1,c1,c2,c3); + sqr_add_c2(a,6,0,c1,c2,c3); + r[6]=c1; + c1=0; + sqr_add_c2(a,7,0,c2,c3,c1); + sqr_add_c2(a,6,1,c2,c3,c1); + sqr_add_c2(a,5,2,c2,c3,c1); + sqr_add_c2(a,4,3,c2,c3,c1); + r[7]=c2; + c2=0; + sqr_add_c(a,4,c3,c1,c2); + sqr_add_c2(a,5,3,c3,c1,c2); + sqr_add_c2(a,6,2,c3,c1,c2); + sqr_add_c2(a,7,1,c3,c1,c2); + r[8]=c3; + c3=0; + sqr_add_c2(a,7,2,c1,c2,c3); + sqr_add_c2(a,6,3,c1,c2,c3); + sqr_add_c2(a,5,4,c1,c2,c3); + r[9]=c1; + c1=0; + sqr_add_c(a,5,c2,c3,c1); + sqr_add_c2(a,6,4,c2,c3,c1); + sqr_add_c2(a,7,3,c2,c3,c1); + r[10]=c2; + c2=0; + sqr_add_c2(a,7,4,c3,c1,c2); + sqr_add_c2(a,6,5,c3,c1,c2); + r[11]=c3; + c3=0; + sqr_add_c(a,6,c1,c2,c3); + sqr_add_c2(a,7,5,c1,c2,c3); + r[12]=c1; + c1=0; + sqr_add_c2(a,7,6,c2,c3,c1); + r[13]=c2; + c2=0; + sqr_add_c(a,7,c3,c1,c2); + r[14]=c3; + r[15]=c1; + } +#endif + +#ifdef SPLIT_BN_SQR_COMBA4 +#undef bn_sqr_comba4 +void bn_sqr_comba4(r,a) +BN_ULONG *r,*a; + { +#ifdef BN_LLONG + BN_ULLONG t,tt; +#else + BN_ULONG bl,bh; +#endif + BN_ULONG t1,t2; + BN_ULONG c1,c2,c3; + + c1=0; + c2=0; + c3=0; + sqr_add_c(a,0,c1,c2,c3); + r[0]=c1; + c1=0; + sqr_add_c2(a,1,0,c2,c3,c1); + r[1]=c2; + c2=0; + sqr_add_c(a,1,c3,c1,c2); + sqr_add_c2(a,2,0,c3,c1,c2); + r[2]=c3; + c3=0; + sqr_add_c2(a,3,0,c1,c2,c3); + sqr_add_c2(a,2,1,c1,c2,c3); + r[3]=c1; + c1=0; + sqr_add_c(a,2,c2,c3,c1); + sqr_add_c2(a,3,1,c2,c3,c1); + r[4]=c2; + c2=0; + sqr_add_c2(a,3,2,c3,c1,c2); + r[5]=c3; + c3=0; + sqr_add_c(a,3,c1,c2,c3); + r[6]=c1; + r[7]=c2; + } +#endif +#else + +#ifdef SPLIT_BN_SQR_COMBA4 +/* hmm... is it faster just to do a multiply? */ +#undef bn_sqr_comba4 +void bn_sqr_comba4(r,a) +BN_ULONG *r,*a; + { + BN_ULONG t[8]; + bn_sqr_normal(r,a,4,t); + } +#endif + +#ifdef SPLIT_BN_SQR_COMBA8 +#undef bn_sqr_comba8 +void bn_sqr_comba8(r,a) +BN_ULONG *r,*a; + { + BN_ULONG t[16]; + bn_sqr_normal(r,a,8,t); + } +#endif + +#endif + +#endif /* OPT_BN_ASM */ + +#endif diff --git a/build/tools/acsign/bn_div.c b/build/tools/acsign/bn_div.c new file mode 100644 index 0000000..d2c1257 --- /dev/null +++ b/build/tools/acsign/bn_div.c @@ -0,0 +1,365 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +/** + * @file bn_div.c + * @brief Division and modulus functions + */ +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_DIV +#define SPLIT_BN_MOD +#endif /* NO_SPLIT */ + +#ifdef SPLIT_BN_DIV +/* The old slow way */ +#ifdef OLD_BN_DIVISION +int BN_div(dv, rem, m, d,ctx) +BIGNUM *dv; +BIGNUM *rem; +BIGNUM *m; +BIGNUM *d; +BN_CTX *ctx; + { + int i,nm,nd; + BIGNUM *D; + + bn_check_top(m); + bn_check_top(d); + if (BN_is_zero(d)) + { +#ifndef NO_ERR + BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO); +#endif + return(0); + } + + if (BN_ucmp(m,d) < 0) + { + if (rem != NULL) + { if (BN_copy(rem,m) == NULL) return(0); } + if (dv != NULL) BN_zero(dv); + return(1); + } + + D= &(ctx->bn[ctx->tos]); + if (dv == NULL) dv= &(ctx->bn[ctx->tos+1]); + if (rem == NULL) rem= &(ctx->bn[ctx->tos+2]); + + nd=BN_num_bits(d); + nm=BN_num_bits(m); + if (BN_copy(D,d) == NULL) return(0); + if (BN_copy(rem,m) == NULL) return(0); + + /* The next 2 are needed so we can do a dv->d[0]|=1 later + * since BN_lshift1 will only work once there is a value + */ + BN_zero(dv); + bn_wexpand(dv,1); + dv->top=1; + + if (!BN_lshift(D,D,nm-nd)) return(0); + for (i=nm-nd; i>=0; i--) + { + if (!BN_lshift1(dv,dv)) return(0); + if (BN_ucmp(rem,D) >= 0) + { + dv->d[0]|=1; + if (!BN_usub(rem,rem,D)) return(0); + } +/* CAN IMPROVE (and have now :=) */ + if (!BN_rshift1(D,D)) return(0); + } + rem->neg=BN_is_zero(rem)?0:m->neg; + dv->neg=m->neg^d->neg; + return(1); + } + +#else +/** + * Performs Big number division + * + * @param dv [In] division + * @param rm [Out] remainder + * @param num [In] number + * @param divisor [In] divisor + * @param ctx [In] Temporary data storage + * + * @todo add more comments to this function + */ +int BN_div(BIGNUM *dv, BIGNUM *rm, BIGNUM *num, BIGNUM *divisor, BN_CTX *ctx) + { + int norm_shift,i,j,loop; + BIGNUM *tmp,wnum,*snum,*sdiv,*res; + BN_ULONG *resp,*wnump; + BN_ULONG d0,d1; + int num_n,div_n; + + bn_check_top(num); + bn_check_top(divisor); + + if (BN_is_zero(divisor)) + { +#ifndef NO_ERR + BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO); +#endif + return(0); + } + + if (BN_ucmp(num,divisor) < 0) + { + if (rm != NULL) + { if (BN_copy(rm,num) == NULL) return(0); } + if (dv != NULL) (void)BN_zero(dv); + return(1); + } + + tmp= &(ctx->bn[ctx->tos]); + tmp->neg=0; + snum= &(ctx->bn[ctx->tos+1]); + sdiv= &(ctx->bn[ctx->tos+2]); + if (dv == NULL) + res= &(ctx->bn[ctx->tos+3]); + else res=dv; + + /* First we normalise the numbers */ + norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2); + if (!BN_lshift(sdiv,divisor,norm_shift)) return(0); + sdiv->neg=0; + norm_shift+=BN_BITS2; + if (!BN_lshift(snum,num,norm_shift)) return(0); + snum->neg=0; + div_n=sdiv->top; + num_n=snum->top; + loop=num_n-div_n; + + /* Lets setup a 'window' into snum + * This is the part that corresponds to the current + * 'area' being divided */ + BN_init(&wnum); + wnum.d= &(snum->d[loop]); + wnum.top= div_n; + wnum.max= snum->max+1; /* a bit of a lie */ + + /* Get the top 2 words of sdiv */ + /* i=sdiv->top; */ + d0=sdiv->d[div_n-1]; + d1=(div_n == 1)?0:sdiv->d[div_n-2]; + + /* pointer to the 'top' of snum */ + wnump= &(snum->d[num_n-1]); + + /* Setup to 'res' */ + if (!bn_wexpand(res,(loop+1))) goto err; + res->neg= (num->neg^divisor->neg); + res->top=loop; + resp= &(res->d[loop-1]); + + /* space for temp */ + if (!bn_wexpand(tmp,(div_n+1))) goto err; + + if (BN_ucmp(&wnum,sdiv) >= 0) + { + if (!BN_usub(&wnum,&wnum,sdiv)) goto err; + *resp=1; + res->d[res->top-1]=1; + } + else + res->top--; + resp--; + + for (i=0; i>BN_BITS2) || + (t2 <= ((BN_ULLONG)(rem< t1l) t3h++; + t3h=(t1h-t3h)&BN_MASK2; + + /*if ((t3>>BN_BITS2) || + (t2 <= ((t3<d,sdiv->d,div_n,q); + tmp->d[div_n]=l0; + for (j=div_n+1; j>0; j--) + if (tmp->d[j-1]) break; + tmp->top=j; + + j=wnum.top; +#ifdef BN_DEBUG + /* Sometimes this is 0 now (wnum.top is not). + * We need to look at this some time, I am quite + * sure it has no affect. + */ + bn_fix_top(&wnum); +#endif + (void)BN_sub(&wnum,&wnum,tmp); + + snum->top=snum->top+wnum.top-j; + + if (wnum.neg) + { + q--; + j=wnum.top; + (void)BN_add(&wnum,&wnum,sdiv); + snum->top+=wnum.top-j; + } + *(resp--)=q; + wnump--; + } + bn_fix_top(snum); + if (rm != NULL) + { + i=num->neg; /* just in case num == rm */ + if (BN_rshift(rm,snum,norm_shift) == 0) + return(0); + rm->neg=i; + } + return(1); +err: + return(0); + } +#endif +#endif + +#ifdef SPLIT_BN_MOD +/** + * Calculate the remainder where rem = m mod d + * + * @param rem [Out] Modulus result + * @param m [In] Base value + * @param d [In] Divisor + * @param ctx [In] BN_CTX for data space + * + * @pre variables are initialised and valid + * @post rem contained modulus + * + * @retval 1 success + * @retval 0 failure + * + * @note when BN_LIBRARY_SMALL define uses following algorithm + * otherwise calls through to BN_div + * + * @note m < d rem = m + * (length m = length of d) and (m > d) , rem = m - d + * alg otherwise + * let rem = m + * loop while rem > d + * let dv = shift left d, n bits to = length rem + * if dv > rem + * let dv = shift left d, n - 1 bits ( = length rem - 1) + * end if + * let rem = rem - dv; + * end loop + * + * @relates BN_div + */ +int BN_mod(BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx) +{ +#ifdef BN_LIBRARY_SMALL + int nm,nd; + BIGNUM *dv, *dv2; + + /* if m < d , mod = m */ + if (BN_ucmp(m,d) < 0) + return((BN_copy(rem,m) == NULL)?0:1); + + dv= &(ctx->bn[ctx->tos]); + dv2 = &(ctx->bn[ctx->tos+1]); + + nm=BN_num_bits(m); + nd=BN_num_bits(d); + + /* if bits m = bits d and m >= d (from above) + * rem = m - d + */ + if(nm == nd) + { + BN_usub(rem, m, d); + goto end; + } + + if (BN_copy(rem, m) == NULL) + { + return 0; + } + + /* while the rem > d */ + while(BN_ucmp(rem,d) > 0) + { + nm=BN_num_bits(rem); + if(!BN_lshift(dv2,d,nm-nd)) + { + return(0); + } + + if(BN_ucmp(dv2, rem) >0) + { + if(!BN_lshift(dv2,d,nm-nd-1)) + { + return(0); + } + } + + BN_usub(rem,rem,dv2); + } +end: + return(1); +#else + return(BN_div(NULL,rem,m,d,ctx)); +#endif +} +#endif + +#endif diff --git a/build/tools/acsign/bn_ex_str.c b/build/tools/acsign/bn_ex_str.c new file mode 100644 index 0000000..dc40f5c --- /dev/null +++ b/build/tools/acsign/bn_ex_str.c @@ -0,0 +1,437 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +#include "bn_lcl.h" + +const static unsigned char p2 []={0,8,1,1,1,1,1,0,0,0}; +const static unsigned char p4 []={0,8,1,1,1,4,1,0,0,0}; +const static unsigned char p16[]={0,8,1,1,1,16,1,0,0,0}; + +/* The following defines allow for redefinition of the window size + * of the exponent string at compile time, this affects the size + * of temporary data required in montgomery operations. + * Larger window sizes have more memory and are slightly faster + */ +#ifndef MAX_WIN_SIZE +#define MAX_WIN_SIZE 5 +#endif + +#if (MAX_WIN_SIZE == 6) +#define MAX_NUM_SIZE 16 +#endif + +#if (MAX_WIN_SIZE == 5) +#define MAX_NUM_SIZE 16 +#endif + +#if (MAX_WIN_SIZE == 4) +#define MAX_NUM_SIZE 8 +#endif + +#if (MAX_WIN_SIZE == 3) +#define MAX_NUM_SIZE 4 +#endif + +#ifndef MAX_NUM_SIZE +#define MAX_NUM_SIZE 16 +#endif + +/* This table is used to calculate how far to shift a window to find + * the next 1 bit within the window, for a given window size + * Comment next to each value represents window size, value of the window + * and the number of shifts to find the next 1 bit. + * where the value of the window is 0, the shift is the size of the window + * and thus may not necessary yield a 1 bit, but refreshes the window + */ +const static unsigned char shift[64]= + {6, /* window 6, bits 000000, shift 6 */ + 0, /* 6, bits 000001, shift 0 */ + 1, /* 6, bits 000010, shift 1 */ + 0, /* 6, bits 000011, shift 0 */ + 2, /* 6, bits 000100, shift 2 */ + 0, /* 6, bits 000101, shift 0 */ + 1, /* 6, bits 000110, shift 1 */ + 0, /* 6, bits 000111, shift 0 */ + 3, /* 6, bits 001000, shift 3 */ + 0, /* 6, bits 001001, shift 0 */ + 1, /* 6, bits 001010, shift 1 */ + 0, /* 6, bits 001011, shift 0 */ + 2, /* 6, bits 001100, shift 2 */ + 0, /* 6, bits 001101, shift 0 */ + 1, /* 6, bits 001110, shift 1 */ + 0, /* 6, bits 001111, shift 0 */ + 4, /* 6, bits 010000, shift 4 */ + 0, /* 6, bits 010001, shift 0 */ + 1, /* 6, bits 010010, shift 1 */ + 0, /* 6, bits 010011, shift 0 */ + 2, /* 6, bits 010100, shift 2 */ + 0, /* 6, bits 010101, shift 0 */ + 1, /* 6, bits 010110, shift 1 */ + 0, /* 6, bits 010111, shift 0 */ + 3, /* 6, bits 011000, shift 3 */ + 0, /* 6, bits 011001, shift 0 */ + 1, /* 6, bits 011010, shift 1 */ + 0, /* 6, bits 011011, shift 0 */ + 2, /* 6, bits 011100, shift 2 */ + 0, /* 6, bits 011101, shift 0 */ + 1, /* 6, bits 011110, shift 1 */ + 0, /* 6, bits 011111, shift 0 */ + 5, /* 6, bits 100000, shift 5 */ + /* also window 5, bits 00000, shift 5 */ + 0, /* 5 ,bits 00001, shift 0 */ + 1, /* 5 ,bits 00010, shift 1 */ + 0, /* 5 ,bits 00011, shift 0 */ + 2, /* 5 ,bits 00100, shift 2 */ + 0, /* 5 ,bits 00101, shift 0 */ + 1, /* 5 ,bits 00110, shift 1 */ + 0, /* 5 ,bits 00111, shift 0 */ + 3, /* 5 ,bits 01000, shift 3 */ + 0, /* 5 ,bits 01001, shift 0 */ + 1, /* 5 ,bits 01010, shift 1 */ + 0, /* 5 ,bits 01011, shift 0 */ + 2, /* 5 ,bits 01100, shift 2 */ + 0, /* 5 ,bits 01101, shift 0 */ + 1, /* 5 ,bits 01110, shift 1 */ + 0, /* 5 ,bits 01111, shift 0 */ + 4, /* 5 ,bits 10000, shift 1 */ + /* also window 4, bits 0000, shift 4 */ + 0, /* 4 ,bits 0001, shift 0 */ + 1, /* 4 ,bits 0010, shift 1 */ + 0, /* 4 ,bits 0011, shift 0 */ + 2, /* 4 ,bits 0100, shift 2 */ + 0, /* 4 ,bits 0101, shift 0 */ + 1, /* 4 ,bits 0110, shift 1 */ + 0, /* 4 ,bits 0111, shift 0 */ + 3, /* 4 ,bits 1000, shift 3 */ + /* also window 3, bits 000, shift 3 */ + 0, /* 3 ,bits 001, shift 0 */ + 1, /* 3 ,bits 010, shift 1 */ + 0, /* 3 ,bits 011, shift 0 */ + 2, /* 3 ,bits 100, shift 2 */ + 0, /* 3 ,bits 101, shift 0 */ + 1, /* 3 ,bits 110, shift 1 */ + 0 /* 3 ,bits 111, shift 0 */ + }; + +/* This table defines the starting point in the shift table for + * a particular window size + */ +const static unsigned char *shift_val[7]= + { + &(shift[63]), /* window 0 - unused */ + &(shift[62]), /* window 1 */ + &(shift[60]), /* window 2 - unused */ + &(shift[56]), /* window 3 */ + &(shift[48]), /* window 4 */ + &(shift[32]), /* window 5 */ + &(shift[ 0]), /* window 6 - unused */ + }; + +/** + * Calculates a Montgomery exponent string. + * + * For a supplied exponent p, generate an exponent string strp, which + * defines in pairs the number of multiplies and square operations + * required by a particular bit pattern, commonly used exponents + * 3, 11 and F4 have predefined constant string values, the rest + * are calculated into a cast unsigned char * array via the data + * pointer of a BIGNUM taken from the BN_CTX stack of BIGNUMs + * + * @param p [In] Exponent + * @param strp [Out] Exponent string result + * @param flags [In] Unused + * @param ctx [In] Temporary data storage + * + * @pre p, and ctx are initialised and valid + * @post strp points to required exponent string + * + * @notes String length value in strp[2] is invalid for strings + * greater than length 255 + * string terminates with pattern, 0, 0 this should be + * used in accurately determining the length of a returned + * string strp. + * + * @note strings with value sqr = 255, mul = 0, sqr value should be + * treated as value 256, and added to the next sqr value, this + * is used by exponent strings where more then 256 contiguous + * zero bits are in the exponent bit representation. + * + * @note code contains conditional compilation of code dependent on + * the OS int/long sizes + */ +int BN_gen_exp_bits(p,strp,flags,ctx) +BIGNUM *p; +unsigned char **strp; +int flags; +BN_CTX *ctx; + { + int bits,i,j,window,num; + unsigned char *str=NULL; + BIGNUM *tmp; + + flags=flags; + bits=p->top*BN_BITS2; + tmp=&(ctx->bn[ctx->tos]); + if (p->top == 0) + return(0); + +#if (BN_BITS2 > 17) + if (p->top == 1) +#else + if (bits <= 32) +#endif + { +#if (BN_BITS2 > 17) + if ((p->top == 1) && (p->d[0] == 0x10001)) + str=(unsigned char *)p16; +#endif +#if (16 >= BN_BITS2) && (BN_BITS > 8) + if ( (p->top == 2) && + (p->d[0] == 0x0001) && + (p->d[1] == 0x0001)) + str=(unsigned char *)p16; +#endif +#if (8 >= BN_BITS) + if ( (p->top == 3) && + (p->d[0] == 0x01) && + (p->d[1] == 0x00) && + (p->d[2] == 0x01)) + str=(unsigned char *)p16; +#endif + else if ((p->d[0] == 0x11) && (p->top == 1)) + str=(unsigned char *)p4; + else if ((p->d[0] == 0x3) && (p->top == 1)) + str=(unsigned char *)p2; + window=1; + num=1; + i=BN_BITS2; + } + else if (bits >= 256) + { + window=MAX_WIN_SIZE; /* max size of window */ + num=MAX_NUM_SIZE; + i=(BN_BITS2+(MAX_WIN_SIZE -1))/MAX_WIN_SIZE; + } + else if (bits >= 128) + { + window=4; + num=8; + i=(BN_BITS2+3)/4; + } + else /* 128 to 33 */ + { + window=3; + num=4; + i=(BN_BITS2+2)/3; + } + + /* Number of tmp words */ + j=(p->top*i*2+BN_BYTES-1+4)/BN_BYTES; + + if (str == NULL) + { + if (!bn_wexpand(tmp,j)) + return(0); + str=(unsigned char *)tmp->d; + i=BN_gen_exp_string(&(str[4]),p,window); + i+=2; + str[0]=(unsigned char)((i>>8)&0xff); + str[1]=(unsigned char)((i )&0xff); + str[2]=(unsigned char)window; + str[3]=(unsigned char)num; + } + else + { + i=8; + } + *strp=str; + return(i+2); + } + + +/** + * Generates the Montgomery exponent string. + * + * This function is used to generate an 'exponent string' + * which is an array of bytes that encode how to perform the steps in + * the a^p%m operation. + * + * @param str [Out] Containing the generated string + * @param p [In] Exponent to generate the string for + * @param bits [In] Size of the window for shifting the values of the BIGNUM + * + * @pre p is initialised and value BIGNUM, bits is not 0 + * @post str points to generated exponent string + * + * @note str is cast assigned the data of a BIGNUM allocated and + * expanded from the BN_CTX of the calling function BN_gen_exp_bits + * it does not need to be de-allocated + * + * @note string consisted of unsigned char pairs and 4 byte init + * pairs are sqr count and multiply, where strings are greater + * than 256 bit, length in position str[2] is invalid + * + * @note strings with value sqr = 255, mul = 0, sqr value should be + * treated as value 256, and added to the next sqr value, this + * is used by exponent strings where more then 256 contiguous + * zero bits are in the exponent bit representation. + * + */ +int BN_gen_exp_string(str,p,bits) +unsigned char *str; +BIGNUM *p; +int bits; + { + unsigned char *sp; + unsigned int mask; + const unsigned char *shift; + BN_ULONG w,wh,wl,*d; + unsigned int i,mul,sqr,t,s,ss; + int top; + + if (bits > 6) bits=6; + shift= shift_val[bits]; + + /* This is the mask for the bits we wish to operate on */ + mask=(1<top*BN_BITS2+bits-1)/bits)*2+2]); + *sp-- = 0; + *sp-- = 0; + top=p->top; /* Total words we will shift in */ + d=p->d; + w=wl= *d++; + if (top <= 1) + wh=0; + else + wh= *d++; + sqr=0; + i=0; + + for (;;) + { + /* t will contain how far we need to shift to set a 1 + * in the bottom bit. */ + for (;;) + { + t=w&mask; /* retrieve our window */ + s=shift[t]; /* get the shift value for the window */ + if (s == 0) break; /* no shift write out the vals */ + sqr+=s; /* add the shifted zero count to sqr */ + ss+=s; /* ss is total shift for wl */ + if (ss >= BN_BITS2) /* we have shifted > word len */ + { + if (top <= 1) break; /* no more to do */ + top--; /* dec the count */ + + wl=wh; /* copy the next word */ + /* load the word after or 0 if no more */ + wh=(top <= 1)?0:(*d++); + /* adjust our shift by len of word */ + ss-=BN_BITS2; + } + /* reset our window word w */ + if (ss == 0) + w=wl; + else + w=(wl>>ss)|(wh<<(BN_BITS2-ss)); + } + + /* At this point we have the 0th bit set */ + mul=t; + if (t == 0) break; /* we have reached the end of p */ + /* write out sqr/mul pair */ + *sp-- = (unsigned char)(sqr & 0xff); + *sp-- = (unsigned char)(mul & 0xff); + if(sqr >= 256) /* check whether sqr exceeds max uchar */ + { + /* output the expanded list of to allow for this + * and numbers will require to be added together + * at interpret time + */ + while(sqr >= 256) + { + *sp-- = 255; + *sp-- = 0; /* mul is never zero normally */ + sqr-= 256; + } + } + sqr=bits; /* set sqr to be the window size */ + + ss+=bits; /* ss is total shift for wl */ + if (ss >= BN_BITS2) /* adjust window words w,wl, wh again */ + { + if (top <= 1) break; + top--; + + wl=wh; + wh=(top <= 1)?0:(*(d++)); + ss-=BN_BITS2; + } + + if (ss == 0) + w=wl; + else + w=(wl>>ss)|(wh<<(BN_BITS2-ss)); + } + sp++; + i=2; + /* reverse the string from the top of the exponent string + * and copy to the bottom, allocated exponent string is 2 * max length + * expected for exponent string + */ + while (sp[0] != 0 || sp[1] != 0) + { + str[0]=sp[0]; + str[1]=sp[1]; + str+=2; + sp+=2; + i+=2; + } + str[0]=0; + str[1]=0; + + return(i); + } + +#ifdef MAIN +main() + { + BIGNUM p; + unsigned char buf[512],*pp; + int i; + + BN_init(&p); + BN_rand(&p,33,1,0); +#ifndef NO_FP_API + BN_print_fp(stdout,&p); fprintf(stdout,"\n"); +#endif + + BN_rand(&p,512,1,1); +#ifndef NO_FP_API + BN_print_fp(stdout,&p); fprintf(stdout,"\n"); +#endif + for (i=0; i<10000; i++) + BN_gen_exp_string(buf,&p,5); + +#if 0 + BN_gen_exp_string(buf,&p,3); + + pp=buf; + for (;;) + { + printf("mul %d sqr %d\n",pp[0],pp[1]); + if (pp[1] == 0) break; + pp+=2; + } +#endif + } +#endif diff --git a/build/tools/acsign/bn_exp.c b/build/tools/acsign/bn_exp.c new file mode 100644 index 0000000..08634e7 --- /dev/null +++ b/build/tools/acsign/bn_exp.c @@ -0,0 +1,156 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_MOD_EXP_ORIG +#define SPLIT_BN_MOD_EXP +#endif /* NO_SPLIT */ + +#define TABLE_SIZE 16 + +#ifdef SPLIT_BN_MOD_EXP_ORIG +#if 0 +/* this one works - simple but works */ +int BN_mod_exp_orig(r,a,p,m,ctx) +BIGNUM *r,*a,*p,*m; +BN_CTX *ctx; + { + int i,bits,ret=0; + BIGNUM *v,*tmp; + + v= &(ctx->bn[ctx->tos++]); + tmp= &(ctx->bn[ctx->tos++]); + + if (BN_copy(v,a) == NULL) goto err; + bits=BN_num_bits(p); + + if (BN_is_odd(p)) + { if (BN_copy(r,a) == NULL) goto err; } + else { if (!BN_one(r)) goto err; } + + for (i=1; itos-=2; + return(ret); + } + +#endif + +/* this one works - simple but works */ +int BN_exp(r,a,p,ctx) +BIGNUM *r,*a,*p; +BN_CTX *ctx; + { + int i,bits,ret=0,tos; + BIGNUM *v,*rr; + + bn_check_top(a); + bn_check_top(p); + + tos=ctx->tos; + v= &(ctx->bn[ctx->tos++]); + if ((r == a) || (r == p)) + rr= &(ctx->bn[ctx->tos++]); + else + rr=r; + + if (BN_copy(v,a) == NULL) goto err; + bits=BN_num_bits(p); + + if (BN_is_odd(p)) + { if (BN_copy(rr,a) == NULL) goto err; } + else { if (!BN_one(rr)) goto err; } + + for (i=1; itos=tos; + if (r != rr) (void)BN_copy(r,rr); + return(ret); + } +#endif + +#ifdef SPLIT_BN_MOD_EXP +/** + * Perform mod exp on BIGNUM + * @param r Pointer to return value BIGNUM + * @param a Pointer to data value BIGNUM + * @param p Pointer to Public exponent BIGNUM + * @param m Pointer to modulus BIGNUM + * @param ctx Pointer to BN_CTX + * @return 0 success + * @pre BIGNUMs a, p, m and BN_CTX ctx exist and are valid + * @post BIGNUM r points to evaluated mod_exp + * @note BN_mod_exp_mont is only available if library compiled + * with define BN_MONT_MUL, and will only be used to compute + * mod_exp operation where the modulus m is odd. + * BN_mod_exp_recp is only available if library is compiled + * with define RECP_MUL_MOD. + * BN_mod_exp_simple is the default method, not available if + * library is compiled with define RECP_MUL_MOD. + * if BN_mod_exp_mont is available, which ever of BN_mod_exp_simple + * or BN_mod_exp_recp is available will only be used for even + * modulus m values. + * @relates BN_mod_exp_mont + * @relates BN_mod_exp_recp + * @relates BN_mod_exp_simple + */ +int BN_mod_exp(r,a,p,m,ctx) +BIGNUM *r; +BIGNUM *a; +BIGNUM *p; +BIGNUM *m; +BN_CTX *ctx; + { + int ret; + + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + +#ifdef MONT_MUL_MOD + + if (BN_is_odd(m)) + { ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL); } + else +#endif +#ifdef RECP_MUL_MOD + { ret=BN_mod_exp_recp(r,a,p,m,ctx); } +#else + { ret=BN_mod_exp_simple(r,a,p,m,ctx); } +#endif + + return(ret); + } +#endif + +#endif diff --git a/build/tools/acsign/bn_fm_w.c b/build/tools/acsign/bn_fm_w.c new file mode 100644 index 0000000..999ed55 --- /dev/null +++ b/build/tools/acsign/bn_fm_w.c @@ -0,0 +1,63 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +#include "bn_lcl.h" + +/* rp has w words, the top w words are 0 */ +void bn_from_montgomery_words(ret,a,np,w,n0) +BN_ULONG *ret; +BN_ULONG *a; +BN_ULONG *np; +int w; +BN_ULONG n0; + { + BN_ULONG v0,v1,*ap,*wap; + int i; + + v1=0; + + ap=a; + wap= &(a[w]); + /* Consider putting this loop in ASM */ + for (i=0; i0; i--) + if (ap[i] != np[i]) break; + } + v1=(ap[i] >= np[i]); + } + if (v1) + (void)bn_sub_words(ret,ap,np,w); + else + { +#if 0 /* Alpha does not like Memcpy */ + Memcpy(ret,ap,sizeof(BN_ULONG)*w); +#else + for (i=0; ibn[ctx->tos]); + b= &(ctx->bn[ctx->tos+1]); + + if (BN_copy(a,in_a) == NULL) goto err; + if (BN_copy(b,in_b) == NULL) goto err; + + if (BN_cmp(a,b) < 0) { t=a; a=b; b=t; } + t=bn_euclid(a,b); + if (t == NULL) goto err; + + if (BN_copy(r,t) == NULL) goto err; + ret=1; +err: + return(ret); + } + +BIGNUM *bn_euclid(a,b) +BIGNUM *a,*b; + { + BIGNUM *t; + int shifts=0; + + bn_check_top(a); + bn_check_top(b); + + for (;;) + { + if (BN_is_zero(b)) + break; + + if (BN_is_odd(a)) + { + if (BN_is_odd(b)) + { + if (!BN_sub(a,a,b)) goto err; + if (!BN_rshift1(a,a)) goto err; + if (BN_cmp(a,b) < 0) + { t=a; a=b; b=t; } + } + else /* a odd - b even */ + { + if (!BN_rshift1(b,b)) goto err; + if (BN_cmp(a,b) < 0) + { t=a; a=b; b=t; } + } + } + else /* a is even */ + { + if (BN_is_odd(b)) + { + if (!BN_rshift1(a,a)) goto err; + if (BN_cmp(a,b) < 0) + { t=a; a=b; b=t; } + } + else /* a even - b even */ + { + if (!BN_rshift1(a,a)) goto err; + if (!BN_rshift1(b,b)) goto err; + shifts++; + } + } + } + if (shifts) + { + if (!BN_lshift(a,a,shifts)) goto err; + } + return(a); +err: + return(NULL); + } +#endif + +#ifdef SPLIT_BN_MOD_INVERSE +/* solves ax == 1 (mod n) */ +BIGNUM *BN_mod_inverse(in, a, n, ctx) +BIGNUM *in; +BIGNUM *a; +BIGNUM *n; +BN_CTX *ctx; + { + BIGNUM *A,*B,*X,*Y,*M,*D,*R; + BIGNUM *T,*ret=NULL; + int sign; + + bn_check_top(a); + bn_check_top(n); + + A= &(ctx->bn[ctx->tos]); + B= &(ctx->bn[ctx->tos+1]); + X= &(ctx->bn[ctx->tos+2]); + D= &(ctx->bn[ctx->tos+3]); + M= &(ctx->bn[ctx->tos+4]); + Y= &(ctx->bn[ctx->tos+5]); + ctx->tos+=6; + if (in == NULL) + R=BN_new(); + else + R=in; + if (R == NULL) goto err; + + (void)BN_zero(X); + (void)BN_one(Y); + if (BN_copy(A,a) == NULL) goto err; + if (BN_copy(B,n) == NULL) goto err; + sign=1; + + while (!BN_is_zero(B)) + { + if (!BN_div(D,M,A,B,ctx)) goto err; + T=A; + A=B; + B=M; + /* T has a struct, M does not */ + + if (!BN_mul(T,D,X,ctx)) goto err; + if (!BN_add(T,T,Y)) goto err; + M=Y; + Y=X; + X=T; + sign= -sign; + } + if (sign < 0) + { + if (!BN_sub(Y,n,Y)) goto err; + } + + if (BN_is_one(A)) + { if (!BN_mod(R,Y,n,ctx)) goto err; } + else + { +#ifndef NO_ERR + BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE); +#endif + goto err; + } + ret=R; +err: + if ((ret == NULL) && (in == NULL)) BN_free(R); + ctx->tos-=6; + return(ret); + } +#endif + +#ifdef SPLIT_BN_MOD_INVERSE_WORD +/* solves 1 == (ret*(1<l + * @param l [In] a word (size of word depends on machine) + * @returns number of bits in parameter l + */ +#ifdef SPLIT_BN_NUM_BITS_WORD +int BN_num_bits_word(l) +BN_ILONG l; + { + int i; + + /* + * This table represents the number of bits required to + * represent a "number", where "number" is indexed from + * 0 into the table. So: + * number 0 = # bits req'd to represent 0 = bits[0] = 0 + * number 1 = # bits req'd to represent 1 = bits[1] = 1 + * number 2 = # bits req'd to represent 2 = bits[2] = 2 + * number 3 = # bits req'd to represent 3 = bits[3] = 2 + * number 4 = # bits req'd to represent 4 = bits[4] = 3 + * etc. + * + * The small code size table exists to save some space, + * but requires (at most) an extra shift, an extra AND, + * and an extra add. + */ +#ifdef SMALL_CODE_SIZE + const static char bits[16]={ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 + }; +#else + const static char bits[256]={ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + }; +#endif + +#if defined(SIXTY_FOUR_BIT_LONG) + if (l & 0xffffffff00000000L) + { + if (l & 0xffff000000000000L) + { + if (l & 0xff00000000000000L) + i=56; + else i=48; + } + else + { + if (l & 0x0000ff0000000000L) + i=40; + else i=32; + } + } + else +#else +#ifdef SIXTY_FOUR_BIT + if (l & 0xffffffff00000000LL) + { + if (l & 0xffff000000000000LL) + { + if (l & 0xff00000000000000LL) + i=56; + else i=48; + } + else + { + if (l & 0x0000ff0000000000LL) + i=40; + else i=32; + } + } + else +#endif +#endif + { +#if defined(THIRTY_BIT) || defined(THIRTY_ONE_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG) + if (l & 0xffff0000L) + { + if (l & 0xff000000L) + i=24; + else i=16; + } + else +#endif + { + if (l & 0xff00L) + i=8; + else + i=0; + } + } +#ifndef SMALL_CODE_SIZE + return(i+bits[l>>i]); +#else + l>>=i; + if (l & 0xf0) + return(bits[l>>4]+i+4); + else + return(bits[l]+i); +#endif + } +#endif + +#ifdef SPLIT_BN_NUM_BITS +int BN_num_bits(a) +BIGNUM *a; + { + BN_ULONG l; + int i; + + bn_check_top(a); + + if (a->top == 0) return(0); + l=a->d[a->top-1]; + i=(a->top-1)*BN_BITS2; +#ifdef BN_DEBUG + if (l == 0) + { +#if !defined(NO_FP_API) && !defined(WIN16) + fprintf(stderr,"BAD TOP VALUE\n"); +#endif + abort(); /* BN_DEBUG */ + /* TODO: need to understand what sort of error can + * be reported for this error + */ + return(0); + } +#endif + return(i+BN_num_bits_word(l)); + } +#endif + +/** + * Clears and free a BIGNUM + * + * @param a [In] BIGNUM to clear then free + */ +#ifdef SPLIT_BN_CLEAR_FREE +void BN_clear_free(BIGNUM *a) +{ + if (a == NULL) + { + return; + } + + BN_clear(a); + BN_free(a); +} +#endif + +#ifdef SPLIT_BN_FREE +/** + * Frees a BIGNUM + * + * @param a [In] BIGNUM to free + */ +void BN_free(a) +BIGNUM *a; + { + if (a == NULL) return; + if ((a->d != NULL) && !(BN_get_flags(a,BN_FLG_STATIC_DATA))) + Free(a->d); + a->flags|=BN_FLG_FREE; /* REMOVE? */ + if (a->flags & BN_FLG_MALLOCED) + Free(a); + } +#endif + +#ifdef SPLIT_BN_INIT + +#ifdef SMALL_CODE_SIZE +/** + * Zero expands a bignum + * + * @param a [In] BIGNUM to expand + * @param n [In] number of bits to expand to + * + * @pre a is a valid BIGNUM. + */ +void bn_zexpand(a,n) +BIGNUM *a; +int n; + { + if ((a)->top < n) + { + int i; + bn_wexpand((a),n); + if (a->d!=NULL) + { + for (i=(a)->top; id[i]=0; + } + } + } + +/** + * Fixes the top value in the BIGNUM to be the count of BN_ULONGs with data. + * + * @param a [In] BIGNUM to free + * + * @pre a is a valid BIGNUM. + */ +void bn_fix_top(a) +BIGNUM *a; + { + BN_ULONG *ftl; + if ((a)->top > 0) + { + for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) + if (*(ftl--)) break; + } + } +#endif + +/** + * Initializes a BIGNUM + * + * @param a [In] BIGNUM reference + * + * @pre a is a valid BIGNUM. + */ +void BN_init(a) +BIGNUM *a; + { + (void)Memset(a,0,sizeof(BIGNUM)); + } +#endif + +#ifdef SPLIT_BN_NEW +/** + * Allocates a BIGNUM + * + * @return pointer to allocated BIGNUM + */ +BIGNUM *BN_new() + { + BIGNUM *ret; + + if ((ret=(BIGNUM *)Malloc(sizeof(BIGNUM))) == NULL) + { +#ifndef NO_ERR + BNerr(BN_F_BN_NEW,ERR_R_MALLOC_FAILURE); +#endif + return(NULL); + } + ret->flags=BN_FLG_MALLOCED; + ret->top=0; + ret->neg=0; + ret->max=0; + ret->d=NULL; + return(ret); + } +#endif + +#ifdef SPLIT_BN_CTX_NEW +/** + * Allocates a BIGNUM context + * + * @return pointer to allocated BIGNUM context + */ +BN_CTX *BN_CTX_new() + { + BN_CTX *ret; + + ret=(BN_CTX *)Malloc(sizeof(BN_CTX)); + if (ret == NULL) + { +#ifndef NO_ERR + BNerr(BN_F_BN_CTX_NEW,ERR_R_MALLOC_FAILURE); +#endif + return(NULL); + } + + BN_CTX_init(ret); + ret->flags=BN_FLG_MALLOCED; + return(ret); + } +#endif + +#ifdef SPLIT_CTX_INIT +/** + * Initializes a BIGNUM context + * + * @param a [In] BIGNUM context reference + * + * @pre a is a valid BIGNUM context. + */ +void BN_CTX_init(ctx) +BN_CTX *ctx; + { + (void)Memset(ctx,0,sizeof(BN_CTX)); + ctx->tos=0; + ctx->flags=0; + } +#endif + +#ifdef SPLIT_BN_CTX_FREE +/** + * Frees a BIGNUM context + * + * @param a [In] BIGNUM context reference + * + * @pre a is a valid BIGNUM context. + */ +void BN_CTX_free(c) +BN_CTX *c; + { + int i; + + for (i=0; ibn[i])); + if (c->flags & BN_FLG_MALLOCED) + Free(c); + } +#endif + +#ifdef SPLIT_BN_EXPAND2 +BIGNUM *bn_expand2(b, words) +BIGNUM *b; +int words; + { + BN_ULONG *A,*B,*a; + + R_DIAG_CHECK_STACK; + + bn_check_top(b); + + if (words > b->max) + { + bn_check_top(b); + if (BN_get_flags(b,BN_FLG_STATIC_DATA)) + { +#ifndef NO_ERR + BNerr(BN_F_BN_EXPAND2,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); +#endif + return(NULL); + } + a=A=(BN_ULONG *)Malloc(sizeof(BN_ULONG)*(words+1)); + if (A == NULL) + { +#ifndef NO_ERR + BNerr(BN_F_BN_EXPAND2,ERR_R_MALLOC_FAILURE); +#endif + return(NULL); + } + /* during development this is a nice way of making sure + * that we are not relying on the top byte being 0 or + * other such things + */ +#ifdef BN_DEBUG + (void)Memset(A,0x5c,sizeof(BN_ULONG)*(words+1)); +#endif + + B=b->d; + if (B != NULL) + { +#ifndef SMALL_CODE_SIZE + int i; + + /* for (i=b->top&(~7); i>0; i-=8) */ + /* The above line can induce a SunC compiler bug */ + for (i=(b->top>>3); i>0; i--) + { + BN_ULONG T0,T1,T2,T3; + + T0=B[0]; + T1=B[1]; + T2=B[2]; + T3=B[3]; + A[0]=T0; + A[1]=T1; + A[2]=T2; + A[3]=T3; + T0=B[4]; + T1=B[5]; + T2=B[6]; + T3=B[7]; + A[4]=T0; + A[5]=T1; + A[6]=T2; + A[7]=T3; + A+=8; + B+=8; + } + switch (b->top&7) + { + case 7: + A[6]=B[6]; + case 6: + A[5]=B[5]; + case 5: + A[4]=B[4]; + case 4: + A[3]=B[3]; + case 3: + A[2]=B[2]; + case 2: + A[1]=B[1]; + case 1: + A[0]=B[0]; + case 0: + /* I need the 'case 0' entry for utrix cc. + * If the optimiser is turned on, it does the + * switch table by doing + * a=top&7 + * a--; + * goto jump_table[a]; + * If top is 0, this makes us jump to 0xffffffc + * which is rather bad. + * eric 23-Apr-1998 + */ + ; + } +#if 0 /* Not needed */ + B= &(b->d[b->top]); + j=b->max-8; + for (i=b->top; itop); +#endif + Free(b->d); + } + + b->d=a; + b->max=words; + } + return(b); + } +#endif + +#ifdef SPLIT_BN_DUP +/** + * Duplicates a BIGNUM + * + * @param a [In] BIGNUM reference + * + * @returns pointer to duplicate BIGNUM of a + */ +BIGNUM *BN_dup(a) +BIGNUM *a; + { + BIGNUM *r; + BIGNUM *ret; + + bn_check_top(a); + + r=BN_new(); + if (r == NULL) return(NULL); + ret = (BIGNUM *)BN_copy(r,a); + if (ret == NULL) + { + BN_free(r); + } + return(ret); + } +#endif + +#ifdef SPLIT_BN_COPY +/** + * Copies a BIGNUM to an existing BIGNUM + * + * @param a [In] To BIGNUM reference + * @param b [Out] From BIGNUM reference + * + * @pre Both a and b are valid BIGNUMs + * + * @returns pointer to duplicate BIGNUM of a + */ +BIGNUM *BN_copy(a, b) +BIGNUM *a; +BIGNUM *b; + { +#ifndef SMALL_CODE_SIZE + int i; + BN_ULONG *A,*B; +#endif + + bn_check_top(b); + + if (a == b) return(a); + if (bn_wexpand(a,b->top) == NULL) return(NULL); +#ifndef SMALL_CODE_SIZE + A=a->d; + B=b->d; + +/* for (i=b->top&~0x07; i>0; i-=8) */ +/* The above version of this loop has been removed. It appeared + to generate a compiler bug in SunC 4.x and 5.x. I do not believe + that the code was to blame. Compiling with -fast was the problem + since this would loop unroll the loop below another 3 times. + The compiler would generate generate + andcc %o0,-8,%o1 # load ~0x07 + ld [%i2],%o3 # load *B + ble .L77000125 # exit loop unless 8 or more + ld [%i1],%o2 # load *A + sub %o1,-7,%o0 # + sdivcc %o0,8,%o0 # when do we clear %y? + bvs,a .L900001510 + sethi %hi(0x80000000),%o0 +.L900001510: + cmp %o0,3 + bl .L77000114 # one loop + ld [%o2],%o0 + # three loop code + + The loop would then be unrolled 3 times. The problem I believe + I was seeing was that the sdivcc operates is %y:%o0 / 8. + %y is not being cleared, and so occasionally this would + cause problems. The replacement code sequence stops + the compiler generating the sdiv instruction. + */ + for (i=(b->top>>3); i>0; i--) + { + BN_ULONG T0,T1,T2,T3; + T0=B[0]; + T1=B[1]; + T2=B[2]; + T3=B[3]; + A[0]=T0; + A[1]=T1; + A[2]=T2; + A[3]=T3; + T0=B[4]; + T1=B[5]; + T2=B[6]; + T3=B[7]; + A[4]=T0; + A[5]=T1; + A[6]=T2; + A[7]=T3; + A+=8; + B+=8; + } + switch (b->top&0x07) + { + case 7: + A[6]=B[6]; + case 6: + A[5]=B[5]; + case 5: + A[4]=B[4]; + case 4: + A[3]=B[3]; + case 3: + A[2]=B[2]; + case 2: + A[1]=B[1]; + case 1: + A[0]=B[0]; + case 0: + /* I need the 'case 0' entry for utrix cc. + * If the optimiser is turned on, it does the + * switch table by doing + * a=top&7 + * a--; + * goto jump_table[a]; + * If top is 0, this makes us jump to 0xffffffc which is + * rather bad. + * eric 23-Apr-1998 + */ + ; + } +#else + (void)Memcpy(a->d,b->d,sizeof(b->d[0])*b->top); +#endif + +/* (void)Memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top));*/ + a->top=b->top; + if ((a->top == 0) && (a->d != NULL)) + a->d[0]=0; + a->neg=b->neg; + return(a); + } +#endif + +#ifdef SPLIT_BN_CLEAR +/** + * Clears a BIGNUM + * + * @param a [In] BIGNUM to clear + * + * @pre a is valid + */ +void BN_clear(a) +BIGNUM *a; + { + if (a->d != NULL) + (void)Memset(a->d,0,a->max*sizeof(a->d[0])); + a->top=0; + a->neg=0; + } +#endif + +#ifdef SPLIT_BN_GET_WORD +BN_ULONG BN_get_word(a) +BIGNUM *a; + { + int i,n; + BN_ULONG ret=0; + + n=BN_num_bytes(a); + if (n > ((int) sizeof(BN_ULONG))) + return(BN_MASK2); + for (i=a->top-1; i>=0; i--) + { +#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */ + ret<<=BN_BITS4; /* stops the compiler complaining */ + ret<<=BN_BITS4; +#else + ret=0; +#endif + ret|=a->d[i]; + } + return(ret); + } +#endif + +#ifdef SPLIT_BN_SET_WORD +/** + * Set the BIGNUM to the supplied BN_ULONG value. + * + * @param a [In/Out] BIGNUM to be updated + * @param w [In] Value to be set in a + * + * @notes Function will expand a to be an + * array of 8 BN_ULONGs in size. + * @todo Review behaviour of expansion without checking + * of size first. + */ +int BN_set_word(a,w) +BIGNUM *a; +BN_ULONG w; + { + int i,n; + + if (bn_expand(a,(int)(sizeof(BN_ULONG)*8)) == NULL) return(0); + +#ifdef BN_BYTES + /* This is used when a BN_ULONG is greater in size + * than the BN_BYTES of the array, eg BN_ULONG 64 bits + * and actual a->d array of 32 bits. + */ + n=sizeof(BN_ULONG)/BN_BYTES; +#else + n=1; +#endif + a->neg=0; + a->top=0; + a->d[0]=(BN_ULONG)w&BN_MASK2; + if (a->d[0] != 0) a->top=1; + for (i=1; i>=BN_BITS2 so compilers don't complain + * on builds where sizeof(long) == BN_TYPES */ +#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */ + w>>=BN_BITS4; + w>>=BN_BITS4; +#else + w=0; +#endif + a->d[i]=(BN_ULONG)w&BN_MASK2; + if (a->d[i] != 0) a->top=i+1; + } + return(1); + } +#endif + +#ifdef BN_BYTES +#ifdef SPLIT_BN_BIN2BN +/* ignore negative */ +BIGNUM *BN_bin2bn(s, len, ret) +unsigned char *s; +int len; +BIGNUM *ret; + { + unsigned int i,m; + unsigned int n; + BN_ULONG l; + + if (ret == NULL) ret=BN_new(); + if (ret == NULL) return(NULL); + l=0; + n=len; + if (n == 0) + { + ret->top=0; + return(ret); + } + if (bn_expand(ret,(int)(n+2)*8) == NULL) + return(NULL); + i=((n-1)/BN_BYTES)+1; + m=((n-1)%(BN_BYTES)); + ret->top=i; + while (n-- > 0) + { + l=(l<<8L)| *(s++); + if (m-- == 0) + { + ret->d[--i]=l; + l=0; + m=BN_BYTES-1; + } + } + /* need to call this due to clear byte at top if avoiding + * having the top bit set (-ve number) */ + bn_fix_top(ret); + return(ret); + } +#endif + +#ifdef SPLIT_BN_BN2BIN +/* ignore negative */ +int BN_bn2bin(a, to) +BIGNUM *a; +unsigned char *to; + { + int n,i; + BN_ULONG l; + + bn_check_top(a); + + n=i=BN_num_bytes(a); + while (i-- > 0) + { + l=a->d[i/BN_BYTES]; + *(to++)=(unsigned char)((l>>(8*(i%BN_BYTES)))&0xff); + } + return(n); + } +#endif +#else +#ifdef SPLIT_BN_BIN2BN +/* ignore negative */ +BIGNUM *BN_bin2bn(s, len, ret) +unsigned char *s; +int len; +BIGNUM *ret; + { + int i,w,r,b,j,v; + int n; + BN_ULONG l; + + if (ret == NULL) ret=BN_new(); + if (ret == NULL) return(NULL); + while (len > 0) + { + if (*s != 0) break; + s++; + len--; + } + n=len*8; + if (bn_expand(ret,n) == NULL) + return(NULL); + for (i=0; imax; i++) + ret->d[i]=0; + j=0; + for (i=len-1; i>=0; i--) + { + v=((int)s[i])&0xff; + w=j/BN_BITS2; + b=j%BN_BITS2; + r=BN_BITS2-b; + j+=8; + if (r >= 8) + { + ret->d[w]|=(((BN_ULONG)v)<d[w] =(ret->d[w]|(((BN_ULONG)v)<d[w+1]=(ret->d[w+1]|(((BN_ULONG)v)>>r)); + } + } + + ret->top=((n-1)/BN_BITS2)+1; + bn_fix_top(ret); + return(ret); + } +#endif + +#ifdef SPLIT_BN_BN2BIN +int BN_bn2bin(a, to) +BIGNUM *a; +unsigned char *to; + { + int num,i,bi,w,b,r,max; + BN_ULONG l,*lp; + + bn_check_top(a); + + num=bi=BN_num_bytes(a); + lp=a->d; + for (i=0; i= 8) + to[bi]=(lp[w]>>b)&0xff; + else + { + to[bi]=(lp[w]>>b); + if (w+1 < a->top) + to[bi]|=lp[w+1]<top-b->top; + if (i != 0) return(i); + ap=a->d; + bp=b->d; + for (i=a->top-1; i>=0; i--) + { + t1= ap[i]; + t2= bp[i]; + if (t1 != t2) + return(t1 > t2?1:-1); + } + return(0); + } +#endif + +#ifdef SPLIT_BN_CMP +int BN_cmp(a, b) +BIGNUM *a; +BIGNUM *b; + { + int i; + int gt,lt; + BN_ULONG t1,t2; + + if ((a == NULL) || (b == NULL)) + { + if (a != NULL) + return(-1); + else if (b != NULL) + return(1); + else + return(0); + } + + bn_check_top(a); + bn_check_top(b); + + if (a->neg != b->neg) + { + if (a->neg) + return(-1); + else return(1); + } + if (a->neg == 0) + { gt=1; lt= -1; } + else { gt= -1; lt=1; } + + if (a->top > b->top) return(gt); + if (a->top < b->top) return(lt); + for (i=a->top-1; i>=0; i--) + { + t1=a->d[i]; + t2=b->d[i]; + if (t1 > t2) return(gt); + if (t1 < t2) return(lt); + } + return(0); + } +#endif + +#ifdef SPLIT_BN_SET_BIT +int BN_set_bit(a, n) +BIGNUM *a; +int n; + { + int i,j,k; + + bn_check_top(a); + + i=n/BN_BITS2; + j=n%BN_BITS2; + if (a->top <= i) + { + if (bn_wexpand(a,i+1) == NULL) return(0); + for(k=a->top; kd[k]=0; + a->top=i+1; + } + + a->d[i]|=(((BN_ULONG)1)<top <= i) return(0); + + a->d[i]&=(~(((BN_ULONG)1)<top <= i) return(0); + return((a->d[i]&(((BN_ULONG)1)<= a->top) return(0); + if (b == 0) + a->top=w; + else + { + a->top=w+1; + a->d[w]&= ~(((BN_ULONG)BN_MASK2)< bb)?1:-1); + for (i=n-2; i>=0; i--) + { + aa=a[i]; + bb=b[i]; + if (aa != bb) return((aa > bb)?1:-1); + } + return(0); + } +#endif +#endif + diff --git a/build/tools/acsign/bn_lsh.c b/build/tools/acsign/bn_lsh.c new file mode 100644 index 0000000..133b33e --- /dev/null +++ b/build/tools/acsign/bn_lsh.c @@ -0,0 +1,112 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_LSHIFT1 +#define SPLIT_BN_LSHIFT +#endif /* NO_SPLIT */ + +#ifdef SPLIT_BN_LSHIFT1 +#ifdef SMALL_CODE_SIZE + +int BN_lshift1(r, a) +BIGNUM *r,*a; + { + return(BN_lshift(r, a, 1)); + } + +#else + +int BN_lshift1(r, a) +BIGNUM *r; +BIGNUM *a; + { + register BN_ULONG *ap,*rp,t,c; + int i; + + bn_check_top(a); + + if (r != a) + { + if (bn_wexpand(r,a->top+1) == NULL) return(0); + r->neg=a->neg; + r->top=a->top; + } + else + { + if (bn_wexpand(r,a->top+1) == NULL) return(0); + } + ap=a->d; + rp=r->d; + c=0; + for (i=0; itop; i++) + { + t= *(ap++); + *(rp++)=((t<<1L)|c)&BN_MASK2; + c=(t & BN_TBIT)?1:0; + } + if (c) + { + *rp=1; + r->top++; + } + return(1); + } +#endif +#endif + +#ifdef SPLIT_BN_LSHIFT +int BN_lshift(r, a, n) +BIGNUM *r; +BIGNUM *a; +int n; + { + int i,nw,lb,rb; + BN_ULONG *t,*f; + BN_ULONG l; + + bn_check_top(a); + +#ifndef SMALL_CODE_SIZE + if (n == 1) return(BN_lshift1(r,a)); +#endif + if (bn_wexpand(r,a->top+(n/BN_BITS2)+1) == NULL) return(0); + r->neg=a->neg; + nw=n/BN_BITS2; + lb=n%BN_BITS2; + rb=BN_BITS2-lb; + f=a->d; + t=r->d; + t[a->top+nw]=0; + if (lb == 0) + for (i=a->top-1; i>=0; i--) + t[nw+i]=f[i]; + else + for (i=a->top-1; i>=0; i--) + { + l=f[i]; + t[nw+i+1]|=(l>>rb)&BN_MASK2; + t[nw+i]=(l<top=a->top+nw+1; + bn_fix_top(r); + return(1); + } +#endif + +#endif diff --git a/build/tools/acsign/bn_m_exp.c b/build/tools/acsign/bn_m_exp.c new file mode 100644 index 0000000..8d8afe9 --- /dev/null +++ b/build/tools/acsign/bn_m_exp.c @@ -0,0 +1,283 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#if 0 //RSA +#include +#endif +#include "bn_lcl.h" + +/* #ifdef MONT_MUL_MOD */ +/** + * Generic form of Montgomery Exponentiation, can be called directly + * out side of a BN_ME_METH + * + * @param rr_in BIGNUM pointer for result + * @param a_in BIGNUM pointer for base + * @param p BIGNUM pointer to the exponent + * @param m BIGNUM pointer to the modulus + * @param ctx BN_CTX pointer for temp values are argument storage + * @param in_mont BN_MONT_CTX pointer to structure of montgomery values + * + * @pre arguments are all initialised and not NULL or zero + * @post rr_in contains evaluated result + * + * @note + */ +int BN_mod_exp_mont(rr_in,a_in,p,m,ctx,in_mont) +BIGNUM *rr_in; +BIGNUM *a_in; +BIGNUM *p; +BIGNUM *m; +BN_CTX *ctx; +BN_MONT_CTX *in_mont; + { + int i,j,k,ret=0,tos,top; + int mul,sqr,num; + BIGNUM *d,*aa,*r,*a,*t; + BN_ULONG *vall[BN_EXP_TABLE_SIZE],*dp,*rp,n0,*rr,*tmp,*np; + BN_MONT_CTX *mont=NULL; + unsigned char *str=NULL; +#ifdef BN_SURRENDER + R_SURRENDER *surrender=NULL; + int count=0; +#endif + + bn_check_top(a_in); + bn_check_top(p); + bn_check_top(m); + + if (!(m->d[0] & 1)) + { +#ifndef NO_ERR + BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS); +#endif + return(0); + } + + tos=ctx->tos; + + if (BN_is_zero(a_in)) + { (void)BN_zero(rr_in); return(1); } + if (BN_is_zero(p)) + { (void)BN_one(rr_in); return(1); } + if (BN_is_one(p)) + { (void)BN_copy(rr_in,a_in); return(1); } + + /* If this is not done, things will break in the montgomery + * part */ + +#if 1 + if (in_mont != NULL) + mont=in_mont; + else +#endif + { + if ((mont=BN_MONT_CTX_new()) == NULL) goto err; + if (!BN_MONT_CTX_set(mont,m,ctx)) goto err; + } + +#ifdef BN_SURRENDER + surrender=ctx->surrender; +#endif + + if (!BN_gen_exp_bits(p,&str,0,ctx)) goto err; + /* Remember this function uses another element from the passed ctx */ + ctx->tos++; + num=str[3]; + i=(BN_BITS+str[2]-1)/str[2]; + str+=4; + + + top=mont->N.top; + if ((a_in->top == top) && (a_in->d[top-1] < m->d[top-1])) + { + a=a_in; + } + else if (a_in->top < top) + { + a= &(ctx->bn[ctx->tos++]); + a->top=a_in->top; + bn_zexpand(a,top); + for (j=0; jtop; j++) + a->d[j]=a_in->d[j]; + } + else /* if (a_in->top > i) */ + { + a= &(ctx->bn[ctx->tos++]); + if (!BN_mod(a,a_in,m,ctx)) goto err; + bn_zexpand(a,top); + } + + /* At this point a is the size of the modulus and is 0 padded + * out to its size if needed. + */ + + /* Number of tmp words */ + k=num*top; + j=k+(p->top*i*2+BN_BYTES-1+4)/BN_BYTES; + + aa=&(ctx->bn[ctx->tos++]); + d= &(ctx->bn[ctx->tos++]); + r= &(ctx->bn[ctx->tos++]); + t= &(ctx->bn[ctx->tos++]); + + if (bn_wexpand(rr_in,top) == NULL) goto err; + if (bn_wexpand(d,top*4) == NULL) goto err; /* *2? */ + if (bn_wexpand(r,top*2) == NULL) goto err; + if (bn_wexpand(aa,j) == NULL) goto err; + if (bn_wexpand(t,top*2) == NULL) goto err; + dp=d->d; + rp=r->d; + tmp=t->d; + rr=mont->RR.d; + + n0=mont->n0; + np=mont->N.d; + + vall[0]=aa->d; + + bn_mul_normal(tmp,a->d,top,rr,top); + bn_from_montgomery_words(vall[0],tmp,np,top,n0); + + if (num > 1) + { + bn_sqr_normal(tmp,vall[0],top,dp); + bn_from_montgomery_words(dp,tmp,np,top,n0); + + for (i=1; i>1],sizeof(BN_ULONG)*top); + while (sqr != 0) + { +#ifdef BN_SURRENDER + /* + * Check this at the start of the loop rather than the + * end so we avoid as many of the bn operations as possible + */ + if (surrender != NULL) + { + if (surrender->callback(surrender,0xff, count++) != 0) + { + goto err; + } + } +#endif /* BN_SURRENDER */ + + /* + * check the abort flag at the start of the loop so we avoid + * as many of the bn operations as possible + */ + if (BN_CTX_get_flags(ctx, BN_CTX_FLG_ABORT)) + { + goto err; + } + + for (i=0; i>1],top); + bn_from_montgomery_words(rp,tmp,np,top,n0); + } + else + { + bn_mul_normal(tmp,rp,top,a->d,top); + bn_from_montgomery_words(rr_in->d,tmp,np,top,n0); + goto end; + } + } + + /* if (mul != 1) */ + { + for (i=top; id,rp,np,top,n0); + } +end: /* Use this to avoid an if */ + + /* + * Even if the operation has completed successfully, if the + * abort flag is set we want to abort so that anything + * calling this function will know not to continue. + */ + if (BN_CTX_get_flags(ctx, BN_CTX_FLG_ABORT)) + { + goto err; + } + + rr_in->top=top; + bn_fix_top(rr_in); + ret=1; +err: +#ifdef BN_SURRENDER + /* + * Even if the operation completed successfully we want to abort + * if the abort flag has been is set, so that subsequent operations + * do not continue. Allow the caller change to return value and + * cause the function to fail. + */ + if (surrender != NULL) + { + if (surrender->callback(surrender, 0xff, -1) != 0) + { + ret = 0; + } + } +#endif + if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); + ctx->tos=tos; + return(ret); + } +/* #endif */ + diff --git a/build/tools/acsign/bn_me.c b/build/tools/acsign/bn_me.c new file mode 100644 index 0000000..250967c --- /dev/null +++ b/build/tools/acsign/bn_me.c @@ -0,0 +1,251 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +/** + * @file bn_me.c + * @brief BN method functions and utilities + */ +#include "bn_lcl.h" +#include "bn_thx.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_MOD_EXP_METH_DEFAULT +#define SPLIT_BN_MONT_CTX_USEIT +#define SPLIT_BN_ME_CTX_NAME +#define SPLIT_BN_ME_CTX_NEW +#define SPLIT_BN_ME_CTX_FREE +#define SPLIT_BN_ME_CTX_SET +#define SPLIT_BN_ME_CTX_MOD_EXP +#endif /* NO_SPLIT */ + +#ifndef NOPROTO +BN_ME_METH *bn_mod_exp_meth_default(int fallback); +#else +BN_ME_METH *bn_mod_exp_meth_default(); +#endif + +#ifdef SPLIT_BN_MOD_EXP_METH_DEFAULT + +/** + * Returns the default mod_exp method, choose first available in the + * method table or a hardwired default + * + * @param fallback [In] Flag for choice of method + * - 0 use the first value in the method table + * - 1 use the all encompassing default method + * + * @pre BN_default_init() has been run setting up library + * + * @post + * + * @internal uses global table bnme[] and counter me_num + * + * @internal only read the BN_ME_METH_INFO table no need for locking + * + * @relates BN_library_init + * @relates BN_default_init + * @relates BN_ME_CTX_new + * @relates BN_ME_CTX_free + * + */ +BN_ME_METH *bn_mod_exp_meth_default(int fallback) +{ + const BN_ME_METH *tmp; + +#ifndef BN_LIBRARY_SMALL + BN_ME_METH_INFO *meth_info; + + if(!fallback && ((meth_info = BN_bnme_get_info(0)) != NULL)) + { + tmp = meth_info->meth(); + } + else +#endif + { + /* set in bn.h or override bn_thx.h */ + tmp = BN_ME_METH_DEFAULT(); + } + return((BN_ME_METH *)tmp); +} +#endif + +#ifdef SPLIT_BN_MONT_CTX_USEIT + +#ifndef NOPROTO +int bn_mont_ctx_useit(int argi); +#else +int bn_mont_ctx_useit(); +#endif + +/** + * Montgomery method default useit function + * + * @param argi [In] reserved for future use + * + * @return 0 success + */ +int bn_mont_ctx_useit(int argi) + { + return(0); + } +#endif + +#ifdef SPLIT_BN_ME_CTX_NAME +/** + * Retrieve the BN method name string + * + * @param ctx [In] Method + * + * @pre ctx is valid and not NULL + * + * @return string pointer + */ +char *BN_ME_CTX_name(BN_ME_CTX *ctx) + { + return(ctx->meth->name); + } +#endif + +#ifdef SPLIT_BN_ME_CTX_NEW +/** + * Allocate a new BN_ME_CTX structure and assign method + * + * @param meth [In] Method to assign + * @param in [Out] Result BN_ME_CTX + * + * @note if meth is NULL system method default is used + * + * @retval pointer to BN_ME_CTX success + * @retval NULL failure + */ +BN_ME_CTX *BN_ME_CTX_new(BN_ME_METH *meth, BN_ME_CTX **in) + { + int i; + BN_ME_CTX *ret; + + if (in == NULL) + in= &ret; + + if (meth == NULL) + meth=bn_mod_exp_meth_default(0); + i=meth->init_ctx(meth,in); + if (i) + return(NULL); + else + return(*in); + } +#endif + +#ifdef SPLIT_BN_ME_CTX_FREE +/** + * Free context method + * + * @param mctx [In] Context object to be deallocated + * + * @note it is the callers responsibility to set mctx to NULL after free + * + * @pre mctx is not NULL and is valide BN_ME_CTX + */ +void BN_ME_CTX_free(BN_ME_CTX *mctx) + { + mctx->meth->free_ctx(mctx); + } +#endif + +#ifdef SPLIT_BN_ME_CTX_SET +/** + * Set value to BN_ME_CTX by identifier + * + * @param mctx [In] Method context object + * @param b [In] Big number + * @param cmd [In] Command identifier + * @param flags [In] Mask operation directives + * @param ctx [In] BN data store + * + * @note cmd values: + * @li BN_ME_SET_MOD will cause a method lookup is method not set + * + * @note passes control to set method in mctx + * + * @return result of mctx method set operation + */ +int BN_ME_CTX_set(BN_ME_CTX *mctx, BIGNUM *b, int cmd, int flags, BN_CTX *ctx) + { +#ifndef BN_LIBRARY_SMALL +#ifndef NOPROTO + const BN_ME_METH *(*meth)(void); +#else + const BN_ME_METH *(*meth)(); +#endif +#endif /* BN_LIBRARY_SMALL */ + + /* If we are loading the modulus, and we do not have the + * no_lookup flag (without a null method) + */ + if ((cmd == BN_ME_SET_MOD) && + ((mctx->meth != NULL) && !(flags & BN_ME_SET_FLG_NO_LOOKUP))) + { +#ifndef BN_LIBRARY_SMALL + meth=(const BN_ME_METH*(*)(void)) + BN_bnme_get(BN_num_bits(b),BN_BNME_F_BITS); + if (meth != NULL) + mctx->meth=meth(); + else +#endif + mctx->meth=bn_mod_exp_meth_default(1); + } + return(mctx->meth->set(mctx,b,cmd,flags,ctx)); + } +#endif + +#ifdef SPLIT_BN_ME_CTX_MOD_EXP +/** + * Call method mod_exp operation + * + * @param mctx [In] Method context object + * @param ret [Out] Result + * @param a [In] Base value + * @param p [In] Exponent + * @param m [In] Modulus + * @param ctx [In] Data storage + * + * @pre a must be expandable + * + * @return 0 success + */ +int BN_ME_CTX_mod_exp(BN_ME_CTX *mctx, BIGNUM *ret, BIGNUM *a, BIGNUM *p, + BIGNUM *m, BN_CTX *ctx) + { + int wtop; + + /* Before we call the method, make sure we are not doing 0^p, + * and p is not 0 or 1 */ + if (BN_is_zero(a)) + { BN_zero(ret); return(0); } + if (p != NULL) + { + if (BN_is_zero(p)) + { BN_one(ret); return(0); } + else if (BN_is_one(p)) + { BN_copy(ret,a); return(0); } + } + + /* wtop is the size 'a' needs to be for the method */ + wtop=mctx->meth->num; + bn_zexpand(a,wtop); + + return(mctx->meth->mod_exp(mctx,ret,a,p,ctx)); + } +#endif + +#endif + diff --git a/build/tools/acsign/bn_mont.c b/build/tools/acsign/bn_mont.c new file mode 100644 index 0000000..6fc5fea --- /dev/null +++ b/build/tools/acsign/bn_mont.c @@ -0,0 +1,231 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#undef BN_DEBUG +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_MOD_MUL_MONTGOMERY +#define SPLIT_BN_FROM_MONTGOMERY +#define SPLIT_BN_MONT_CTX_NEW +#define SPLIT_BN_MONT_CTX_INIT +#define SPLIT_BN_MONT_CTX_FREE +#define SPLIT_BN_MONT_CTX_COPY +#endif /* NO_SPLIT */ + +/* #define DEBUG */ + +#ifdef SPLIT_BN_MOD_MUL_MONTGOMERY +/* We multiply a by b, generating a number 2n words long. + * This is then reduced by the montogmery number, which is + * n words. */ +int BN_mod_mul_montgomery(r,a,b,mont,ctx) +BIGNUM *r,*a,*b; +BN_MONT_CTX *mont; +BN_CTX *ctx; + { + BIGNUM *tmp,*tmp2; + int ret=0,w; + int i; + + bn_check_top(a); + bn_check_top(b); + + w=mont->riw; + + tmp= &(ctx->bn[ctx->tos++]); + tmp2= &(ctx->bn[ctx->tos++]); + bn_check_top(tmp); + bn_check_top(tmp2); + if (bn_wexpand(tmp,w+w) == NULL) goto err; + if (bn_wexpand(r,w+w) == NULL) goto err; + + if (a == b) + { + if (bn_wexpand(tmp2,w+w) == NULL) goto err; +#ifdef BN_SQR_COMBA + if ((a->top == 8) && (a->top == b->top)) + bn_sqr_comba8(tmp->d,a->d); + else +#endif + { + bn_sqr_normal(tmp->d,a->d,a->top,tmp2->d); + } + } + else + { +#ifdef BN_MUL_COMBA + if (a->top == 8) + bn_mul_comba8(tmp->d,a->d,b->d); + else +#endif + { + bn_mul_normal(tmp->d,a->d,a->top,b->d,b->top); + } + } + + i=a->top+b->top; + while (i<(w+w)) + { + tmp->d[i]=0; + i++; + } + tmp->top=w+w; + tmp->neg=0; + + /* reduce from aRR to aR */ + /* tmp->d is 2w words */ +#if 0 + bn_fix_top(tmp); + BN_from_montgomery_words(r,tmp,mont,ctx); +#else + bn_from_montgomery_words(r->d,tmp->d,mont->N.d,w,mont->n0); +#endif + r->top=w; + r->neg=0; + bn_fix_top(r); + + ret=1; +err: + ctx->tos-=2; + return(ret); + } +#endif + +#ifdef SPLIT_BN_FROM_MONTGOMERY +int BN_from_montgomery(ret,a,mont,ctx) +BIGNUM *ret; +BIGNUM *a; +BN_MONT_CTX *mont; +BN_CTX *ctx; + { + BIGNUM *n,*r; + BN_ULONG *np,*rp,n0,v0,v1,*nrp; + int al,nl,max,i; + int retn=0; + + bn_check_top(a); + + r= &(ctx->bn[ctx->tos]); + + if (!BN_copy(r,a)) goto err1; + n= &(mont->N); + + /* mont->riw is the size of mont->N in bits/words */ + al=mont->riw; + + nl=n->top; + if ((al == 0) || (nl == 0)) { r->top=0; return(1); } + + max=(nl+al+1); /* allow for overflow (no?) XXX */ + if (bn_wexpand(r,max) == NULL) goto err1; + if (bn_wexpand(ret,max) == NULL) goto err1; + + r->neg=a->neg^n->neg; + np=n->d; + rp=r->d; + nrp= &(r->d[nl]); + + /* clear the top words of T */ + for (i=r->top; id[i]=0; + + r->top=max; + n0=mont->n0; + + v1=0; + for (i=0; iriw will be a multiple of the word size */ + (void)BN_rshift(ret,r,mont->riw*BN_BITS2); + + if (BN_ucmp(ret, &(mont->N)) >= 0) + { + (void)BN_usub(ret,ret,&(mont->N)); /* XXX */ + } + retn=1; + +err1: + return(retn); + } +#endif + +#ifdef SPLIT_BN_MONT_CTX_NEW +BN_MONT_CTX *BN_MONT_CTX_new() + { + BN_MONT_CTX *ret; + + if ((ret=(BN_MONT_CTX *)Malloc(sizeof(BN_MONT_CTX))) == NULL) + return(NULL); + + BN_MONT_CTX_init(ret); + ret->flags=BN_FLG_MALLOCED; + return(ret); + } +#endif + +#ifdef SPLIT_BN_MONT_CTX_INIT +void BN_MONT_CTX_init(ctx) +BN_MONT_CTX *ctx; + { + ctx->use_word=0; + ctx->riw=0; + BN_init(&(ctx->RR)); + BN_init(&(ctx->N)); + BN_init(&(ctx->Ni)); + ctx->flags=0; + } +#endif + +#ifdef SPLIT_BN_MONT_CTX_FREE +void BN_MONT_CTX_free(mont) +BN_MONT_CTX *mont; + { + BN_free(&(mont->RR)); + BN_free(&(mont->N)); + BN_free(&(mont->Ni)); + if (mont->flags & BN_FLG_MALLOCED) + Free(mont); + } +#endif + +#ifdef SPLIT_BN_MONT_CTX_COPY +BN_MONT_CTX *BN_MONT_CTX_copy(to, from) +BN_MONT_CTX *to, *from; + { + if (to == from) return(to); + + (void)BN_copy(&(to->RR),&(from->RR)); + (void)BN_copy(&(to->N),&(from->N)); + (void)BN_copy(&(to->Ni),&(from->Ni)); + bn_zexpand(&(to->RR),from->riw); + bn_zexpand(&(to->Ni),from->riw); + to->use_word=from->use_word; + to->riw=from->riw; + to->n0=from->n0; + return(to); + } +#endif + +#endif diff --git a/build/tools/acsign/bn_ms_w.c b/build/tools/acsign/bn_ms_w.c new file mode 100644 index 0000000..1ddd40e --- /dev/null +++ b/build/tools/acsign/bn_ms_w.c @@ -0,0 +1,121 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +int BN_MONT_CTX_set_word(mont,mod,ctx) +BN_MONT_CTX *mont; +BIGNUM *mod; +BN_CTX *ctx; + { + BIGNUM Ri,*R; +#if 1 + BN_ULONG tmod,rr; +#else + BN_ULONG buf[2]; + BIGNUM tmod; +#endif + + + bn_check_top(mod); + if (mod->top == 0) return(0); + + R= &(mont->RR); /* grab RR as a temp */ + if (BN_copy(&(mont->N),mod) == NULL) /* Set N */ + return(0); + + BN_init(&Ri); + + mont->use_word=1; + +/* EAY is this number of words to shift, or the number to shift to end up + * with a '1' in the next word? + * for 8 bit words, is 0x01ab == 1 or 2 + */ + mont->riw=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2; + if (!BN_zero(R)) return(0); + + /* We are now setting a number which is larger than our current + * one after we do the shift + */ + if (!BN_set_bit(R,BN_BITS2)) + goto err; + +#if 0 + tmod.d=buf; + tmod.top=1; + tmod.max=mod->max; + tmod.neg=mod->neg; + buf[0]=mod->d[0]&BN_MASK2; + buf[1]=0; + + if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL) + goto err; +#else + tmod=mod->d[0]; + rr=BN_mod_inverse_word(tmod); + if (!BN_set_word(&Ri,rr)) + goto err; +#endif + + /* R*Ri */ + if (!BN_lshift(&Ri,&Ri,BN_BITS2)) + goto err; + + if (!BN_is_zero(&Ri)) + (void)BN_sub_word(&Ri,1); + else + { + /* This is not common..., 1 in BN_MASK2, + * It happens when buf[0] was == 1. So for 8 bit, + * this is 1/256, 16bit, 1 in 2^16 etc. + */ + if (!BN_set_word(&Ri,BN_MASK2)) + goto err; + } +#if 0 + BN_div(&Ri,NULL,&Ri,&tmod,ctx); + //BN_div_word(&Ri,tmod); + mont->n0=Ri.d[0]; +#else +#if 0 + { + BN_ULONG h,l; + + h=l=0; + if (Ri.top >= 2) h=Ri.d[1]; + if (Ri.top >= 1) l=Ri.d[0]; + mont->n0=bn_div_words(h,l,tmod); + } +#endif + mont->n0=bn_div_words( + (Ri.top >= 2)?Ri.d[1]:0, + (Ri.top >= 1)?Ri.d[0]:0, + tmod); +#endif + /* mod->top=z; */ + + /* setup RR for conversions */ + (void)BN_zero(&(mont->RR)); + if (!BN_set_bit(&(mont->RR),mont->riw*2*BN_BITS2)) + goto err; + (void)BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx); + bn_zexpand(&(mont->RR),mont->riw); +#if 0 + bn_zexpand(&(mont->Ni),mont->riw); /*This is not used? */ +#endif + +err: + BN_free(&Ri); + return(1); + } + + diff --git a/build/tools/acsign/bn_mul.c b/build/tools/acsign/bn_mul.c new file mode 100644 index 0000000..4dd0e23 --- /dev/null +++ b/build/tools/acsign/bn_mul.c @@ -0,0 +1,779 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_MUL_RECURSIVE +#define SPLIT_BN_MUL_PART_RECURSIVE +#define SPLIT_BN_MUL_LOW_RECURSIVE +#define SPLIT_BN_MUL_HIGH +#define SPLIT_BN_MUL +#define SPLIT_BN_MUL_NORMAL +#define SPLIT_BN_MUL_LOW_NORMAL +#endif /* NO_SPLIT */ + +#ifdef SMALL_CODE_SIZE +#undef BN_RECURSION_MUL +#endif + +#ifdef BN_RECURSION_MUL +#if 0 /* Replaced by bn_mul_rec_words() */ +/* r is 2*n2 words in size, + * a and b are both n2 words in size. + * n2 must be a power of 2. + * We multiply and return the result. + * t must be 2*n2 words in size + * We calulate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +#ifdef SPLIT_BN_MUL_RECURSIVE +void bn_mul_recursive(r,a,b,n2,t) +BN_ULONG *r,*a,*b; +int n2; +BN_ULONG *t; + { + int n=n2/2,c1,c2; + unsigned int neg,zero; + BN_ULONG ln,lo,*p; + +#ifdef BN_COUNT +printf(" bn_mul_recursive %d * %d\n",n2,n2); +#endif +#ifdef BN_MUL_COMBA +/* if (n2 == 4) + { + bn_mul_comba4(r,a,b); + return; + } + else */ if (n2 == 8) + { + bn_mul_comba8(r,a,b); + return; + } +#endif + if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) + { + /* This should not happen */ + bn_mul_normal(r,a,n2,b,n2); + return; + } + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + c1=bn_cmp_words(a,&(a[n]),n); + c2=bn_cmp_words(&(b[n]),b,n); + zero=neg=0; + switch (c1*3+c2) + { + case -4: + bn_sub_words(t, &(a[n]),a, n); /* - */ + bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */ + break; + case -3: + zero=1; + break; + case -2: + bn_sub_words(t, &(a[n]),a, n); /* - */ + bn_sub_words(&(t[n]),&(b[n]),b, n); /* + */ + neg=1; + break; + case -1: + case 0: + case 1: + zero=1; + break; + case 2: + bn_sub_words(t, a, &(a[n]),n); /* + */ + bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */ + neg=1; + break; + case 3: + zero=1; + break; + case 4: + bn_sub_words(t, a, &(a[n]),n); + bn_sub_words(&(t[n]),&(b[n]),b, n); + break; + } + +#ifdef BN_MUL_COMBA + if (n == 4) + { + if (!zero) + bn_mul_comba4(&(t[n2]),t,&(t[n])); + else + Memset(&(t[n2]),0,8*sizeof(BN_ULONG)); + + bn_mul_comba4(r,a,b); + bn_mul_comba4(&(r[n2]),&(a[n]),&(b[n])); + } + else if (n == 8) + { + if (!zero) + bn_mul_comba8(&(t[n2]),t,&(t[n])); + else + Memset(&(t[n2]),0,16*sizeof(BN_ULONG)); + + bn_mul_comba8(r,a,b); + bn_mul_comba8(&(r[n2]),&(a[n]),&(b[n])); + } + else +#endif + { + p= &(t[n2*2]); + if (!zero) + bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p); + else + Memset(&(t[n2]),0,n2*sizeof(BN_ULONG)); + bn_mul_recursive(r,a,b,n,p); + bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),n,p); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1=(int)bn_add_words(t,r,&(r[n2]),n2); + + if (neg) /* if t[32] is negative */ + { + c1-=(int)bn_sub_words(&(t[n2]),t,&(t[n2]),n2); + } + else + { + /* Might have a carry */ + c1+=(int)bn_add_words(&(t[n2]),&(t[n2]),t,n2); + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1+=(int)bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2); + if (c1) + { + p= &(r[n+n2]); + lo= *p; + ln=(lo+c1)&BN_MASK2; + *p=ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) + { + do { + p++; + lo= *p; + ln=(lo+1)&BN_MASK2; + *p=ln; + } while (ln == 0); + } + } + } +#endif +#endif + +#if 0 +#ifdef SPLIT_BN_MUL_PART_RECURSIVE +/* n+tn is the word length + * t must be n*4 is size, as does r */ +void bn_mul_part_recursive(r,a,b,tn,n,t) +BN_ULONG *r,*a,*b; +int tn,n; +BN_ULONG *t; + { + int i,j,n2=n*2; + int c1; + BN_ULONG ln,lo,*p; + +#ifdef BN_COUNT +printf(" bn_mul_part_recursive %d * %d\n",tn+n,tn+n); +#endif + if (n < 8) + { + i=tn+n; + bn_mul_normal(r,a,i,b,i); + return; + } + + /* r=(a[0]-a[1])*(b[1]-b[0]) */ + bn_sub_words(t, a, &(a[n]),n); /* + */ + bn_sub_words(&(t[n]),b, &(b[n]),n); /* - */ + +#ifdef BN_MUL_COMBA +/* if (n == 4) + { + bn_mul_comba4(&(t[n2]),t,&(t[n])); + bn_mul_comba4(r,a,b); + bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn); + Memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2)); + } + else */ if (n == 8) + { + bn_mul_comba8(&(t[n2]),t,&(t[n])); + bn_mul_comba8(r,a,b); + bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn); + Memset(&(r[n2+tn*2]),0,sizeof(BN_ULONG)*(n2-tn*2)); + } + else +#endif + { + p= &(t[n2*2]); + bn_mul_recursive(&(t[n2]),t,&(t[n]),n,p); + bn_mul_recursive(r,a,b,n,p); + i=n/2; + /* If there is only a bottom half to the number, + * just do it */ + j=tn-i; + if (j == 0) + { + bn_mul_recursive(&(r[n2]),&(a[n]),&(b[n]),i,p); + Memset(&(r[n2+i*2]),0,sizeof(BN_ULONG)*(n2-i*2)); + } + else if (j > 0) /* eg, n == 16, i == 8 and tn == 11 */ + { + bn_mul_part_recursive(&(r[n2]),&(a[n]),&(b[n]), + j,i,p); + Memset(&(r[n2+tn*2]),0, + sizeof(BN_ULONG)*(n2-tn*2)); + } + else /* (j < 0) eg, n == 16, i == 8 and tn == 5 */ + { + Memset(&(r[n2]),0,sizeof(BN_ULONG)*n2); + if (tn < BN_MUL_RECURSIVE_SIZE_NORMAL) + { + bn_mul_normal(&(r[n2]),&(a[n]),tn,&(b[n]),tn); + } + else + { + for (;;) + { + i/=2; + if (i < tn) + { + bn_mul_part_recursive(&(r[n2]), + &(a[n]),&(b[n]), + tn-i,i,p); + break; + } + else if (i == tn) + { + bn_mul_recursive(&(r[n2]), + &(a[n]),&(b[n]), + i,p); + break; + } + } + } + } + } + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1=(int)bn_add_words(t,r,&(r[n2]),n2); + c1-=(int)bn_sub_words(&(t[n2]),t,&(t[n2]),n2); + + /* t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1]) + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + * c1 holds the carry bits + */ + c1+=(int)bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2); + if (c1) + { + p= &(r[n+n2]); + lo= *p; + ln=(lo+c1)&BN_MASK2; + *p=ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) + { + do { + p++; + lo= *p; + ln=(lo+1)&BN_MASK2; + *p=ln; + } while (ln == 0); + } + } + } +#endif +#endif + +#if 0 +#ifdef SPLIT_BN_MUL_LOW_RECURSIVE +/* a and b must be the same size, which is n2. + * r must be n2 words and t must be n2*2 + */ +void bn_mul_low_recursive(r,a,b,n2,t) +BN_ULONG *r,*a,*b; +int n2; +BN_ULONG *t; + { + int n=n2/2; + +#ifdef BN_COUNT +printf(" bn_mul_low_recursive %d * %d\n",n2,n2); +#endif + + bn_mul_recursive(r,a,b,n,&(t[0])); + if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) + { + bn_mul_low_recursive(&(t[0]),&(a[0]),&(b[n]),n,&(t[n2])); + bn_add_words(&(r[n]),&(r[n]),&(t[0]),n); + bn_mul_low_recursive(&(t[0]),&(a[n]),&(b[0]),n,&(t[n2])); + bn_add_words(&(r[n]),&(r[n]),&(t[0]),n); + } + else + { + bn_mul_low_normal(&(t[0]),&(a[0]),&(b[n]),n); + bn_mul_low_normal(&(t[n]),&(a[n]),&(b[0]),n); + bn_add_words(&(r[n]),&(r[n]),&(t[0]),n); + bn_add_words(&(r[n]),&(r[n]),&(t[n]),n); + } + } +#endif +#endif + +#ifdef SPLIT_BN_MUL_HIGH +#if 0 +/* a and b must be the same size, which is n2. + * r must be n2 words and t must be n2*2 + * l is the low words of the output. + * t must be n2*3 + */ +void bn_mul_high(r,a,b,l,n2,t) +BN_ULONG *r,*a,*b,*l; +int n2; +BN_ULONG *t; + { + int i,n; + int c1,c2; + int neg,oneg,zero; + BN_ULONG ll,lc,*lp,*mp; + +#ifdef BN_COUNT +printf(" bn_mul_high %d * %d\n",n2,n2); +#endif + n=n2/2; + + /* Calculate (al-ah)*(bh-bl) */ + neg=zero=0; + c1=bn_cmp_words(&(a[0]),&(a[n]),n); + c2=bn_cmp_words(&(b[n]),&(b[0]),n); + switch (c1*3+c2) + { + case -4: + bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n); + bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n); + break; + case -3: + zero=1; + break; + case -2: + bn_sub_words(&(r[0]),&(a[n]),&(a[0]),n); + bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n); + neg=1; + break; + case -1: + case 0: + case 1: + zero=1; + break; + case 2: + bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n); + bn_sub_words(&(r[n]),&(b[0]),&(b[n]),n); + neg=1; + break; + case 3: + zero=1; + break; + case 4: + bn_sub_words(&(r[0]),&(a[0]),&(a[n]),n); + bn_sub_words(&(r[n]),&(b[n]),&(b[0]),n); + break; + } + + oneg=neg; + /* t[10] = (a[0]-a[1])*(b[1]-b[0]) */ + /* r[10] = (a[1]*b[1]) */ +#ifdef BN_MUL_COMBA + if (n == 8) + { + bn_mul_comba8(&(t[0]),&(r[0]),&(r[n])); + bn_mul_comba8(r,&(a[n]),&(b[n])); + } + else +#endif + { +#ifdef BN_MUL_RECURSION + bn_mul_recursive(&(t[0]),&(r[0]),&(r[n]),n,&(t[n2])); + bn_mul_recursive(r,&(a[n]),&(b[n]),n,&(t[n2])); +#else + bn_mul_normal(&(t[0]),&(r[0]),n,&(r[n]),n); + bn_mul_normal(r,&(a[n]),n,&(b[n]),n); +#endif + } + + /* s0 == low(al*bl) + * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl) + * We know s0 and s1 so the only unknown is high(al*bl) + * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl)) + * high(al*bl) == s1 - (r[0]+l[0]+t[0]) + */ + if (l != NULL) + { + lp= &(t[n2+n]); + c1=(int)bn_add_words(lp,&(r[0]),&(l[0]),n); + } + else + { + c1=0; + lp= &(r[0]); + } + + if (neg) + neg=(int)bn_sub_words(&(t[n2]),lp,&(t[0]),n); + else + { + bn_add_words(&(t[n2]),lp,&(t[0]),n); + neg=0; + } + + if (l != NULL) + { + bn_sub_words(&(t[n2+n]),&(l[n]),&(t[n2]),n); + } + else + { + lp= &(t[n2+n]); + mp= &(t[n2]); + for (i=0; i 0) + { + lc=c1; + do { + ll=(r[i]+lc)&BN_MASK2; + r[i++]=ll; + lc=(lc > ll); + } while (lc); + } + else + { + lc= -c1; + do { + ll=r[i]; + r[i++]=(ll-lc)&BN_MASK2; + lc=(lc > ll); + } while (lc); + } + } + if (c2 != 0) /* Add starting at r[1] */ + { + i=n; + if (c2 > 0) + { + lc=c2; + do { + ll=(r[i]+lc)&BN_MASK2; + r[i++]=ll; + lc=(lc > ll); + } while (lc); + } + else + { + lc= -c2; + do { + ll=r[i]; + r[i++]=(ll-lc)&BN_MASK2; + lc=(lc > ll); + } while (lc); + } + } + } +#endif +#endif +#endif + +#ifdef SPLIT_BN_MUL +int BN_mul(r,a,b,ctx) +BIGNUM *r,*a,*b; +BN_CTX *ctx; + { + int top,al,bl,neg; + BIGNUM *rr; +#ifdef BN_RECURSION_MUL + BIGNUM *t; + int i,j,k,l; +#endif + +#ifdef BN_COUNT +printf("BN_mul %d * %d\n",a->top,b->top); +#endif + + bn_check_top(a); + bn_check_top(b); + bn_check_top(r); + + al=a->top; + bl=b->top; + + if ((al == 0) || (bl == 0)) + { + (void)BN_zero(r); + return(1); + } + top=al+bl; + neg=a->neg^b->neg; + + if ((r == a) || (r == b)) + rr= &(ctx->bn[ctx->tos+1]); + else + rr=r; + + if (bn_wexpand(rr,top) == NULL) return(0); + rr->top=top; + +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION_MUL) + if (al == bl) + { +# ifdef BN_MUL_COMBA +/* if (al == 4) + { + bn_mul_comba4(rr->d,a->d,b->d); + goto end; + } + else */ if (al == 8) + { + bn_mul_comba8(rr->d,a->d,b->d); + goto end; + } + else +# endif +#ifdef BN_RECURSION_MUL + if (al < BN_MULL_SIZE_NORMAL) +#endif + { + bn_mul_normal(rr->d,a->d,al,b->d,bl); + goto end; + } +# ifdef BN_RECURSION_MUL + goto symetric; +# endif + } +#endif +#ifdef BN_RECURSION_MUL + else if ((al < BN_MULL_SIZE_NORMAL) || (bl < BN_MULL_SIZE_NORMAL)) + { + bn_mul_normal(rr->d,a->d,al,b->d,bl); + goto end; + } + else + { + i=(al-bl); + if ((i == 1) && !BN_get_flags(b,BN_FLG_STATIC_DATA)) + { + bn_wexpand(b,al); + b->d[bl]=0; + bl++; + goto symetric; + } + else if ((i == -1) && !BN_get_flags(a,BN_FLG_STATIC_DATA)) + { + bn_wexpand(a,bl); + a->d[al]=0; + al++; + goto symetric; + } + } +#endif + +#ifdef BN_RECURSION_MUL +normal_mul: +#endif + bn_mul_normal(rr->d,a->d,al,b->d,bl); + +#ifdef BN_RECURSION_MUL + if (0) + { +symetric: + /* symetric and > 4 */ + /* 16 or larger */ + l=BN_num_bits_word((BN_ULONG)al); + j=1<<(l-1); + k=j+j; + t= &(ctx->bn[ctx->tos]); + if (al == j) /* exact multiple */ + { + BN_REC rec; + rec.depth=l-5; + rec.n=j; + rec.mul=bn_mul_comba8; + rec.sqr=bn_sqr_comba8; + if (bn_wexpand(t,k+k) == NULL) + return(0); + if (bn_wexpand(rr,k) == NULL) + return(0); + bn_mul_rec_words(rr->d,a->d,b->d,t->d,&rec); + } + else + goto normal_mul; +#if 0 + { + bn_zexpand(a,k); + bn_zexpand(b,k); + bn_wexpand(t,k); + bn_wexpand(rr,k); + bn_mul_part_recursive(rr->d,a->d,b->d,al-j,j,t->d); + } +#endif + } +#endif +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION_MUL) +end: +#endif + + r->neg=neg; + bn_fix_top(rr); + if (r != rr) (void)BN_copy(r,rr); + return(1); + } +#endif + + +#ifdef SPLIT_BN_MUL_NORMAL +void bn_mul_normal(r,a,na,b,nb) +BN_ULONG *r,*a; +int na; +BN_ULONG *b; +int nb; + { + BN_ULONG *rr; + +#ifdef BN_COUNT +printf(" bn_mul_normal %d * %d\n",na,nb); +#endif + /* asymetric and >= 4 */ +#if 0 + if ((na == nb) && (na == 8)) + { + bn_mul_normal(r,a,na,b,nb); + return; + } +#endif + + if (na < nb) + { + int itmp; + BN_ULONG *ltmp; + + itmp=na; na=nb; nb=itmp; + ltmp=a; a=b; b=ltmp; + + } + rr= &(r[na]); + rr[0]=bn_mul_words(r,a,na,b[0]); + + for (;;) + { + if (--nb <= 0) return; + rr[1]=bn_mul_add_words(&(r[1]),a,na,b[1]); + if (--nb <= 0) return; + rr[2]=bn_mul_add_words(&(r[2]),a,na,b[2]); + if (--nb <= 0) return; + rr[3]=bn_mul_add_words(&(r[3]),a,na,b[3]); + if (--nb <= 0) return; + rr[4]=bn_mul_add_words(&(r[4]),a,na,b[4]); + rr+=4; + r+=4; + b+=4; + } + } +#endif + +#ifdef SPLIT_BN_MUL_LOW_NORMAL +void bn_mul_low_normal(r,a,b,n) +BN_ULONG *r,*a,*b; +int n; + { +#ifdef BN_COUNT +printf(" bn_mul_low_normal %d * %d\n",n,n); +#endif + (void)bn_mul_words(r,a,n,b[0]); + + for (;;) + { + if (--n <= 0) return; + (void)bn_mul_add_words(&(r[1]),a,n,b[1]); + if (--n <= 0) return; + (void)bn_mul_add_words(&(r[2]),a,n,b[2]); + if (--n <= 0) return; + (void)bn_mul_add_words(&(r[3]),a,n,b[3]); + if (--n <= 0) return; + (void)bn_mul_add_words(&(r[4]),a,n,b[4]); + r+=4; + b+=4; + } + } +#endif +#endif diff --git a/build/tools/acsign/bn_r_exp.c b/build/tools/acsign/bn_r_exp.c new file mode 100644 index 0000000..9465e40 --- /dev/null +++ b/build/tools/acsign/bn_r_exp.c @@ -0,0 +1,134 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +/* #ifdef RECP_MUL_MOD */ +int BN_mod_exp_recp(r,a,p,m,ctx) +BIGNUM *r; +BIGNUM *a; +BIGNUM *p; +BIGNUM *m; +BN_CTX *ctx; + { + int i,j,bits,ret=0,wstart,wend,window,wvalue; + int start=1,ts=0; + BIGNUM *aa; + BIGNUM val[BN_EXP_TABLE_SIZE]; + BN_RECP_CTX recp; + + bits=BN_num_bits(p); + + if (BN_is_zero(a)) + { (void)BN_zero(r); return(1); } + if (BN_is_zero(p)) + { (void)BN_one(r); return(1); } + if (BN_is_one(p)) + { (void)BN_copy(r,a); return(1); } + + BN_RECP_CTX_init(&recp); + if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err; + + BN_init(&(val[0])); + ts=1; + + aa= &(ctx->bn[ctx->tos++]); + + if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */ + if (!BN_mod_mul_reciprocal(aa,&(val[0]),&(val[0]),&recp,ctx)) + goto err; /* 2 */ + + if (bits <= 17) /* This is probably 3 or 0x10001, so just do singles */ + window=1; + else if (bits >= 256) + window=5; /* max size of window */ + else if (bits >= 128) + window=4; + else + window=3; + + j=1<<(window-1); + for (i=1; i>1]),&recp,ctx)) + goto err; + + /* move the 'window' down further */ + wstart-=wend+1; + wvalue=0; + start=0; + if (wstart < 0) break; + } + ret=1; +err: + ctx->tos--; + for (i=0; in; + int n2=n/2; + int c1,neg=0; + + + if (rec->depth == 0) + { + /* t needs to have space for 4*n words + * The multiply needs to be a n2*n2 -> n + */ +#ifndef NOPROTO + void (PRE_CCONV CCONV *rmul)(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); +#else + void (PRE_CCONV CCONV *rmul)(); +#endif + rmul=rec->mul; + +#ifdef _EXTRA_ARG_ + /* THIS IS WRONG - there is no extra int arg on the end */ + rmul(&(r[0]),&(a[0]),&(b[0]),n2); + rmul(&(r[n]),&(a[n2]),&(b[n2]),n2); +#else + rmul(&(r[0]),&(a[0]),&(b[0])); + rmul(&(r[n]),&(a[n2]),&(b[n2])); +#endif + + if (bn_sub_words(&(tt[n+0]), &(a[0]),&(a[n2]),n2)) + { + bn_2s_comp(&(tt[n+ 0]),&(tt[n+ 0]),n2); + neg=1; + } + else + neg=0; + if (bn_sub_words(&(tt[n+n2]),&(b[n2]),&(b[0]),n2)) + { + neg^=1; + bn_2s_comp(&(tt[n+n2]),&(tt[n+n2]),n2); + } + +#ifdef _EXTRA_ARG_ + rmul(&(tt[0]),&(tt[n+0]),&(tt[n+n2]),n2); +#else + rmul(&(tt[0]),&(tt[n+0]),&(tt[n+n2])); +#endif + } + else /* Leaf node */ + { + /* t has 4*n words taken per call. + * Since n is half the size per call, we need + * 6*n words for our current level and all sub levels + * The multiply needs to be a n2*n2 -> n + */ + rec->depth--; + rec->n=n2; + bn_mul_rec_words(&(r[0]), &(a[0]), &(b[0]), &(tt[n+n]),rec); + bn_mul_rec_words(&(r[n]), &(a[n2]),&(b[n2]), &(tt[n+n]),rec); + + neg=0; + if (bn_sub_words(&(tt[n+0]), &(a[0]),&(a[n2]),n2)) + { + bn_2s_comp(&(tt[n+ 0]),&(tt[n+ 0]),n2); + neg=1; + } + else + neg=0; + if (bn_sub_words(&(tt[n+n2]),&(b[n2]),&(b[0]),n2)) + { + neg^=1; + bn_2s_comp(&(tt[n+n2]),&(tt[n+n2]),n2); + } + + bn_mul_rec_words(&(tt[0]),&(tt[n]),&(tt[n+n2]),&(tt[n+n]),rec); + rec->n=n; + rec->depth++; + } + + c1=bn_add_words(&(tt[n]),&(r[0]),&(r[n]),n); + + if (neg) + c1-=bn_sub_words(&(tt[0]),&(tt[n]),&(tt[0]),n); + else + c1+=bn_add_words(&(tt[0]),&(tt[n]),&(tt[0]),n); + tt[n]=c1; + c1=bn_add_words(&(r[n2]),&(r[n2]),&(tt[0]),n+1); + if (c1) + { + tt= &(r[n+n2+1]); + do { + } while (++(*(tt++)) == 0); + } + } +#endif + +#ifdef SPLIT_BN_SQR_REC_WORDS +/* tt needs to be 3*n words */ +void bn_sqr_rec_words(r,a,tt,rec) +BN_ULONG *r,*a,*tt; +BN_REC *rec; + { + int n=rec->n; + int n2=n/2; + int c1; + + if (rec->depth == 0) + { + /* t needs to have space for 4*n words + * The multiply needs to be a n2*n2 -> n + */ +#ifndef NOPROTO + void (PRE_CCONV CCONV *rsqr)(BN_ULONG *r, BN_ULONG *a); +#else + void (PRE_CCONV CCONV *rsqr)(); +#endif + + rsqr=rec->sqr; + +#ifdef _EXTRA_ARG_ + /* THIS IS WRONG - there is no extra int arg on the end */ + rsqr(&(r[0]), &(a[0]), n2); + rsqr(&(r[n]), &(a[n2]),n2); +#else + rsqr(&(r[0]), &(a[0])); + rsqr(&(r[n]), &(a[n2])); +#endif + + if (bn_sub_words(&(tt[n+0]), &(a[0]),&(a[n2]),n2)) + bn_2s_comp(&(tt[n+0]),&tt[n+0], n2); + +#ifdef _EXTRA_ARG_ + rsqr(&(tt[0]),&(tt[n]), n2); +#else + rsqr(&(tt[0]),&(tt[n])); +#endif + + } + else /* Leaf node */ + { + /* t has 4*n words taken per call. + * Since n is half the size per call, we need + * 6*n words for our current level and all sub levels + * The multiply needs to be a n2*n2 -> n + */ + rec->depth--; + rec->n=n2; + bn_sqr_rec_words(&(r[0]), &(a[0]), &(tt[n+n]),rec); + bn_sqr_rec_words(&(r[n]), &(a[n2]),&(tt[n+n]),rec); + + if (bn_sub_words(&(tt[n+0]), &(a[0]),&(a[n2]),n2)) + bn_2s_comp(&(tt[n+0]),&tt[n+0], n2); + bn_sqr_rec_words(&(tt[0]),&(tt[n]),&(tt[n+n]),rec); + + rec->n=n; + rec->depth++; + } + + c1=bn_add_words(&(tt[n]),&(r[0]),&(r[n]),n); + c1-=bn_sub_words(&(tt[0]),&(tt[n]),&(tt[0]),n); + + tt[n]=c1; + c1=bn_add_words(&(r[n2]),&(r[n2]),&(tt[0]),n+1); + if (c1) + { + tt= &(r[n+n2+1]); + do { + } while (++(*(tt++)) == 0); + } + } +#endif + +#endif /* !NO_SPLIT || !SPLIT_FILE */ diff --git a/build/tools/acsign/bn_recp.c b/build/tools/acsign/bn_recp.c new file mode 100644 index 0000000..e762a81 --- /dev/null +++ b/build/tools/acsign/bn_recp.c @@ -0,0 +1,202 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +void BN_RECP_CTX_init(recp) +BN_RECP_CTX *recp; + { + BN_init(&(recp->N)); + BN_init(&(recp->Nr)); + recp->num_bits=0; + recp->flags=0; + } + +BN_RECP_CTX *BN_RECP_CTX_new() + { + BN_RECP_CTX *ret; + + if ((ret=(BN_RECP_CTX *)Malloc(sizeof(BN_RECP_CTX))) == NULL) + return(NULL); + + BN_RECP_CTX_init(ret); + ret->flags=BN_FLG_MALLOCED; + return(ret); + } + +void BN_RECP_CTX_free(recp) +BN_RECP_CTX *recp; + { + BN_free(&(recp->N)); + BN_free(&(recp->Nr)); + if (recp->flags & BN_FLG_MALLOCED) + Free(recp); + } + +int BN_RECP_CTX_set(recp,d,ctx) +BN_RECP_CTX *recp; +BIGNUM *d; +BN_CTX *ctx; + { + (void)BN_copy(&(recp->N),d); + (void)BN_zero(&(recp->Nr)); + recp->num_bits=BN_num_bits(d); + recp->shift=0; + ctx=ctx; /* Stop warning */ + return(1); + } + +int BN_mod_mul_reciprocal(r, x, y, recp, ctx) +BIGNUM *r; +BIGNUM *x; +BIGNUM *y; +BN_RECP_CTX *recp; +BN_CTX *ctx; + { + int ret=0; + BIGNUM *a; + + bn_check_top(x); + bn_check_top(y); + + a= &(ctx->bn[ctx->tos++]); + if (y != NULL) + { + if (x == y) + { if (!BN_sqr(a,x,ctx)) goto err; } + else + { if (!BN_mul(a,x,y,ctx)) goto err; } + } + else + a=x; /* Just do the mod */ + + (void)BN_div_recp(NULL,r,a,recp,ctx); + ret=1; +err: + ctx->tos--; + return(ret); + } + +int BN_div_recp(dv,rem,m,recp,ctx) +BIGNUM *dv; +BIGNUM *rem; +BIGNUM *m; +BN_RECP_CTX *recp; +BN_CTX *ctx; + { + int i,j,tos,ret=0,ex; + BIGNUM *a,*b,*d,*r; + + bn_check_top(m); + + tos=ctx->tos; + a= &(ctx->bn[ctx->tos++]); + b= &(ctx->bn[ctx->tos++]); + if (dv != NULL) + d=dv; + else + d= &(ctx->bn[ctx->tos++]); + if (rem != NULL) + r=rem; + else + r= &(ctx->bn[ctx->tos++]); + + if (BN_ucmp(m,&(recp->N)) < 0) + { + (void)BN_zero(d); + (void)BN_copy(r,m); + ctx->tos=tos; + return(1); + } + + /* We want the remainder + * Given input of ABCDEF / ab + * we need multiply ABCDEF by 3 digests of the reciprocal of ab + * + */ + i=BN_num_bits(m); + + j=recp->num_bits*2; + if (j > i) + { + i=j; + ex=0; + } + else + { + ex=(i-j)/2; + } + + j=i/2; + + if (i != recp->shift) + recp->shift=BN_reciprocal(&(recp->Nr),&(recp->N), + i,ctx); + + if (!BN_rshift(a,m,j-ex)) goto err; + if (!BN_mul(b,a,&(recp->Nr),ctx)) goto err; + if (!BN_rshift(d,b,j+ex)) goto err; + d->neg=0; + if (!BN_mul(b,&(recp->N),d,ctx)) goto err; + if (!BN_usub(r,m,b)) goto err; + r->neg=0; + + j=0; +#if 1 + while (BN_ucmp(r,&(recp->N)) >= 0) + { + if (j++ > 2) + { +#ifndef NO_ERR + BNerr(BN_F_BN_DIV_RECP,BN_R_BAD_RECIPROCAL); +#endif + goto err; + } + if (!BN_usub(r,r,&(recp->N))) goto err; + if (!BN_add_word(d,1)) goto err; + } +#endif + + r->neg=BN_is_zero(r)?0:m->neg; + d->neg=m->neg^recp->N.neg; + ret=1; +err: + ctx->tos=tos; + return(ret); + } + +/* len is the expected size of the result + * We actually calculate with an extra word of precision, so + * we can do faster division if the remainder is not required. + */ +int BN_reciprocal(r,m,len,ctx) +BIGNUM *r; +BIGNUM *m; +int len; +BN_CTX *ctx; + { + int ret= -1; + BIGNUM t; + + bn_check_top(m); + + BN_init(&t); + + (void)BN_zero(&t); + if (!BN_set_bit(&t,len)) goto err; + + if (!BN_div(r,NULL,&t,m,ctx)) goto err; + ret=len; +err: + BN_free(&t); + return(ret); + } + diff --git a/build/tools/acsign/bn_rsh.c b/build/tools/acsign/bn_rsh.c new file mode 100644 index 0000000..909cd9a --- /dev/null +++ b/build/tools/acsign/bn_rsh.c @@ -0,0 +1,123 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_RSHIFT1 +#define SPLIT_BN_RSHIFT +#endif /* NO_SPLIT */ + +#ifdef SPLIT_BN_RSHIFT1 +#ifdef SMALL_CODE_SIZE +int BN_rshift1(r, a) +BIGNUM *r; +BIGNUM *a; + { + return(BN_rshift(r,a,1)); + } + +#else + +int BN_rshift1(r, a) +BIGNUM *r; +BIGNUM *a; + { + BN_ULONG *ap,*rp,t,c; + int i; + + bn_check_top(a); + + if (BN_is_zero(a)) + { + BN_zero(r); + return(1); + } + if (a != r) + { + if (bn_wexpand(r,a->top) == NULL) return(0); + r->top=a->top; + r->neg=a->neg; + } + ap=a->d; + rp=r->d; + c=0; + for (i=a->top-1; i>=0; i--) + { + t=ap[i]; + rp[i]=((t>>1)&BN_MASK2)|c; + c=(t&1)?BN_TBIT:0; + } + bn_fix_top(r); + return(1); + } +#endif +#endif + +#ifdef SPLIT_BN_RSHIFT +int BN_rshift(r, a, n) +BIGNUM *r; +BIGNUM *a; +int n; + { + int i,j,nw,lb,rb; + BN_ULONG *t,*f; + BN_ULONG l,tmp; + + bn_check_top(a); + +#ifndef SMALL_CODE_SIZE + if (n == 1) return(BN_rshift1(r,a)); +#endif + nw=n/BN_BITS2; + rb=n%BN_BITS2; + lb=BN_BITS2-rb; + if (nw > a->top) + { + (void)BN_zero(r); + return(1); + } + if (r != a) + { + if (bn_wexpand(r,a->top-nw+1+1/*???*/) == NULL) return(0); + r->neg=a->neg; + } + + f= &(a->d[nw]); + t=r->d; + j=a->top-nw; + r->top=j; + + if (rb == 0) + { + for (i=j+1; i > 0; i--) + *(t++)= *(f++); + } + else + { + l= *(f++); + for (i=1; i>rb)&BN_MASK2; + l= *(f++); + *(t++) =(tmp|(l<>rb)&BN_MASK2; + *t=0; + } + bn_fix_top(r); + return(1); + } +#endif + +#endif diff --git a/build/tools/acsign/bn_sqr.c b/build/tools/acsign/bn_sqr.c new file mode 100644 index 0000000..4762cd9 --- /dev/null +++ b/build/tools/acsign/bn_sqr.c @@ -0,0 +1,273 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#ifdef SMALL_CODE_SIZE +#undef BN_RECURSION_SQR +#endif + +#if !(defined(NO_SPLIT) && defined(SPLIT_FILE)) + +#ifdef NO_SPLIT +#define SPLIT_BN_SQR +#define SPLIT_BN_SQR_NORMAL +#define SPLIT_BN_RECURSION_SQR +#endif /* NO_SPLIT */ + +#ifdef SPLIT_BN_SQR +/* r must not be a */ +int BN_sqr(r, a, ctx) +BIGNUM *r; +BIGNUM *a; +BN_CTX *ctx; + { + int max,al; + BIGNUM *tmp,*rr; + +#ifdef BN_COUNT +printf("BN_sqr %d * %d\n",a->top,a->top); +#endif + bn_check_top(a); + tmp= &(ctx->bn[ctx->tos]); + rr=(a != r)?r: (&ctx->bn[ctx->tos+1]); + + al=a->top; + if (al <= 0) + { + r->top=0; + return(1); + } + + max=(al+al); + if (bn_wexpand(rr,max) == NULL) return(0); + + rr->top=max; + rr->neg=0; + + if (al == 4) + { +#ifndef BN_SQR_COMBA + BN_ULONG t[8]; + bn_sqr_normal(rr->d,a->d,4,t); +#else + bn_sqr_comba4(rr->d,a->d); +#endif + } + else if (al == 8) + { +#ifndef BN_SQR_COMBA + BN_ULONG t[16]; + bn_sqr_normal(rr->d,a->d,8,t); +#else + bn_sqr_comba8(rr->d,a->d); +#endif + } + else + { +#if 1 && defined(BN_RECURSION_SQR) + if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) + { + BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL*2]; + bn_sqr_normal(rr->d,a->d,al,t); + } + else + { + int j,l,k; + + l=BN_num_bits_word((BN_ULONG)al); + j=1<<(l-1); + k=j+j; + if ((al == j) && !BN_get_flags(a,BN_FLG_STATIC_DATA)) + { + BN_REC rec; + if (bn_wexpand(tmp,k*2) == NULL) return(0); + rec.depth=l-5; + rec.n=j; + rec.mul=bn_mul_comba8; + rec.sqr=bn_sqr_comba8; + + bn_sqr_rec_words(rr->d,a->d,tmp->d,&rec); + } + else + { + if (bn_wexpand(tmp,max) == NULL) return(0); + bn_assert(al*2 <= max); + bn_sqr_normal(rr->d,a->d,al,tmp->d); + } + } +#else + if (bn_wexpand(tmp,max) == NULL) return(0); + bn_assert(al*2 <= max); + bn_sqr_normal(rr->d,a->d,al,tmp->d); +#endif +#ifdef BN_DEBUG + tmp->top=0; +#endif + } + + if ((max > 0) && (rr->d[max-1] == 0)) rr->top--; + if (rr != r) (void)BN_copy(r,rr); + return(1); + } +#endif + +#ifdef SPLIT_BN_SQR_NORMAL +/* tmp must have 2*n words */ +void bn_sqr_normal(r, a, n, tmp) +BN_ULONG *r; +BN_ULONG *a; +int n; +BN_ULONG *tmp; + { + int i,j,max; + BN_ULONG *ap,*rp,m; + + max=n*2; + ap=a; + rp=r; + rp[0]=rp[max-1]=0; + rp++; + j=n; + + if (--j > 0) + { + m= (*ap++); + rp[j]=bn_mul_words(rp,ap,j,m); + rp+=2; + } + + for (i=n-2; i>0; i--) + { + j--; + m= *(ap++); + rp[j]=bn_mul_add_words(rp,ap,j,m); + rp+=2; + } + + (void)bn_add_words(r,r,r,max); + + /* There will not be a carry */ + + bn_sqr_words(tmp,a,n); + + (void)bn_add_words(r,r,tmp,max); + } +#endif + +#if 0 /* replaced by bn_sqr_rec_words() AND this has bugs */ +#ifdef SPLIT_BN_RECURSION_SQR +#ifdef BN_RECURSION_SQR +/* r is 2*n words in size, + * a and b are both n words in size. + * n must be a power of 2. + * We multiply and return the result. + * t must be 2*n words in size + * We calulate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +void bn_sqr_recursive(r,a,n2,t) +BN_ULONG *r,*a; +int n2; +BN_ULONG *t; + { + int n=n2/2; + int zero,c1; + BN_ULONG ln,lo,*p; + +#ifdef BN_COUNT +printf(" bn_sqr_recursive %d * %d\n",n2,n2); +#endif + if (n2 == 4) + { +#ifndef BN_SQR_COMBA + bn_sqr_normal(r,a,4,t); +#else + bn_sqr_comba4(r,a); +#endif + return; + } + else if (n2 == 8) + { +#ifndef BN_SQR_COMBA + bn_sqr_normal(r,a,8,t); +#else + bn_sqr_comba8(r,a); +#endif + return; + } + if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) + { + bn_sqr_normal(r,a,n2,t); + return; + } + /* r=(a[0]-a[1])*(a[1]-a[0]) */ + c1=bn_cmp_words(a,&(a[n]),n); + zero=0; + if (c1 > 0) + bn_sub_words(t,a,&(a[n]),n); + else if (c1 < 0) + bn_sub_words(t,&(a[n]),a,n); + else + zero=1; + + /* The result will always be negative unless it is zero */ + p= &(t[n2*2]); + + if (!zero) + bn_sqr_recursive(&(t[n2]),t,n,p); + else + Memset(&(t[n2]),0,n*sizeof(BN_ULONG)); + bn_sqr_recursive(r,a,n,p); + bn_sqr_recursive(&(r[n2]),&(a[n]),n,p); + + /* t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + + c1=(int)(bn_add_words(t,r,&(r[n2]),n2)); + + /* t[32] is negative */ + c1-=(int)(bn_sub_words(&(t[n2]),t,&(t[n2]),n2)); + + /* t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1]) + * r[10] holds (a[0]*a[0]) + * r[32] holds (a[1]*a[1]) + * c1 holds the carry bits + */ + c1+=(int)(bn_add_words(&(r[n]),&(r[n]),&(t[n2]),n2)); + if (c1) + { + p= &(r[n+n2]); + lo= *p; + ln=(lo+c1)&BN_MASK2; + *p=ln; + + /* The overflow will stop before we over write + * words we should not overwrite */ + if (ln < (BN_ULONG)c1) + { + do { + p++; + lo= *p; + ln=(lo+1)&BN_MASK2; + *p=ln; + } while (ln == 0); + } + } + } +#endif +#endif +#endif +#endif diff --git a/build/tools/acsign/bn_wdiv.c b/build/tools/acsign/bn_wdiv.c new file mode 100644 index 0000000..d76752a --- /dev/null +++ b/build/tools/acsign/bn_wdiv.c @@ -0,0 +1,100 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#include "bn_lcl.h" + +#ifndef OPT_BN_ASM + +#ifndef BN_DIV_WORDS +#define BN_DIV_WORDS +#endif + +#endif + +#ifdef BN_DIV_WORDS +#if defined(BN_LLONG) +BN_ULONG bn_div_words(h,l,d) +BN_ULONG h,l,d; + { + return((BN_ULONG)(((((BN_ULLONG)h)< ((BN_ULONG)1)<= d) h-=d; + + if (i) + { + d=(d<>(BN_BITS2-i)))&BN_MASK2; + l=(l<>BN_BITS4)&BN_MASK2lh; + dl=(d&BN_MASK2l); + for (;;) + { + if ((h>>BN_BITS4) == dh) + q=BN_MASK2l; + else + q=h/dh; + + for (;;) + { + t=(h-q*dh)&BN_MASK2; + if ((t&BN_MASK2h) || + (((dl*q)&BN_MASK2) <= (( + (t<>BN_BITS4)&BN_MASK2lh))&BN_MASK2))) + break; + q--; + } + th=(q*dh)&BN_MASK2; + tl=(q*dl)&BN_MASK2; + t=(tl>>BN_BITS4); + tl=(tl&BN_MASK2lh)<>BN_BITS4))&BN_MASK2; + l=(l&BN_MASK2l)<top-1; i>=0; i--) + { +#ifndef BN_LLONG + ret=((ret<d[i]>>BN_BITS4)&BN_MASK2l))%w; + ret=((ret<d[i]&BN_MASK2l))%w; +#else + ret=(BN_ULLONG)(((ret<<(BN_ULLONG)BN_BITS2)|a->d[i])% + (BN_ULLONG)w); +#endif + } + return((BN_ULONG)ret); + } +#endif + +#ifdef SPLIT_BN_DIV_WORD +BN_ULONG BN_div_word(a, w) +BIGNUM *a; +BN_ULONG w; + { + BN_ULONG ret; + int i; + + if (a->top == 0) return(0); + ret=0; + w=w&BN_MASK2;//w&=BN_MASK2; + for (i=a->top-1; i>=0; i--) + { + BN_ULONG l,d; + + l=a->d[i]; + d=bn_div_words(ret,l,w); + ret=(l-((d*w)&BN_MASK2))&BN_MASK2; + a->d[i]=d; + } + if ((a->top > 0) && (a->d[a->top-1] == 0)) + a->top--; + return(ret); + } +#endif + +#ifdef SPLIT_BN_ADD_WORD +int BN_add_word(a, w) +BIGNUM *a; +BN_ULONG w; + { + BN_ULONG l; + int i; + + if (w == 0) return(1); + bn_check_top(a); + + w=w&BN_MASK2;//w&=BN_MASK2; + if (a->neg) + { + if(a->top > 1) + { + a->neg=0; + i=BN_sub_word(a,w); + a->neg=1; + return(i); + } + else + { /* a->top == 1, it cannot be 0 */ + l=a->d[0]; + if (l > w) + a->d[0]=l-w; + else if (l < w) + { + a->neg=0; + a->d[0]=w-l; + } + else + { + a->neg=0; + a->top=0; + } + return(1); + } + } + w=w&BN_MASK2;//w&=BN_MASK2; + if (bn_wexpand(a,a->top+1) == NULL) return(0); + a->d[a->top]=0; + i=0; + for (;;) + { + l=(a->d[i]+(BN_ULONG)w)&BN_MASK2; + a->d[i]=l; + if (w > l) + w=1; + else + break; + i++; + } + if (i >= a->top) + a->top++; + return(1); + } +#endif + +#ifdef SPLIT_BN_SUB_WORD +int BN_sub_word(a, w) +BIGNUM *a; +BN_ULONG w; + { + int i; + + bn_check_top(a); + if (w == 0) return(1); + + w=w&BN_MASK2;//w&=BN_MASK2; + if (a->neg) + { + a->neg=0; + i=BN_add_word(a,w); + a->neg=1; + return(i); + } + + w=w&BN_MASK2;//w&=BN_MASK2; + if (a->top <= 1) + { + BN_ULONG l; + + if (a->top == 0) + { + if (bn_wexpand(a,1) == NULL) return(0); + a->d[0]=w; + a->neg = 1; + a->top = 1; + return(1); + } + l=a->d[0]; + if (l == w) + a->top=0; + else if (l > w) + a->d[0]=l-w; + else + { + a->neg=1; + a->d[0]=w-l; + } + return(1); + } + i=0; + for (;;) + { + if (a->d[i] >= w) + { + a->d[i]-=w; + break; + } + else + { + a->d[i]=(a->d[i]-w)&BN_MASK2; + i++; + w=1; + } + } + if ((a->d[i] == 0) && (i == (a->top-1))) + a->top--; + return(1); + } +#endif + +#ifdef SPLIT_BN_MUL_WORD +int BN_mul_word(a,w) +BIGNUM *a; +BN_ULONG w; + { + BN_ULONG ll; + + w=w&BN_MASK2;//w&=BN_MASK2; + if (a->top) + { + ll=bn_mul_words(a->d,a->d,a->top,w); + if (ll) + { + if (bn_wexpand(a,a->top+1) == NULL) return(0); + a->d[a->top++]=ll; + } + } + return(1); + } +#endif + +#endif diff --git a/build/tools/acsign/include/acsign.h b/build/tools/acsign/include/acsign.h new file mode 100644 index 0000000..6e11663 --- /dev/null +++ b/build/tools/acsign/include/acsign.h @@ -0,0 +1,49 @@ +#ifndef _ACSIGN_H_ +#define _ACSIGN_H_ + +#include "sha.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HASHContext SHA_CTX + +#define HASHReset( _context ) \ +do{ \ + (_context)->sha_block = NULL; \ + (void)SHA1_Init( _context ); \ +} while(0) +#define HASHUpdate( _context, _ptr, _len ) (void)SHA1_Update( _context, _ptr, _len ) +#define HASHGetDigest( _context, _ptr ) (void)SHA1_Final( _ptr, _context ) + +// +BOOL ACSign_Encrypto(void *sign, const void *key, const void *data, int length); +BOOL ACSign_Decrypto(void *buf, const void *key, const void *sign, int length); + +// +int ACSign_DigestUnit( + void* buffer, // o͗̈ + const void* buf, // f[^ւ̃|C^ + unsigned int len // f[^̒ + ); + +// +int ACSign_CompareUnit( + const void* decedHash, // ACSign_Decryptȍo + const void* digest // ACSign_DigestUnit̏o + ); + +// +int ACSign_GetKey( + void* dest_ptr, // o̓f[^ւ̃|C^ + unsigned int dest_len, // o̓f[^̒ + const void* src_ptr, // ̓f[^ւ̃|C^ + unsigned int src_len // ̓f[^̒ + ); + +#ifdef __cplusplus +} +#endif + +#endif //_ACSIGN_H_ diff --git a/build/tools/acsign/include/acsign_gcd.h b/build/tools/acsign/include/acsign_gcd.h new file mode 100644 index 0000000..2c9853e --- /dev/null +++ b/build/tools/acsign/include/acsign_gcd.h @@ -0,0 +1,30 @@ +#ifndef _ACSIGN_GCD_H_ +#define _ACSIGN_GCD_H_ + +#include "sha.h" +#include "format_sign.h" +#include "format_rom.h" +#include "acsign.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// +int ACSign_Final( + GCDHeader* header, // wb_ւ̃|C^ + void* buffer, // o͗̈ + const void* key + ); + +// +int ACSign_DigestHeader( + void* buffer, // o͗̈ + GCDHeader* header // f[^ւ̃|C^ + ); + +#ifdef __cplusplus +} +#endif + +#endif //_ACSIGN_GCD_H_ diff --git a/build/tools/acsign/include/acsign_nand.h b/build/tools/acsign/include/acsign_nand.h new file mode 100644 index 0000000..97afa98 --- /dev/null +++ b/build/tools/acsign/include/acsign_nand.h @@ -0,0 +1,30 @@ +#ifndef _ACSIGN_NAND_H_ +#define _ACSIGN_NAND_H_ + +#include "sha.h" +#include "format_sign.h" +#include "format_rom.h" +#include "acsign.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// +int ACSign_Final( + NANDHeader* header, // wb_ւ̃|C^ + void* buffer, // o͗̈ + const void* key + ); + +// +int ACSign_DigestHeader( + void* buffer, // o͗̈ + NANDHeader* header // f[^ւ̃|C^ + ); + +#ifdef __cplusplus +} +#endif + +#endif //_ACSIGN_NAND_H_ diff --git a/build/tools/acsign/include/acsign_nor.h b/build/tools/acsign/include/acsign_nor.h new file mode 100644 index 0000000..eb097b5 --- /dev/null +++ b/build/tools/acsign/include/acsign_nor.h @@ -0,0 +1,30 @@ +#ifndef _ACSIGN_NOR_H_ +#define _ACSIGN_NOR_H_ + +#include "sha.h" +#include "format_sign.h" +#include "format_rom.h" +#include "acsign.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// +int ACSign_Final( + NORHeader* header, // wb_ւ̃|C^ + void* buffer, // o͗̈ + const void* key + ); + +// +int ACSign_DigestHeader( + void* buffer, // o͗̈ + NORHeader* header // f[^ւ̃|C^ + ); + +#ifdef __cplusplus +} +#endif + +#endif //_ACSIGN_NOR_H_ diff --git a/build/tools/acsign/include/bn.h b/build/tools/acsign/include/bn.h new file mode 100644 index 0000000..f68b3d2 --- /dev/null +++ b/build/tools/acsign/include/bn.h @@ -0,0 +1,1120 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#ifndef HEADER_COMMON_BN_H +#define HEADER_COMMON_BN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef FLAT_INC +#include "r_types.h" +#else +#include "../include/r_types.h" +#endif + +#if !defined(CCONV) +#define CCONV +#endif + +#ifndef PRE_CCONV +#define PRE_CCONV +#endif + +/* convert from the new to the old option names */ +#if defined(OPT_BN_LLONG) +#define BN_LLONG /* comment to make sure Configure leaves this alone */ +#endif + +#if defined(OPT_BN_MUL_LATENCY) +#define BN_MUL_LATENCY +#endif + +/* by default we have the following switched on - unless we have an option + * that switched them off for a specific platform + */ +#ifdef OPT_NO_COMBA +#define OPT_NO_BN_MUL_COMBA +#define OPT_NO_BN_SQR_COMBA +#endif + +#ifdef OPT_NO_REC +#define OPT_NO_BN_RECURSION_MUL +#define OPT_NO_BN_RECURSION_SQR +#endif + +#ifndef OPT_NO_BN_MUL_COMBA +#define BN_MUL_COMBA +#endif +#ifndef OPT_NO_BN_SQR_COMBA +#define BN_SQR_COMBA +#endif +#ifndef OPT_NO_BN_RECURSION_MUL +#define BN_RECURSION_MUL +#endif +#ifndef OPT_NO_BN_RECURSION_SQR +#define BN_RECURSION_SQR +#endif +#ifndef OPT_NO_BN_RECURSION_MONT +#undef BN_RECURSION_MONT /* DO NOT TURN THIS ON, IT IS BROKEN */ +#endif + +#if (!defined(OPT_NO_BN_MUL_COMBA) && !defined(OPT_NO_BN_SQR_COMBA)) +#if OPT_MONT_REDUCE_COMBA /* TEMP UNTIL C IS IMPLEMENTED-DEF'd ON PLATFORMS W/ ASM */ +#define BN_REDUCE_COMBA +#endif +#endif + +#define RECP_MUL_MOD +#define MONT_MUL_MOD + +#ifndef OPT_NO_BN_SURRENDER +#define BN_SURRENDER +#else +#undef BN_SURRENDER +#endif + +#ifdef SMALL_CODE_SIZE +#undef BN_MUL_COMBA /* stop modification */ +#undef BN_SQR_COMBA /* stop modification */ +#undef BN_REDUCE_COMBA /* stop modification */ +#undef BN_RECURSION_MUL /* stop modification */ +#undef BN_RECURSION_SQR /* stop modification */ +#undef BN_RECURSION_MONT /* stop modification */ +#endif + + + +/* This next option uses the C libraries (2 word)/(1 word) function. + * If it is not defined, I use my C version (which is slower). + * The reason for this flag is that when the particular C compiler + * library routine is used, and the library is linked with a different + * compiler, the library is missing. This mostly happens when the + * library is built with gcc and then linked using nornal cc. This would + * be a common occurance because gcc normally produces code that is + * 2 times faster than system compilers for the big number stuff. + * For machines with only one compiler (or shared libraries), this should + * be on. Again this in only really a problem on machines + * using "long long's", are 32bit, and are not using my assember code. */ +#if defined(MSDOS) || defined(WINDOWS) || defined(linux) +#define BN_DIV2W +#endif + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debuging the bignum libraries */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#undef SIXTY_BIT +#undef THIRTY_TWO_BIT +#undef THIRTY_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#undef TEST_EIGHT_BIT + +#if defined(OPT_64_BIT_LONG) +#define SIXTY_FOUR_BIT_LONG +#endif +#if defined(OPT_64_BIT) +#define SIXTY_FOUR_BIT +#endif +#if defined(OPT_60_BIT) +#define SIXTY_BIT +#endif +#if defined(OPT_32_BIT) +#define THIRTY_TWO_BIT +#endif +#if defined(OPT_32_BIT_INT) +#define THIRTY_TWO_BIT +#endif +#if defined(OPT_30_BIT) +#define THIRTY_BIT +#endif +#if defined(OPT_16_BIT) +#define SIXTEEN_BIT +#endif +#if defined(OPT_8_BIT) +#define EIGHT_BIT +#endif +#if defined(OPT_8_BIT_TEST) +#define TEST_EIGHT_BIT +#endif + +/* This define is used for those few functions that 'break' when + * things are compiled for 8 bit words. Basically the size of an + * integer. + */ +#define BN_ILONG BN_ULONG + +/* assuming long is 64bit - this is the DEC Alpha + * unsigned long long is only 64 bits, don't define + * BN_LLONG for the DEC Alpha */ +#ifdef SIXTY_FOUR_BIT_LONG +#undef BN_LLONG +#define BN_ULLONG unsigned long long +#define BN_ULONG unsigned long +#define BN_LONG long +#define BN_BITS 128 +#define BN_BYTES 8 +#define BN_BITS2 64 +#define BN_BITS4 32 +#define BN_MASK (0xffffffffffffffffffffffffffffffffLL) +#define BN_MASK2 (0xffffffffffffffffL) +#define BN_MASK2l (0xffffffffL) +#define BN_MASK2lh (0xffffffffL) +#define BN_MASK2h (0xffffffff00000000L) +#define BN_MASK2h1 (0xffffffff80000000L) +#define BN_TBIT (0x8000000000000000L) +#define BN_DEC_CONV (10000000000000000000UL) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%019lu" +#define BN_DEC_NUM 19 +#define BN_HEX_FMT "%016lX" +#endif + +/* This is where the long long data type is 64 bits, but long is 32. + * For machines where there are 64bit registers, this is the mode to use. + * IRIX, on R4000 and above should use this mode, along with the relevent + * assember code. Do NOT define BN_LLONG. + */ +#ifdef SIXTY_FOUR_BIT +#undef BN_LLONG /* Protect against config */ +/* #define BN_ULLONG unsigned long long */ +#ifdef WIN64 +#define BN_ULONG unsigned _int64 +#define BN_LONG _int64 +#else +#define BN_ULONG unsigned long long +#define BN_LONG long long +#endif +#define BN_BITS 128 +#define BN_BYTES 8 +#define BN_BITS2 64 +#define BN_BITS4 32 +#define BN_MASK2 (0xffffffffffffffffLL) +#define BN_MASK2l (0xffffffffL) +#define BN_MASK2lh (0xffffffffL) +#define BN_MASK2h (0xffffffff00000000LL) +#define BN_MASK2h1 (0xffffffff80000000LL) +#define BN_TBIT (0x8000000000000000LL) +#define BN_DEC_CONV (10000000000000000000ULL) +#ifdef WIN64 +#define BN_DEC_FMT1 "%I64u" +#define BN_DEC_FMT2 "%019I64u" +#define BN_DEC_NUM 19 +#define BN_HEX_FMT "%016I64X" +#else +#define BN_DEC_FMT1 "%llu" +#define BN_DEC_FMT2 "%019llu" +#define BN_DEC_NUM 19 +#define BN_HEX_FMT "%016llX" +#endif +#endif + +#ifdef SIXTY_BIT +#undef SIXTY_FOUR_BIT +#undef BN_LLONG /* Protect against config */ +/* #define BN_ULLONG unsigned long long */ +#define BN_ULONG unsigned long long +#define BN_LONG long long +#define BN_BITS 120 +#define BN_BITS2 60 +#define BN_BITS4 30 +#define BN_MASK2 (0x0fffffffffffffffLL) +#define BN_MASK2l ( 0x3fffffffL) +#define BN_MASK2lh ( 0x3fffffffL) +#define BN_MASK2h (0x0fffffffc0000000LL) +#define BN_MASK2h1 (0x0fffffffe0000000LL) +#define BN_TBIT (0x0800000000000000LL) +#define BN_DEC_CONV (100000000000000000LL) +#define BN_DEC_FMT1 "%9u" +#define BN_DEC_FMT2 "%017llu" +#define BN_DEC_NUM 17 +#define BN_HEX_FMT "%016llX" +#endif + +#ifdef THIRTY_TWO_BIT +#ifdef WIN32 +#if defined(__BORLANDC__) +#define BN_ULLONG unsigned __int64 +#else /* !__BORLANDC__ */ +#if defined(__MINGW32__) || defined(__DJGPP__) +#define BN_ULLONG unsigned long long +#else +#define BN_ULLONG unsigned _int64 +#endif /* __MINGW32__ || __DJGPP__ */ +#endif /* __BORLANDC__ */ +#else /* !WIN32 */ +#define BN_ULLONG unsigned long long +#endif /* WIN32 */ +#ifdef OPT_32_BIT_INT +#define BN_ULONG unsigned int +#define BN_LONG int +#else +#define BN_ULONG unsigned long +#define BN_LONG long +#endif +#define BN_BITS 64 +#define BN_BYTES 4 +#define BN_BITS2 32 +#define BN_BITS4 16 +/* This is needed because the Watcom compiler pre-processor + * under QNX tries to parses the 'LL' part even though it is + * never used. + */ +#ifdef BN_LLONG +#ifndef WIN32 +#define BN_MASK (0xffffffffffffffffLL) +#else +#define BN_MASK (0xffffffffffffffffL) +#endif +#endif +#define BN_MASK2 (0xffffffffL) +#define BN_MASK2l (0xffff) +#define BN_MASK2lh (0xffff) +#define BN_MASK2h1 (0xffff8000L) +#define BN_MASK2h (0xffff0000L) +#define BN_TBIT (0x80000000L) +#define BN_DEC_CONV (1000000000L) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%09lu" +#define BN_DEC_NUM 9 +#define BN_HEX_FMT "%08lX" +#endif + +#ifdef THIRTY_BIT +#ifdef WIN32 +#if defined(__MINGW32__) || defined(__DJGPP__) +#define BN_ULLONG unsigned long long +#else /* ! (__MINGW32__ || __DJGPP__) */ +#define BN_ULLONG unsigned _int64 +#endif /* __MINGW32__ || __DJGPP__ */ +#else /* !WIN32 */ +#define BN_ULLONG unsigned long long +#endif /* WIN32 */ +#define BN_ULONG unsigned long +#define BN_LONG long +#define BN_BITS 60 +#define BN_BITS2 30 +#define BN_BITS4 15 +/* This is needed because the Watcom compiler pre-processor + * under QNX tries to parses the 'LL' part even though it is + * never used. + */ +#ifdef BN_LLONG +#ifndef WIN32 +#define BN_MASK (0x0fffffffffffffffLL) +#else +#define BN_MASK (0x0fffffffffffffffL) +#endif +#endif +#define BN_MASK2 (0x3fffffffL) +#define BN_MASK2l (0x7fff) +#define BN_MASK2lh (0x7fff) +#define BN_MASK2h1 (0x3fffc000L) +#define BN_MASK2h (0x3fff8000L) +#define BN_TBIT (0x20000000L) +#define BN_DEC_CONV (1000000000L) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%09lu" +#define BN_DEC_NUM 9 +#define BN_HEX_FMT "%08lX" +#endif + +#ifdef SIXTEEN_BIT +#ifndef BN_DIV2W +#define BN_DIV2W +#endif +#define BN_ULLONG unsigned long +#define BN_ULONG unsigned short +#define BN_LONG short +#define BN_BITS 32 +#define BN_BYTES 2 +#define BN_BITS2 16 +#define BN_BITS4 8 +#define BN_MASK (0xffffffff) +#define BN_MASK2 (0xffff) +#define BN_MASK2l (0xff) +#define BN_MASK2lh (0xff) +#define BN_MASK2h1 (0xff80) +#define BN_MASK2h (0xff00) +#define BN_TBIT (0x8000) +#define BN_DEC_CONV (10000) +#define BN_DEC_FMT1 "%u" +#define BN_DEC_FMT2 "%04u" +#define BN_DEC_NUM 4 +#define BN_HEX_FMT "%04X" +#endif + +#ifdef TEST_EIGHT_BIT +#define EIGHT_BIT /* comment to stop editing */ +#endif + +#ifdef EIGHT_BIT +#undef BN_ILONG +#define BN_ILONG unsigned int +#ifndef BN_DIV2W +#define BN_DIV2W +#endif +#ifdef TEST_EIGHT_BIT +#define BN_ULLONG unsigned int +#define BN_ULONG unsigned int +#define BN_LONG int +#else +#define BN_ULLONG unsigned short +#define BN_ULONG unsigned char +#define BN_LONG char +#endif +#define BN_BITS 16 +#define BN_BYTES 1 +#define BN_BITS2 8 +#define BN_BITS4 4 +#define BN_MASK (0xffff) +#define BN_MASK2 (0xff) +#define BN_MASK2lh (0xf) +#define BN_MASK2l (0xf) +#define BN_MASK2h1 (0xf8) +#define BN_MASK2h (0xf0) +#define BN_TBIT (0x80) +#define BN_DEC_CONV (100) +#define BN_DEC_FMT1 "%u" +#define BN_DEC_FMT2 "%02u" +#define BN_DEC_NUM 2 +#define BN_HEX_FMT "%02X" +#endif + +#ifdef BIGNUM +#undef BIGNUM +#endif + +#define BN_FLG_MALLOCED 0x01 +#define BN_FLG_STATIC_DATA 0x02 +#define BN_FLG_FREE 0x8000 /* used for debuging */ +#define BN_CTX_FLG_ABORT 0x4000 /* used for aborting RSA operations*/ +#define BN_set_flags(b,n) ((b)->flags|=(n)) +#define BN_get_flags(b,n) ((b)->flags&(n)) +#define BN_CTX_set_flags(b,n) ((b)->flags|=(n)) +#define BN_CTX_get_flags(b,n) ((b)->flags&(n)) + +#ifndef HEADER_COMMON_BN_H_TYPEDEF_DEF +#define HEADER_COMMON_BN_H_TYPEDEF_DEF +typedef struct bignum_st BIGNUM; +typedef struct bignum_ctx BN_CTX; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct bn_recp_ctx_st BN_RECP_CTX; +typedef struct bn_prime_ctx_st BN_PRIME_CTX; +typedef struct bn_blind_ctx_st BN_BLIND_CTX; +typedef struct bn_blind_meth_st BN_BLIND_METH; +#endif + +typedef struct bn_mod_exp_meth_st BN_ME_METH; +typedef struct bn_mod_exp_ctx_st BN_ME_CTX; + + +/* The data array d must always have an extra 'valid' word in location + * bn->d[bn->max]. It must be ok for reading. This is needed if + * BN_MUL_LATENCY is defined. + */ +struct bignum_st + { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int max; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; + }; + +/* Used for temp variables */ +#define BN_CTX_NUM 12 +struct bignum_ctx + { + int tos; + BIGNUM bn[BN_CTX_NUM+1]; + int flags; + R_SURRENDER *surrender; + }; + +#if defined(WIN64) || defined(__ia64__) || defined(CPU_IA64) +#define BN_USHORT unsigned int +#else +#define BN_USHORT unsigned short +#endif + +/* Used for prime number generation */ +struct bn_prime_ctx_st + { + BN_USHORT *primes; + BN_USHORT *mods; + int num_primes; + int prime_checks; + R_SURRENDER *surrender; + R_RANDOM *random; + int flags; + }; + +struct bn_blind_ctx_st + { + int init; + BN_BLIND_METH *meth; + BIGNUM B; + BIGNUM Bi; + BIGNUM mod; + }; + +struct bn_blind_meth_st + { + void (*init) (BN_BLIND_CTX *); + void (*ctx_free)(BN_BLIND_CTX *); + int (*set) (BN_BLIND_CTX *,R_RANDOM *,BIGNUM *,BIGNUM *, BN_ME_CTX *,BN_CTX *); + int (*convert) (BN_BLIND_CTX *,BIGNUM *,BN_CTX *); + int (*invert) (BN_BLIND_CTX *,BIGNUM *,BN_CTX *); + int (*update) (BN_BLIND_CTX *,BN_CTX *); + int (*copy) (BN_BLIND_CTX *,BN_BLIND_CTX *); + }; + +/* Used for montgomery multiplication */ +struct bn_mont_ctx_st + { + int use_word; /* 0 for word form, 1 for long form */ + int ri; /* number of bits in R */ + int riw; /* number of words in R */ + BIGNUM RR; /* used to convert to montgomery form */ + BIGNUM N; /* The modulus */ + BIGNUM Ni; /* The inverse of N */ + BN_ULONG n0; /* word form of inverse, normally only one of + * Ni or n0 is defined */ + int flags; + }; + +/* Used by the recursive exponentiation implementations */ +typedef struct bn_mod_exp_rec_meth_st + { +#ifndef NOPROTO + void (PRE_CCONV CCONV *mul)(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); + void (PRE_CCONV CCONV *sqr)(BN_ULONG *r, BN_ULONG *a); + void (PRE_CCONV CCONV *low_mul)(); +#else + void (PRE_CCONV CCONV *mul)(); + void (PRE_CCONV CCONV *sqr)(); + void (PRE_CCONV CCONV *low_mul)(); +#endif + } BN_MOD_EXP_REC_METH; + +/* If this flag is set, if there is a custom method for a modulus + * two times larger, use it. This is mostly mean for use on the + * itanium where a 512*512 routine is 10 times faster than the C + * code version, so we need to detect that we can turn of CRT + * for RSA if there is an native IA64 512*512 present. + */ +#define BN_ME_FLG_FAST_ASM 0x0001 + +struct bn_mod_exp_meth_st + { + int num; /* Word size we target */ + char *name; /* Identify the method */ +#ifndef NOPROTO + int (*useit)(const BN_ME_METH *meth); + /* If 'power' is null, reuse the old one */ + int (*mod_exp)(BN_ME_CTX *mctx,BIGNUM *r,BIGNUM *a,BIGNUM *p, + BN_CTX *ctx); + /* Create the BN_ME_CTX */ + int (*init_ctx)(const BN_ME_METH *meth,BN_ME_CTX **mctx); + /* Get rid of it */ + int (*free_ctx)(BN_ME_CTX *mctx); + /* Assign the modulus */ + int (*set)(BN_ME_CTX *mctx,BIGNUM *n,int cmd,int flags,BN_CTX *ctx); +#else + int (*useit)(); + int (*mod_exp)(); + int (*init_ctx)(); + int (*free_ctx)(); + int (*set)(); +#endif + int argi; + char *argp; /* 'Extra stuff' */ + }; + +#define BN_ME_METH_TABLE_MAX 32 +/* Used in BN_library_init */ +#define BN_INIT_LAST 0x00 +#define BN_INIT_BN_ME_METH 0x01 + +#define BN_BNME_F_DEFAULT 0x01 +/* Used only when loading, kept as bits internally, normally loaded as + * words */ +#define BN_BNME_F_BITS 0x02 +typedef struct bn_me_meth_info_st + { +#ifndef NOPROTO + const BN_ME_METH *(*meth)(void); +#else + const BN_ME_METH *(*meth)(); +#endif + int min; + int max; + int flags; + } BN_ME_METH_INFO; + +#define BN_ME_SET_MOD 0x01 +#define BN_ME_SET_BASE 0x02 +#define BN_ME_SET_EXP 0x03 +#define BN_ME_SET_FLG_NO_LOOKUP 0x01 /* Passed to BN_ME_CTX_set() */ + +#define BN_FLG_CACHE 0x10 /* Cache values */ +#define BN_ME_FLG_BASE 0x40 /* base has been cached */ +#define BN_ME_FLG_EXP 0x80 /* power has been cached */ +/* When one of these structures is setup, it is intended that the + * base or power, if not null, will be used for the current calculation. + * If the base and/or power are cached, they will only be used if the input + * value is null. + * For RSA, the power would normally be set. + * For DH, the base and power would be set. The initial value generated + * would be the public key, which is exchanged. The phase2 part would + * change the base but not the power. + * For DSA signing, a fixed base is used, but a random power. + * For DSA verification, there are two bases and two powers, + * a^p%m * b^q%m + * One way to implement this is to use a special function to + * generate a composite power value, and or a special base form. + * The other option is to have a special function to generate + * the 'base' array. The problem is that we are exponentiating with + * a 3 value power value, instead of the normal two. It should be possible + * to use the standard a^b%m function. + */ +struct bn_mod_exp_ctx_st + { + const BN_ME_METH *meth; + char *callback; + char *cb_arg; + int flags; + /* Evil hack for storage of data values, it should really be here + * other than the first value */ + char *modulus; /* eg BN_MONT_CTX */ + char *power; /* eg power representation */ + char *base; /* eg base representation */ + char *arg; + }; + +/* Used for reciprocal division/mod functions + * It cannot be shared between threads + */ +struct bn_recp_ctx_st + { + BIGNUM N; /* the divisor */ + BIGNUM Nr; /* the reciprocal */ + int num_bits; + int shift; + int flags; + }; + +typedef struct bn_rec_st + { + int depth; + int n; +#ifndef NOPROTO + void (PRE_CCONV CCONV *mul)(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); + void (PRE_CCONV CCONV *sqr)(BN_ULONG *r, BN_ULONG *a); + void (PRE_CCONV CCONV *low_mul)(); +#else + void (PRE_CCONV CCONV *mul)(); + void (PRE_CCONV CCONV *sqr)(); + void (PRE_CCONV CCONV *low_mul)(); +#endif + } BN_REC; + +#define BN_to_montgomery(r,a,mont,ctx) BN_mod_mul_montgomery(\ + r,a,&((mont)->RR),(mont),ctx) + +#define BN_prime_checks (5) + +#define BN_num_bytes(a) ((BN_num_bits(a)+7)/8) +#define BN_length(a) ((a)->top * BN_BYTES) +#define BN_is_word(a,w) (((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) +#define BN_is_zero(a) (((a)->top == 0) || BN_is_word(a,0)) +#define BN_is_one(a) (BN_is_word((a),1)) +#define BN_is_odd(a) (((a)->top > 0) && ((a)->d[0] & 1)) +#define BN_one(a) (BN_set_word((a),(BN_ULONG)1)) +#define BN_zero(a) (BN_set_word((a),(BN_ULONG)0)) + +/*#define BN_ascii2bn(a) BN_hex2bn(a) */ +/*#define BN_bn2ascii(a) BN_bn2hex(a) */ + +#define bn_expand(n,b) ((((((b+BN_BITS2-1))/BN_BITS2)) <= (n)->max)?\ + (n):bn_expand2((n),(b)/BN_BITS2+1)) +#define bn_wexpand(n,b) (((b) <= (n)->max)?(n):bn_expand2((n),(b))) + +#ifdef SMALL_CODE_SIZE +void bn_zexpand(BIGNUM *a,int n); +void bn_fix_top(BIGNUM *a); +#else +#define bn_zexpand(a,n) \ + if ((a)->top < n) \ + { \ + int i; \ + bn_wexpand((a),n); \ + if ((a)->d!=NULL) \ + { \ + for (i=(a)->top; id[i]=0; \ + } \ + } + +#define bn_fix_top(a) \ + { \ + BN_ULONG *ftl; \ + if ((a)->top > 0) \ + { \ + for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \ + if (*(ftl--)) break; \ + } \ + } +#endif + +#define BN_MONT_CTX_set(a,b,c) BN_MONT_CTX_set_word((a),(b),(c)) + +#ifndef NOPROTO + + +const BN_ME_METH *BN_ME_METH_word(void); +const BN_ME_METH *BN_ME_METH_full(void); + +#if (defined(BN_MUL_COMBA) || defined(BN_SQR_COMBA)) + +/* word4 - used for 64bit multiprime*/ +const BN_ME_METH *BN_ME_METH_word4(void); +const BN_ME_METH *BN_ME_METH_rec4_word8(void); +const BN_ME_METH *BN_ME_METH_rec4_word16(void); +const BN_ME_METH *BN_ME_METH_rec4_word32(void); +const BN_ME_METH *BN_ME_METH_rec4_word64(void); +const BN_ME_METH *BN_ME_METH_rec4_word128(void); + +/* word6 - used for 64bit multiprime*/ +const BN_ME_METH *BN_ME_METH_word6(void); +const BN_ME_METH *BN_ME_METH_rec6_word12(void); +const BN_ME_METH *BN_ME_METH_rec6_word24(void); +const BN_ME_METH *BN_ME_METH_rec6_word48(void); +const BN_ME_METH *BN_ME_METH_rec6_word96(void); + +const BN_ME_METH *BN_ME_METH_word8(void); +const BN_ME_METH *BN_ME_METH_rec8_word16(void); +const BN_ME_METH *BN_ME_METH_rec8_word32(void); +const BN_ME_METH *BN_ME_METH_rec8_word64(void); +const BN_ME_METH *BN_ME_METH_rec8_word128(void); +const BN_ME_METH *BN_ME_METH_rec8_word256(void); + +const BN_ME_METH *BN_ME_METH_word11(void); +const BN_ME_METH *BN_ME_METH_rec11_word22(void); +const BN_ME_METH *BN_ME_METH_rec11_word44(void); +const BN_ME_METH *BN_ME_METH_rec11_word88(void); + +const BN_ME_METH *BN_ME_METH_word16(void); +const BN_ME_METH *BN_ME_METH_rec16_word32(void); +const BN_ME_METH *BN_ME_METH_rec16_word64(void); +const BN_ME_METH *BN_ME_METH_rec16_word128(void); +const BN_ME_METH *BN_ME_METH_rec16_word256(void); + +#endif + +#ifdef CPU_IA64 +const BN_ME_METH *BN_ME_METH_ia64_384(void); +const BN_ME_METH *BN_ME_METH_ia64_512(void); +const BN_ME_METH *BN_ME_METH_ia64_1024(void); +#endif + +#if (defined(CPU_SPARC_V8PLUS) || defined (CPU_SPARC_V9)) +const BN_ME_METH *BN_ME_METH_usparc(void); +const BN_ME_METH *BN_ME_METH_usparc_352(void); +const BN_ME_METH *BN_ME_METH_usparc_512(void); +#endif + +#if 1 || defined(CPU_X86) +const BN_ME_METH *BN_ME_METH_pentium4_29(void); +const BN_ME_METH *BN_ME_METH_pentium4_28(void); +#endif + +/* NCipher Nfast hardware accelerator method prototype */ +const BN_ME_METH *BN_ME_METH_nfast(void); + + +BIGNUM *BN_value_one(void); +const char * BN_options(void); +BN_CTX *BN_CTX_new(void); +void BN_CTX_init(BN_CTX *c); +void BN_CTX_free(BN_CTX *c); +#ifndef NO_BN_RAND +int BN_rand(BIGNUM *rnd, R_RANDOM *rand, int bits, int top,int bottom); +#endif +int BN_num_bits(BIGNUM *a); +int BN_num_bits_word(BN_ILONG); +BIGNUM *BN_new(void); +void BN_init(BIGNUM *); +void BN_clear_free(BIGNUM *a); +BIGNUM *BN_copy(BIGNUM *a, BIGNUM *b); +BIGNUM *BN_bin2bn(unsigned char *s,int len,BIGNUM *ret); +int BN_bn2bin(BIGNUM *a, unsigned char *to); +BIGNUM *BN_mpi2bn(unsigned char *s,int len,BIGNUM *ret); +int BN_bn2mpi(BIGNUM *a, unsigned char *to); +int BN_sub(BIGNUM *r, BIGNUM *a, BIGNUM *b); +int BN_usub(BIGNUM *r, BIGNUM *a, BIGNUM *b); +int BN_uadd(BIGNUM *r, BIGNUM *a, BIGNUM *b); +int BN_add(BIGNUM *r, BIGNUM *a, BIGNUM *b); +int BN_mod(BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx); +int BN_div(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx); +int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b,BN_CTX *ctx); +int BN_sqr(BIGNUM *r, BIGNUM *a,BN_CTX *ctx); +BN_ULONG BN_mod_word(BIGNUM *a, BN_ULONG w); +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w); +int BN_mul_word(BIGNUM *a, BN_ULONG w); +int BN_add_word(BIGNUM *a, BN_ULONG w); +int BN_sub_word(BIGNUM *a, BN_ULONG w); +int BN_set_word(BIGNUM *a, BN_ULONG w); +BN_ULONG BN_get_word(BIGNUM *a); +int BN_cmp(BIGNUM *a, BIGNUM *b); +void BN_free(BIGNUM *a); +int BN_is_bit_set(BIGNUM *a, int n); +int BN_lshift(BIGNUM *r, BIGNUM *a, int n); +int BN_lshift1(BIGNUM *r, BIGNUM *a); +int BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p,BN_CTX *ctx); +int BN_mod_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx); +int BN_mod_exp_mont(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx, + BN_MONT_CTX *m_ctx); +int BN_mod_exp2_mont(BIGNUM *r, BIGNUM *a1, BIGNUM *p1,BIGNUM *a2, + BIGNUM *p2,BIGNUM *m,BN_CTX *ctx,BN_MONT_CTX *m_ctx); +int BN_mod_exp_simple(BIGNUM *r, BIGNUM *a, BIGNUM *p, + BIGNUM *m,BN_CTX *ctx); +int BN_mask_bits(BIGNUM *a,int n); +int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, BIGNUM *m, + BN_CTX *ctx); +#if !defined(WIN16) && !defined(NO_FP_API) +int BN_print_fp(FILE *fp, BIGNUM *a); +#endif +#ifdef HEADER_COMMON_BIO_H +int BN_print(BIO *fp, BIGNUM *a); +#else +/* int BN_print(char *fp, BIGNUM *a); */ +#endif +int BN_reciprocal(BIGNUM *r, BIGNUM *m, int len, BN_CTX *ctx); +int BN_rshift(BIGNUM *r, BIGNUM *a, int n); +int BN_rshift1(BIGNUM *r, BIGNUM *a); +void BN_clear(BIGNUM *a); +BIGNUM *bn_expand2(BIGNUM *b, int bits); +BIGNUM *BN_dup(BIGNUM *a); +int BN_ucmp(BIGNUM *a, BIGNUM *b); +int BN_set_bit(BIGNUM *a, int n); +int BN_clear_bit(BIGNUM *a, int n); +char * BN_bn2hex(BIGNUM *a); +char * BN_bn2dec(BIGNUM *a); +int BN_hex2bn(BIGNUM **a,char *str); +int BN_dec2bn(BIGNUM **a,char *str); +int BN_gcd(BIGNUM *r,BIGNUM *in_a,BIGNUM *in_b,BN_CTX *ctx); +BIGNUM *BN_mod_inverse(BIGNUM *ret,BIGNUM *a, BIGNUM *n,BN_CTX *ctx); +/* Return R, where it is R*(1< +#include +//#include "r_error.h" +//#include "err.h" +#include + +#ifndef STANDALONE +#include "r_com.h" +#else +#define NO_STDLIB_MAPPING +#define Malloc(a) malloc(a) +#define Free(a) free(a) +#define Memset(a,b,c) memset(a,b,c) +#define Memcpy(a,b,c) memcpy(a,b,c) +#endif + +/* TEMP FIX */ +#undef BNerr +#define BNerr(a,b) +#include "bn.h" + +#define BN_EXP_TABLE_SIZE 16 + +/* see the bn_limit_ fields which are the start of a runtime + * tunable set of values to match these fixed compile-time constants + */ +/* Pentium pro 16,16,16,32,64 */ +/* Alpha 16,16,16,16.64 */ +/* StrongARM */ +#define BN_MULL_SIZE_NORMAL (16) /* 32 */ +#define BN_MUL_RECURSIVE_SIZE_NORMAL (16) /* 32 */ /* less than */ +#define BN_SQR_RECURSIVE_SIZE_NORMAL (16) /* 32 */ +#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */ +#define BN_MONT_CTX_SET_SIZE_WORD (64) /* 32 */ + +/************************************************************* + * Using the long long type + */ +#define Lw(t) (((BN_ULONG)(t))&BN_MASK2) +#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2) + +/* These are used for internal error checking and are not normally used */ +#ifdef BN_DEBUG +#define bn_check_top(a) \ + { if ( ((a)->top < 0) || \ + ((a)->top > (a)->max) || \ + (((a)->top == 0) && (a)->neg) || \ + (((a)->top == 1) && (a->d[0] == 0))) \ + { char *nullp=NULL; *nullp='z'; } } +#define bn_check_num(a) if ((a) < 0) { char *nullp=NULL; *nullp='z'; } +#define bn_assert(a) if (!(a)) { char *nullp=NULL; *nullp='z'; } +#define bn_set_used_check(l,size,num) bn_su_check(l,size,num) +#ifdef BN_DEBUG2 +#define bn_do_used_check(fp,str,l,size,num) bn_du_check(fp,str,l,size,num) +#else +#define bn_do_used_check(fp,str,l,size,num) +#endif +#else +#define bn_assert(a) +#define bn_check_top(a) +#define bn_check_num(a) +#define bn_set_used_check(l,size,num) +#define bn_do_used_check(fp,str,l,size,num) +#endif + + +/*********************************************** +* IA64 32 bit build SWIZZLE code +* This essentially casts our points which are +* 32bits under abi32 to 64bit unsigned long +* longs and then grabs the top two bits of the +* pointer and places it in the 2nd and 3rd bits +* of the unsigned long long. +**********************************************/ +#ifdef HPUX_IA64_32 +#define SWIZLLE(VALUE) ((((unsigned long long)(VALUE) & 0xc0000000LL) <<31)\ +|((unsigned long long)(VALUE))) +#else +#define SWIZZLE(VALUE) (VALUE) +#endif + +#define bn_neg_words(a,n) \ + { \ + int iii; \ + \ + for (iii=0; iiimax=(r)->top,BN_set_flags((r),BN_FLG_STATIC_DATA)) +#else +#define bn_set_max(r) +#endif + +/* These macros are used to 'take' a section of a bignum for read only use */ +#define bn_set_low(r,a,n) \ + { \ + (r)->top=((a)->top > (n))?(n):(a)->top; \ + (r)->d=(a)->d; \ + (r)->neg=(a)->neg; \ + (r)->flags|=BN_FLG_STATIC_DATA; \ + bn_set_max(r); \ + } + +#define bn_set_high(r,a,n) \ + { \ + if ((a)->top > (n)) \ + { \ + (r)->top=(a)->top-n; \ + (r)->d= &((a)->d[n]); \ + } \ + else \ + (r)->top=0; \ + (r)->neg=(a)->neg; \ + (r)->flags|=BN_FLG_STATIC_DATA; \ + bn_set_max(r); \ + } + +/* #define bn_expand(n,b) ((((b)/BN_BITS2) <= (n)->max)?(n):bn_expand2((n),(b))) */ + +#ifdef BN_LLONG +#define mul_add(r,a,w,c) { \ + BN_ULLONG t; \ + t=(BN_ULLONG)w * (a) + (r) + (c); \ + (r)= Lw(t); \ + (c)= Hw(t); \ + } + +#define mul(r,a,w,c) { \ + BN_ULLONG t; \ + t=(BN_ULLONG)w * (a) + (c); \ + (r)= Lw(t); \ + (c)= Hw(t); \ + } + +#else +/************************************************************* + * No long long type + */ + +#define LBITS(a) ((a)&BN_MASK2l) +#define HBITS(a) (((a)>>BN_BITS4)&BN_MASK2lh) +#define L2HBITS(a) ((BN_ULONG)((a)&BN_MASK2lh)<>(BN_BITS4-1); \ + m =((m&BN_MASK2l)<<(BN_BITS4+1))&BN_MASK2; \ + l=(l+m)&BN_MASK2; if (l < m) h++; \ + (lo)=l; \ + (ho)=h; \ + } + +#if 0 +#define mul_add(r,a,bl,bh,b_hl,c) { \ + BN_ULONG l,h; \ + BN_ULONG lt,mt; \ + \ + h= (a); \ + l=LBITS(h); \ + h=HBITS(h); \ + mt=bl*l; \ + lt=mt+c+(r); \ + c=bh*h; \ + mt+=c+(l-h)*b_hl; \ + mt+=(lt>>BN_BITS4); \ + (r)=(lt&BN_MASK2l)|((mt&BN_MASK2l)<>BN_BITS4); \ + } +#else /* Normal version */ +#define mul_add(r,a,bl,bh,b_hl,c) { \ + BN_ULONG l,h; \ + \ + h= (a); \ + l=LBITS(h); \ + h=HBITS(h); \ + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ + l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ + (c)=(r); \ + l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ + (c)=h&BN_MASK2; \ + (r)=l; \ + } +#endif + +#define mul(r,a,bl,bh,c) { \ + BN_ULONG l,h; \ + \ + h= (a); \ + l=LBITS(h); \ + h=HBITS(h); \ + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ + l+=(c); if ((l&BN_MASK2) < (c)) h++; \ + (c)=h&BN_MASK2; \ + (r)=l&BN_MASK2; \ + } + +#endif + +#ifndef BN_MUL_COMBA +#define bn_mul_comba4(r,a,b) bn_mul_normal(r,a,4,b,4) +#define bn_mul_comba5(r,a,b) bn_mul_normal(r,a,5,b,5) +#define bn_mul_comba6(r,a,b) bn_mul_normal(r,a,6,b,6) +#define bn_mul_comba8(r,a,b) bn_mul_normal(r,a,8,b,8) +#define bn_mul_comba11(r,a,b) bn_mul_normal(r,a,11,b,11) +#define bn_mul_comba12(r,a,b) bn_mul_normal(r,a,12,b,12) +#define bn_mul_comba16(r,a,b) bn_mul_normal(r,a,16,b,16) +#endif +#if 1 +#ifndef BN_SQR_COMBA +#define bn_sqr_comba4(r,a) bn_mul_normal(r,a,4,a,4) +#define bn_sqr_comba5(r,a) bn_mul_normal(r,a,5,a,5) +#define bn_sqr_comba6(r,a) bn_mul_normal(r,a,6,a,6) +#define bn_sqr_comba8(r,a) bn_mul_normal(r,a,8,a,8) +#define bn_sqr_comba11(r,a) bn_mul_normal(r,a,11,a,11) +#define bn_sqr_comba12(r,a) bn_mul_normal(r,a,12,a,12) +#define bn_sqr_comba16(r,a) bn_mul_normal(r,a,16,a,16) +#endif +#else +#ifndef BN_SQR_COMBA +#define bn_sqr_comba4(r,a) bn_mul_comba4(r,a,a) +#define bn_sqr_comba5(r,a) bn_mul_comba5(r,a,a) +#define bn_sqr_comba6(r,a) bn_mul_comba6(r,a,a) +#define bn_sqr_comba8(r,a) bn_mul_comba8(r,a,a) +#define bn_sqr_comba11(r,a) bn_mul_comba11(r,a,a) +#define bn_sqr_comba12(r,a) bn_mul_comba12(r,a,a) +#define bn_sqr_comba16(r,a) bn_mul_comba16(r,a,a) +#endif +#endif +#ifndef BN_REDUCE_COMBA +#define r0_bn_mont_comba4(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba5(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba6(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba8(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba11(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba12(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#define r0_bn_mont_comba16(r,a,n,num,n0) bn_from_montgomery_words(r,a,n,num,n0) +#endif + +#ifndef NOPROTO + +BIGNUM *bn_expand2(BIGNUM *b, int bits); + +#ifdef X86_ASM +void bn_add_words(BN_ULONG *r,BN_ULONG *a,int num); +#endif + +#else + +BIGNUM *bn_expand2(); +#ifdef X86_ASM +BN_ULONG bn_add_words(); +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_COMMON_BN_LCL_H */ + +void bn_mul_low_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,BN_ULONG *t); +void bn_mul_high(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,BN_ULONG *l,int n2, BN_ULONG *t); +int BN_gen_exp_string(unsigned char *str, BIGNUM *p, int bits); +void bn_from_montgomery_rec_full(BN_ULONG *rp, BN_ULONG *ap, + BN_ULONG *np, BN_ULONG *nip, BN_ULONG *tmp,BN_REC *rec); + +int bn_mont_ctx_new_word(const BN_ME_METH *meth, BN_ME_CTX **retp); + diff --git a/build/tools/acsign/include/bn_thx.h b/build/tools/acsign/include/bn_thx.h new file mode 100644 index 0000000..13e157b --- /dev/null +++ b/build/tools/acsign/include/bn_thx.h @@ -0,0 +1,301 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +/***************************************************************************** + * Copyright (c). 2001 RSA Security Inc. All rights reserved. + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + ****************************************************************************/ +/** + * @file bn_thx.h + * @brief header file created for used as interface defines for systems + * containing hetergeneous environments where some bn operations + * will be performed in isolation from the rest of the library + */ +#ifndef HEADER_COMMON_BN_THX_H +#define HEADER_COMMON_BN_THX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* These defines are required on systems so that the mod_exp code + * to be used in isolation from the bn operation with library will work, + * if these are not available, the header files with equivalent functionality + * should be added inside a CPU or Operating system define + */ +#ifndef NO_STDIO_H +#include +#endif + +#ifndef NO_STDLIB_H +#include +#endif + +#ifndef NO_STRING_H +#include +#endif + +/* Interface for ARM/DSP systems, this interface requires only + * the standard defines and includes at the moment + */ +#ifdef CPU_TMS320 +#define THX_RECIPIENT +#define CPU_DSP +#endif + +#ifdef THX_RECIPIENT + +#ifndef restrict +#define restrict +#endif + +#ifndef Malloc +#define Malloc malloc +#endif + +#ifndef Memcpy +#define Memcpy memcpy +#endif + +#ifndef Memmove +#define Memmove memmove +#endif + +#ifndef Memset +#define Memset memset +#endif + +#ifndef Free +#define Free free +#endif + +#endif /* THX_RECIPIENT */ + +#ifndef THX_RECIPIENT /* not the recipient, we must be the caller */ + +#include "bn_lcl.h" + +#endif /* ! THX_RECIPIENT */ + +/* The follow define protected inclusions are excerpts from the + * header file bn.h, this has been done, so that code written for the + * THX systems can be used in isolation from the library + * This code may need to be updated in line with changes to the bn.h + * header file. + */ +#ifndef HEADER_COMMON_BN_H +#define HEADER_COMMON_BN_H + +#if !defined(CCONV) +#define CCONV +#endif + +#ifndef PRE_CCONV +#define PRE_CCONV +#endif + +/* convert from the new to the old option names */ +#if defined(OPT_BN_LLONG) +#define BN_LLONG /* comment to make sure Configure leaves this alone */ +#endif + +#if defined(OPT_32_BIT_INT) || defined(OPT_32_BIT) +#define THIRTY_TWO_BIT +#endif + +#define BN_ILONG BN_ULONG + +#ifdef THIRTY_TWO_BIT +#define BN_ULLONG unsigned long long +#ifdef OPT_32_BIT_INT +#define BN_ULONG unsigned int +#define BN_LONG int +#else +#define BN_ULONG unsigned long +#define BN_LONG long +#endif +#define BN_BITS 64 +#define BN_BYTES 4 +#define BN_BITS2 32 +#define BN_BITS4 16 +/* This is needed because the Watcom compiler pre-processor + * under QNX is perverted and tries to parses the 'LL' + * part even though it is never used. + */ +#ifdef BN_LLONG +#define BN_MASK (0xffffffffffffffffL) +#endif +#define BN_MASK2 (0xffffffffL) +#define BN_MASK2l (0xffff) +#define BN_MASK2lh (0xffff) +#define BN_MASK2h1 (0xffff8000L) +#define BN_MASK2h (0xffff0000L) +#define BN_TBIT (0x80000000L) +#define BN_DEC_CONV (1000000000L) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%09lu" +#define BN_DEC_NUM 9 +#define BN_HEX_FMT "%08lX" +#endif + +#define BN_EXP_TABLE_SIZE 16 + +typedef struct bignum_st BIGNUM; + +struct bignum_st + { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int max; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; + }; + +PRE_CCONV BN_ULONG CCONV bn_mul_add_words(BN_ULONG *rp,BN_ULONG *ap, + int num, BN_ULONG w); +PRE_CCONV BN_ULONG CCONV bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, + int num, BN_ULONG w); +PRE_CCONV void CCONV bn_sqr_words(BN_ULONG *rp, BN_ULONG *ap, int num); +BN_ULONG CCONV bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d); +PRE_CCONV BN_ULONG CCONV bn_add_words(BN_ULONG *rp, BN_ULONG *ap, + BN_ULONG *bp,int num); +PRE_CCONV BN_ULONG CCONV bn_sub_words(BN_ULONG *rp, BN_ULONG *ap, + BN_ULONG *bp,int num); + +#ifndef BN_ME_METH +#define BN_ME_METH void +#endif + +#endif /* ! HEADER_COMMON_BN_H */ + +/* The follow define protected inclusions are excerpts from the + * header file r_error.h, this has been done, so that code written for the + * THX systems can be used in isolation from the library + * This code may need to be updated in line with changes to the r_error.h + * header file. + */ +#ifndef HEADER_COMMON_R_ERROR_H +#define HEADER_COMMON_R_ERROR_H + +/* The FATAL_INTERNAL_ERROR is a flag that is set with the following + * error codes: + * R_ERROR_INVALID_STATE + * R_ERROR_INIT_NOT_CALLED + * R_ERROR_SHOULD_NOT_HAVE_BEEN_CALLED + */ +#define R_ERROR_FATAL_INTERNAL_ERROR 64 + +/* The BAD_PARAMETER is a flag that is set with the following error + * codes: + * R_ERROR_NULL_ARG + * R_ERROR_BUFFER_TOO_SMALL + * R_ERROR_BAD_VALUE + * R_ERROR_BAD_RANGE + * R_ERROR_BAD_FORMAT + * R_ERROR_BAD_TYPE + * R_ERROR_BAD_DATA + * R_ERROR_BAD_LENGTH + */ +#define R_ERROR_BAD_PARAMETER 32 + +/* Base value for all general errors used through all products */ +#define R_ERROR_BASE 10000 + +#define R_ERROR_NONE 0 + +#define R_ERROR_FAILED (R_ERROR_BASE+1) +#define R_ERROR_IO (R_ERROR_BASE+2) +#define R_ERROR_PROTOCOL (R_ERROR_BASE+3) +#define R_ERROR_EOF (R_ERROR_BASE+4) +#define R_ERROR_ALLOC_FAILURE (R_ERROR_BASE+5) +#define R_ERROR_EVAL_RESTRICTION (R_ERROR_BASE+6) +#define R_ERROR_EVAL_EXPIRED (R_ERROR_BASE+7) +#define R_ERROR_NOT_FOUND (R_ERROR_BASE+8) +#define R_ERROR_NOT_AVAILABLE (R_ERROR_BASE+9) +#define R_ERROR_NOT_IMPLEMENTED (R_ERROR_BASE+10) +#define R_ERROR_NOT_SUPPORTED (R_ERROR_BASE+11) +#define R_ERROR_INVALID_STATE \ + ((R_ERROR_BASE+12) | R_ERROR_FATAL_INTERNAL_ERROR) +#define R_ERROR_INIT_NOT_CALLED \ + ((R_ERROR_BASE+13) | R_ERROR_FATAL_INTERNAL_ERROR) +#define R_ERROR_SHOULD_NOT_HAVE_BEEN_CALLED \ + ((R_ERROR_BASE+14) | R_ERROR_FATAL_INTERNAL_ERROR) +#define R_ERROR_METHOD_UNDEFINED \ + ((R_ERROR_BASE+15) | R_ERROR_FATAL_INTERNAL_ERROR) +#define R_ERROR_BUFFER_TOO_SMALL \ + ((R_ERROR_BASE+16) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_NULL_ARG ((R_ERROR_BASE+17) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_VALUE ((R_ERROR_BASE+18) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_RANGE ((R_ERROR_BASE+19) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_FORMAT ((R_ERROR_BASE+20) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_TYPE ((R_ERROR_BASE+21) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_DATA ((R_ERROR_BASE+22) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_BAD_LENGTH ((R_ERROR_BASE+23) | R_ERROR_BAD_PARAMETER) +#define R_ERROR_RCOM_LIBRARY_NOT_SUPPORTED (R_ERROR_BASE+24) + +/* Resource Manager base for errors */ +#define R_COM_ERR_LIB_CTX_BASE 10100 + +#endif /* HEADER_COMMON_R_ERROR_H */ + + +const BN_ME_METH *BN_ME_METH_thxc(void); +/** + * @note THX code only needs to store rr, n0, str + * + */ +typedef struct thxc_mont_ctx_st + { + BIGNUM *rr; + unsigned char *str; + unsigned int str_len; + BN_ULONG n0; + } THXC_MONT_CTX; + + +int Rx_thxr_mod_exp_mont( BN_ULONG *result, BN_ULONG *ap, BN_ULONG *np, + BN_ULONG *rrp, BN_ULONG n0, int top, int tmp_len, unsigned char *str); + +int Ri_thxr_mod_exp_mont( BN_ULONG *result, BN_ULONG *ap, BN_ULONG *np, + BN_ULONG *rrp, BN_ULONG *dp, BN_ULONG *aap, BN_ULONG *rp, BN_ULONG *tmp, + BN_ULONG n0, int top, unsigned char *str); + +void Ri_thxr_mul_normal(BN_ULONG *r,BN_ULONG *a,int na,BN_ULONG *b,int nb); +void Ri_thxr_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp); + +void Ri_thxr_from_montgomery_words(BN_ULONG *ret,BN_ULONG *ap,BN_ULONG *np, + int w, BN_ULONG n0); + +BN_ULONG Ri_thxr_from_mont_words(BN_ULONG *ap,BN_ULONG *wap, + BN_ULONG *np, int w, BN_ULONG n0); + +#ifdef CPU_TMS320 + +/* Method and functions required for the ARM/DSP interface */ + +const BN_ME_METH *BN_ME_METH_dspc(void); + +int Rx_dsp_mod_exp_mont( BN_ULONG *result, BN_ULONG *ap, BN_ULONG *np, + BN_ULONG *rrp, BN_ULONG n0, int top, int tmp_len, unsigned char *str); + +int Ri_dsp_mod_exp_mont( BN_ULONG *result, BN_ULONG *ap, BN_ULONG *np, + BN_ULONG *rrp, BN_ULONG *dp, BN_ULONG *aap, BN_ULONG *rp, BN_ULONG *tmp, + BN_ULONG n0, int top, unsigned char *str); + +#endif + +#ifdef __cplusplus +} +#endif +#endif /* HEADER_COMMON_BN_THX_H */ diff --git a/build/tools/acsign/include/r_error.h b/build/tools/acsign/include/r_error.h new file mode 100644 index 0000000..8e269f3 --- /dev/null +++ b/build/tools/acsign/include/r_error.h @@ -0,0 +1,210 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +/** + * @file r_error.h + * This file contains the error definitions for the toolkit. + */ +#ifndef HEADER_COMMON_R_ERROR_H +#define HEADER_COMMON_R_ERROR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup R_ERROR_IDS Error Identifiers + * This section outlines the error codes returned, enabling identification of + * specific errors. For more information, see the + * Developer's Guide. + * + * @{ + */ +/** + * Indicates that a fatal error has occurred in the operation performed. + * This flag is set with the following error codes:
+ *

    + *
  • #R_ERROR_INVALID_STATE.
  • + *
  • #R_ERROR_INIT_NOT_CALLED.
  • + *
  • #R_ERROR_SHOULD_NOT_HAVE_BEEN_CALLED.
  • + *
+ */ +#define R_ERROR_FATAL_INTERNAL_ERROR 64 + +/** + * Indicates that the specified parameter is incorrect or contains invalid + * information. This flag is set with the following error codes:
+ *
    + *
  • #R_ERROR_NULL_ARG.
  • + *
  • #R_ERROR_BUFFER_TOO_SMALL.
  • + *
  • #R_ERROR_BAD_VALUE.
  • + *
  • #R_ERROR_BAD_RANGE.
  • + *
  • #R_ERROR_BAD_FORMAT.
  • + *
  • #R_ERROR_BAD_TYPE.
  • + *
  • #R_ERROR_BAD_DATA.
  • + *
  • #R_ERROR_BAD_LENGTH.
  • + *
+ */ +#define R_ERROR_BAD_PARAMETER 32 + +/* Indicates the base value for all general errors used through all products */ +#define R_ERROR_BASE 10000 + +/** + * Indicates that no errors were detected in the requested operation. + */ +#define R_ERROR_NONE 0 + +/** + * Indicates that the requested operation failed. + */ +#define R_ERROR_FAILED (R_ERROR_BASE+1) +/** + * Indicates that the requested operation detected an Input/Output error. + */ +#define R_ERROR_IO (R_ERROR_BASE+2) +/** + * Indicates that the requested operation detected a protocol error. + */ +#define R_ERROR_PROTOCOL (R_ERROR_BASE+3) +/** + * Indicates that the requested operation detected an End-of-File (EOF) error. + */ +#define R_ERROR_EOF (R_ERROR_BASE+4) +/** + * Indicates that the requested operation failed in a memory allocation + * operation. + */ +#define R_ERROR_ALLOC_FAILURE (R_ERROR_BASE+5) +/** + * Indicates that the requested operation is restricted in an evaluation + * version of the library. + */ +#define R_ERROR_EVAL_RESTRICTION (R_ERROR_BASE+6) +/** + * Indicates that the evaluation period of the library has expired. + */ +#define R_ERROR_EVAL_EXPIRED (R_ERROR_BASE+7) +/** + * Indicates that the requested operation detected that a pre-requirement was + * not found. + */ +#define R_ERROR_NOT_FOUND (R_ERROR_BASE+8) +/** + * Indicates that the requested operation detected that a pre-requirement was + * unavailable. + */ +#define R_ERROR_NOT_AVAILABLE (R_ERROR_BASE+9) +/** + * Indicates that the requested operation is not implemented in the current + * instantiation of the library. + */ +#define R_ERROR_NOT_IMPLEMENTED (R_ERROR_BASE+10) +/** + * Indicates that the requested operation is not supported in the current + * instantiation of the library. + */ +#define R_ERROR_NOT_SUPPORTED (R_ERROR_BASE+11) +/** + * Indicates that the requested operation entered an invalid state. + */ +#define R_ERROR_INVALID_STATE \ + ((R_ERROR_BASE+12) | R_ERROR_FATAL_INTERNAL_ERROR) +/** + * Indicates that the requested operation detected that an initialization + * operation has not been performed. + */ +#define R_ERROR_INIT_NOT_CALLED \ + ((R_ERROR_BASE+13) | R_ERROR_FATAL_INTERNAL_ERROR) +/** + * Indicates that the requested operation should not have been called. + */ +#define R_ERROR_SHOULD_NOT_HAVE_BEEN_CALLED \ + ((R_ERROR_BASE+14) | R_ERROR_FATAL_INTERNAL_ERROR) +/** + * Indicates that the requested method is not defined. + */ +#define R_ERROR_METHOD_UNDEFINED \ + ((R_ERROR_BASE+15) | R_ERROR_FATAL_INTERNAL_ERROR) +/** + * Indicates that the requested operation detected an inadequately sized + * buffer. + */ +#define R_ERROR_BUFFER_TOO_SMALL \ + ((R_ERROR_BASE+16) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * was passed as NULL. + */ +#define R_ERROR_NULL_ARG ((R_ERROR_BASE+17) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed contained a bad or incorrect value. + */ +#define R_ERROR_BAD_VALUE ((R_ERROR_BASE+18) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed was out of the allowed range. + */ +#define R_ERROR_BAD_RANGE ((R_ERROR_BASE+19) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed used a format that is not supported or incorrect. + */ +#define R_ERROR_BAD_FORMAT ((R_ERROR_BASE+20) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed used a type that is not supported or incorrect. + */ +#define R_ERROR_BAD_TYPE ((R_ERROR_BASE+21) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed contained incorrect or invalid data. + */ +#define R_ERROR_BAD_DATA ((R_ERROR_BASE+22) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the requested operation detected that a required argument + * passed contained an incorrect length value. + */ +#define R_ERROR_BAD_LENGTH ((R_ERROR_BASE+23) | R_ERROR_BAD_PARAMETER) +/** + * Indicates that the library instantiation requested is not supported. + */ +#define R_ERROR_RCOM_LIBRARY_NOT_SUPPORTED (R_ERROR_BASE+24) +/** + * Indicates that the request operation was denied. + */ +#define R_ERROR_DENIED (R_ERROR_BASE+25) +/** + * Indicates that authentication is required before the operation + * can succeed. + */ +#define R_ERROR_AUTHENTICATION_REQUIRED (R_ERROR_BASE+26) + +/** + * Indicates that a required module was unable to be loaded. + */ +#define R_ERROR_MODULE_LOAD_FAILED \ + ((R_ERROR_BASE+27)|R_ERROR_FATAL_INTERNAL_ERROR) + +/* Resource Manager base for errors */ +#define R_COM_ERR_LIB_CTX_BASE 10100 + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* HEADER_COMMON_R_ERROR_H */ + + + diff --git a/build/tools/acsign/include/r_stdiag.h b/build/tools/acsign/include/r_stdiag.h new file mode 100644 index 0000000..566de6f --- /dev/null +++ b/build/tools/acsign/include/r_stdiag.h @@ -0,0 +1,82 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +/* + * *************************************************************************** + * + * Purpose: + * + * This file defines an API for performing stack diagnostics. + * + * It provides: + * Peek Stack Usage statistics + * To use it: + * 1. Build the library without "NO_R_DIAG" defined + * 2. Make a call to R_DIAG_set_stack_datum() prior to + * calling the first library function. + * 3. Add calls to the macro R_DIAG_CHECK_STACK where potential + * high stack usage points are. + * 4. Call R_DIAG_get_stack_low_water_mark() at then end of the + * library calls to return the maximum stack usage OR + * 5. Call R_DIAG_print_stack_depth() to display the peek stack + * usage + * + * + * + * History: + * 3-Aug-00 mjs development + * + * ************************************************************************** + */ + + +#ifndef HEADER_COMMON_R_STDIAG_H +#define HEADER_COMMON_R_STDIAG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NO_R_DIAG + +#ifdef NOPROTO +int R_DIAG_set_stack_datum(char *ptr); +int R_DIAG_check_stack(char *ptr, char *file, int line, int hit); +int R_DIAG_get_stack_low_water_mark(int *depth, char **file, int *line, + int *hit); +int R_DIAG_print_stack_depth(BIO *bio); + +#else + +int R_DIAG_set_stack_datum(); +int R_DIAG_check_stack(); +int R_DIAG_get_stack_low_water_mark(); +int R_DIAG_print_stack_depth(); + +#endif + +#define R_DIAG_CHECK_STACK {\ + char r_diag_stack_check_var = 0;\ + static int r_diag_stack_check_cnt = 0;\ +\ + R_DIAG_check_stack(&r_diag_stack_check_var, __FILE__,\ + __LINE__,++r_diag_stack_check_cnt);\ + } +#else +#define R_DIAG_CHECK_STACK +#endif + + +#ifdef __cplusplus +} +#endif +#endif /* HEADER_COMMON_R_STDIAG_H */ + diff --git a/build/tools/acsign/include/r_types.h b/build/tools/acsign/include/r_types.h new file mode 100644 index 0000000..d35556a --- /dev/null +++ b/build/tools/acsign/include/r_types.h @@ -0,0 +1,241 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ +/** + * @file r_types.h + * This file contains the library structure and type definitions. + */ +#ifndef HEADER_COMMON_R_TYPES_H +#define HEADER_COMMON_R_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup DATA_MNG_FLAGS Data Management Flags + * This section lists the data management flags. + * @{ + */ + +/** + * @} + */ + +/* This gets set if the flags field if the we need to 'free' the + * R_RANDOM when we call R_rand_free(). If it is not set, the + * rand_ctrl will only be called to clean things up. + */ +#define R_RANDOM_FLG_MALLOCED 0x01 + +/* portable form of a random callback function */ +/** + * @typedef R_RANDOM + * The random object type. + */ +typedef struct r_random_st R_RANDOM; +/** + * This structure is used by the random object type. + */ +struct r_random_st +{ + /** + * A method function for generation of random data. + * + * @see R_rand_bytes(). + */ + int (*rand_bytes)(R_RANDOM *ctx,unsigned char *bytes,int len); + /** + * A method function for seeding of the random generator. + * @see R_rand_seed(). + */ + int (*rand_seed)(R_RANDOM *ctx,unsigned char *bytes,int len); + /** + * A method function for control of the random generator used by + * other functions as a single interface. + * + * @see R_rand_entropy_count(), R_rand_set_entropy_func(), + * R_rand_get_entropy_func(), R_rand_load_file(), R_rand_write_file() + * and R_rand_file_name(). + */ + int (*rand_ctrl)(R_RANDOM *ctx,int op,char *arg); + /** + * The data used by the random implementation. + */ + char *arg; + /** + * A method flag for used for keeping the state of the #R_RANDOM. + */ + int flags; /* normally set to zero */ +}; +/** + * @typedef R_SURRENDER + * The surrender function and argument. + */ +typedef struct r_surrender_st R_SURRENDER; +/** + * This structure provides a status update of a time intensive operation. It + * also allows you to abort the operation if required. + */ +struct r_surrender_st +{ + /* Return 0 to continue, non-zero to 'cancel' function */ + /** + * The surrender function pointer used as a generic method of + * passing user-defined callback or information collection functions. + */ + int (*callback)(R_SURRENDER *ctx,int function,int num); + /** + * The argument data used by the callback operation. + */ + char *arg; +}; + +typedef struct r_fixed_point_number_st R_FIXED_POINT_NUMBER; +struct r_fixed_point_number_st +{ + unsigned long hi; + unsigned long lo; +}; + +/** + * @typedef R_INDEXED_INFO + * This structure details the index containing information for get and set + * functions. + */ +typedef struct r_indexed_info_st R_INDEXED_INFO; +/** This structure details the index containing information for get and set + * functions. + */ +struct r_indexed_info_st +{ + /** The index into the list of the item to work with. */ + int index; + /** The data of the item in the list. */ + void *data; + /** The length of the data. */ + unsigned int len; + /** The data value as an integer. */ + int value; +}; + +/** + * @typedef R_ID_INFO + * The information to work with requires a second identity value to find it. + */ +typedef struct r_id_info_st R_ID_INFO; +/** The information to get or set requires a second information identifier. + * This type is used when calling set_info and get_info to get a number of + * information items in one call. + */ +struct r_id_info_st +{ + /** The information identifier. */ + int info_id; + /** The information data associated with the identifier. */ + void *value; +}; + +/** @defgroup R_FLAG_COPY_IDS Copy Flag Identifiers + * + * This section provides information on the copy mode. When data is passed + * to/from the library you can specify whether or not the copy should be done + * by value, by reference or by direct assignment. + * @ingroup DATA_MNG_FLAGS + * @{ + */ + +/** + * The copy flag. When data is passed to/from the library you can specify + * whether or not the copy should be done by value, by reference or + * by direct assignment. + */ +typedef int R_FLAG_COPY; + +/* + * action flag app lib + * obj_get BY_VAL F X + * BY_REF X F [app will not free "obj" until it is + * BY_ASSIGN F X finished with the returned reference] + * obj_set BY_VAL F X + * BY_REF F X [app will not free passed reference + * BY_ASSIGN X F until after it has freed "obj"] + * + * BY_REF makes the lifetime of the two objects linked and it is up to + * the application to manage the objects in a manner that preserves this + * relationship. + */ + +/** + * Indicates to copy by value. A complete clone of the object is made. + * The lifecycles of the two objects are independent. + */ +#define R_FLAG_COPY_BY_VALUE 0x0000 + +/** + * Indicates to copy by reference. A reference to the object is made. + * The lifecycles of objects sharing references are linked. + */ +#define R_FLAG_COPY_BY_REFERENCE 0x0001 + +/** + * Indicates to copy by assignment. The object is assigned to the required + * party. The caller does not keep a reference to the passed object. + */ +#define R_FLAG_COPY_BY_ASSIGN 0x0002 + +/** + * Indicates to copy using the default flag settings. + */ +#define R_FLAG_COPY_DEFAULT R_FLAG_COPY_BY_VALUE + +/** + * @} + */ + +/** @defgroup R_FLAG_SHARE_IDS Shared Flag Identifiers + * + * This section provides information on the shared flags available. + * @ingroup DATA_MNG_FLAGS + * @{ + */ + +/** + * The constructor flag. Indicates whether or not it is permissible to share + * the internal state between objects. + */ +typedef int R_FLAG_SHARE; + +/** + * Indicates to share nothing. The states of the two objects are completely + * separate. + */ +#define R_FLAG_SHARE_NONE 0x0000 + +/** + * Indicates to share data. Constructed objects may reference the state of + * the object from which it was constructed. The lifecycles of the two objects + * are linked. + */ +#define R_FLAG_SHARE_DATA 0x0001 + +/** Indicates the share default in which nothing is shared. */ +#define R_FLAG_SHARE_DEFAULT R_FLAG_SHARE_NONE + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/build/tools/acsign/include/sha.h b/build/tools/acsign/include/sha.h new file mode 100644 index 0000000..d6eeed2 --- /dev/null +++ b/build/tools/acsign/include/sha.h @@ -0,0 +1,89 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#ifndef HEADER_COMMON_SHA_H +#define HEADER_COMMON_SHA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(CCONV) +#define CCONV +#endif + +#ifndef PRE_CCONV +#define PRE_CCONV +#endif + +#define SHA_CBLOCK 64 +#define SHA_LBLOCK 16 +#define SHA_BLOCK 16 +#define SHA_LAST_BLOCK 56 +#define SHA_LENGTH_BLOCK 8 +#define SHA_DIGEST_LENGTH 20 + +/* the default is to use unsigned long */ +#if !defined(OPT_SHA_INT) && !defined(OPT_SHA_LONG) +#define OPT_SHA_LONG +#endif + +#ifdef OPT_SHA_LONG +#define SHA_LONG unsigned long +#endif + +#ifdef OPT_SHA_INT +#define SHA_LONG unsigned int +#endif + +typedef struct sha_ctx_st SHA_CTX; + +struct sha_ctx_st + { + SHA_LONG h0,h1,h2,h3,h4; + SHA_LONG Nl,Nh; + SHA_LONG data[SHA_LBLOCK]; + int num; + void (PRE_CCONV CCONV *sha_block)(SHA_CTX *c, const unsigned char *W, + int num); + }; + +#ifndef NOPROTO +int SHA1_Setup(SHA_CTX *c, void (PRE_CCONV CCONV *sha_block)(SHA_CTX *c, + const unsigned char *W, int num)); +void SHA_Init(SHA_CTX *c); +void SHA_Update(SHA_CTX *c, const unsigned char *data, unsigned long len); +void SHA_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA(const unsigned char *d, unsigned long n,unsigned char *md); +void SHA_Transform(SHA_CTX *c, const unsigned char *data); +void SHA1_Init(SHA_CTX *c); +void SHA1_Update(SHA_CTX *c, const unsigned char *data, unsigned long len); +void SHA1_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA1(const unsigned char *d, unsigned long n,unsigned char *md); +void SHA1_Transform(SHA_CTX *c, const unsigned char *data); +#else +void SHA_Init(); +void SHA_Update(); +void SHA_Final(); +unsigned char *SHA(); +void SHA_Transform(); +void SHA1_Init(); +void SHA1_Update(); +void SHA1_Final(); +unsigned char *SHA1(); +void SHA1_Transform(); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_COMMON_SHA_H */ diff --git a/build/tools/acsign/include/sha1.h b/build/tools/acsign/include/sha1.h new file mode 100644 index 0000000..ed4a672 --- /dev/null +++ b/build/tools/acsign/include/sha1.h @@ -0,0 +1,73 @@ +/* + * sha1.h + * + * Description: + * This is the header file for code which implements the Secure + * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published + * April 17, 1995. + * + * Many of the variable names in this code, especially the + * single character names, were used because those were the names + * used in the publication. + * + * Please read the file sha1.c for more information. + * + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _SHA_enum_ +#define _SHA_enum_ +enum +{ + shaSuccess = 0, + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError /* called Input after Result */ +}; +#endif + +/* + * This structure will hold context information for the SHA-1 + * hashing operation + */ +typedef struct SHA1Context +{ + unsigned long Intermediate_Hash[20/4]; /* Message Digest */ + + unsigned long Length_Low; /* Message length in bits */ + unsigned long Length_High; /* Message length in bits */ + + int Message_Block_Index; /* Index into message block array */ + unsigned char Message_Block[64]; /* 512-bit message blocks */ + + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corrupted? */ +} SHA1Context; + +/* + * Function Prototypes + */ + +int SHA1Reset( SHA1Context *); +int SHA1Input( SHA1Context *, + const unsigned char *, + unsigned int); +int SHA1Result( SHA1Context *, + unsigned char Message_Digest[20]); + +#if defined( SHA1_TEST ) +int SHA1Test( ); +#endif // SHA1_TEST + + +#ifdef __cplusplus +} +#endif + +#endif // _SHA1_H_ diff --git a/build/tools/acsign/include/sha_locl.h b/build/tools/acsign/include/sha_locl.h new file mode 100644 index 0000000..2361282 --- /dev/null +++ b/build/tools/acsign/include/sha_locl.h @@ -0,0 +1,274 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +#ifndef HEADER_COMMON_SHA_LOCL_H +#define HEADER_COMMON_SHA_LOCL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STANDALONE +//#include "r_com.h" +#else +#if 1 //RSA +#include +#include +#include +//#define Memcpy memcpy +//#define Memset memset +#define Strcpy strcpy +#else //NITRO +#include "acmemory.h" +#define Malloc(a) ACMemory_Alloc(a) +#define Free(a) ACMemory_Free(a) +#define Memset(a,b,c) ACMemory_Memset(a,b,c) +#define Memcpy(a,b,c) ACMemory_Memcpy(a,b,c) +#endif +#endif + +#ifdef undef +/* one or the other must be defined */ +#ifndef SHA_1 /* FIPE 180-1 */ +#define SHA_0 /* FIPS 180 */ +#endif +#endif + +#define ULONG unsigned long +#define UCHAR unsigned char +#define UINT unsigned int + +#ifdef NOCONST +#define const +#endif + +#undef c2nl +#define c2nl(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) )) + +#undef p_c2nl +#define p_c2nl(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + case 3: l|=((unsigned long)(*((c)++))); \ + } \ + } + +#undef c2nl_p +/* NOTE the pointer is not incremented at the end of this */ +#define c2nl_p(c,l,n) { \ + l=0; \ + (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<< 8; \ + case 2: l|=((unsigned long)(*(--(c))))<<16; \ + case 1: l|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +#undef p_c2nl_p +#define p_c2nl_p(c,l,sc,len) { \ + switch (sc) \ + { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + } \ + } + +#undef nl2c +#define nl2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#undef c2l +#define c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24)) + +#undef p_c2l +#define p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++))); \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + case 3: l|=((unsigned long)(*((c)++)))<<24; \ + } \ + } + +#undef c2l_p +/* NOTE the pointer is not incremented at the end of this */ +#define c2l_p(c,l,n) { \ + l=0; \ + (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<<16; \ + case 2: l|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l|=((unsigned long)(*(--(c)))); \ + } \ + } + +#undef p_c2l_p +#define p_c2l_p(c,l,sc,len) { \ + switch (sc) \ + { \ + case 0: l =((unsigned long)(*((c)++))); \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +#ifdef OPT_SHA_B_ENDIAN +#define B_ENDIAN +#endif +#ifdef OPT_SHA_L_ENDIAN +#define L_ENDIAN +#endif + +#undef ROTATE +#if defined(WIN32) +#define ROTATE(a,n) _lrotl(a,n) +#else +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + +/* byte order reversal */ +#if defined(WIN32) +/* 5 instructions with rotate instruction, else 9 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + (a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \ + } +#else +/* 6 instructions with rotate instruction, else 8 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \ + (a)=ROTATE(l,16L); \ + } +#endif + +/* F() below can be + * simplified to the code in F_00_19. + * #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) + * another tweak to be made + * in F_40_59, (x&a)|(y&a) -> (x|y)&a + */ +#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) +#define F_40_59(b,c,d) (((b) & (c)) | (((b)|(c)) & (d))) +#define F_60_79(b,c,d) F_20_39(b,c,d) + +#ifdef SHA_0 +#undef Xupdate +#define Xupdate(a,i,ia,ib,ic,id) X[(i)&0x0f]=(a)=\ + (ia[(i)&0x0f]^ib[((i)+2)&0x0f]^ic[((i)+8)&0x0f]^id[((i)+13)&0x0f]); +#endif +#ifdef SHA_1 +#undef Xupdate +#define Xupdate(a,i,ia,ib,ic,id) (a)=\ + (ia[(i)&0x0f]^ib[((i)+2)&0x0f]^ic[((i)+8)&0x0f]^id[((i)+13)&0x0f]);\ + X[(i)&0x0f]=(a)=ROTATE((a),1); +#endif + +#define BODY_00_15(i,a,b,c,d,e,f,xa) \ + (f)=xa[i]+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_60_79(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)=X[(i)&0x0f]+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \ + (b)=ROTATE((b),30); + +/* + * The CodeWarrior compiler has a problem correctly expanding things like + * + * (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); + * + * so we separate this to 3 explicit adds, just for PalmOS. + */ +#ifndef UNDER_PALMOS + +#define BODY_16_19(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,i,xa,xb,xc,xd); \ + (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_20_31(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,i,xa,xb,xc,xd); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_32_39(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_40_59(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#else /* UNDER_PALMOS */ + +#define BODY_16_19(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,i,xa,xb,xc,xd); \ + (f)+=(e); \ + (f)+=K_00_19; \ + (f)+=ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_20_31(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,i,xa,xb,xc,xd); \ + (f)+=(e); \ + (f)+=K_20_39; \ + (f)+=ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_32_39(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)+=(e); \ + (f)+=K_20_39; \ + (f)+=ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_40_59(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)+=(e); \ + (f)+=K_40_59; \ + (f)+=ROTATE((a),5)+F_40_59((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#endif /* UNDER_PALMOS */ + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_COMMON_SHA_LOCL_H */ diff --git a/build/tools/acsign/sha1.c b/build/tools/acsign/sha1.c new file mode 100644 index 0000000..6bebd12 --- /dev/null +++ b/build/tools/acsign/sha1.c @@ -0,0 +1,453 @@ +/* + * sha1.c + * + * Description: + * This file implements the Secure Hashing Algorithm 1 as + * defined in FIPS PUB 180-1 published April 17, 1995. + * + * The SHA-1, produces a 160-bit message digest for a given + * data stream. It should take about 2**n steps to find a + * message with the same digest as a given message and + * 2**(n/2) to find any two messages with the same digest, + * when n is the digest size in bits. Therefore, this + * algorithm can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code + * uses (included via "sha1.h" to define 32 and 8 + * bit unsigned integer types. If your C compiler does not + * support 32 bit unsigned integers, this code is not + * appropriate. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated + * for messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is + * a multiple of the size of an 8-bit character. + * + */ + +#include "sha1.h" + +/* + * Define the SHA1 circular left shift macro + */ +#define SHA1CircularShift(bits,word) \ + (((word) << (bits)) | ((word) >> (32-(bits)))) + +/* Local Function Prototyptes */ +void SHA1PadMessage(SHA1Context *); +void SHA1ProcessMessageBlock(SHA1Context *); + +/* + * SHA1Reset + * + * Description: + * This function will initialize the SHA1Context in preparation + * for computing a new SHA1 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Reset(SHA1Context *context) +{ + if (!context) + { + return shaNull; + } + + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Intermediate_Hash[0] = 0x67452301; + context->Intermediate_Hash[1] = 0xEFCDAB89; + context->Intermediate_Hash[2] = 0x98BADCFE; + context->Intermediate_Hash[3] = 0x10325476; + context->Intermediate_Hash[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; + + return shaSuccess; +} + +/* + * SHA1Result + * + * Description: + * This function will return the 160-bit message digest into the + * Message_Digest array provided by the caller. + * NOTE: The first octet of hash is stored in the 0th element, + * the last octet of hash in the 19th element. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * Message_Digest: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Result( SHA1Context *context, + unsigned char Message_Digest[20]) +{ + int i; + + if (!context || !Message_Digest) + { + return shaNull; + } + + if (context->Corrupted) + { + return context->Corrupted; + } + + if (!context->Computed) + { + SHA1PadMessage(context); + for(i=0; i<64; ++i) + { + /* message may be sensitive, clear it out */ + context->Message_Block[i] = 0; + } + context->Length_Low = 0; /* and clear length */ + context->Length_High = 0; + context->Computed = 1; + + } + + for(i = 0; i < 20; ++i) + { + Message_Digest[i] = (unsigned char) + (context->Intermediate_Hash[i>>2] + >> 8 * ( 3 - ( i & 0x03 ) )); + } + + return shaSuccess; +} + +/* + * SHA1Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update + * message_array: [in] + * An array of characters representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array + * + * Returns: + * sha Error Code. + * + */ +int SHA1Input( SHA1Context *context, + const unsigned char *message_array, + unsigned int length) +{ + if (!length) + { + return shaSuccess; + } + + if (!context || !message_array) + { + return shaNull; + } + + if (context->Computed) + { + context->Corrupted = shaStateError; + + return shaStateError; + } + + if (context->Corrupted) + { + return context->Corrupted; + } + while(length-- && !context->Corrupted) + { + context->Message_Block[context->Message_Block_Index++] = + (unsigned char)(*message_array & 0xFF); + + context->Length_Low += 8; + if (context->Length_Low == 0) + { + context->Length_High++; + if (context->Length_High == 0) + { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) + { + SHA1ProcessMessageBlock(context); + } + + message_array++; + } + + return shaSuccess; +} + +/* + * SHA1ProcessMessageBlock + * + * Description: + * This function will process the next 512 bits of the message + * stored in the Message_Block array. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + * + * Comments: + * + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the publication. + * + * + */ +void SHA1ProcessMessageBlock(SHA1Context *context) +{ + const unsigned long K[] = { /* Constants defined in SHA-1 */ + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + unsigned long temp; /* Temporary word value */ + unsigned long W[80]; /* Word sequence */ + unsigned long A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for(t = 0; t < 16; t++) + { + W[t] = context->Message_Block[t * 4 ] << 24; + W[t] |= context->Message_Block[t * 4 + 1] << 16; + W[t] |= context->Message_Block[t * 4 + 2] << 8; + W[t] |= context->Message_Block[t * 4 + 3]; + } + + for(t = 16; t < 80; t++) + { + W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + + for(t = 0; t < 20; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + + B = A; + A = temp; + } + + for(t = 20; t < 40; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 40; t < 60; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 60; t < 80; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + + context->Message_Block_Index = 0; +} + +/* + * SHA1PadMessage + * + + * Description: + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 + * bits represent the length of the original message. All bits in + * between should be 0. This function will pad the message + * according to those rules by filling the Message_Block array + * accordingly. It will also call the ProcessMessageBlock function + * provided appropriately. When it returns, it can be assumed that + * the message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad + * ProcessMessageBlock: [in] + * The appropriate SHA*ProcessMessageBlock function + * Returns: + * Nothing. + * + */ + +void SHA1PadMessage(SHA1Context *context) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 64) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + + SHA1ProcessMessageBlock(context); + + while(context->Message_Block_Index < 56) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + else + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 56) + { + + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = (unsigned char)(context->Length_High >> 24); + context->Message_Block[57] = (unsigned char)(context->Length_High >> 16); + context->Message_Block[58] = (unsigned char)(context->Length_High >> 8); + context->Message_Block[59] = (unsigned char)(context->Length_High ); + context->Message_Block[60] = (unsigned char)(context->Length_Low >> 24); + context->Message_Block[61] = (unsigned char)(context->Length_Low >> 16); + context->Message_Block[62] = (unsigned char)(context->Length_Low >> 8); + context->Message_Block[63] = (unsigned char)(context->Length_Low ); + + SHA1ProcessMessageBlock(context); +} + + + + +////////////////////////////////////////////////////////////////////////////// +#if defined( SHA1_TEST ) + +#include "string.h" + +char* samplearray[4] = +{ + "abc", + "abcdbcdecdefdefgefghfghighijhi" "jkijkljklmklmnlmnomnopnopq", + "a", + "01234567012345670123456701234567" "01234567012345670123456701234567" +}; + +char* resultarray[ 4 ] = +{ + "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D", + "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1", + "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F", + "\xDE\xA3\x56\xA2\xCD\xDD\x90\xC7\xA7\xEC\xED\xC5\xEB\xB5\x63\x93\x4F\x46\x04\x52" +}; + +long int repeatcount[4] = { 1, 1, 1000000, 10 }; + +int SHA1Test( ) +{ + SHA1Context sha; + unsigned char digest[20]; + int i, j, error; + + error = 0; + for ( j = 0; j < 4; ++j ) + { + if ( !error ) + error = SHA1Reset(&sha); + + for(i = 0; i < repeatcount[j]; ++i) + { + if ( !error ) + error = SHA1Input(&sha, + (const unsigned char *)samplearray[j], + (unsigned int)strlen(samplearray[j])); + } + + if ( !error ) + error = SHA1Result(&sha, digest); + + if ( !error ) + error = memcmp( digest, resultarray[j], 20 ); + + if (error) + break; + } + + return error ? 0 : 1; +} + +#endif // SHA1_TEST +////////////////////////////////////////////////////////////////////////////// + diff --git a/build/tools/acsign/sha1dgst.c b/build/tools/acsign/sha1dgst.c new file mode 100644 index 0000000..f975915 --- /dev/null +++ b/build/tools/acsign/sha1dgst.c @@ -0,0 +1,770 @@ +/* $Id$ */ +/* + * Copyright (C) 1998-2002 RSA Security Inc. All rights reserved. + * + * This work contains proprietary information of RSA Security. + * Distribution is limited to authorized licensees of RSA + * Security. Any unauthorized reproduction, distribution or + * modification of this work is strictly prohibited. + * + */ + +////!!!!#include "r_com.h" + +#ifndef NO_SHA1 +#undef SHA_0 +#define SHA_1 +#include "sha.h" +#include "sha_locl.h" +#ifdef CPU_X86 +#include "r_cpuid.h" +#endif /* NO_SHA1 */ + +const char *SHA1_version="SHA1 part of RCOM 2.3.0 11-Jun-2002"; + +/* Implemented from SHA-1 document - The Secure Hash Algorithm + */ + +#define INIT_DATA_h0 (SHA_LONG)0x67452301L +#define INIT_DATA_h1 (SHA_LONG)0xefcdab89L +#define INIT_DATA_h2 (SHA_LONG)0x98badcfeL +#define INIT_DATA_h3 (SHA_LONG)0x10325476L +#define INIT_DATA_h4 (SHA_LONG)0xc3d2e1f0L + +#define K_00_19 (SHA_LONG)0x5a827999L +#define K_20_39 (SHA_LONG)0x6ed9eba1L +#define K_40_59 (SHA_LONG)0x8f1bbcdcL +#define K_60_79 (SHA_LONG)0xca62c1d6L + +#ifndef CCONV +#define CCONV +#endif + +#ifndef PRE_CCONV +#define PRE_CCONV +#endif + +/* Endian flags are only used for the assembler code */ +#ifndef OPT_SHA1_ASM +#undef L_ENDIAN +#undef B_ENDIAN +#endif + + +#ifdef OPT_SHA1_ASM + +#ifdef CPU_X86 +void CCONV sha1_block_586(SHA_CTX *c,const unsigned char *p, int num); +void CCONV sha1_block_686(SHA_CTX *c,const unsigned char *p, int num); +void CCONV sha1_block_786(SHA_CTX *c,const unsigned char *p, int num); +unsigned long r_cpuid(unsigned long *,char **name); + +#elif OPT_SHA1_ARM +PRE_CCONV void CCONV sha1_arm4_fast(SHA_CTX *c, const unsigned char *p, + int num); +PRE_CCONV void CCONV sha1_arm4_small(SHA_CTX *c, const unsigned char *p, + int num); +#else +void CCONV sha1_block_asm(SHA_CTX *c, const unsigned char *p, int num); +#endif /* CPU_X86 */ + +#else /* OPT_SHA1_ASM */ + +void sha1_block(SHA_CTX *c, SHA_LONG *p, int num); + +#endif /* OPT_SHA1_ASM */ + +#undef M_c2nl +#undef M_p_c2nl +#undef M_c2nl_p +#undef M_p_c2nl_p +#undef M_nl2c + +#if defined(L_ENDIAN) && !defined(OPT_SHA1_ASM) +# define M_c2nl c2l +# define M_p_c2nl p_c2l +# define M_c2nl_p c2l_p +# define M_p_c2nl_p p_c2l_p +# define M_nl2c l2c +#else +# define M_c2nl c2nl +# define M_p_c2nl p_c2nl +# define M_c2nl_p c2nl_p +# define M_p_c2nl_p p_c2nl_p +# define M_nl2c nl2c +#endif /* defined(L_ENDIAN) && !defined(OPT_SHA1_ASM) */ + +int SHA1_Setup(c,sha_block) +SHA_CTX *c; +void (PRE_CCONV CCONV *sha_block)(SHA_CTX *c, const unsigned char *W, int num); + { + c->sha_block=sha_block; + return(0); + } + +void SHA1_Init(c) +SHA_CTX *c; + { + c->h0=INIT_DATA_h0; + c->h1=INIT_DATA_h1; + c->h2=INIT_DATA_h2; + c->h3=INIT_DATA_h3; + c->h4=INIT_DATA_h4; + c->Nl=0; + c->Nh=0; + c->num=0; + +#ifdef OPT_SHA1_ASM +#ifdef CPU_X86 + if (c->sha_block == NULL) + { + unsigned long cpu,attrib; + + /* We should make the methods loadable */ + cpu=r_cpuid(&attrib,NULL); + if (attrib & R_CPU_X86_HAS_PENTIUM_IV) + c->sha_block=sha1_block_786; + else if (attrib & R_CPU_X86_HAS_PENTIUM_PRO) + c->sha_block=sha1_block_686; + else + c->sha_block=sha1_block_586; + } +#else /* CPU_X86 */ + +#ifndef OPT_SHA1_ARM + c->sha_block=sha1_block_asm; +#else /* OPT_SHA1_ARM */ + if (c->sha_block == NULL) + { +#ifdef SMALL_CODE_SIZE + c->sha_block = sha1_arm4_small; +#else /* SMALL_CODE_SIZE */ + c->sha_block = sha1_arm4_fast; +#endif /* SMALL_CODE_SIZE */ + } +#endif /* OPT_SHA1_ARM */ +#endif /* CPU_X86 */ + +#else /* OPT_SHA1_ASM */ + c->sha_block=(void (PRE_CCONV CCONV *)(SHA_CTX *, const unsigned char *, int))sha1_block; +#endif /* OPT_SHA1_ASM */ + } + +#ifdef OPT_SHA1_ASM + +void SHA1_Update(c, data, len) +SHA_CTX *c; +const register unsigned char *data; +unsigned long len; + { + int i; + unsigned int alignment; + unsigned long l; + unsigned char *cp=(unsigned char *)c->data; + + if (len == 0) return; + + l=(c->Nl+(len<<3))&0xffffffffL; + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); + c->Nl=l; + + if (c->num != 0) + { + if (c->num+len >= SHA_CBLOCK) + { + i=SHA_CBLOCK-c->num; + Memcpy(&(cp[c->num]),data,i); + len-=i; + data+=i; + + c->sha_block(c,cp,64); + c->num=0; + /* drop through and do the rest */ + } + else + { + Memcpy(&(cp[c->num]),data,len); + c->num+=(int)len; + return; + } + } + /* we now can process the input data in blocks of SHA_CBLOCK + * chars and save the leftovers to c->data. */ + if (len >= SHA_CBLOCK) + { + i=(int)(len& ~63); + len-=i; + + /* + * Check to see if the input data lies on a word boundary. + * Do this as the ASM relies on input data being word aligned. + */ + alignment = (((unsigned int)data) & (sizeof(unsigned int)-1)) + & 0x03; + if (alignment == 0) + { + c->sha_block(c,data,i); + data+=i; + } + else + { + do { + Memcpy(cp, data, SHA_CBLOCK); + data += SHA_CBLOCK; + c->sha_block(c, cp, SHA_CBLOCK); + i -= SHA_CBLOCK; + } while (i > 0); + } + } + c->num=len; + if (len) + { + Memcpy(cp,data,(int)len); + } + } + +void SHA1_Transform(c,b) +SHA_CTX *c; +const unsigned char *b; + { + c->sha_block(c,b,64); + } + +void SHA1_Final(md, c) +unsigned char *md; +SHA_CTX *c; + { + register int i,j; + register SHA_LONG l; + register SHA_LONG *p; + const static unsigned char end[4]={0x80,0x00,0x00,0x00}; + unsigned char *cp= (unsigned char *)end; + unsigned char *pc; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + j=c->num; + i=j>>2; + +#ifdef PURIFY + /* PURIFY */ + /* we reference uninitialised data but don't keep the result + * which purify complains about ... and we don't want to have + * to come back here to find a non-existant problem later + */ + + /* purify often complains about the following line as an + * Uninitialized Memory Read. While this can be true, the + * following p_c2l macro will reset l when that case is true. + * This is because j&0x03 contains the number of 'valid' bytes + * already in p[i]. If and only if j&0x03 == 0, the UMR will + * occur but this is also the only time p_c2l will do + * l= *(cp++) instead of l|= *(cp++) + */ + if ((j&0x03) == 0) p[i]=0; +#endif + + pc=(unsigned char *)c->data; + pc[j]=0x80; + for (j++; j & 0x03; j++) + pc[j]=0; + i++; + /* i is the next 'undefined word' */ + if (c->num >= SHA_LAST_BLOCK) + { + for (; isha_block(c,(unsigned char *)p,64); + i=0; + } + for (; i<(SHA_LBLOCK-2); i++) + p[i]=0; + + l=c->Nl; + pc[63]=(unsigned char)((l )&0xff); + pc[62]=(unsigned char)((l>> 8)&0xff); + pc[61]=(unsigned char)((l>>16)&0xff); + pc[60]=(unsigned char)((l>>24)&0xff); + l=c->Nh; + pc[59]=(unsigned char)((l )&0xff); + pc[58]=(unsigned char)((l>> 8)&0xff); + pc[57]=(unsigned char)((l>>16)&0xff); + pc[56]=(unsigned char)((l>>24)&0xff); + + c->sha_block(c,(unsigned char *)p,64); + cp=md; + l=c->h0; nl2c(l,cp); + l=c->h1; nl2c(l,cp); + l=c->h2; nl2c(l,cp); + l=c->h3; nl2c(l,cp); + l=c->h4; nl2c(l,cp); + + /* clear stuff, sha1_block_asm may be leaving some stuff on the stack + * but I'm not worried :-) */ + c->num=0; +/* Memset((char *)&c,0,sizeof(c));*/ + } + +#else /* !OPT_SHA1_ASM */ + +void SHA1_Update(c, data, len) +SHA_CTX *c; +const register unsigned char *data; +unsigned long len; + { + register SHA_LONG *p; + int ew,ec,sw,sc; + SHA_LONG l; + + if (len == 0) return; + + l=(c->Nl+(len<<3))&0xffffffffL; + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); + c->Nl=l; + + if (c->num != 0) + { + p=c->data; + sw=c->num>>2; + sc=c->num&0x03; + + if ((c->num+len) >= SHA_CBLOCK) + { + l= p[sw]; + M_p_c2nl(data,l,sc); + p[sw++]=l; + for (; swnum); + + c->sha_block(c,(unsigned char *)p,64); + c->num=0; + /* drop through and do the rest */ + } + else + { + c->num+=(int)len; + if ((sc+len) < 4) /* ugly, add char's to a word */ + { + l= p[sw]; + M_p_c2nl_p(data,l,sc,len); + p[sw]=l; + } + else + { + ew=(c->num>>2); + ec=(c->num&0x03); + l= p[sw]; + M_p_c2nl(data,l,sc); + p[sw++]=l; + for (; sw < ew; sw++) + { M_c2nl(data,l); p[sw]=l; } + if (ec) + { + M_c2nl_p(data,l,ec); + p[sw]=l; + } + } + return; + } + } + /* We can only do the following code for assember, the reason + * being that the sha1_block 'C' version changes the values + * in the 'data' array. The assember code avoids this and + * copies it to a local array. I should be able to do this for + * the C version as well.... + */ +#if defined(B_ENDIAN) || defined(OPT_SHA1_ASM) + if ((((unsigned long)data)%sizeof(SHA_LONG)) == 0) + { + sw=len/SHA_CBLOCK; + if (sw) + { + sw*=SHA_CBLOCK; + c->sha_block(c,(SHA_LONG *)data,sw); + data+=sw; + len-=sw; + } + } +#endif + /* we now can process the input data in blocks of SHA_CBLOCK + * chars and save the leftovers to c->data. */ + p=c->data; + while (len >= SHA_CBLOCK) + { +#if defined(B_ENDIAN) || defined(L_ENDIAN) + if (p != (SHA_LONG *)data) + Memcpy(p,data,SHA_CBLOCK); + data+=SHA_CBLOCK; +# ifdef L_ENDIAN +# ifndef OPT_SHA1_ASM /* Will not happen */ + for (sw=(SHA_LBLOCK/4); sw; sw--) + { + Endian_Reverse32(p[0]); + Endian_Reverse32(p[1]); + Endian_Reverse32(p[2]); + Endian_Reverse32(p[3]); + p+=4; + } + p=c->data; +# endif +# endif +#else + for (sw=(SHA_BLOCK/4); sw; sw--) + { + M_c2nl(data,l); *(p++)=l; + M_c2nl(data,l); *(p++)=l; + M_c2nl(data,l); *(p++)=l; + M_c2nl(data,l); *(p++)=l; + } + p=c->data; +#endif + c->sha_block(c,(unsigned char *)p,64); + len-=SHA_CBLOCK; + } + ec=(int)len; + c->num=ec; + ew=(ec>>2); + ec&=0x03; + + for (sw=0; sw < ew; sw++) + { M_c2nl(data,l); p[sw]=l; } + M_c2nl_p(data,l,ec); + p[sw]=l; + } + +void SHA1_Transform(c,b) +SHA_CTX *c; +const unsigned char *b; + { + SHA_LONG p[16]; +#ifndef B_ENDIAN + SHA_LONG *q; + int i; +#endif + +#if defined(B_ENDIAN) || defined(L_ENDIAN) + Memcpy(p,b,64); +#ifdef L_ENDIAN + q=p; + for (i=(SHA_LBLOCK/4); i; i--) + { + Endian_Reverse32(q[0]); + Endian_Reverse32(q[1]); + Endian_Reverse32(q[2]); + Endian_Reverse32(q[3]); + q+=4; + } +#endif +#else + q=p; + for (i=(SHA_LBLOCK/4); i; i--) + { + SHA_LONG l; + c2nl(b,l); *(q++)=l; + c2nl(b,l); *(q++)=l; + c2nl(b,l); *(q++)=l; + c2nl(b,l); *(q++)=l; + } +#endif + c->sha_block(c,(unsigned char *)p,64); + } + + +void sha1_block(c, W, num) +SHA_CTX *c; +SHA_LONG *W; +int num; + { +#ifndef SMALL_CODE_SIZE + register SHA_LONG A,B,C,D,E,T; + SHA_LONG X[16]; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + BODY_00_15( 0,A,B,C,D,E,T,W); + BODY_00_15( 1,T,A,B,C,D,E,W); + BODY_00_15( 2,E,T,A,B,C,D,W); + BODY_00_15( 3,D,E,T,A,B,C,W); + BODY_00_15( 4,C,D,E,T,A,B,W); + BODY_00_15( 5,B,C,D,E,T,A,W); + BODY_00_15( 6,A,B,C,D,E,T,W); + BODY_00_15( 7,T,A,B,C,D,E,W); + BODY_00_15( 8,E,T,A,B,C,D,W); + BODY_00_15( 9,D,E,T,A,B,C,W); + BODY_00_15(10,C,D,E,T,A,B,W); + BODY_00_15(11,B,C,D,E,T,A,W); + BODY_00_15(12,A,B,C,D,E,T,W); + BODY_00_15(13,T,A,B,C,D,E,W); + BODY_00_15(14,E,T,A,B,C,D,W); + BODY_00_15(15,D,E,T,A,B,C,W); + BODY_16_19(16,C,D,E,T,A,B,W,W,W,W); + BODY_16_19(17,B,C,D,E,T,A,W,W,W,W); + BODY_16_19(18,A,B,C,D,E,T,W,W,W,W); + BODY_16_19(19,T,A,B,C,D,E,W,W,W,X); + + BODY_20_31(20,E,T,A,B,C,D,W,W,W,X); + BODY_20_31(21,D,E,T,A,B,C,W,W,W,X); + BODY_20_31(22,C,D,E,T,A,B,W,W,W,X); + BODY_20_31(23,B,C,D,E,T,A,W,W,W,X); + BODY_20_31(24,A,B,C,D,E,T,W,W,X,X); + BODY_20_31(25,T,A,B,C,D,E,W,W,X,X); + BODY_20_31(26,E,T,A,B,C,D,W,W,X,X); + BODY_20_31(27,D,E,T,A,B,C,W,W,X,X); + BODY_20_31(28,C,D,E,T,A,B,W,W,X,X); + BODY_20_31(29,B,C,D,E,T,A,W,W,X,X); + BODY_20_31(30,A,B,C,D,E,T,W,X,X,X); + BODY_20_31(31,T,A,B,C,D,E,W,X,X,X); + BODY_32_39(32,E,T,A,B,C,D,X); + BODY_32_39(33,D,E,T,A,B,C,X); + BODY_32_39(34,C,D,E,T,A,B,X); + BODY_32_39(35,B,C,D,E,T,A,X); + BODY_32_39(36,A,B,C,D,E,T,X); + BODY_32_39(37,T,A,B,C,D,E,X); + BODY_32_39(38,E,T,A,B,C,D,X); + BODY_32_39(39,D,E,T,A,B,C,X); + + BODY_40_59(40,C,D,E,T,A,B,X); + BODY_40_59(41,B,C,D,E,T,A,X); + BODY_40_59(42,A,B,C,D,E,T,X); + BODY_40_59(43,T,A,B,C,D,E,X); + BODY_40_59(44,E,T,A,B,C,D,X); + BODY_40_59(45,D,E,T,A,B,C,X); + BODY_40_59(46,C,D,E,T,A,B,X); + BODY_40_59(47,B,C,D,E,T,A,X); + BODY_40_59(48,A,B,C,D,E,T,X); + BODY_40_59(49,T,A,B,C,D,E,X); + BODY_40_59(50,E,T,A,B,C,D,X); + BODY_40_59(51,D,E,T,A,B,C,X); + BODY_40_59(52,C,D,E,T,A,B,X); + BODY_40_59(53,B,C,D,E,T,A,X); + BODY_40_59(54,A,B,C,D,E,T,X); + BODY_40_59(55,T,A,B,C,D,E,X); + BODY_40_59(56,E,T,A,B,C,D,X); + BODY_40_59(57,D,E,T,A,B,C,X); + BODY_40_59(58,C,D,E,T,A,B,X); + BODY_40_59(59,B,C,D,E,T,A,X); + + BODY_60_79(60,A,B,C,D,E,T,X); + BODY_60_79(61,T,A,B,C,D,E,X); + BODY_60_79(62,E,T,A,B,C,D,X); + BODY_60_79(63,D,E,T,A,B,C,X); + BODY_60_79(64,C,D,E,T,A,B,X); + BODY_60_79(65,B,C,D,E,T,A,X); + BODY_60_79(66,A,B,C,D,E,T,X); + BODY_60_79(67,T,A,B,C,D,E,X); + BODY_60_79(68,E,T,A,B,C,D,X); + BODY_60_79(69,D,E,T,A,B,C,X); + BODY_60_79(70,C,D,E,T,A,B,X); + BODY_60_79(71,B,C,D,E,T,A,X); + BODY_60_79(72,A,B,C,D,E,T,X); + BODY_60_79(73,T,A,B,C,D,E,X); + BODY_60_79(74,E,T,A,B,C,D,X); + BODY_60_79(75,D,E,T,A,B,C,X); + BODY_60_79(76,C,D,E,T,A,B,X); + BODY_60_79(77,B,C,D,E,T,A,X); + BODY_60_79(78,A,B,C,D,E,T,X); + BODY_60_79(79,T,A,B,C,D,E,X); + + c->h0=(c->h0+E)&0xffffffffL; + c->h1=(c->h1+T)&0xffffffffL; + c->h2=(c->h2+A)&0xffffffffL; + c->h3=(c->h3+B)&0xffffffffL; + c->h4=(c->h4+C)&0xffffffffL; + + num-=64; + if (num <= 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + W+=16; + } +#else /* SMALL_CODE_SIZE */ + SHA_LONG A,B,C,D,E,T; + SHA_LONG X[16]; + SHA_LONG *a1,*a2,*a3; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + int i; + + for (i=0; i<16; i++) + { + BODY_00_15(i,A,B,C,D,E,T,W); + E=D; D=C; C=B; B=A; A=T; + } + + a1=W; + for (i=16; i<20; i++) + { + if (i == 19) a1=X; + BODY_16_19(i,A,B,C,D,E,T,W,W,W,a1); + E=D; D=C; C=B; B=A; A=T; + } + + a1=a2=a3=W; + for (i=20; i<40; i++) + { + if (i == 24) a3=X; + if (i == 30) a2=X; + if (i == 32) a1=X; + BODY_20_31(i,A,B,C,D,E,T,a1,a2,a3,X); + E=D; D=C; C=B; B=A; A=T; + } + + for (i=40; i<60; i++) + { + BODY_40_59(i,A,B,C,D,E,T,X); + E=D; D=C; C=B; B=A; A=T; + } + + for (i=60; i<80; i++) + { + BODY_60_79(i,A,B,C,D,E,T,X); + E=D; D=C; C=B; B=A; A=T; + } + + c->h0=(c->h0+A)&0xffffffffL; + c->h1=(c->h1+B)&0xffffffffL; + c->h2=(c->h2+C)&0xffffffffL; + c->h3=(c->h3+D)&0xffffffffL; + c->h4=(c->h4+E)&0xffffffffL; + + num-=64; + if (num <= 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + W+=16; + } +#endif /* SMALL_CODE_SIZE */ + } + +void SHA1_Final(md, c) +unsigned char *md; +SHA_CTX *c; + { + register int i,j; + register SHA_LONG l; + register SHA_LONG *p; + const static unsigned char end[4]={0x80,0x00,0x00,0x00}; + unsigned char *cp= (unsigned char *)end; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + j=c->num; + i=j>>2; + +#ifdef PURIFY + /* PURIFY */ + /* we reference uninitialised data but don't keep the result + * which purify complains about ... and we don't want to have + * to come back here to find a non-existant problem later + */ + + /* purify often complains about the following line as an + * Uninitialized Memory Read. While this can be true, the + * following p_c2l macro will reset l when that case is true. + * This is because j&0x03 contains the number of 'valid' bytes + * already in p[i]. If and only if j&0x03 == 0, the UMR will + * occur but this is also the only time p_c2l will do + * l= *(cp++) instead of l|= *(cp++) + */ + if ((j&0x03) == 0) p[i]=0; +#endif + + l=p[i]; + M_p_c2nl(cp,l,j&0x03); + p[i]=l; + i++; + /* i is the next 'undefined word' */ + if (c->num >= SHA_LAST_BLOCK) + { + for (; isha_block(c,(unsigned char *)p,64); + i=0; + } + for (; i<(SHA_LBLOCK-2); i++) + p[i]=0; + p[SHA_LBLOCK-2]=c->Nh; + p[SHA_LBLOCK-1]=c->Nl; +#if defined(L_ENDIAN) + Endian_Reverse32(p[SHA_LBLOCK-2]); + Endian_Reverse32(p[SHA_LBLOCK-1]); +#endif + c->sha_block(c,(unsigned char *)p,64); + cp=md; + l=c->h0; nl2c(l,cp); + l=c->h1; nl2c(l,cp); + l=c->h2; nl2c(l,cp); + l=c->h3; nl2c(l,cp); + l=c->h4; nl2c(l,cp); + + /* clear stuff, sha1_block may be leaving some stuff on the stack + * but I'm not worried :-) */ + c->num=0; +/* Memset((char *)&c,0,sizeof(c));*/ + } +#endif + +#if 0 +int pr(ctx) +SHA_CTX *ctx; + { + int i,j; + unsigned char *p=(unsigned char *)(ctx->data); + + fprintf(stderr,"num = %08X%08X\n",ctx->Nh,ctx->Nl); + fprintf(stderr," %08X %08X %08X %08X %08X\n", + ctx->h0,ctx->h1,ctx->h2,ctx->h3,ctx->h4); + fprintf(stderr,"bufnum = %d\n",ctx->num); + fprintf(stderr," "); + for (j=0; j<64; j+=16) + { + for (i=0; i<16; i++) + { +/* + if ((i+j) >= ctx->num) + fprintf(stderr,"--"); + else +*/ + fprintf(stderr,"%02X",p[i+j]); + } + if ((j+16) >=64) + fprintf(stderr,"\n"); + else + fprintf(stderr,"\n "); + } + } + +#endif + +#endif /* NO_SHA1 */ diff --git a/build/tools/makegcdfirm/Makefile b/build/tools/makegcdfirm/Makefile new file mode 100644 index 0000000..7158170 --- /dev/null +++ b/build/tools/makegcdfirm/Makefile @@ -0,0 +1,151 @@ +#! make -f +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makegcdfirm +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#--------------------------------------------------------------------------- + +TARGET_PLATFORM = TWL + +SUPPORT_ECC = 0 + +ifeq ($(SUPPORT_ECC),1) +ECC_SRCDIR = ../../libraries/acsign_ecc/common \ + ../../libraries/acsign_ecc/common/algae/common/ecc \ + ../../libraries/acsign_ecc/common/algae/cmp \ + ../../libraries/acsign_ecc/common/algae/ecsource \ + +ECC_INCDIR = ../../libraries/acsign_ecc/include \ + ../../libraries/acsign_ecc/common/algae/include \ + ../../libraries/acsign_ecc/common/algae/common/include \ + +ECC_SRCS = acsign_ecc.c acsign_cryptoc.c \ + \ + cmparith.c cmpbits.c cmpcnv.c cmpdiv.c cmpmem.c \ + cmpmod.c cmpmuldv.c cmpspprt.c cmpsqr.c cmpvectr.c \ + computem.c ecfpatbl.c ecfpsmul.c \ + spcprime.c secfpcom.c \ + \ + p224v1.c p224v1a.c \ + +ECC_DEFS = -DRSA_PROTOTYPES=RSA_ENABLED \ + -DRCOM_BUILD=RSA_ENABLED -DRSA_FAST_INVERSE=RSA_ENABLED \ + -DRSA_STD_MEM_FUNCS=RSA_ENABLED -DRSA_STD_ALLOC_FUNCS=RSA_ENABLED \ +else +ECC_SRCDIR = +ECC_INCDIR = +ECC_SRCS = +ECC_DEFS = +endif + +SRCDIR += ../acsign $(ECC_SRCDIR) +INCDIR += ../acsign/include $(ECC_INCDIR) $(ECC_SRCDIR) + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +TARGETS = makegcdfirm.exe + +SOURCES_C = makegcdfirm.c \ + out_gcdfirm.c \ + misc.c \ + path.c \ + defval.c \ + compress.c \ + wram_regs.c \ + acsign.c \ + acsign_gcd.c \ + aes2.c \ + $(ECC_SRCS) + +SOURCES = $(SORUCES_C) + +OBJECTS = $(SOURCES_C:.c=.o) + +HEADERS = format_nlist.h \ + makegcdfirm.h \ + path.h \ + format_rom.h \ + misc.h \ + defval.h \ + compress.h \ + +MACROS += -DSMALL_CODE_SIZE \ + -DSTANDALONE \ + -DOPT_32_BIT \ + -DNO_SPLIT \ + -DNO_FP_API \ + -DNO_R_DIAG \ + $(ECC_DEFS) + +INSTALL_DIR = $(FIRM_INSTALL_TOOLSDIR)/bin +INSTALL_TARGETS = $(TARGETS) + +LDIRT_CLEAN = $(OBJECTS) $(TARGETS) version.h + + +VPATH = $(SRCDIR) +TWL_INCDIR := $(TWL_INCDIR) $(addprefix -I,$(INCDIR)) $(addprefix -I,$(FIRM_INCDIR)) + +include $(TWLSDK_ROOT)/build/buildtools/twl/modulerules.x86 + +#---------------------------------------------------------------------------- +# build +#---------------------------------------------------------------------------- +do-build: $(TARGETS) + +$(TARGETS): $(OBJECTS) + $(CC_X86) $+ -o $@ + +makegcdfirm.o: makegcdfirm.c makegcdfirm.h format_rom.h path.h version.h +out_gcdfirm.o: out_gcdfirm.c misc.h format_rom.h format_nlist.h format_sign.h elf.h compress.h \ + $(FIRM_INCDIR)/firm/format/sign.h \ + $(FIRM_INCDIR)/firm/format/wram_regs.h \ + $(FIRM_INCDIR)/firm/format/gcdfirm.h \ + +misc.o: misc.c misc.h +path.o: path.c path.h +compress.o: compress.c compress.h +wram_regs.o: wram_regs.c +acsign.o: acsign.c ../acsign/include/acsign.h +acsign_gcd.o: acsign_gcd.c format_sign.h \ + $(FIRM_INCDIR)/firm/format/sign.h \ + $(FIRM_INCDIR)/firm/format/wram_regs.h \ + $(FIRM_INCDIR)/firm/format/gcdfirm.h \ + +aes2.o: aes2.c aes2.h + +$(FIRM_INCDIR)/firm/format/sign.h: +$(FIRM_INCDIR)/firm/format/wram_regs.h: +$(FIRM_INCDIR)/firm/format/gcdfirm.h: +format_nlist.h: +format_rom.h: +makegcdfirm.h: +acsign.h: +acsign_gcd.h: +path.h: + +# avoid to warning message +misc.o:WARNING += -Wno-format-y2k + +# + +version.h: $(SOURCES) $(HEADERS) + @for i in $^ ; \ + do \ + date -r $$i +'#define SDK_DATE_OF_LATEST_FILE %Y%m%dUL'; \ + done | sort | tail -1 > $@ + +test: path.c misc.c + $(CC_X86) -DTEST $+ -o $@ diff --git a/build/tools/makegcdfirm/compress.c b/build/tools/makegcdfirm/compress.c new file mode 100644 index 0000000..6a8c403 --- /dev/null +++ b/build/tools/makegcdfirm/compress.c @@ -0,0 +1,293 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makegcdfirm + File: compress.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include // atoi() +#include // strcmp() +#include // isprint() +#include // chdir() +#include +#include // UCHAR_MAX +#include +#include // stat() +#include "elf.h" +#include "misc.h" +#include "defval.h" +#include "format_rom.h" +#include "format_nlist.h" +#include "makegcdfirm.h" + +//#define ADD_HEADER + +#define DIFF_CODE_HEADER (0x80) +#define RL_CODE_HEADER (0x30) +#define LZ_CODE_HEADER (0x10) +#define HUFF_CODE_HEADER (0x20) +#define CODE_HEADER_MASK (0xF0) + +//=========================================================================== +// LZ77k +//=========================================================================== +static u8 SearchLZ(const u8 *nextp, u32 remainSize, u16 *offset); + +static u16 windowPos; +static u16 windowLen; + +static s16 LZOffsetTable[4096]; +static s16 LZByteTable[256]; +static s16 LZEndTable[256]; + + +static void LZInitTable(void) +{ + u16 i; + + for (i = 0; i < 256; i++) + { + LZByteTable[i] = -1; + LZEndTable[i] = -1; + } + windowPos = 0; + windowLen = 0; +} + +static void SlideByte(const u8 *srcp) +{ + s16 offset; + u8 in_data = *srcp; + u16 insert_offset; + + if (windowLen == 4096) + { + u8 out_data = *(srcp - 4096); + if ((LZByteTable[out_data] = LZOffsetTable[LZByteTable[out_data]]) == -1) + { + LZEndTable[out_data] = -1; + } + insert_offset = windowPos; + } + else + { + insert_offset = windowLen; + } + + offset = LZEndTable[in_data]; + if (offset == -1) + { + LZByteTable[in_data] = insert_offset; + } + else + { + LZOffsetTable[offset] = insert_offset; + } + LZEndTable[in_data] = insert_offset; + LZOffsetTable[insert_offset] = -1; + + if (windowLen == 4096) + { + windowPos = (u16)((windowPos + 1) % 0x1000); + } + else + { + windowLen++; + } +} + +static void LZSlide(const u8 *srcp, u32 n) +{ + u32 i; + + for (i = 0; i < n; i++) + { + SlideByte(srcp++); + } +} + +/*---------------------------------------------------------------------------* + Name: MI_CompressLZ + + Description: LZ77ksȂ֐ + + Arguments: srcp kf[^ւ̃|C^ + size kf[^TCY + dstp kf[^ւ̃|C^ + kf[^傫TCỸobt@KvłB + + Returns: k̃f[^TCYB + k̃f[^kO傫Ȃꍇɂ͈k𒆒f0Ԃ܂B + *---------------------------------------------------------------------------*/ +u32 LZCompWrite(u8 *srcp, u32 size, u8 *dstp, int boundary) +{ + u32 LZDstCount; // kf[^̃oCg + u8 LZCompFlags; // k̗LtOn + u8 *LZCompFlagsp; // LZCompFlags i[郁̈|Cg + u16 lastOffset; // vf[^܂ł̃ItZbg (̎_ł̍Œvf[^) + u8 lastLength; // vf[^ (̎_ł̍Œvf[^) + u8 i; + u32 dstMax; + +#ifdef ADD_HEADER + *(u32 *)dstp = size << 8 | LZ_CODE_HEADER; // f[^Ewb_ + dstp += 4; +#endif + LZDstCount = 4; + dstMax = size; + LZInitTable(); + + while (size > 0) + { + LZCompFlags = 0; + LZCompFlagsp = dstp++; // tOn̊i[ + LZDstCount++; + + // tOn8rbgf[^ƂĊi[邽߁A8񃋁[v + for (i = 0; i < 8; i++) + { + LZCompFlags <<= 1; // (i=0) ͓ɈӖ͂Ȃ + if (size <= 0) + { + // I[ɗꍇ̓tOŌ܂ŃVtgĂI + continue; + } + + if ((lastLength = SearchLZ(srcp, size, &lastOffset))) + { + // k”\ȏꍇ̓tO𗧂Ă + LZCompFlags |= 0x1; + + // ItZbg͏4rbgƉ8rbgɕĊi[ + *dstp++ = (u8)((lastLength - 3) << 4 | (lastOffset - 1) >> 8); + *dstp++ = (u8)((lastOffset - 1) & 0xff); + LZDstCount += 2; + LZSlide(srcp, lastLength); + srcp += lastLength; + size -= lastLength; + } + else + { + // kȂ + LZSlide(srcp, 1); + *dstp++ = *srcp++; + size--; + LZDstCount++; + } + } // 8񃋁[vI + *LZCompFlagsp = LZCompFlags; // tOni[ + } + + // 16oCgEACg + // ACgpf[^0 ̓f[^TCYɊ܂߂ + i = 0; + while (LZDstCount & (boundary - 1)) +// while ((LZDstCount + i) & 0x3) + { + *dstp++ = 0; + LZDstCount++; + i++; + } + + return LZDstCount; +} + +//-------------------------------------------------------- +// LZ77kŃXCh̒Œv܂B +// Arguments: startp f[^̊Jnʒu|C^ +// nextp Jnf[^̃|C^ +// remainSize cf[^TCY +// offset vItZbgi[̈ւ̃|C^ +// Return : v񂪌‚ꍇ TRUE +// ‚Ȃꍇ FALSE +//-------------------------------------------------------- +static u8 SearchLZ(const u8 *nextp, u32 remainSize, u16 *offset) +{ + const u8 *searchp; + const u8 *headp, *searchHeadp; + u16 maxOffset; + u8 maxLength = 2; + u8 tmpLength; + s32 w_offset; + + if (remainSize < 3) + { + return 0; + } + + w_offset = LZByteTable[*nextp]; + + while (w_offset != -1) + { + if (w_offset < windowPos) + { + searchp = nextp - windowPos + w_offset; + } + else + { + searchp = nextp - windowLen - windowPos + w_offset; + } + + /* ĂǂA͂ɍ */ + if (*(searchp + 1) != *(nextp + 1) || *(searchp + 2) != *(nextp + 2)) + { + w_offset = LZOffsetTable[w_offset]; + continue; + } + + if (nextp - searchp < 2) + { + // VRAM2oCgANZXȂ̂ (VRAMf[^ǂݏoꍇ邽)A + // Ώۃf[^2oCgÕf[^ɂȂ΂ȂȂB + // + // ItZbg12rbgŊi[邽߁A4096ȉ + break; + } + tmpLength = 3; + searchHeadp = searchp + 3; + headp = nextp + 3; + + while (((u32)(headp - nextp) < remainSize) && (*headp == *searchHeadp)) + { + headp++; + searchHeadp++; + tmpLength++; + + // f[^4rbgŊi[邽߁A18ȉ (3̉ʂ͂) + if (tmpLength == (0xF + 3)) + { + break; + } + } + if (tmpLength > maxLength) + { + // ő咷ItZbgXV + maxLength = tmpLength; + maxOffset = (u16)(nextp - searchp); + if (maxLength == (0xF + 3)) + { + // vőȂ̂ŁAIB + break; + } + } + w_offset = LZOffsetTable[w_offset]; + } + + if (maxLength < 3) + { + return 0; + } + *offset = maxOffset; + return maxLength; +} + diff --git a/build/tools/makegcdfirm/compress.h b/build/tools/makegcdfirm/compress.h new file mode 100644 index 0000000..e3dc58f --- /dev/null +++ b/build/tools/makegcdfirm/compress.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: compress.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef COMPRESS_H_ +#define COMPRESS_H_ + +#include "misc.h" + + +/*---------------------------------------------------------------------------* + Name: MI_CompressLZ + + Description: LZ77ksȂ֐ + + Arguments: srcp kf[^ւ̃|C^ + size kf[^TCY + dstp kf[^ւ̃|C^ + kf[^傫TCỸobt@KvłB + + Returns: k̃f[^TCYB + *---------------------------------------------------------------------------*/ +u32 LZCompWrite(u8 *srcp, u32 size, u8 *dstp, int boundary); + + +#endif //COMPRESS_H_ diff --git a/build/tools/makegcdfirm/defval.c b/build/tools/makegcdfirm/defval.c new file mode 100644 index 0000000..679fb0e --- /dev/null +++ b/build/tools/makegcdfirm/defval.c @@ -0,0 +1,315 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makerom + File: defval.c + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: defval.c,v $ + Revision 1.10 2006/01/18 02:11:19 kitase_hirotake + do-indent + + Revision 1.9 2005/02/28 05:26:03 yosizaki + do-indent. + + Revision 1.8 2004/08/05 13:50:13 yasu + Support -M option + + Revision 1.7 2004/06/29 04:55:40 yasu + Use VBuffer to resolve variables + + Revision 1.6 2004/06/23 07:51:02 yasu + fix a bug as illegal memory freeing at ResolveDefVal() + + Revision 1.5 2004/05/27 00:40:49 yasu + care also about current directory (dot ".") + + Revision 1.4 2004/05/27 00:25:46 yasu + care about double-dots ".." for defvalue option :r, :e + + Revision 1.3 2004/05/27 00:11:19 yasu + fix a error when searching a "dot" of file extension + + Revision 1.2 2004/05/26 12:02:47 yasu + support :h, :t, :r, :e option for variable name + + Revision 1.1 2004/03/26 05:06:45 yasu + support variables like as -DNAME=VALUE + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +#include // getenv() +#include // strcasecmp() +#include // getopt() +#include "misc.h" +#include "defval.h" + +typedef struct tValdef +{ + struct tValdef *next; + char *name; + char *value; +} +tValdef; + +tValdef *valdef_top = NULL; + + +// +// Add new define value via file +// +// opt : "DEFINE=VALUE" +// +BOOL AddDefValFromFile(char *filename) +{ + char *buffer; + int buffer_size; + int read_size; + FILE *fp; + + if (filename[0] == '-' && filename[1] == '\0') + { + fp = stdin; + } + else if (NULL == (fp = fopen(filename, "rb"))) + { + fprintf(stderr, "Cannot open file \"%s\".\n", filename); + return FALSE; + } + + buffer_size = DEFVAL_DEFAULT_BUFFER_SIZE; + + if (NULL == (buffer = malloc(buffer_size))) + { + fprintf(stderr, "Cannot allocate memory.\n"); + return FALSE; + } + + read_size = 0; + + while (NULL != fgets(buffer + read_size, buffer_size - read_size, fp)) + { + read_size = strlen(buffer); + + if (read_size == buffer_size - 1 && buffer[read_size - 1] != '\n') + { + buffer_size *= 2; + + if (NULL == (buffer = realloc(buffer, buffer_size))) + { + fprintf(stderr, "Cannot allocate memory.\n"); + return FALSE; + } + continue; + } + + AddDefVal(buffer); + read_size = 0; + } + + if (fp != stdin) + { + fclose(fp); + } + free(buffer); + + return TRUE; +} + + +// +// Add new define value +// +// opt : "DEFINE=VALUE" +// +void AddDefVal(char *opt) +{ + int i; + tValdef *t; + + for (i = 0;; i++) + { + if ('=' == opt[i] || '\0' == opt[i]) + { + break; + } + } + + if (i > 0) + { + t = Alloc(sizeof(tValdef)); + t->name = strncpy(Alloc(i + 1), opt, i); + t->name[i] = '\0'; + + if (opt[i] == '=') + { + i++; + } + t->value = strdup(opt + i); + + t->next = valdef_top; + valdef_top = t; + + debug_printf("DEFINE:$(%s)=\"%s\"\n", t->name, t->value); + } + return; +} + +// +// Search define value +// +// Return: value of specified name +// +char *SearchDefVal(char *name) +{ + tValdef *t; + + for (t = valdef_top; t; t = t->next) + { + if (!strcmp(t->name, name)) + { + return t->value; + } + } + + return getenv(name); +} + + +// +// Search define value and Modify it by : option +// +// Return: duplicated value of specified name modified by :x option +// +char *SearchDefValWithOption(char *name) +{ + int len_name = strlen(name); + char *value; + char option = '\0'; + + if (len_name > 2 && name[len_name - 2] == ':') + { + name[len_name - 2] = '\0'; + option = name[len_name - 1]; + } + + value = SearchDefVal(name); + + if (value) + { + int value_len = strlen(value); + int col_dot = value_len; + int col_filename = 0; + int i; + + for (i = 0; i < value_len; i++) + { + switch (value[i]) + { + case '.': + if (col_filename == i && + (value[i + 1] == '\0' || (value[i + 1] == '.' && value[i + 2] == '\0'))) + { + i = value_len; // exit loop if last entry is . or .. + } + else + { + col_dot = i; // Save the last dot column + } + break; + + case '/': + case '\\': + case ':': + col_filename = i + 1; // Save the last filename + col_dot = value_len; // Reset dot position + break; + + default: + ; + } + } + + switch (option) + { + case 'h': // Dirname with the last slash + value = strdup(value); + value[col_filename] = '\0'; + break; + + case 't': // Filename + value = strdup(value + col_filename); + break; + + case 'r': // All without . file extension + value = strdup(value); + value[col_dot] = '\0'; + break; + + case 'e': // File extension + value = strdup(value + col_dot + 1); + break; + + default: + value = strdup(value); + } + } + return value; +} + + +// +// Resolve define value +// +// Return: new string +// +char *ResolveDefVal(char *str) +{ + int i, j; + char *val; + VBuffer buf; + + InitVBuffer(&buf); + + for (i = 0; '\0' != str[i]; i++) + { + // search $(XXX) + if ('$' == str[i] && '(' == str[i + 1]) + { + for (j = i + 2; '\0' != str[j]; j++) + { + if (')' == str[j]) + { + str[j] = '\0'; + + // get value of XXX + val = SearchDefValWithOption(&str[i + 2]); + + // copy value of XXX + if (val) + { + char *s = val; + + while (*s) + { + PutVBuffer(&buf, *s); + s++; + } + free(val); + } + i = j; + goto next; + } + } + } + PutVBuffer(&buf, str[i]); + next:; + } + return GetVBuffer(&buf); // pass allocated buffer, should be freed by caller +} diff --git a/build/tools/makegcdfirm/defval.h b/build/tools/makegcdfirm/defval.h new file mode 100644 index 0000000..7135510 --- /dev/null +++ b/build/tools/makegcdfirm/defval.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makerom + File: defval.h + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: defval.h,v $ + Revision 1.4 2006/01/18 02:11:19 kitase_hirotake + do-indent + + Revision 1.3 2005/02/28 05:26:03 yosizaki + do-indent. + + Revision 1.2 2004/08/05 13:50:13 yasu + Support -M option + + Revision 1.1 2004/03/26 05:06:45 yasu + support variables like as -DNAME=VALUE + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef DEFVAL_H_ +#define DEFVAL_H_ + +#define DEFVAL_DEFAULT_BUFFER_SIZE (1024) + +BOOL AddDefValFromFile(char *filename); +void AddDefVal(char *opt); +char *SearchDefVal(char *name); +char *ResolveDefVal(char *str); + +#endif //DEFVAL_H_ diff --git a/build/tools/makegcdfirm/elf.h b/build/tools/makegcdfirm/elf.h new file mode 100644 index 0000000..c360cd3 --- /dev/null +++ b/build/tools/makegcdfirm/elf.h @@ -0,0 +1,431 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - ELF + File: elf.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + *---------------------------------------------------------------------------*/ + +#ifndef ELF_H_ +#define ELF_H_ + +#include "misc.h" + +/*--------------------------------------------------------- + ^` + --------------------------------------------------------*/ +typedef u32 Elf32_Addr; /* size:4, align:4 Unsigned program address */ +typedef u16 Elf32_Half; /* size:2, align:2 Unsigned medium int */ +typedef u32 Elf32_Off; /* size:4, align:4 Unsigned file offset */ +typedef s32 Elf32_Sword; /* size:4, align:4 Signed large int */ +typedef u32 Elf32_Word; /* size:4, align:4 Unsigned large int */ + +/*--------------------------------------------------------- + ELF Header + --------------------------------------------------------*/ +/* e_ident̃CfbNX */ +#define EI_MAG0 0 /* File identification */ +#define EI_MAG1 1 /* File identification */ +#define EI_MAG2 2 /* File identification */ +#define EI_MAG3 3 /* File identification */ +#define EI_CLASS 4 /* File class 0=invalid, 1=32bit, 2=64bit */ +#define EI_DATA 5 /* Data encoding 0=invalid, 1=LSB, 2=MSB */ +#define EI_VERSION 6 /* File version ݂1 */ +#define EI_PAD 7 /* Start of padding bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; /* ELF̌`(Ĕzu”\, s”\Ȃ) */ + Elf32_Half e_machine; /* t@CŗvA[LeN` */ + Elf32_Word e_version; /* ELFtH[}bg̃o[Wi݂1j */ + Elf32_Addr e_entry; /* vÕGg|CgBw薳Ȃ0B */ + Elf32_Off e_phoff; /* vOwb_e[ũt@C擪̃ItZbg */ + Elf32_Off e_shoff; /* ZNVwb_e[ũt@C擪̃ItZbg */ + Elf32_Word e_flags; /* vZbTŗL̃tO */ + Elf32_Half e_ehsize; /* ELFwb_̃TCY */ + Elf32_Half e_phentsize; /* 1vOwb_̃TCY */ + Elf32_Half e_phnum; /* vOwb_̐ */ + Elf32_Half e_shentsize; /* 1ZNVwb_̃TCY */ + Elf32_Half e_shnum; /* ZNVwb_̐ */ + Elf32_Half e_shstrndx; /* ZNVe[uZNVւ̃CfbNX */ +} Elf32_Ehdr; + +/* e_ident[EI_*]̒g` */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFCLASSNONE 0 /* invalid */ +#define ELFCLASS32 1 /* ARM and Thumb processors use 32-bit ELF. */ +#define ELFCLASS64 2 +#define ELFDATANONE 0 /* invalid */ +#define ELFDATA2LSB 1 /* little-endian */ +#define ELFDATA2MSB 2 /* big-endian */ + + +/* [e_type] */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Re-locatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOPROC 0xff00 /* Processor-specific */ +#define ET_HIPROC 0xffff /* Processor-specific */ + +/* [e_machine] */ +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_860 7 +#define EM_MIPS 8 +#define EM_MIPS_RS4_BE 10 +#define EM_ARM 40 /* ARM/Thumb Architecture */ + + +/* [e_version] This member identifies the object file version.*/ +#define EV_NONE 0 /* Invalid version */ +#define EV_CURRENT 1 /* Current version */ + + +/* + ARM-specific e_flags + e_flags Field Value Meaning + EF_ARM_HASENTRY (0x02) e_entry contains a program-loader entry point + (see section 4.1.1, Entry points, below). + EF_ARM_SYMSARESORTED (0x04) Each subsection of the symbol table is sorted by symbol value + (see section 4.4.8, Symbol table order, below) + EF_ARM_DYNSYMSUSESEGIDX (0x8) Symbols in dynamic symbol tables that are defined in sections + included in program segment n have st_shndx = n + 1. + (see section 4.4.9, Dynamic symbol table entries, below). + EF_ARM_MAPSYMSFIRST (0x10) Mapping symbols precede other local symbols in the symbol table + (see section 4.4.8, Symbol table order, below). + + EF_ARM_EABIMASK (0xFF000000)(current version is 0x02000000) + This masks an 8-bit version number, the version of the ARM + EABI to which this ELF file conforms. This EABI is version 2. A + value of 0 denotes unknown conformance. +*/ +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x8 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0xFF000000 + + +/*--------------------------------------------------------- + Program headers + --------------------------------------------------------*/ +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* [p_type] */ +#define PT_NULL 0 /* gȂGgŁÃo̒l̈Ӗ͖` */ +#define PT_LOAD 1 /* sɃ[hZOg */ +#define PT_DYNAMIC 2 /* I\̔zێZOg */ +#define PT_INTERP 3 /* t@C̉߂ɎgC^v^̃pXێZOg */ +#define PT_NOTE 4 /* t@C̉߂ɂ͎gȂێZOg */ +#define PT_SHLIB 5 /* \ */ +#define PT_PHDR 6 /* vOwb_e[uivÕC[Ẅꕔłꍇ̂ݑ݁j */ +//#define PT_TLS ? /* XbhǏL̈̃ev[g */ + +#define PT_LOOS 0x60000000 /* OSŗLɗ\񂳂ꂽ̈ */ +#define PT_HIOS 0x6fffffff + +#define PT_LOPROC 0x70000000 /* vZbTŗLɗ\񂳂ꂽ̈ */ +#define PT_HIPROC 0x7fffffff + +/* [p_flags]*/ +#define PF_X 1 /*s”\*/ +#define PF_W 2 /*݉”\*/ +#define PF_R 4 /*ǂݏo”\*/ +#define PF_ARM_SB 0x10000000 /*The segment contains the location addressed by the static base*/ +#define PF_ARM_PI 0x20000000 /*The segment is position-independent*/ +#define PF_ARM_ENTRY 0x80000000 /*The segment contains the entry point*/ +#define PF_MASKPROC 0xf0000000 + + +/*--------------------------------------------------------- + Section headers + --------------------------------------------------------*/ +typedef struct { + Elf32_Word sh_name; /*ZNVwb_e[uZNṼCfbNX*/ + Elf32_Word sh_type; /* ^CviL`QƁj */ + Elf32_Word sh_flags; + Elf32_Addr sh_addr; /* */ + Elf32_Off sh_offset; /* t@C̐擪̃ItZbg */ + Elf32_Word sh_size; /* oCgPʂ̃TCY */ + Elf32_Word sh_link; /* sh_typeɂĒl̈Ӗς */ + Elf32_Word sh_info; /* sh_typeɂĒl̈Ӗς */ + Elf32_Word sh_addralign; /* ACg(0or1ŐȂ,44ByteAlign) */ + Elf32_Word sh_entsize; /* ŒTCỸGge[uꍇA1vf̃TCY */ +} Elf32_Shdr; + +/* sh_addr mod sh_addralign = 0 łȂ΂ȂȂ */ + +/* Section Types, [sh_type] */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + + +/* [sh_flags] */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 +/* ARM-EABI-specific */ +#define SHF_ENTRYSECT 0x10000000 /* The section contains an entry point. */ +#define SHF_COMDEF 0x80000000 /* The section may be multiply defined in the input to a link step. */ +/* others */ +#define SHF_LINK_ORDER 0x80 + +/*ZNVCfbNX*/ +//Sym->st_shndxȂ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + + +//̓wb_łȂ̃f[^\ + +/*--------------------------------------------------------- + Symbol Table Entry + --------------------------------------------------------*/ +typedef struct { + Elf32_Word st_name; /* V{e[ũCfbNX */ + Elf32_Addr st_value; /* 炭֘AZNVł̃ItZbgl */ + Elf32_Word st_size; /* TCYȂAsȏꍇ 0 */ + unsigned char st_info; /* oCh ^Cv */ + unsigned char st_other; /* ݂ 0 */ + Elf32_Half st_shndx; /* ֘AZNVwb_e[ũCfbNX */ +} Elf32_Sym; + + +/* st_info */ +#define ELF32_ST_BIND(i) ((i)>>4) +#define ELF32_ST_TYPE(i) ((i)&0xf) +#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + +/* st_info BIND */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +/* st_info TYPE */ +#define STT_NOTYPE 0 /*`*/ +#define STT_OBJECT 1 /*f[^IuWFNg*/ +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + + +/*--------------------------------------------------------- + Relocation Entry + --------------------------------------------------------*/ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) + + +/* r_info TYPE */ +#define R_ARM_NONE 0 /* Any No relocation. Encodes dependencies between sections. */ +#define R_ARM_PC24 1 /* ARM B/BL S . P + A */ +#define R_ARM_ABS32 2 /* 32-bit word S + A */ +#define R_ARM_REL32 3 /* 32-bit word S . P + A */ +#define R_ARM_PC13 4 /* ARM LDR r, [pc,c] S . P + A */ +#define R_ARM_ABS16 5 /* 16-bit half-word S + A */ +#define R_ARM_ABS12 6 /* ARM LDR/STR S + A */ +#define R_ARM_THM_ABS5 7 /* Thumb LDR/STR S + A */ +#define R_ARM_ABS8 8 /* 8-bit byte S + A */ +#define R_ARM_SBREL32 9 /* 32-bit word S . B + A */ +#define R_ARM_THM_PC22 10 /* Thumb BL pair S . P+ A */ +#define R_ARM_THM_PC8 11 /* Thumb LDR r, [pc,c] S . P + A */ +#define R_ARM_AMP_VCALL9 12 /* AMP VCALL Obsolete.SA-1500 only. */ +#define R_ARM_SWI24 13 /* ARM SWI S + A */ +#define R_ARM_THM_SWI8 14 /* Thumb SWI S + A */ +#define R_ARM_XPC25 15 /* ARM BLX S . P+ A */ +#define R_ARM_THM_XPC22 16 /* Thumb BLX pair S . P+ A */ + +/* 17-31, reserved to ARM Linux */ +//17-19 Reserved to ARM LINUX +#define R_ARM_COPY 20 /* 32 bit word Copy symbol at dynamic link time. */ +#define R_ARM_GLOB_DAT 21 /* 32 bit word Create GOT entry. */ +#define R_ARM_JUMP_SLOT 22 /* 32 bit word Create PLT entry. */ +#define R_ARM_RELATIVE 23 /* 32 bit word Adjust by program base. */ +#define R_ARM_GOTOFF 24 /* 32 bit word Offset relative to start of GOT. */ +#define R_ARM_GOTPC 25 /* 32 bit word Insert address of GOT. */ +#define R_ARM_GOT32 26 /* 32 bit word Entry in GOT. */ +#define R_ARM_PLT32 27 /* ARM BL Entry in PLT. */ + +/* 28-31 Reserved to ARM LINUX */ +#define R_ARM_ALU_PCREL_7_0 32 /* ARM ADD/SUB (S . P + A) & 0x000000FF */ +#define R_ARM_ALU_PCREL_15_8 33 /* ARM ADD/SUB (S . P + A) & 0x0000FF00 */ +#define R_ARM_ALU_PCREL_23_15 34 /* ARM ADD/SUB (S . P + A) & 0x00FF0000 */ +#define R_ARM_LDR_SBREL_11_0 35 /* ARM LDR/STR (S . B + A) & 0x00000FFF */ +#define R_ARM_ALU_SBREL_19_12 36 /* ARM ADD/SUB (S . B + A) & 0x000FF000 */ +#define R_ARM_ALU_SBREL_27_20 37 /* ARM ADD/SUB (S . B + A) & 0x0FF00000 */ + +#define R_ARM_TARGET1 38 +#define R_ARM_ROSEGREL32 39 +#define R_ARM_V4BX 40 +#define R_ARM_TARGET2 41 +#define R_ARM_PREL31 42 + +/* 96-111, reserved to ARM g++ */ +#define R_ARM_GNU_VTENTRY 100 /* 32 bit word Record C++ vtable entry. */ +#define R_ARM_GNU_VTINHERIT 101 /* 32 bit word Record C++ member usage. */ +#define R_ARM_THM_PC11 102 /* Thumb B S . P + A */ +#define R_ARM_THM_PC9 103 /* Thumb B S . P + A */ + +/* 112-127, reserved for private experiments */ + +/* 128-248, reserved to ARM */ +#define R_ARM_RXPC25 249 /* ARM BLX (S . P) + A #define For calls between program segments. */ +#define R_ARM_RSBREL32 250 /* Word (S . SB) + A For an offset from SB, the static base. */ +#define R_ARM_THM_RPC22 251 /* Thumb BL/BLX pair (S . P) + A For calls between program segments. */ +#define R_ARM_RREL32 252 /* Word (S . P) + A For on offset between two segments. */ +#define R_ARM_RABS32 253 /* Word S + A For the address of a location in the target segment. */ +#define R_ARM_RPC24 254 /* ARM B/BL (S . P) + A For calls between program segments. */ +#define R_ARM_RBASE 255 /* None None.Identifies the segment being relocated by the following + relocation directives. The ARM EABI poses two problems for relocating + executables and shared objects encoded in */ + + +// shirait +#define R_ARM_LDR_PC_G0 4 //LDR + +#define R_ARM_ABS12 6 //LDR, STR + +#define R_ARM_THM_CALL 10 //R_ARM_THM_PC22Ɠ + +#define R_ARM_CALL 28 //BL/BLX +#define R_ARM_JUMP24 29 //B/BL +#define R_ARM_THM_JUMP24 30 + +#define R_ARM_MOVW_ABS_NC 43 //MOVW +#define R_ARM_MOVT_ABS 44 //MOVT +#define R_ARM_MOVW_PREL_NC 45 //MOVW +#define R_ARM_MOVT_PREL 46 //MOVT + +#define R_ARM_ALU_PC_G0_NC 57 //ADD, SUB +#define R_ARM_ALU_PC_G0 58 //ADD, SUB +#define R_ARM_ALU_PC_G1_NC 59 //ADD, SUB +#define R_ARM_ALU_PC_G1 60 //ADD, SUB +#define R_ARM_ALU_PC_G2 61 //ADD, SUB +#define R_ARM_LDR_PC_G1 62 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_PC_G2 63 //LDR, STR, LDRB, STRB +#define R_ARM_LDRS_PC_G0 64 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_PC_G1 65 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_PC_G2 66 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDC_PC_G0 67 //LDC, STC +#define R_ARM_LDC_PC_G1 68 //LDC, STC +#define R_ARM_LDC_PC_G2 69 //LDC, STC +#define R_ARM_ALU_SB_G0_NC 70 //ADD, SUB +#define R_ARM_ALU_SB_G0 71 //ADD, SUB +#define R_ARM_ALU_SB_G1_NC 72 //ADD, SUB +#define R_ARM_ALU_SB_G1 73 //ADD, SUB +#define R_ARM_ALU_SB_G2 74 //ADD, SUB +#define R_ARM_LDR_SB_G0 75 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_SB_G1 76 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_SB_G2 77 //LDR, STR, LDRB, STRB +#define R_ARM_LDRS_SB_G0 78 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_SB_G1 79 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_SB_G2 80 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDC_SB_G0 81 //LDC, STC +#define R_ARM_LDC_SB_G1 82 //LDC, STC +#define R_ARM_LDC_SB_G2 83 //LDC, STC +#define R_ARM_MOVW_BREL_NC 84 //MOVW +#define R_ARM_MOVT_BREL 85 //MOVT +#define R_ARM_MOVW_BREL 86 //MOVW + +#define R_ARM_GOT_BREL12 97 //LDR +#define R_ARM_GOTOFF12 98 //LDR, STR + +#define R_ARM_TLS_LDO12 109 //LDR, STR +#define R_ARM_TLS_LE12 110 //LDR, STR +#define R_ARM_TLS_TE12GP 111 //LDR + + + +/*--------------------------------------------------------- + Dynamic Section elf_v1.2 + --------------------------------------------------------*/ +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + + +/* Additional symbol types for Thumb. */ +#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ +#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ + + + + + + + + + +/*--------------------------------------------------------- + ELFwb_ǂݏo + --------------------------------------------------------*/ +void *ELF_LoadELFHeader(const void *buf, Elf32_Ehdr *ehdr); + + + +#endif /* ELF_H_ */ + diff --git a/build/tools/makegcdfirm/format_nlist.h b/build/tools/makegcdfirm/format_nlist.h new file mode 100644 index 0000000..e3bee64 --- /dev/null +++ b/build/tools/makegcdfirm/format_nlist.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makegcdfirm + File: format_nlist.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FORMAT_NLIST_H_ +#define FORMAT_NLIST_H_ + +#include +#include "misc.h" +#include "path.h" + +#define SPECFILE_MAGIC_ID "#NORSF" + +#define CRC16_INIT_VALUE 0xffff + +//--------------------------------------------------------------------------- +// Banner Spec File +//--------------------------------------------------------------------------- + +// Command List +typedef struct +{ + char *string; + BOOL (*funcp) (char *, int num); + +} +tCommandDesc; + + +// F Command +typedef struct +{ + u32 offsetStart; + u32 offsetEnd; + u32 padding; + char fullPathSrc[FILENAME_MAX]; + +} +tFileDesc; + + +#endif // FORMAT_NLIST_H_ diff --git a/build/tools/makegcdfirm/format_rom.h b/build/tools/makegcdfirm/format_rom.h new file mode 100644 index 0000000..c1c6d89 --- /dev/null +++ b/build/tools/makegcdfirm/format_rom.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makegcdfirm + File: format_rom.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FORMAT_ROM_H_ +#define FORMAT_ROM_H_ + +#include "misc.h" +#include + + +#define DEFAULT_ALIGN 0x200 +#define FIRM_ALIGN DEFAULT_ALIGN +#define FIRM_ALIGN_MASK (FIRM_ALIGN - 1) + +#define NML_AREA_ALIGN 0x80000 // 512KB +#define TWL_AREA_ALIGN 0x80000 // 512KB +#define SEC2_AREA_OFFSET 0x3000 // 12KB +#define GAME2_AREA_OFFSET 0x7000 // 28KB + +#define DEFAULT_HOSTROOT "." +#define DEFAULT_ROOT "/" + +#define DEFAULT_REJECT_1 "CVS" +#define DEFAULT_REJECT_2 "vssver.scc" + +#define FORMAT_VERSION "1.0" + +#define ENTRYNAME_MAX 127 + +#define ROM_SIZE_MIN 0x20000 + +#define DEFAULT_ROMHEADER_TEMPLATE "gcdfirm_header_twlj.template.sbin" +#define DEFAULT_LISTFILE "default.nlf" + +#define DEFAULT_NORFIRM_SUFFIX ".gcd" +#define DEFAULT_SPECFILE_SUFFIX ".gcdsf" + +/*===========================================================================* + * ROM FORMAT + *===========================================================================*/ + +//--------------------------------------------------------------------------- +// ROM HEADER +//--------------------------------------------------------------------------- + +#endif //FORMAT_ROM_H_ diff --git a/build/tools/makegcdfirm/format_sign.h b/build/tools/makegcdfirm/format_sign.h new file mode 100644 index 0000000..782a5d2 --- /dev/null +++ b/build/tools/makegcdfirm/format_sign.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - SS + File: format_sign.h + + Copyright 2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_MAKENORFIRM_ACSIGN_FORMAT_H_ +#define FIRM_MAKENORFIRM_ACSIGN_FORMAT_H_ + +#include "format_rom.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_MAKENORFIRM_ACSIGN_FORMAT_H_ */ +#endif diff --git a/build/tools/makegcdfirm/gcdfirm_header_twlj.template.sbin b/build/tools/makegcdfirm/gcdfirm_header_twlj.template.sbin new file mode 100644 index 0000000000000000000000000000000000000000..60ed6b7f1c5e8d50dba1c3820d4dcff7ea73a12b GIT binary patch literal 16384 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 Cvf-cr literal 0 HcmV?d00001 diff --git a/build/tools/makegcdfirm/makegcdfirm.c b/build/tools/makegcdfirm/makegcdfirm.c new file mode 100644 index 0000000..9afa68a --- /dev/null +++ b/build/tools/makegcdfirm/makegcdfirm.c @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makegcdfirm + File: makegcdfirm.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include +#include // strcasecmp() +#include // getopt() +#include "makegcdfirm.h" +#include "format_rom.h" +#include "path.h" +#include "defval.h" +#include "version.h" + +static int makegcdfirm(const char *specFile, const char *norFile); + +//--------------------------------------------------------------------------- +// Main +//--------------------------------------------------------------------------- + +int main(int argc, char *argv[]) +{ + int n; + int narg; + char *gcdfirmFile; + + InitAppName(argv[0]); + + while ((n = getopt(argc, argv, "D:hvpd")) != -1) + { + switch (n) + { + case 'h': + case 'v': + goto usage; + + case 'D': + AddDefVal(optarg); + break; + + case 'p': + PrintMode = TRUE; + break; + + case 'd': + DebugMode = TRUE; + break; + + default: + break; + } + } + + narg = argc - optind; + if (narg > 0) + { + // Make SpecFile->GcdfirmFile + gcdfirmFile = + strdup(narg > + 1 ? argv[optind + 1] : ChangeSuffix(argv[optind], DEFAULT_NORFIRM_SUFFIX)); + return makegcdfirm(argv[optind], gcdfirmFile); + } + + usage: + { + char *makegcdfirm = GetAppName(); + + fprintf(stderr, + "NITRO-SDK Development Tool - %s - Make gcdfirm file \n" + "Build %lu\n\n" + "Usage: %s [-phv] [-DNAME=VALUE ...] SPECFILE [NORFIRMFILE]\n\n", + makegcdfirm, SDK_DATE_OF_LATEST_FILE, makegcdfirm); + } + return 1; +} + + +//--------------------------------------------------------------------------- +// makegcdfirm +//--------------------------------------------------------------------------- + +static int makegcdfirm(const char *specFile, const char *norFile) +{ + debug_printf("makegcdfirm(): '%s' -> '%s'\n", specFile, norFile); + + // Check identical + if (specFile && norFile && !strcasecmp(specFile, norFile)) + { + error("gcdfirm spec file is identical '%s'", norFile); + return 1; + } + + return OutputGcdfirmFile(specFile, norFile) ? 0 : 1; +} diff --git a/build/tools/makegcdfirm/makegcdfirm.h b/build/tools/makegcdfirm/makegcdfirm.h new file mode 100644 index 0000000..c38c14a --- /dev/null +++ b/build/tools/makegcdfirm/makegcdfirm.h @@ -0,0 +1,24 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makegcdfirm + File: makegcdfirm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef MAKEGCDFIRM_H_ +#define MAKEGCDFIRM_H_ + +#include "misc.h" + +BOOL OutputGcdfirmFile(const char *specFile, const char *gcdFile); + +#endif //MAKEGCDFIRM_H_ diff --git a/build/tools/makegcdfirm/misc.c b/build/tools/makegcdfirm/misc.c new file mode 100644 index 0000000..7706d6b --- /dev/null +++ b/build/tools/makegcdfirm/misc.c @@ -0,0 +1,628 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: misc.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include // calloc() +#include // free(), exit() +#include // setmode() +#include // stat() +#include // setmode() +#include // strlen() +#include // va_start(),va_end() +#include // localtime() + +#include +#include "misc.h" + +BOOL DebugMode = FALSE; +BOOL PrintMode = FALSE; +char *PubkeyFileName = NULL; + +/*---------------------------------------------------------------------------* + * File Output Utilities + * + * BOOL OpenFile( const char* filename ) + * void CloseFile( void ) + * BOOL CheckResult( void ) + * void PutBuffer( const void* ptr, int len ) + * void PutByte( u8 c ) + * void PutWord( u16 c ) + * void PutWord( u32 c ) + * void PutString( const char *str ) + *---------------------------------------------------------------------------*/ + +static FILE *OutFile = NULL; +static const char *FileName = NULL; +static BOOL Status = FALSE; + + +// +// File Open +// + +BOOL OpenFile(const char *filename) +{ + if (OutFile) + CloseFile(); + + if (filename) + { + if (NULL == (OutFile = fopen(filename, "wb+"))) + { + error("Can't write '%s'", filename); + Status = FALSE; + return FALSE; + } + } + else + { + setmode(1, O_BINARY); + OutFile = stdout; // out to console if filename == NULL + } + FileName = filename; + Status = TRUE; + + return TRUE; +} + + +// +// File Close +// + +BOOL CloseFile(void) +{ + if (OutFile) + { + if (FileName) + { + if (fclose(OutFile) == -1) + { + error("Can't close '%s'", FileName); + Status = FALSE; + } + } + else + { + setmode(1, O_TEXT); + } + } + OutFile = NULL; + + return Status; +} + + +// +// File Seek +// + +void SeekFile(long pos) +{ + if (OutFile && fseek(OutFile, pos, SEEK_SET)) + { + error("Can't seek '%s'", FileName ? FileName : ""); + CloseFile(); + Status = FALSE; + } +} + + +// +// Error Check +// + +BOOL CheckResult(void) +{ + return Status; +} + + +// +// Delete outfile +// + +void DeleteOutFile(void) +{ + // Delete outfile + if (FileName) + { + debug_printf("Delete '%s'\n", FileName); + (void)unlink(FileName); + FileName = NULL; + } + return; +} + + +// +// Buffer Output +// + +void PutBuffer(const void *ptr, int len) /* If error, close file */ +{ + if (OutFile && len != fwrite(ptr, 1, len, OutFile)) + { + error("Can't write buffer to '%s'", FileName ? FileName : ""); + CloseFile(); + Status = FALSE; + } +} + +// +// Buffer Input +// + +void GetBuffer(void *ptr, int len) /* If error, close file */ +{ + if (OutFile && len != fread(ptr, 1, len, OutFile)) + { + error("Can't read '%s'", FileName ? FileName : ""); + CloseFile(); + Status = FALSE; + } +} + +// +// Byte/Half/Word Output +// + +void PutByte(u8 c) +{ + PutBuffer(&c, 1); +} +void PutHalf(u16 c) +{ + PutBuffer(&c, 2); +} +void PutWord(u32 c) +{ + PutBuffer(&c, 4); +} +void PutString(const char *str) +{ + PutBuffer(str, strlen(str)); +} + + +// +// Printf +// + +void PrintString(const char *fmt, ...) +{ + char *buffer; + va_list va; + int nchars; + int bufsize = FILENAME_MAX; + + while (1) + { + buffer = Alloc(bufsize); + va_start(va, fmt); + nchars = vsnprintf(buffer, bufsize, fmt, va); + va_end(va); + + if (0 <= nchars && nchars < bufsize) + { + break; + } + + Free(&buffer); + bufsize *= 2; + } + + if (nchars > 0) + { + PutBuffer(buffer, nchars); + } + Free(&buffer); +} + + +/*---------------------------------------------------------------------------* + * File Read/Write Utilities + * + * int ReadFile( const char* filename, void** buffer ) + * + * Read a file to buffer allocated internally + * Return read size + * Add '\0' at tail of file for help to handle text file + * + * BOOL WriteFile( const char* filename, void** buffer, int size ) + *---------------------------------------------------------------------------*/ + +int ReadFile(const char *filename, void *filebuffer, int size) +{ + FILE *fp; + struct stat fileStat; + int fileSize, readSize; + void **buffer = (void **)filebuffer; + + /* Check file */ + if (stat(filename, &fileStat) || !S_ISREG(fileStat.st_mode)) + { + goto error; + } + fileSize = fileStat.st_size; + if (fileSize < 0) + { + goto error; + } + + /* Open file */ + fp = fopen(filename, "rb"); + if (!fp) + { + goto error; + } + + if (size && (size < fileSize)) + { + readSize = size; + } + else + { + readSize = fileSize; + } + + /* Read file */ + *buffer = Alloc(readSize + 1); /* error handle is done in Alloc() */ + /* size+1 for '\0' to handle text file */ + if (readSize != fread(*buffer, sizeof(char), readSize, fp)) + { + goto error_free_close; + } + + (*(char **)buffer)[readSize] = '\0'; /* Works as terminater if file is text file */ + + /* Close file */ + fclose(fp); + return readSize; + + error_free_close: + Free(buffer); + fclose(fp); + error: + error("Can't read '%s'", filename); + return -1; +} + + +int ReadFileWithPadding(const char *filename, void *filebuffer, int size, int boundary) +{ + FILE *fp; + struct stat fileStat; + int fileSize, readSize, padSize; + void **buffer = (void **)filebuffer; + + if (!boundary) + { + return ReadFile(filename, buffer, size); + } + + /* Check file */ + if (stat(filename, &fileStat) || !S_ISREG(fileStat.st_mode)) + { + goto error; + } + fileSize = fileStat.st_size; + if (fileSize < 0) + { + goto error; + } + + /* Open file */ + fp = fopen(filename, "rb"); + if (!fp) + { + goto error; + } + + if (size && (size < fileSize)) + { + readSize = size; + } + else + { + readSize = fileSize; + } + + padSize = (boundary - (readSize & (boundary-1))) & (boundary-1); + + /* Read file */ + *buffer = Alloc(readSize + padSize); /* error handle is done in Alloc() */ + /* size+1 for '\0' to handle text file */ + if (readSize != fread(*buffer, sizeof(char), readSize, fp)) + { + goto error_free_close; + } + + memset((char*)*buffer + readSize, 0, padSize); + + /* Close file */ + fclose(fp); + return readSize + padSize; + + error_free_close: + Free(buffer); + fclose(fp); + error: + error("Can't read '%s'", filename); + return -1; +} + + +BOOL WriteFile(const char *filename, void *buffer, int size) +{ + debug_printf("WriteFile %s\n", filename); + + (void)OpenFile(filename); + PutBuffer(buffer, size); + CloseFile(); + Free(&buffer); + return CheckResult(); +} + + +/*---------------------------------------------------------------------------* + * Time Format Utilities + * + * char* GetGMTime( const time_t time ) Show GMT + * char* GetTime( const time_t time ) Show local Time + *---------------------------------------------------------------------------*/ + +char *GetGMTime(const time_t time) +{ + static char timebuffer[32]; + strftime(timebuffer, sizeof(timebuffer), "%y/%m/%d-%H:%M:%S", gmtime(&time)); + return timebuffer; +} + + +char *GetTime(const time_t time) +{ + static char timebuffer[32]; + strftime(timebuffer, sizeof(timebuffer), "%y/%m/%d-%H:%M:%S", localtime(&time)); + return timebuffer; +} + + +/*---------------------------------------------------------------------------* + * Memory Allocation Utilities + * + * void* Alloc( size_t size ) + *---------------------------------------------------------------------------*/ + +void *Alloc(size_t size) +{ + void *t = calloc(1, size); + + if (t == NULL) + { + error("Can't allocate memory."); + exit(10); + } + return t; +} + + +void Free(void *p) +{ + void **ptr = (void **)p; + + if (*ptr) + { + free(*ptr); + (*ptr) = NULL; + } +} + + +/*---------------------------------------------------------------------------* + * VBuffer + * + * void PutVBuffer( VBuffer* vbuf, char c ) + *---------------------------------------------------------------------------*/ + +void PutVBuffer(VBuffer * vbuf, char c) +{ + int size; + char *tmp_buffer; + + if (vbuf->buffer == 0) + { + vbuf->size = VBUFFER_INITIAL_SIZE; + vbuf->buffer = Alloc(vbuf->size); // buffer is CALLOCed + } + size = strlen(vbuf->buffer); + + if (size >= vbuf->size - 1) + { + // Need buffer expansion + vbuf->size *= 2; + tmp_buffer = Alloc(vbuf->size); // buffer is CALLOCed + strcpy(tmp_buffer, vbuf->buffer); + Free(&vbuf->buffer); + vbuf->buffer = tmp_buffer; + } + vbuf->buffer[size] = c; + return; +} + +char *GetVBuffer(VBuffer * vbuf) +{ + return vbuf->buffer; +} + +void InitVBuffer(VBuffer * vbuf) +{ + vbuf->buffer = 0; + vbuf->size = 0; +} + +void FreeVBuffer(VBuffer * vbuf) +{ + Free(&vbuf->buffer); +} + + +/*---------------------------------------------------------------------------* + * File Path Utilities + * + * char* ChangeBackSlash( char* path ) + *---------------------------------------------------------------------------*/ + +char *ChangeBackSlash(char *path) +{ + char *p = path; + + while (*p) + { + if (*p == '\\') + { + *p = '/'; + } + p++; + } + return path; +} + + +/*---------------------------------------------------------------------------* + * Math + * + * u16 CalcCRC16( u16 start, u8 *data, int size ) + *---------------------------------------------------------------------------*/ + +static u16 crc16_table[16] = { + 0x0000, 0xCC01, 0xD801, 0x1400, + 0xF001, 0x3C00, 0x2800, 0xE401, + 0xA001, 0x6C00, 0x7800, 0xB401, + 0x5000, 0x9C01, 0x8801, 0x4400 +}; + +u16 CalcCRC16(u16 start, u8 *data, int size) +{ + u16 r1; + u16 total = start; + + while (size-- > 0) + { + // 4bit + r1 = crc16_table[total & 0xf]; + total = (total >> 4) & 0x0fff; + total = total ^ r1 ^ crc16_table[*data & 0xf]; + + // 4bit + r1 = crc16_table[total & 0xf]; + total = (total >> 4) & 0x0fff; + total = total ^ r1 ^ crc16_table[(*data >> 4) & 0xf]; + + data++; + } + return total; +} + + +/*---------------------------------------------------------------------------* + * for firm header + * + *---------------------------------------------------------------------------*/ + +static u8 ConvertAlign( u32 ofs ) +{ + u8 i; + + ofs /= 4; + for (i=0; i<7; i++) + { + if ( ofs & 1 ) + { + break; + } + ofs >>= 1; + } + + return i; +} + +tROMAddrConvType ConvertHeaderRamAddr( s32 p ) +{ + tROMAddrConvType retval; + + retval.align = ConvertAlign( p ); + retval.address = (u16)((p - HW_WRAM)/(4< + +typedef enum +{ + FALSE = 0, + TRUE = 1 +} +BOOL; + +typedef unsigned char u8; +typedef unsigned short int u16; +typedef unsigned long int u32; +typedef unsigned long long u64; +typedef signed char s8; +typedef signed short int s16; +typedef signed long int s32; +typedef signed long long s64; +typedef volatile u8 vu8; +typedef volatile u32 vu32; +typedef vu32 REGType32v; + +#define error(...) do { fprintf(stderr, "Error: "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); } while(0) + +#define warning(...) do { fprintf(stderr, "Warning: "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); } while(0) + +BOOL OpenFile(const char *filename); +BOOL CloseFile(void); +void SeekFile(long pos); +BOOL CheckResult(void); +void DeleteOutFile(void); +void PutBuffer(const void *ptr, int len); +void GetBuffer(void *ptr, int len); +void PutByte(u8 c); +void PutHalf(u16 c); +void PutWord(u32 c); +void PutString(const char *str); +void PrintString(const char *fmt, ...); + +#define READ_ALL 0 +int ReadFile(const char *filename, void *filebuffer, int size); +int ReadFileWithPadding(const char *filename, void *filebuffer, int size, int boundary); +BOOL WriteFile(const char *filename, void *buffer, int size); + +char *GetGMTime(const time_t time); +char *GetTime(const time_t time); + +void *Alloc(size_t size); +void Free(void *p); + +typedef struct +{ + char *buffer; + int size; +} +VBuffer; + +#define VBUFFER_INITIAL_SIZE 1024 +void InitVBuffer(VBuffer * vbuf); +void FreeVBuffer(VBuffer * vbuf); +void PutVBuffer(VBuffer * vbuf, char c); +char *GetVBuffer(VBuffer * vbuf); + +char *ChangeBackSlash(char *path); + +u16 CalcCRC16(u16 start, u8 *data, int size); +const char *WrapNull(const char *str); + +typedef struct +{ + u16 address; + u8 align; +} +tROMAddrConvType; + +tROMAddrConvType ConvertHeaderRamAddr( s32 p ); +tROMAddrConvType ConvertHeaderRomOffset( s32 p ); +u16 ConvertHeaderRomOffsetAlign( s32 p, u32 align ); + +typedef union +{ + struct + { + u32 sign:1; + u32 header_hash:1; + u32 arm9_hash:1; + u32 arm7_hash:1; + u32 hash_table_hash:1; + u32 final_hash:1; + u32 header_footer:1; + } + e; + u32 raw; +} +tErrorFlags; + +extern BOOL DebugMode; +extern BOOL PrintMode; +extern char *PubkeyFileName; +void debug_printf(const char *str, ...); +void debug_printf2(const char *str, ...); + +#endif //MISC_H_ diff --git a/build/tools/makegcdfirm/out_gcdfirm.c b/build/tools/makegcdfirm/out_gcdfirm.c new file mode 100644 index 0000000..44ee62a --- /dev/null +++ b/build/tools/makegcdfirm/out_gcdfirm.c @@ -0,0 +1,994 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makegcdfirm + File: out_gcdfirm.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include // atoi() +#include // strcmp() +#include // isprint() +#include // chdir() +#include +#include // UCHAR_MAX +#include +#include // stat() +#include "elf.h" +#include "misc.h" +#include "defval.h" +#include "format_rom.h" +#include "format_nlist.h" +#include "makegcdfirm.h" +#include "format_sign.h" +#include "acsign_gcd.h" +#include "compress.h" + +#define SDK_ASM + +#include +#include "../acsign/aes2.h" + +#define ROMHDRCMD "ROM_HDR" +#define SBIN9CMD "ARM9_SBIN" +#define SBIN7CMD "ARM7_SBIN" +#define ELF9CMD "ARM9_ELF" +#define ELF7CMD "ARM7_ELF" +#define GAMECODECMD "GAMECODE" +#define ARM9X2CMD "ARM9_X2" +#define NMLOFSCMD "NML_OFS" +#define TWLOFSCMD "TWL_OFS" +#define VERCMD "VERSION" +#define RSAKEYCMD "RSA_KEY" +#define OUTKEYCMD "OUT_KEY" +#define WREGCMD "WRAM_RBIN" +#define NANDFMCMD "NANDFIRM" +#define NORFMCMD "NORFIRM" +#define ERRCMD "ERROR" + +static BOOL ConstructGcdfirmFile(char * specFile); +static BOOL ReadRomHeaderFile(const char *fileName); +static BOOL ReadSbinFile(const char *fileName, void* minfo, void* hash, BOOL comp); +static size_t ReadFirmFile(const char *fileName); +static BOOL ReadKeyFile(const char *fileName); +static BOOL ReadWramRegFile(const char *fileName); +static s32 GetRamAddr(const char *fileName); + +static BOOL EncryptBuffer(char *buffer, int length); + +static BOOL RomHeader_Command(char * line, int num); +static BOOL Sbin9_Command(char * line, int num); +static BOOL Sbin7_Command(char * line, int num); +static BOOL Elf9_Command(char * line, int num); +static BOOL Elf7_Command(char * line, int num); +static BOOL GAMECODE_Command(char * line, int num); +static BOOL ARM9X2_Command(char * line, int num); +static BOOL NMLOFS_Command(char * line, int num); +static BOOL TWLOFS_Command(char * line, int num); +static BOOL VERSION_Command(char * line, int num); +static BOOL RSAKEY_Command(char * line, int num); +static BOOL OUTKEY_Command(char * line, int num); +static BOOL WramRegs_Command(char * line, int num); +static BOOL NorFirm_Command(char * line, int num); +static BOOL NandFirm_Command(char * line, int num); +static BOOL ERROR_Command(char * line, int num); + +static BOOL InitializeAesKey(void); +static BOOL InitializeGcdfirmFile(void); +static BOOL FinalizeGcdfirmFile(const char *gcdFile); + +static s32 Offset; // Current offset +static int LineNum; // Line number for error message +static const char *specFileName; // specFile name for error message + +GCDHeader gcdHeader; // Gcdfirm Header Shadow +FIRMSignedContext signedContext; +u8 *keyFileBuf; +BOOL compArm9 = FALSE; +BOOL compArm7 = FALSE; +tErrorFlags errFlags; + +//--------------------------------------------------------------------------- +// Output - gcdfirm File +//--------------------------------------------------------------------------- + +BOOL OutputGcdfirmFile(const char *specFile, const char *gcdFile) +{ + char *buffer; + BOOL state; + + if (ReadFile(specFile, &buffer, READ_ALL) <= 0) + { + return FALSE; + } + + if (!OpenFile(gcdFile)) + { + return FALSE; + } + + specFileName = specFile; + + state = InitializeGcdfirmFile() && ConstructGcdfirmFile(buffer) && + FinalizeGcdfirmFile(gcdFile) && CloseFile(); + + if (!state) + { + DeleteOutFile(); + } + + return state; +} + + +//--------------------------------------------------------------------------- +// Output - Gcdfirm File +//--------------------------------------------------------------------------- + +static const tCommandDesc command[] = { + {ROMHDRCMD, RomHeader_Command}, + {SBIN9CMD, Sbin9_Command}, {SBIN7CMD, Sbin7_Command}, + {ELF9CMD, Elf9_Command},{ELF7CMD, Elf7_Command}, + {VERCMD, VERSION_Command}, + {GAMECODECMD, GAMECODE_Command}, + {ARM9X2CMD, ARM9X2_Command}, + {NMLOFSCMD, NMLOFS_Command}, + {TWLOFSCMD, TWLOFS_Command}, + {RSAKEYCMD, RSAKEY_Command}, + {OUTKEYCMD, OUTKEY_Command}, + {WREGCMD, WramRegs_Command}, + {NANDFMCMD, NandFirm_Command}, + {NORFMCMD, NorFirm_Command}, + {ERRCMD, ERROR_Command}, +}; + +BOOL ConstructGcdfirmFile(char * specFile) +{ + char *line; + char *line_top; + char *p; + int i; + + LineNum = 0; + Offset = 0x4000; + SeekFile(Offset); + + line = specFile++; + + while (*line != '\0') + { + LineNum++; + + // Get command line + line_top = line; + while (*line != '\0') + { + if (*line++ == '\n') + { + break; + } + } + + // Print for debug + debug_printf("GCDSF Line%4d [", LineNum, line); + for (p = line_top; p != line; p++) + { + if (isprint(*p)) + { + debug_printf("%c", *p); + } + } + debug_printf("]\n"); + + if (*line_top == '#') + { + } + else + { + for (i = 0; i < (sizeof(command) / sizeof(command[0])); i++) + { + if (!strncmp(line_top, command[i].string, strlen(command[i].string))) + { + if (command[i].funcp != NULL) + { + char line_cmd[FILENAME_MAX]; + char line_scan[FILENAME_MAX]; + char* line_conv; + int num; + + num = sscanf( line_top, + "%1024[^ :] : %1024[^ \x0d:#\n]", + line_cmd, line_scan + ); + line_conv = ResolveDefVal(line_scan); + + debug_printf("line_cmd = %s, line_conv = %s\n", line_cmd, line_conv); + + if (!command[i].funcp(line_conv, num - 1)) + return FALSE; + } + } + } + } + + } + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - 'RomHeader' Command +//--------------------------------------------------------------------------- + +static BOOL RomHeader_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("hom header file = %s\n", line); + + return ReadRomHeaderFile(line); +} + + +static BOOL ReadRomHeaderFile(const char *fileName) +{ + char *file; + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &file, READ_ALL)) < 0) + return FALSE; + + gcdHeader = *(GCDHeader*)file; + + // Output file image with fitting region + SeekFile(0L); + PutBuffer(file, file_size); + + Free(&file); + + return CheckResult(); +} + +//--------------------------------------------------------------------------- +// Output - 'WramRegs' Command +//--------------------------------------------------------------------------- + +extern MIHeader_WramRegs wram_regs_init; +MIHeader_WramRegs* wram_regs; + +static BOOL WramRegs_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("wram regs file = %s\n", line); + + return ReadWramRegFile(line); +} + +static BOOL ReadWramRegFile(const char *fileName) +{ + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &wram_regs, READ_ALL)) < 0) + return FALSE; + + gcdHeader.h.w = *wram_regs; + + return CheckResult(); +} + +//--------------------------------------------------------------------------- +// Output - 'RSAKEY' Command +//--------------------------------------------------------------------------- + +static BOOL RSAKEY_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("rsa key = %s\n", line); + + return ReadKeyFile(line); +} + +static BOOL ReadKeyFile(const char *fileName) +{ + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &keyFileBuf, READ_ALL)) < 0) + return FALSE; + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'OUTKEY' Command +//--------------------------------------------------------------------------- + +static BOOL OUTKEY_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("out key = %s\n", line); + + PubkeyFileName = line; + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'VERSION' Command +//--------------------------------------------------------------------------- + +static u8 ConvToBCD8(int x) +{ + u8 bcd = 0; + + x %= 100; + bcd |= (x / 10)<<4; + bcd |= (x % 10); + + return bcd; +} + +static BOOL VERSION_Command(char * line, int num) +{ + char scan[FILENAME_MAX]; + u64 version = -1; + + // rescan + num = sscanf( line, + "0x%1024[^\x0d\n]", + scan + ); + + if (num == 1) + { + // convert version info + version = strtoull(scan, NULL, 16); + } + else if (num == 0) + { + // generate version info + u8* ver8 = (u8*)&version; + time_t timer; + struct tm *t_st; + + time(&timer); + t_st = localtime(&timer); + + ver8[0] = ConvToBCD8(t_st->tm_min); + ver8[1] = ConvToBCD8(t_st->tm_hour); + ver8[2] = ConvToBCD8(t_st->tm_mday); + ver8[3] = ConvToBCD8(t_st->tm_mon+1); + ver8[4] = ConvToBCD8(t_st->tm_year); + ver8[5] = 0xff; + ver8[6] = 0xff; + ver8[7] = 0xff; + } + + debug_printf2("version = %08llx\n", version); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'NMLOFS' Command +//--------------------------------------------------------------------------- + +static BOOL NMLOFS_Command(char * line, int num) +{ + u32 offset = 0; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + offset = strtoul(line, NULL, 0); + + gcdHeader.l.normal_area_offset = offset / NML_AREA_ALIGN; + + debug_printf2("normal area offset = %#x\n", offset); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'TWLOFS' Command +//--------------------------------------------------------------------------- + +static BOOL TWLOFS_Command(char * line, int num) +{ + u32 offset = 0; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + offset = strtoul(line, NULL, 0); + + gcdHeader.l.twl_area_offset = offset / TWL_AREA_ALIGN; + + debug_printf2("twl area offset = %#x\n", offset); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'ARM9_X2' Command +//--------------------------------------------------------------------------- + +static BOOL ARM9X2_Command(char * line, int num) +{ + char* dbg_str = "FALSE"; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + if (!strcmp(line, "TRUE")) + { + gcdHeader.l.arm9_x2 = TRUE; + dbg_str = "TRUE"; + } + + debug_printf2("arm9 x2 = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'GAMECODE' Command +//--------------------------------------------------------------------------- + +static BOOL GAMECODE_Command(char * line, int num) +{ + u32 key; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + key = strtoul(line, NULL, 0); + + debug_printf2("keyinfo = %#x\n", key); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Elf9' Command +//--------------------------------------------------------------------------- + +static BOOL Elf9_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm9 elf = %s\n", line); + + { + s32 ramAddr = GetRamAddr(line); + gcdHeader.l.main_ram_address = (void*)ramAddr; + } + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Elf7' Command +//--------------------------------------------------------------------------- + +static BOOL Elf7_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm7 elf = %s\n", line); + + { + s32 ramAddr = GetRamAddr(line); + gcdHeader.l.sub_ram_address = (void*)ramAddr; + } + + return CheckResult(); +} + + +static s32 GetRamAddr(const char *fileName) +{ + Elf32_Ehdr *ehdr; + s32 ramAddr; + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &ehdr, sizeof(Elf32_Ehdr))) < 0) + return FALSE; + + ramAddr = ehdr->e_entry; + + Free(&ehdr); + + debug_printf2("ramaddr = 0x%08x\n", ramAddr); + + return ramAddr; +} + + +//--------------------------------------------------------------------------- +// Output - 'NANDFIRM' Command +//--------------------------------------------------------------------------- + +static BOOL NandFirm_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("nandfirm = %s\n", line); + + // Set NANDFIRM ROM Offset + if (!Offset) + { + Offset = sizeof(GCDHeader); + SeekFile(Offset); + } + debug_printf2("romoffset = %#x\n", Offset); + { + gcdHeader.l.nandfirm_offset = Offset; + gcdHeader.l.nandfirm_size = ReadFirmFile(line); + } + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'NORFIRM' Command +//--------------------------------------------------------------------------- + +static BOOL NorFirm_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("norfirm = %s\n", line); + + // Set NORFIRM ROM Offset + if (!Offset) + { + Offset = sizeof(GCDHeader); + SeekFile(Offset); + } + debug_printf2("romoffset = %#x\n", Offset); + { + gcdHeader.l.norfirm_offset = Offset; + gcdHeader.l.norfirm_size = ReadFirmFile(line); + } + + return CheckResult(); +} + + +static size_t ReadFirmFile(const char *fileName) +{ + char *file; + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFileWithPadding(fileName, &file, READ_ALL, FIRM_ALIGN)) < 0) + return FALSE; + + Offset += file_size; + + // Output file image with fitting region + PutBuffer(file, file_size); + + Free(&file); + + return file_size; +} + + +//--------------------------------------------------------------------------- +// Output - 'Sbin9' Command +//--------------------------------------------------------------------------- + +static BOOL Sbin9_Command(char * line, int num) +{ + FIRMSignedContext* sc = &signedContext; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm9 sbin = %s\n", line); + + // Set ARM9 ROM Offset + if (!Offset) + + { + Offset = sizeof(GCDHeader); + SeekFile(Offset); + } + debug_printf2("romoffset = %#x\n", Offset); + { + gcdHeader.l.main_rom_offset = Offset; + } + + return ReadSbinFile(line, &gcdHeader.l.main_rom_offset, &sc->hash[FIRM_SIGNED_HASH_IDX_ARM9], compArm9); +} + +//--------------------------------------------------------------------------- +// Output - 'Sbin7' Command +//--------------------------------------------------------------------------- + +static BOOL Sbin7_Command(char * line, int num) +{ + FIRMSignedContext* sc = &signedContext; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm7 sbin = %s\n", line); + + // Set ARM7 ROM Offset + if (!Offset) + { + Offset = sizeof(GCDHeader); + SeekFile(Offset); + } + debug_printf2("romoffset = %#x\n", Offset); + { + gcdHeader.l.sub_rom_offset = Offset; + } + + return ReadSbinFile(line, &gcdHeader.l.sub_rom_offset, &sc->hash[FIRM_SIGNED_HASH_IDX_ARM7], compArm7); +} + + +static BOOL ReadSbinFile(const char *fileName, void* minfo, void* hash, BOOL comp) +{ + const GCDHeader_ModuleInfo *m = minfo; + u32 *size = (void*)&m->size; + u32 *orig_size = (void*)&m->decomp_size; + char *buffer; + char *file; + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &file, READ_ALL)) < 0) + return FALSE; + + *orig_size = file_size; + + // Digest file image + if (hash) + { + ACSign_DigestUnit(hash, file, file_size); + } + + // Compress file image with fitting region + buffer = Alloc(file_size * 2); + if ( comp ) + { + file_size = LZCompWrite(file, file_size, buffer, FIRM_ALIGN); + } + else + { + memcpy(&buffer[0], file, file_size); + { + u32 pad_size = (DEFAULT_ALIGN - (file_size % FIRM_ALIGN)) % FIRM_ALIGN; + if (pad_size) + memset(&buffer[file_size], 0, pad_size); + file_size += pad_size; + } + } + Free(&file); + file = buffer; + + if (size) + { + *size = file_size; + } + Offset += file_size; + + // Encrypt file image + EncryptBuffer(file, file_size); + + // Output file image with fitting region + PutBuffer(file, file_size); + + Free(&file); + + return CheckResult(); +} + +typedef struct +{ + unsigned long e[4]; +} u128; + +static BOOL EncryptBuffer(char *buffer, int length) +{ + const u128 id = {{ AES_IDS_ID2_A, AES_IDS_ID2_B, AES_IDS_ID2_C, AES_IDS_ID2_D }}; + u128 iv = {{ length, -length, ~length, 0 }}; + FIRMSignedContext* sc = &signedContext; + char *buffer2 = Alloc(length); + AES_KEY key; + if (!buffer2) + return FALSE; + AES_SetKey(&key, sc->aes_key, (unsigned char*)&id); + AES_Ctr(&key, buffer2, buffer, length, (unsigned char*)&iv); + memcpy(buffer, buffer2, length); + memset(buffer2, 0, length); + Free(buffer2); + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - 'ERROR' Command +//--------------------------------------------------------------------------- +static char* error_type[] = +{ + "SIGN", + "HEADER_HASH", + "ARM9_HASH", + "ARM7_HASH", + "HASH_TABLE_HASH", + "FINAL_HASH", + "HEADER_FOOTER", +}; + +static BOOL ERROR_Command(char * line, int num) +{ + char* dbg_str = "UNKNOWN"; + int i; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + for (i=0; ihash[FIRM_SIGNED_HASH_IDX_HEADER][0] ^= 1; + } + if ( errFlags.e.arm9_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_ARM9][0] ^= 1; + } + if ( errFlags.e.arm7_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_ARM7][0] ^= 1; + } + if ( errFlags.e.hash_table_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_HASH_TABLE][0] ^= 1; + } +} + +static void SetFinalHashError(FIRMSignedContext* sc) +{ + if ( errFlags.e.final_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_FINAL][0] ^= 1; + } +} + +static void SetSignError(GCDHeader* nh) +{ + if ( errFlags.e.sign ) + { + nh->sign.raw[0] ^= 1; + } + +} + +static void SetFooterError(GCDHeader* nh) +{ + if ( errFlags.e.header_footer ) + { + nh->h.reserved_footer[sizeof(nh->h.reserved_footer)-1] ^= 1; + } + +} + +//--------------------------------------------------------------------------- +// Output - Initialize AES Key +//--------------------------------------------------------------------------- +static BOOL InitializeAesKey(void) +{ + FIRMSignedContext* sc = &signedContext; + struct stat specstat; + time_t spectime; + if (stat(specFileName, &specstat) != 0) + return FALSE; + time(&spectime); + memcpy(&sc->aes_key[0], &specstat.st_atime, 4); + memcpy(&sc->aes_key[4], &specstat.st_mtime, 4); + memcpy(&sc->aes_key[8], &specstat.st_ctime, 4); + memcpy(&sc->aes_key[12], &spectime, 4); + ACSign_GetKey(sc->aes_key, sizeof(sc->aes_key), sc->aes_key, sizeof(sc->aes_key)); + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - Initialize Gcdfirm File +//--------------------------------------------------------------------------- + +static BOOL InitializeGcdfirmFile(void) +{ + ReadRomHeaderFile( GetSrcPath(GetAppBaseName(), DEFAULT_ROMHEADER_TEMPLATE) ); + + memset(&signedContext.hash[FIRM_SIGNED_HASH_IDX_HASH_TABLE], 0xff, sizeof(signedContext.hash[0])); + gcdHeader.h.w = wram_regs_init; + InitializeAesKey(); + return TRUE; +} + +//--------------------------------------------------------------------------- +// Output - Finalize Gcdfirm File +//--------------------------------------------------------------------------- + +static BOOL FinalizeGcdfirmFile(const char *gcdFile) +{ + GCDHeader* nh = &gcdHeader; + FIRMSignedContext* sc = &signedContext; + u8* key = keyFileBuf; + int size; + + // set rom size + size = ROM_SIZE_MIN; + nh->l.rom_size = 0; + while (size < Offset) + { + size <<= 1; + nh->l.rom_size++; + } + + ACSign_DigestHeader(&sc->hash[FIRM_SIGNED_HASH_IDX_HEADER], nh); + + SetUnitHashErrors(sc); + + ACSign_DigestUnit(&sc->hash[FIRM_SIGNED_HASH_IDX_FINAL], sc, FIRM_HEADER_2ND_HASH_AREA_LEN); + + SetFinalHashError(sc); + + if (key) + { + ACSign_Final(nh, sc, key); + } + + SetFooterError(nh); + + SetSignError(nh); + + // Output file image + SeekFile(0L); + PutBuffer(&gcdHeader, sizeof(gcdHeader)); + + // Output public key (modulus) + if (PubkeyFileName) + { + WriteFile(PubkeyFileName, &keyFileBuf[ACS_RSA_PRVMOD_OFFSET], ACS_RSA_PRVMOD_LEN); + } + + return TRUE; +} diff --git a/build/tools/makegcdfirm/path.c b/build/tools/makegcdfirm/path.c new file mode 100644 index 0000000..eeeb989 --- /dev/null +++ b/build/tools/makegcdfirm/path.c @@ -0,0 +1,931 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makebanner + File: path.c + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: path.c,v $ + Revision 1.3 2006/01/18 02:11:20 kitase_hirotake + do-indent + + Revision 1.2 2005/02/28 05:26:13 yosizaki + do-indent. + + Revision 1.1 2004/08/30 08:41:14 yasu + makebanner moves into CVS tree + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +#include // free() +#include // strcasecmp() +#include // stat() +#include // opendir()/readdir()/closedir() +#include // getcwd() +#ifdef __CYGWIN__ +#include // cygwin_conv_to_win32_path() +#endif +#include "path.h" + +//--------------------------------------------------------------------------- +// Get File Statue +//--------------------------------------------------------------------------- + +tFileStatus GetFileStatus(struct stat *s, const char *filename) +{ + // Get file status + if (stat(filename, s)) + { + error("Can't get status %s", filename); + return FILESTATUS_ERROR; + } + + if (S_ISREG(s->st_mode)) + { + return FILESTATUS_FILE; + } + else if (S_ISDIR(s->st_mode)) + { + return FILESTATUS_DIR; + } + + error("Unknown file type %s", filename); + return FILESTATUS_ERROR; +} + + +//--------------------------------------------------------------------------- +// File Globbing & Dir Listing +//--------------------------------------------------------------------------- + +typedef struct +{ + tCallBack callBack; + void *param; + tWildCard *accept; + tWildCard *reject; + +} +tForeachEntryParam; + + +static BOOL isAcceptEntryName(char *pathName, tWildCard * accept, tWildCard * reject) +{ + char *p = pathName; + + while (*p) + { + if (*p == '/') + pathName = p + 1; + p++; + } + + if (accept) + { + while (accept) + { + if (WildCardCmp(accept->name, pathName)) + { + goto accepted; + } + accept = accept->next; + } + return FALSE; + } + accepted: + + while (reject) + { + if (WildCardCmp(reject->name, pathName)) + { + return FALSE; + } + reject = reject->next; + } + return TRUE; +} + + +static BOOL ForeachEntry_CallBack(char *pathName, void *param) +{ + tForeachEntryParam *t = (tForeachEntryParam *) param; + struct stat fstat; + + if (!isAcceptEntryName(pathName, t->accept, t->reject)) + { + // Reject!!! ignored + return TRUE; + } + + switch (GetFileStatus(&fstat, pathName)) + { + case FILESTATUS_FILE: + return t->callBack(pathName, t->param); + + case FILESTATUS_DIR: + return ForeachDirList(pathName, ForeachEntry_CallBack, param); + + default: + break; + } + return FALSE; +} + + +BOOL ForeachEntry(const char *pathName, tWildCard * reject, tCallBack callBack, void *param) +{ + tForeachEntryParam t; + + t.callBack = callBack; + t.param = param; + t.accept = NULL; + t.reject = reject; + + return ForeachPathGlobbing(pathName, ForeachEntry_CallBack, &t); +} + + +typedef struct +{ + tCallBack callBack; + void *param; + char *baseName; + +} +tForeachFileParam; + + +static BOOL ForeachFile_CallBack(char *pathName, void *param) +{ + tForeachFileParam *t = (tForeachFileParam *) param; + + int len = strlen(t->baseName); + + debug_printf(" ForeachFile_CallBack path[%s] base[%s]\n", pathName, t->baseName); + + if (strncmp(pathName, t->baseName, len)) + { + error("Wildcard in Root is not supported"); + return FALSE; + } + + return t->callBack(pathName + len, t->param); +} + + +BOOL ForeachFile(const char *baseName, const char *fileName, tWildCard * reject, tCallBack callBack, + void *param) +{ + char *cBaseName; + char *cPathName; + BOOL state; + tForeachFileParam t; + + debug_printf("ForeachFile : baseName[%s] fileName[%s]\n", baseName, fileName); + + cBaseName = GetSrcPath(baseName, ""); + cPathName = GetSrcPath(baseName, fileName); + + debug_printf("ForeachFile : cBaseName[%s] cPathName[%s]\n", cBaseName, cPathName); + + t.callBack = callBack; + t.param = param; + t.baseName = cBaseName; + + state = ForeachEntry(cPathName, reject, ForeachFile_CallBack, &t); + + free(cBaseName); + free(cPathName); + + return state; +} + + +//--------------------------------------------------------------------------- +// FilePath Globbing +//--------------------------------------------------------------------------- + +typedef struct +{ + char *baseName; + char *pathName; + tCallBack callBack; + void *param; + +} +tGlobParam; + + +static int CountFile; +static BOOL ForeachPathGlobbing_Entry(tGlobParam * pg); +static BOOL ForeachPathGlobbing_WildCard(char *pathName, void *param); + +BOOL ForeachPathGlobbing(const char *pathName, tCallBack callBack, void *param) +{ + tGlobParam g; + BOOL ret; + + g.baseName = NULL; + g.pathName = PathNormalize(pathName, TRUE); + g.callBack = callBack; + g.param = param; + CountFile = 0; + + debug_printf("PathGlobbing : Name [%s]->[%s]\n", pathName, g.pathName); + + ret = ForeachPathGlobbing_Entry(&g); + + free(g.pathName); + + if (ret && CountFile == 0) + { + error("No file or directory matched %s", pathName); + return FALSE; + } + return ret; +} + + +static BOOL ForeachPathGlobbing_Entry(tGlobParam * pg) +{ + tGlobParam g; + char *entryName; + struct stat s; + BOOL state; + + if (pg->pathName) + { + entryName = PathDup(pg->pathName); + + g = *pg; + g.pathName = PathGetDirLevelDown(pg->pathName); + + if (pg->baseName) + { + g.baseName = Alloc(strlen(pg->baseName) + strlen(entryName) + 2); + sprintf(g.baseName, "%s/%s", pg->baseName, entryName); + } + else + { + g.baseName = strdup(entryName); + } + + // Check if wildcard ? + if (isPathWildCard(entryName)) + { + state = ForeachDirList(pg->baseName, ForeachPathGlobbing_WildCard, &g); + } + else + { + state = ForeachPathGlobbing_Entry(&g); + } + + Free(&entryName); + Free(&g.baseName); + } + else + { + // Check if file exists + if (!stat(pg->baseName, &s)) + { + debug_printf(" File Found [%s]\n", pg->baseName); + + // Globbing done, exec callback + + state = pg->callBack(pg->baseName, pg->param); + CountFile++; + } + else + { + debug_printf(" File Not Found [%s]\n", pg->baseName); + state = TRUE; // Ignored + } + } + return state; +} + + +static BOOL ForeachPathGlobbing_WildCard(char *pathName, void *param) +{ + tGlobParam g; + tGlobParam *pg = (tGlobParam *) param; + + debug_printf(" WildCardCmp: [%s] [%s]\n", pg->baseName, pathName); + + if (WildCardCmp(pg->baseName, pathName)) + { + g = *pg; + g.baseName = pathName; + return ForeachPathGlobbing_Entry(&g); + } + + return TRUE; // Ignored +} + + +//--------------------------------------------------------------------------- +// Directory Listing +// Listing directory & Exec CallBack +//--------------------------------------------------------------------------- + +BOOL ForeachDirList(const char *dirName, tCallBack callBack, void *param) +{ + DIR *dir; + struct dirent *entry; + char *pathName; + BOOL state = TRUE; + + if (!dirName) + { + dirName = "."; + } + + debug_printf("DirectoryList: Name [%s]\n", dirName); + + // Open directory + if (NULL == (dir = opendir(dirName))) + { + error("Can't read directory %s", dirName); + return FALSE; + } + + // Store new files + while (NULL != (entry = readdir(dir))) + { + pathName = entry->d_name; + + if (!strcmp(pathName, ".") || !strcmp(pathName, "..")) + { + continue; + } + + debug_printf(" :%s\n", pathName); + pathName = GetSrcPath(dirName, pathName); + state = callBack(pathName, param); + free(pathName); + + if (!state) + break; + } + + closedir(dir); + return state; +} + + +//--------------------------------------------------------------------------- +// +// PathName Utilities +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// StrCmp/StrCpy entry name terminated / or \0 +//--------------------------------------------------------------------------- + +int PathCmp(const char *path, const char *cmp) +{ + char c; + + do + { + c = *path; + if (c == '/') + c = '\0'; // end of string if '/' + if (c != *cmp) + return 1; + path++; + cmp++; + } + while (c); + + return 0; +} + + +char *PathCpy(char *dest, const char *src) +{ + while (*src != '\0' && *src != '/') + { + *dest++ = *src++; + } + return dest; // Don't set '\0' +} + + +int PathLen(const char *path) +{ + int n = 0; + + while (*path != '\0' && *path != '/') + { + n++; + path++; + } + return n; +} + + +char *PathDup(const char *src) +{ + int n = PathLen(src); + char *dest = Alloc(n + 2); + + PathCpy(dest, src); + dest[n] = '\0'; + + return dest; +} + + +BOOL WildCardCmp(const char *wildcard, const char *path) +{ + if (*wildcard == '*') + { + if (*path != '\0' && WildCardCmp(wildcard, path + 1)) + return TRUE; + if (WildCardCmp(wildcard + 1, path)) + return TRUE; + } + + else if (*wildcard == '?') + { + return *path != '\0' && WildCardCmp(wildcard + 1, path + 1); + } + + else if (*wildcard == *path) + { + return *path == '\0' || WildCardCmp(wildcard + 1, path + 1); + } + + return FALSE; +} + + +BOOL isPathWildCard(const char *path) +{ + while (*path != '\0' && *path != '/') + { + if (*path == '*' || *path == '?') + { + return TRUE; + } + path++; + } + return FALSE; +} + + +//--------------------------------------------------------------------------- +// Go up/down directory level +//--------------------------------------------------------------------------- + +char *PathGetDirLevelDown(const char *path) +{ + while (*path) + { + if (*path == '/') + return (char *)path + 1; + path++; + } + return NULL; +} + + +//--------------------------------------------------------------------------- +// Get Basename +//--------------------------------------------------------------------------- + +char *GetBaseName(const char *path) +{ + int i; + char *new_path; + + for (i = strlen(path) - 1; i >= 0; i--) + { + if (path[i] == '/') + { + new_path = strdup(path); + new_path[i] = '\0'; + return new_path; + } + if (path[i] == ':') + { + new_path = Alloc(i + 3); + strncpy(new_path, path, i); + strcpy(new_path + i, ":."); + return new_path; + } + } + + new_path = strdup("."); + return new_path; +} + + +//--------------------------------------------------------------------------- +// Get Filename +//--------------------------------------------------------------------------- + +char *GetFileName(const char *path) +{ + int i; + char *new_file; + + for (i = strlen(path) - 1; i >= 0; i--) + { + if (path[i] == '/' || path[i] == ':') + { + new_file = strdup(path + i + 1); + return new_file; + } + } + new_file = strdup(path); + return new_file; +} + + +//--------------------------------------------------------------------------- +// Reconstruct path name +// +// - Resolve '.' or '..' in path name +// - Work around . and / to translate regular form +// +// Regular form of path: +// Absolute Path [Drive:]/.[/Entry...] +// Relative Path [Drive:].[/Entry]... +// +// ex) +// abc/def -> ./abc/def +// /aaa -> /./aaa +// D:/aaa -> D:/./aaa +// / -> /. +// . -> . +// ../aa -> ./../aa +//--------------------------------------------------------------------------- + +char *PathNormalize(const char *pathName, BOOL isTreatDotDot) +{ + int i, level, level_root, n; + BOOL isAbsolute; + const char *entry[DIRLEVEL_MAX]; + + char *pathNormal = Alloc(strlen(pathName) + 4); + const char *p_org; + char *p_new; + + // + // Check if drive letter C: D: E: + // Check if absolute path + // + p_new = pathNormal; + p_org = SkipDriveName(pathName); + n = (int)p_org - (int)pathName; + + if (n > 0) + { + strncpy(p_new, pathName, n); + p_new += n; + } + isAbsolute = isAbsolutePath(p_org); + + // + // Resolve '.' and '..' + // + // Slice the path at point of / , put them into entry[] + // + + level = level_root = 0; + + for (; p_org; p_org = PathGetDirLevelDown(p_org)) + { + if (!PathCmp(p_org, "") || !PathCmp(p_org, ".")) + { + // skip it + continue; + } + else if (!PathCmp(p_org, "..") && isTreatDotDot) + { + if (level > level_root) + { + // Back to parent dir + level--; + continue; + } + + // if pathname starts with '/', no directory to go up + if (isAbsolute) + { + error("Can't go up directory, '..' Ignored. %s", pathName); + continue; + } + + // keep '..' + level_root = level + 1; + } + + // name entry + entry[level] = p_org; + level++; + } + + // Reconstruct pathname + if (isAbsolute) + { + *p_new++ = '/'; + } + *p_new++ = '.'; + + for (i = 0; i < level; i++) + { + *p_new++ = '/'; + p_new = PathCpy(p_new, entry[i]); + } + *p_new = '\0'; + +#if 0 + if (strcmp(pathNormal, pathName)) + { + debug_printf(" PathNormal: [%s] -> [%s]\n", pathName, pathNormal); + } +#endif + return pathNormal; +} + + +//--------------------------------------------------------------------------- +// Get Src Path +// Normalize BASENAME +// Normalize FILENAME +// Concat both +//--------------------------------------------------------------------------- + +char *GetSrcPath(const char *baseName, const char *fileName) +{ + char *base; + char *file; + char *t; + char *path; + + base = PathNormalize(baseName, TRUE); + file = PathNormalize(fileName, TRUE); + t = Alloc(strlen(base) + strlen(file) + 2); + + // Concat base + '/' + file + sprintf(t, "%s/%s", base, file); + path = PathNormalize(t, FALSE); + + free(base); + free(file); + free(t); + + debug_printf(" GetSrcPath: [%s]\n", path); + return path; +} + + +//--------------------------------------------------------------------------- +// Get Dest Path +// Concat BASENAME + FILENAME +// Normalize it +//--------------------------------------------------------------------------- + +char *GetDestPath(const char *baseName, const char *fileName) +{ + char *t; + char *path; + + t = Alloc(strlen(baseName) + strlen(fileName) + 2); + + // Concat base + '/' + file + sprintf(t, "%s/%s", baseName, fileName); + path = PathNormalize(t, TRUE); + + free(t); + + debug_printf(" GetDestPath: [%s]\n", path); + return path; +} + + +//--------------------------------------------------------------------------- +// Remake the path into familier shape +// Delete ./ +//--------------------------------------------------------------------------- + +char *PathDenormalize(char *path) +{ + char *p; + + p = (char *)SkipDriveName(path); + if (*p == '/') + { + p++; + } + + // Cut './' + if (*p == '.' && *(p + 1) == '/') + { + while ('\0' != (*p = *(p + 2))) + { + p++; + } + + if (p == path) + { + + } + } + + + + return path; +} + + +//--------------------------------------------------------------------------- +// Get PC Path +//--------------------------------------------------------------------------- + +char *GetWin32Path(char *cygpath) +{ + static char buffer[FILENAME_MAX]; + +#ifdef __CYGWIN__ + if (*cygpath == '/') + { + cygwin_conv_to_win32_path(cygpath, buffer); + } + else +#endif + { + strcpy(buffer, cygpath); + } + + return ChangeBackSlash(buffer); +} + +char *ChangeWin32Path(char *cygpath) +{ + char *win32path = strdup(GetWin32Path(cygpath)); + + free(cygpath); + return win32path; +} + +//--------------------------------------------------------------------------- +// Change suffix +//--------------------------------------------------------------------------- +char *ChangeSuffix(const char *file, const char *suffix) +{ + int i, n; + char *path; + + n = strlen(file); + + for (i = n; file[i] != '.'; i--) + { + if (file[i] == '/' || i == 0) + { + i = n; + break; + } + } + + path = Alloc(i + strlen(suffix) + 1); + strncpy(path, file, i); + strcpy(path + i, suffix); + + return path; +} + + +//--------------------------------------------------------------------------- +// Get Current Dir +//--------------------------------------------------------------------------- + +char *GetCurrentDirectory(void) +{ + static char buffer[FILENAME_MAX]; + char *cwd; + + cwd = getcwd(buffer, FILENAME_MAX); + if (!cwd) + { + error("Can't access current directory"); + exit(10); + } + return cwd; +} + + +//--------------------------------------------------------------------------- +// Check if absolute path +// +// Return True in case of ... +// +// /dirA/dirB/fileC +// D:/dirA/dirB/fileC +// +// Return False in case of ... +// +// dirX/dirY/fileZ +// D:dirX/dirY/fileZ +//--------------------------------------------------------------------------- + +BOOL isAbsolutePath(const char *path) +{ + const char *p = path; + + while (*p != '\0') + { + if (*p == '/' || *p == '\\') + { + if (p == path || p[-1] == ':') + { + return TRUE; + } + } + p++; + } + return FALSE; +} + +//--------------------------------------------------------------------------- +// Check if drive name +// +// Return next character of ':' if drive name +// Return head of path if no drive name +//--------------------------------------------------------------------------- + +const char *SkipDriveName(const char *path) +{ + const char *p = path; + + while (*p != '\0' && *p != '/' && *p != '\\') + { + if (*p == ':') + { + return p + 1; + } + p++; + } + return path; +} + + +//--------------------------------------------------------------------------- +// App Name Utilities +//--------------------------------------------------------------------------- +static char *appName; +static char *appBaseName; +static char *appFileName; + +void InitAppName(const char *path) +{ + char *slash_path = ChangeBackSlash(strdup(path)); + + appBaseName = GetBaseName(slash_path); + appFileName = GetFileName(slash_path); + appName = ChangeSuffix(appFileName, ""); + + free(slash_path); +} + +char *GetAppName(void) +{ + return appName; +} + +char *GetAppBaseName(void) +{ + return appBaseName; +} + +char *GetAppFileName(void) +{ + return appFileName; +} + + +#ifdef TEST +int main(int argc, char *argv[]) +{ + int i; + char *s; + + for (i = 1; i < argc; i++) + { + s = PathNormalize(argv[i], TRUE); + printf("[%s] -> [%s]\n", argv[i], s); + free(s); + } + return 0; +} +#endif diff --git a/build/tools/makegcdfirm/path.h b/build/tools/makegcdfirm/path.h new file mode 100644 index 0000000..e9956dc --- /dev/null +++ b/build/tools/makegcdfirm/path.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makebanner + File: path.h + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: path.h,v $ + Revision 1.3 2006/01/18 02:11:20 kitase_hirotake + do-indent + + Revision 1.2 2005/02/28 05:26:13 yosizaki + do-indent. + + Revision 1.1 2004/08/30 08:41:14 yasu + makebanner moves into CVS tree + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef PATH_H_ +#define PATH_H_ + +#include // struct tat +#include "misc.h" + +#define DIRLEVEL_MAX 256 +#ifndef FILENAME_MAX +#define FILENAME_MAX 1024 +#endif + +typedef enum +{ + FILESTATUS_ERROR = -1, + FILESTATUS_FILE = 0, + FILESTATUS_DIR = 1 +} +tFileStatus; + + +// Item Reject Control + +typedef struct tWildCard +{ + struct tWildCard *next; + char *name; + +} +tWildCard; + + +// CallBacks + +typedef BOOL (*tCallBack) (char *, void *); + + +// Prototypes + +tFileStatus GetFileStatus(struct stat *s, const char *filename); +BOOL ForeachEntry(const char *pathName, tWildCard * reject, tCallBack callBack, void *param); +BOOL ForeachFile(const char *baseName, const char *fileName, tWildCard * reject, + tCallBack callBack, void *param); +BOOL ForeachPathGlobbing(const char *pathName, tCallBack callBack, void *param); +BOOL ForeachDirList(const char *dirName, tCallBack callBack, void *param); +int PathCmp(const char *path, const char *cmp); +char *PathCpy(char *dest, const char *src); +int PathLen(const char *path); +char *PathDup(const char *src); +char *PathGetDirLevelDown(const char *path); +char *GetBaseName(const char *path); +char *GetFileName(const char *path); +BOOL WildCardCmp(const char *wildcard, const char *path); +BOOL isPathWildCard(const char *path); +char *PathNormalize(const char *pathName, BOOL isTreatDotDot); +char *PathDenormalize(char *path); +char *GetSrcPath(const char *base, const char *file); +char *GetDestPath(const char *base, const char *file); +char *GetWin32Path(char *cygpath); +char *ChangeWin32Path(char *cygpath); +char *ChangeSuffix(const char *file, const char *suffix); +char *GetCurrentDirectory(void); +BOOL isAbsolutePath(const char *path); +const char *SkipDriveName(const char *path); +void InitAppName(const char *path); +char *GetAppName(void); +char *GetAppBaseName(void); +char *GetAppFileName(void); + +#endif //PATH_H_ diff --git a/build/tools/makegcdfirm/test/Makefile b/build/tools/makegcdfirm/test/Makefile new file mode 100644 index 0000000..1f985ca --- /dev/null +++ b/build/tools/makegcdfirm/test/Makefile @@ -0,0 +1,56 @@ +#! make -f +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makenorfirm +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#--------------------------------------------------------------------------- + +SUBDIRS = wram_rbin \ + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +MAKEGCDFIRM = ../makegcdfirm.exe + +MAKEFIRM_ARM9 = ./twl_gcdfirm9_print.axf +MAKEFIRM_ARM7 = ./twl_gcdfirm7_print.axf +SDEPENDS_BIN += $(MAKEFIRM_ARM9) $(MAKEFIRM_ARM7) +MAKEFIRM_FLAGS += -d +MAKEFIRM_DEFS += -DFIRM_ROOT='$(FIRM_ROOT)' \ + -DMAKEFIRM_ARM9='$(basename $(MAKEFIRM_ARM9))' \ + -DMAKEFIRM_ARM7='$(basename $(MAKEFIRM_ARM7))' \ + -DMAKEFIRM_RSA_PRVKEY='$(MAKEFIRM_RSA_PRVKEY)' \ + +TARGET = test.srl + +%.srl: %.gcdsf $(MAKEGCDFIRM) + $(MAKEGCDFIRM) $(MAKEFIRM_FLAGS) $(MAKEFIRM_DEFS) $< $@ + +.PHONY: build install do-autotest clean clobber + +define ECHO_CURDIR + echo "==== $(CURDIR)"; +endef + +build: + @$(ECHO_CURDIR) + @$(MAKE) $(TARGET) + +install do-autotest: + @$(ECHO_CURDIR) + +clean clobber super-clobber: + @$(ECHO_CURDIR) + -rm -f $(TARGET) *~ + +test-utf16.bsf: icon.nbfc icon.nbfp diff --git a/build/tools/makegcdfirm/test/nandfirm_print.nand b/build/tools/makegcdfirm/test/nandfirm_print.nand new file mode 100644 index 0000000000000000000000000000000000000000..999ce185fdcfb579f464763668963b8df624cbfe GIT binary patch literal 50688 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 literal 0 HcmV?d00001 diff --git a/build/tools/makegcdfirm/test/norfirm_print.nor b/build/tools/makegcdfirm/test/norfirm_print.nor new file mode 100644 index 0000000000000000000000000000000000000000..2a6baecd577a7a206c2142f3d4d150b051f973ca GIT binary patch literal 30896 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
!FLVkp-gh|pyn{u^Nvd$Xre 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 OP^yOlYL>lFFw77|zB@Sp literal 0 HcmV?d00001 diff --git a/build/tools/makegcdfirm/test/rsa_private.der b/build/tools/makegcdfirm/test/rsa_private.der new file mode 100644 index 0000000000000000000000000000000000000000..06f5f4ccbac2e2f50ebc312c9d601a422754c370 GIT binary patch literal 607 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
U4<#z|> zvnw~zljzpn6xF(4+lc|UyhR_t1C%r}%$?mkOQJ)}(yVtEx{cw5)aO79?b_+u5PLJE zegm9g*IF!+pI@x$wb%2By)x;C-d?#_i>Z$P6|8sH4qn`G!J4VMYu>#cVqUD}esRY? z>jzxBR(dgqXZ5n|B076f57F+#NVb^FjlOrW(-*%*R6e}wO9_i|#p%69hwORdo*z_( z*X(VD%kEdb>cNV=#T8-6TEX>u!(>&sl%f zhQTJ#IqP@ufAg}dwyhs*4qm(Us%_hwLsxIr-*Yx?-16$?#-R=8Y#ZD(xNd0hob5yB ztS7rd*Cb)GMN{pl%O|FH4Nr(K6-#gTbz|ThX-=D9w0OO1Zt81;UpyhN8tgmCRY&7LPt)ct}~uHoF$R& zOpcDhRS;pS#gWk67wayGb$7)UxvRy~F-mZ4@}8f%!PmExqtMdj`)@QZcwk~|zvL!j z;*B|gHIb8W5=Vgx{Q;pYwJLyXf;@~xwSQ!6CLAFo7zAJ-E=!u$)pCGAR5qj^ZURhV zHE>c+07uCiu$0L~H4~3gwafKLL4_IsdERsdNS9fGkje=<2g25wb6g-hCNnR6n3NY* z-1yX{X|9K}Hbi{~5v3-CV2i2*Om+$<5PX9XW|RB11lxVXGh_@@6YL1ryo?D4|6`!! zfsP;?9n%H6J1S7}VFz}{b^v#ESMvRv%~{2Z^)(w9lI%QBAPJTv@wzoj6zSq)mk@-{ zt=y+Z$A{&Z0bKX)4>WM?N*ldr3FcD+1kxGEd@NE`#FdsjS>*B|N}ox|oj0mvpsAh5 z%*QnI(am(4GoSBlIrv#S720xQbYVUoB~7PG9YC@!j-eu4!{AVBpLc#_RT8@)<5@M2 z4{eDK&~_LWiqZvxlunhjHd^mVPDD6RLHFeYxD(-#nS4H%qlx*z!Zhmw2VF^DJ}?t9 z;_P1S3~>FSn(Q=EJ5ZbzHg@2^8y3$aGZU@$U|AF633mI7Z%I7U%z5G3ac9m=?wIhC z&>RikF@XyY85kJPOucem`Qc5jDYD?!;IvJEJv5)?=2)@9bDE5} zdHDXB<^~6e9g}7j4iAor6EGp>d>W>3cqb`^tq2`y4MQUyOo270Y{p7B9}g7XXu^{q zKHLNtqJjKGJwVvhbyT!?4T=bVBnrTN#S(BbQ6?i&B5>hg##ZRHV6OXn)u*Vc@y)9I zq&4W|%$8l;PKCJc2^S`B%NfF#rb-_IPGoY#c##8^)v{0NwBmkg6uyKG zL|0UubRvo&?vm0Q6epR&Bj3WM3%*Q=gL((kHCm`s29~c_waRrZW@cW=rB$Y%I+JYr z8z-N>a-jbxC9;!`QaPP?{&A*yI`Mo6v8IPik3=0}hVvIOb^EHnVcA`rMq^3CFgoV; zBlIcXf*OVce7~q0vWdNONe$6m8&~hKCAGz?lYY_1(30As(;*Mr85X4$@f1jX|B7l0 z|Dw+ay@XUA&PeQZy@XZG8HfNLg8kiZVv$n~Iit>K)igLNYZ?f*YZ_2iWbYa%f~Fy4 zmoyC_oHY#~N=<`;QPTh%Gz~zmX#mKY1_Cur1L34;0FIglz?!CkaMm>BG_Gl&89~#4 z4#LFNASXo=a1b*Iy0l=Lh7>YQLkhX3Aq8F2kbb^ z04y~PqH;|G&1u&(Akr6_1_@!(gdpc+O+zXtXc`FDH4XBF*o*yEJhv5>G!2BJrU9_j zG!SgjG=RyP1_EISp!7(Z2H>D+0IF#k2-h?XgoBU>lr#+p^HIq~I`> z0_0%^!GZ@7g0Dd!saAo5)&VF;>UO6Sb0KOSlz4b%eqmNpH-Vsa018?MAlEtoxYj|K zQtLoCYaIxbS_gtb>j31+1}c6~tpoANuZ6MNrgcz1*?|vt5uq)ev<{?nD%Uzd6|@dS z1Z4qTX<7#|)N)7r(I|A%IzZ4t>tM<3YP)Yx>%e5PE6>O4(MudQ{U zHmXH8^@EeS@S5h%H%${kjZ724U)Mwc1XTl2ubPP7)DO~A#KizOsvjuF)ei;)^#kgO zpnd?G)eoRu{Qx$rA5QV%DRTq(QWHTiOzsv<1R9G&$EipY(RYxNXr7d)Qml+r=s+re zAoGDwpo{oJQ!?Oiah!X}d<^|zU-e>scTfp*av+Q%km4j)cB2W_9YQ^3x}I2?$05%u2L ztA7jgZZX*|&H-bw?j1`PGqhiBu~_}sqV;e4)4`pdmeoV==+yJg2}x~yh<)%7*Yg`i ztj~uy`}M{@)k-+nZq$t*@cqZnWp&D@)!ET{jV7{Sr_%@+tj6|lm>h=rf(I&`QRd+u z=XTqbx~MbiwnPxw(kNwz+rv?F4A0Gt&B{{&I7k}8j)}RWD3eM6QG-MftVG}D@Gkiq zP=~s(jRatbARf2qPom>SlKK>1H)UlrnAz@-w4)8LP+Y)h79j~<@xTSbNXUVd2@8es z-Qc1nuq+mI>`B1P=}OOF21Br!D@GDdb~}TEVj*(a5c|SR|42~Zqy9~RR8B z9JLM!ku(kolUjtq+%ln}l$Ol7NTW4b3o(7;bV`UX-rge^b)IJVf@VlaAu}?hkYA~of_|kU!C<&}Ih8MO$2?QL7LRkC zMYoxkC@Y}WAi~j30vOU6x@KA-F56uQxHSeK7-*C>nr#FZC$tIHPiO~3G6@k5#v-6> zLn6>_Wuh&$6WSrK@`N@hE8ZIivjuRrK3X{6d5&OPN?J5k-%Z5q{JCh3&aF@iJt8lb z>P9q2ue1l>BF|3&}`5h}(Wg|na$1xj;+8CcPGv`*<*G0&)& zza_U7N*8|Fxg}~M2148xKR;o=OU%dHFmHj&(@##d01u>}m-5f^`OYJ%>IOnr4UIQ9 z&c0#0*+^cqFt#uzy6OV{IpLWMtB(;1gqjXow=^}Y&l|qEaocOQ5AT}rl)2EqVEpUn z75wwOPKRS!Af&u5W7*n1Haj^!H9S97ebBJYtqb!*ro1Cq*8lBPqK^44SW*3am4BZ3 zcd(iLC?REzOWMeFmrc)Z7-OMc7@41*tsV(c+s5YLyhax$#@0_SOwCuXB_m5>OIU8+ z(7y5ck-gq8)$M_3{le@lYnx-Y&d*k#4iOvY9JdiZZhUxxi7;CAQ!nKlW9YC`18U>w z#F(S4rqz{g`0BcV+B8f@?H!wSavD+g%kMx`$DA2DJ%5J(4Ogxoc#hChcf;82BSht{ z7#p6kPbrF==G3jPtJK3Ub&7r90snA`SUQGa;nSPy5LQ1 zm>1Fo`uRapd#C)9-eUnX-n0|sddaA{dupV*3!Gy{wZ6^HPEA+eNvfHJ`K{ZVw&hnB z65ca5KeT<__Ubh$?$S-Kt|mPON`-Dqp-t6~C%R45FDH2J28#TXL}tPN9fQ@2sH&A) zo$k>3%^Rvq0GrLR`SU`>=jMm!tC1Gu$mHnkXmv|FcHit=b$<(*E9QqsXPbMg-*1VS z+dIB{zBya{pN{y6>Lk8$SryNy+5kFsE47=Qw~kf!=Z|)D80#7HU&FY~m{Y=Vcr_`h z0YCqn!Kk%xZiwm4qAO(?p9-f;Yo83A*RsDj3SIzDb{JR0ZW_n^_a*RM# zUBW-lZXK1-qKx14c$2Kg@s%BV!vc(yuaZh!#&udd_aH*)Cs+H3m$qUqY@-=ND$JQ9IfnGHtZBKIrXCiP|{ z-a5_qw_$#zZE?7%ZG8MoSY$@X%o5DW?Twc~48`0NqA#5opSms-v}L;bjSlDy!}G(S z%Z2^#Xt1`x_1m{?xO}{s%E(LqFR{x02oxi}ku|R$-=!>yj(rR!sE*kdI_)&jUQ?|= zGlcYEn1`FEwVj%nKi87>_n_2I9>-q|!{V2~dTyVi*4jv#uiL(HXnxHr7!>0p;UvVa zh20xRK(0adoNc1!8lRurI5Id`{eDhx9(%mYV^CNB=n+FCsz|_2Gb9 z#Ao@llua=-8a_07Umq?B2`ISB$Jl?6toOApJ^L8szmT&ozTUI{6fgF1vvJFsb2pEn zVca)1d)?fc3(zslO;3#Rk^#)xf!4vnYPe(SH6*|uFgB`$omw$i-PbW;d$FBUKOIst z(|x^W73#cFpXDRBrFj>|=1nimhxT>XW?|)M-N*to|j;uyXjWKFo)7 z{nOMsw{vEDLPEyR`Ll?bh(+T1kwf3(G4&<#Q;uYb?ADuq)rqoWcbp76Ve`4I3RilJ zO3S;|WJ0#q_HNPsCVBR=Wit$$tuo`)?g-LCAB5A+2Xq|q)sMH4 zb81aj`*bFM!pZfax{UB+(ffH%7nB{p$<{#GeO0-TOE_v%I%y`4DFGyC$MS!JoPeHI?#j`G3TJd!S9hYBwp7q^-DC5s#WH+aGH!{`36J z2TeJy`Y}|_tBs-e#%x^wvgX2F!zkmirsxiprp(-f)o-Tq>*MUHn6|9Knse1qAvt{I<9DH{Rc}C7dgDCfUgDS#!36xDVUL| zpHb0#-0AlU{yv8%1Y^%qo-=}9;qbiR5r_8+{%MEbB=|UoZxs9^4&MjdH^ux_S#Jlv z%i+C(FL!t%z&Aqk0pP}ip7x=DzXbfl0p0-oNPw>ZeoFMnhN|bqH)Z&}1-$7Ux!kRS zf5yw5xfwXrZC>z;9l!OHz-KtTserF2;0*}_X78=cl>?AU+MS<1i#hcCk4OD z;im*2>+mtRX8IEZ2l}%F|B%yMD>$Tmz2J~`zhG3^nzOeHUhDJsZs5NE;PrVx_;rqd zNbswi{!!7K?=;&rZa?e&cCFyej($@no-Am-QqVjjnozf+-UYnZ^E^Xv$bUnD9|i6k z^s@E}4&_b=4&}}W-sCi={wMNT@I0S+ANZg2{yFk4@EaX}l;GGuf-iCW_>dj)^c z+jU<-^BLgSu46w09NKjSaLn^s;XmSK-6)uRG`1fR9P03x=-=w)J|ldr^N#|Dbz?Pf z-+ywND})bu?iU=tsbHiA<$uZD8QugO)7~ijhrAB&5FEbsy@ErY4+?&}=ku`O(5^24 z_uc4qcvSG)9DZChA)l`n^lLv1KGbKE;E>O?z_C8B7yhR3-35pC-Xl2F=L>>kyLh)L z)@{4sfZq!o^Snd&hrEq<3;z+X=RJbu3&77~q6z)*L_zbUU zJOdotyOsBy8d%xY=dTwW#@K}5@O@_lk2}qMg0WYN{tJRbpL`j(?|v`q3Bez8_$k2` zdbt&^JjHU)6&%uD3>@hv3Yr@WnmY>k$%5wT0)OO3bDnzzf7HLrn}B2f4{9y_jMwd< z0)DuFA1UC^7w{Jf_|XD>tbo5gR36N3L=FZc7R+b?_Fo+#k23jTA)FZ)=gIYw~6 zpH<*5F7TTQ{I!Dr(({=q@NX*cw+sGnPIF%YKPVUnB>TPv{_z6;bb(*SZS|4<7{MXW z)q?T7P(Eu5{3QkcY2dyGy-)7v8v6)8@e{y*;rJ&72bv>)k~}}{d43Hz(mW&h=bgU# zIIvU={45h3(+d7M#~&s5vkos8{EH4BBUm1V{2VLz&m2BM@c(dlwcxKfe5&9l96m$v zlMbIH_`f@Ru3-5c@v~O&0}fv#_-7s70Nl9G=hUe1q0Wy8AJ(O>3H|}6Ir2W>H#mHj zV03-z=Zge~xp{@)ZI0h6ILx(C!6BdhfL`1b<${hhbv zUcpZ}e4k+UW&PZLBWeHHzui}W`!03-R|UV?;im=5-GrZeehT_gug`}2frlNwSny$u z>P<$~+b`wVUy`0*nafN>DPI5H$-k2BlC@R!D=Q+E(}?cf{OikTb3B{DH%B-*G>AsN zM_PIXBf>40bN4X>o(#M*XyZ8)|A_z#r=NT9V>tm;y6PgnL_g@$s$b(@$gg^m_2g@T z?^V2hM63A6!e7d@p99fpITF3fx#+V8&aVMcFLcNCNcYk}XZ53B4pcvENLDU?>}O^a zepVF;KLYjd72$6{SNDwJ%=ceo$Z15ku7z&(V555Km5T8nLHf5R{BFAO%OMV zIa6iT_Uta)<^tZLkdOr3M$Lue{9{1kS>&t?2p;iBvLKvjV$wZrAM9@GLQ=_PHJZK8 zw`UrMjaHJos=K7DC)n$H-_ew?_=yf z`Y*h^P&Vv=R}H)Hs^I(0`1q1Fj9J$2_UGx(m;<3{4V~*#nKCY1|D_gHi4p5GYe&S4t_m8-da=#{r5ua_3?2%m76tO4?iZn zH0x?KL(PQIRPLEG0<#8s>nQ?ve^QNps$PxWs;SW=bB@zqS*J#4P=AR2cup1^%5nq4 za*%<1JCs5w_+H)9ow(+WaeeIiS;M=EjCt(UfE&0r`&M%ODJ~`N`jc|hU6fAOPdb`c zuU7hoqr5t`QfpEwol>6+GLGvbfc=yCPB|Yxp6clxN-6bng0}S6QEScvQ9m+xS<$}6 z8B9)@_N8|zwK6b_{+850e{;s|Z{7(mSGj&+s^h0j*VnuU%2xpY6ZB>5`id;JBZr^D z|JuFX2@`qb;92Ed-)QVTJ(ur<>MLvPLj!nZKa7iePn*ceLLSm@G&-jZ-SMI^(+SP0 zjAw$+rp%#aEN}u_RL6bUN0C`dSH@iEDdeI-?^omFqjNmq>_@_s_3?7j?1kO~VXE{9 zeZ7HUZek4&ghlf>{hPpb5IMR2+$ueD0zMyn*MKi+dAgi1Z7Rp`ZwF&3r)*f8!juV*+LqG>yqd^c z_IY_&< z?0wNZ>L1~|X#NPej=(tkuo3Mu{l}q^z#pZoO=V?17_Ieb<5&YetZAvar5QVIl{sR^ z4_0BB|Ed9P`u*2fZ^oAI8$|EZ33Jx)RL}LBSWCiu<_!9P{ax>4lVL_ZGn`TGa3=rE z@EhIUF#0?ELKP?D!wZMDgfTzL+7s$$@9=ZpmTz z4~BE?`DH^n$f*au9|Ep`F7^b<>J1Gw5GEV9fGf|QcO*n627HMuKZ3r+y4Y8>)wA$9 zhQItJwSoMFr#9%_zoF7bhtF%{FVAaZH|MpXbzVC;p4{AG(lrE@bVp&yGD1 zYN}9<*2&&!>|MNX?Z8E{Fz1)iY1WD?)D}u1jQyHJ?NG zEOZ#zh!1|sJmhP)NNiLi@a<2*H|^U^DRtrJRpLe|LVrOt`X zpd;#EsBb*C{tLk={Yw1}YgrM<{=#$m3)Q)6quLF|s{U+j!K~p#XVF&!z&Wn3!-v4% zUWLC!YIvCh9`WtViCHRFWPQTdP3P#o3%dITjzqkOd<4g;Dvs-^g^#fXl~^GDU--W# zrAD*JEz5pId}2%AMh|1(eg-+6>aWBL3pfin@kPgg5gw35>#g9BxwUgnFh^`l%04v| z)o~1XzwiWY!6i6_SA+N}y3+`};JO5u*cRHqh(AM5VxBidYsw>6l@{3dKp!26=AA+| zF&|UatYOjFl-gWQn57_PJ&aE)l-m_+Xmf+VK!4g~?X(SZOGIC6S@hE!+FTai9rQ(L z|2|xo{gJq0S>RiI9OJ0yep1$8x&9EcZK?7s{IhFG-ITTw^j_CKYV7IQ)L*`5V zxYEj&vdTMEu6zwPM=ZHi^iP>bnzey1mWR|!zSgyA1@-8xp6d%n$HzxB>S5{>^=WF8I;6godBosW(HU8rVfB;^ zw~_P8X5@Qwpxn>wWzLh}9!XnrJ_mpPCGTs?rhB$~ZFwmFk}tHe!TleiCa%6LGQJ%8 z&EP#|z2>W;8(doD=R7*an9ePMDtf;|AjPD;ZcRFp>_xulNzesx} zZ4RdC6MV0$jy*wpi1uC9{PHCF^q>FTz){+AzQKQwe3x>BvWW5=1)Uf#YIjOK9Hvwjp5<(0^1V4k-f2xOK_}5w3tdD< zML$JP-_Ngvd8jlI{@GPy5ZEqIvE`K{k;fvyQHn>z}y z36()tO`+2fn}aK=vP`qy^dBNi)|*C-(_%SV$kB2W z`b^o6n}hk(ldCd}aMti6GOXoA_C|OSeE*Ymh^#-0tQE4>GRQ_P_QYOu$O$>7QzkKl zeM{jd4YMIEsslcDGU6~UwkG4HEAZnrFiBN7BephiuAEbZ-u2LvbJQgE2O3dKkMxwW z*e6~mFu9Mgw&lSB4ZR{x7|5A;QILIC*o5fp3u+5@CHBbf<-UAFv`0E}F_6m#1qb$I zMmm!X%-kWaqWBoomG8&2qWffqb!q8ra3yPz_1CW1$aiqp!2ba+es`iw_T@V`pH#-t zqev$4{8UvQseD5uw_14^^u_ZMxkIcY8(a^46Me+LA`fg*tw=1PZ<^IxHm&c4w#7Y_ zTBpw7lNX45fu9Gwj0ucZ9lM6HiEBAg<@NAIuK#vx`DM-ce`hU%S3zHO>iB~j1AVn7 zbpl&WC-WYDf|B1>*3F$>%;&5s-^8#H$Yz~vjm5MZtH}@W~C_$;7v<(6r8t<&aOEi-8h)KUTM_Bd69>sr*_+D}Be%6V zo~sr80bTPn^IA{Nv^IKQr=C46xc(Dd(`)#;7{26eD04->ujXtg-vd|ncnNC-{PmP0 zzTvT=Bl(2j6kMF~TN`U|O_ep4HkUaU1yih~H+`AwPt$>AJ!!EY)?}-my$RLh)~Tc5 zgC_D}9nm^}4!%s}fAivRUmnt40X{GG0iDfd8=I&zOVPXxF-Lfi*iffF>dC%k@C$X; z64pK6le>kc+&$7Kz6$?asxu3oh96Fu*>XjGH=pyx6Mdi9x$N~j`M-=Mc$Y=kHydh{oZYD6oKGHT zB)+5mj615pJk9yuA}=d)`v7Zug1dmmepuX(+axE49?ooV*jw_cvz^eI=7jCk{nlV8 zxnY~{nZV7Uh>nmOK1pu)F!f1x!S|K#7 zM7VU?mT+-tFkEbN=P31rtLR@z*{2`y=Yr!YYGwD3vw17G>X38UMNug6%6-%hMOR94 z#lL>@!!LgOs#ks^d6~z#cgA<5uOkn+quRMGp`9;;J7~+jFTNiNPT@`DE4eUi3wu5m z$`HBDq`#7X$V;4VjbMnse2>-x4?ClB&V-e7dEhtTFTQhf4jDBXT>pv-3+3_F zLix}I$N(PNC-l4Y$M;X{Jo4G~)mr>9bnwAyL~hwy0=_H8jV<@}IB z|8gaHV{phR9*x$&*Ieo!KyPIqiuO@|`s?G-o(TLpz9qLW-v)Ey9FhTDT~o%wuXZQo z%|i4(#hZn^U1-*W<&@;^&7EbTV^r-Xi5%pu;Q+Xb_CbHIJwM7-8@3Z>;Ys+Fbte67XxFK#LLrHcx_ zo^t#QeoIyJNNlVC^qhkOCQb4bZTan?mD?U-i(Zm_ zHEhl+<^gXy{#LUFh)+Aq+pa8l+stX+*2ZaGqU$T3*7^5drmH{PrO2yy_J`<0VB`lv z9sez7#*DoUUblsb+)bXcpChg>_jL7whripMr9Z3s!>qF*Y{^r@v+&#EIL*v$6}hA5 zzTp(Yhv1p>$w*6n8!#&Za&E06E78LiaHPnarhpTCF%BGFtMtVh5qturp9L!IPz2uSmUtQz|pZLxA=sa{y_Mpw&NQ~JSs;-S;i^NOj z8nkoJQ1&)YvmWOi3!KQ|tMuVN{i~QeR@K8Ua!dD9V*hR%~7q&pYV02s&Are@=o;`^#7FfN&cRkwK*YYtwHOb88>qBzOg)*0e!I} zu_w91XH;H8zL!c&xCmHF)@EX7;5X1^Sw~9sB(to=Qd{9y#yI=sD=>_+C4EWRf7vGk zn5mxYH{+MjgBLi~Ec++4Gz*#L`@*ZBDY-v+Ux@HB{$`CF#2zKjF7gmtl>EHB(Fv@` zR(!u^bC(i%;1h4EiGvn%9)F}VuRFs%#=r*2ugm?6x51=lx{1AJNfVwVmnymBSK#qb zjr|Ia9q7a^N_?gn1E<*ZV{eX+4vD_!T;fS3cFcsQ61Z4j6g$NBHeEujpik^iZ*Wda zUdG}K!`*-X4tp@%0bQ-W!heSS9H_QMUJs6qkII;Q|B&xrKvUMhmOiXf`it4)&-4B4XNFG_sRA^pGTi!F!n-SIdl~8qV4yV(Xq%Va{$$d3V zO@21L@dDnrFDUx|&bOMq75UsCaWh>v%k|&a-aHfym`^Yt)d#8wDya_Nrrd_)SG2FjRfICrxOKki5 zw6zMY^bh#9$VC!{&+#NMhihP-<2&Y8#tzAtrpmQ*V%pCzrt5F5r`L?~(oR{f899miMnADuTbg7YNf_@{vp={(9 z^47aNKrb(qxKIyXd?M$9x87hhb@){aAEM=!m+@7tUDY`BG`>*c^sX9SiM5hLA4#Z~ z$9!a;5szKlA|CgeC-FxoeeFIc;xS>J40Uxf)J*Dj2cJ%zE%@4c$IqHy=FC&E4SCzD z<(YSmh-Z9UT6isiu6)w$a;jP$b368mv^s;JoMB5XW*OcNWN5!w7(6GwrZ>u-AGwmkuiBN z_!S!R9$DXcomcPvttYvSQ}Aq8X~pY|-`pnBmiOBDzc;(^F(S9Uk1QA$-Bp^r;r%YZ zqr~i~DOIjdf{XWHtpPNj#z`?5nv<-z_}?b(Js-R z!g@t6PuI*RCN>Yyx2tBp3%px1e>?5%G6#He*J4h%iaDF;%g`rxH#uj->leNx_Rj^z zs_B0xx#+}|*j7a@?xWp_+rL?n&mq3e$M~NTwN2emeQGEF8KW%byPdL@a)|a)#>XhJ z-x2>IdMhz_MvdOa{z>GoLA&-|EC1tC`J%itVE&b}DE830kZ+AQlZE(&T=g6(KBLml zfAjKguf*tU)HcFYz6qUe{TyfLL-Wu>Y(dU%I&yh8{n$uQ{2cMNV=zp2;s?-ig7S#i z*HxTF9LMB6Me)D36Mj2wktaIcYIOF6lU>dporlqL{_jxkzrpB4#5Oc(4_f>J!&KEjQ(7zKK(;7B- z?d+9X#WfV+s>ojO$-Rg(TByUvL>#x*;K+buRTal~Cg2diEbj<2fR{CY=hvJuz$b67B}LKNG^L(W~p+Ch?_JXP@qj?oU~A0d7Nyw~cs?tQ#D=mFgmQ;FslG7PYOr z%gPSQD!;|QPHYR`u62scZV)|Q0-dsMJ?JIuCq3kLa}s)ji+$P8y*=_LmAvr)IrBXp zZPKZ5(F;1`_F z1s>oU_-_I~0Q?@{zj+=!F?~04Mk?dH({yFa+>f-$rmLY(X{&2Rd3L?K6CK@cb=_9B zlfCf3)|%C9{gG-f9C=g(D|^4o>z<%uERI2`NuDr>mIvA=WS2E=eWn@zH7+$mF_Wc&dki}T2D?K%Ck|Fq}-|MgV%T=rQ0+ge+q zHvxiAdfu{+U1i;~e)Zk!@3~x@VAQ^C-I}PSR7y?4F-}(UIFnR(etwT{Bis zUQg+xY_0aUQ_rC+q%5!Y#qj^vwfZu0;D3lLRZYL=>gj8&{OWag+#ln~wR-L9 zyYIaGR;8j3>(;yOUAxBm^ljGawRhjPdd(NCd+)hz&E-|tyKlSaw)Fyg@4C;fyX&vl V0e$D4tJkd|WOOI~ka7)h{{^{CZ=wJI literal 0 HcmV?d00001 diff --git a/build/tools/makegcdfirm/test/twl_gcdfirm9_print.axf b/build/tools/makegcdfirm/test/twl_gcdfirm9_print.axf new file mode 100644 index 0000000000000000000000000000000000000000..3d064b38a5509e8ea9e4ce4cc5302e3f0684d513 GIT binary patch literal 288636 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 literal 0 HcmV?d00001 diff --git a/build/tools/makegcdfirm/test/wram_rbin/Makefile b/build/tools/makegcdfirm/test/wram_rbin/Makefile new file mode 100644 index 0000000..c9cd7eb --- /dev/null +++ b/build/tools/makegcdfirm/test/wram_rbin/Makefile @@ -0,0 +1,48 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - tools - gcdfirm-print +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = wram_regs.rbin + +SRCS = \ + wram_regs.c \ + +#SRCDIR = # using default +#LCFILE = # using default + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_DIR = . +INSTALL_TARGETS = $(BINDIR)/$(TARGET_BIN) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/tools/makegcdfirm/test/wram_rbin/wram_regs.c b/build/tools/makegcdfirm/test/wram_rbin/wram_regs.c new file mode 100644 index 0000000..ee7d112 --- /dev/null +++ b/build/tools/makegcdfirm/test/wram_rbin/wram_regs.c @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makegcdfirm + File: wram_regs.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include + +MIHeader_WramRegs wram_regs = +{ + // ARM9 + { + REG_WRAM_A_BNK_PACK(0, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_0KB, TRUE), + REG_WRAM_A_BNK_PACK(1, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_64KB, TRUE), + REG_WRAM_A_BNK_PACK(2, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_128KB, TRUE), + REG_WRAM_A_BNK_PACK(3, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_192KB, TRUE), + }, + { + REG_WRAM_B_BNK_PACK(0, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_0KB, TRUE), + REG_WRAM_B_BNK_PACK(1, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_32KB, TRUE), + REG_WRAM_B_BNK_PACK(2, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_64KB, TRUE), + REG_WRAM_B_BNK_PACK(3, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_96KB, TRUE), + REG_WRAM_B_BNK_PACK(4, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_128KB, TRUE), + REG_WRAM_B_BNK_PACK(5, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_160KB, TRUE), + REG_WRAM_B_BNK_PACK(6, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_192KB, TRUE), + REG_WRAM_B_BNK_PACK(7, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_224KB, TRUE), + }, + { + REG_WRAM_C_BNK_PACK(0, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_0KB, TRUE), + REG_WRAM_C_BNK_PACK(1, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_32KB, TRUE), + REG_WRAM_C_BNK_PACK(2, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_64KB, TRUE), + REG_WRAM_C_BNK_PACK(3, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_96KB, TRUE), + REG_WRAM_C_BNK_PACK(4, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_128KB, TRUE), + REG_WRAM_C_BNK_PACK(5, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_160KB, TRUE), + REG_WRAM_C_BNK_PACK(6, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_192KB, TRUE), + REG_WRAM_C_BNK_PACK(7, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_224KB, TRUE), + }, + REG_WRAM_A_MAP_PACK(MI_WRAM_MAP_NULL, + MI_WRAM_MAP_NULL, + MI_WRAM_A_IMG_128KB + ), + REG_WRAM_B_MAP_PACK(MI_WRAM_MAP_NULL, + MI_WRAM_MAP_NULL, + MI_WRAM_B_IMG_128KB + ), + REG_WRAM_C_MAP_PACK(HW_WRAM_AREA_HALF, + HW_WRAM_AREA_HALF + 0x00020000, + MI_WRAM_C_IMG_128KB + ), + + // ARM7 + REG_WRAM_A_MAP_PACK(HW_WRAM_AREA_HALF, + HW_WRAM_AREA_HALF + 0x00020000, + MI_WRAM_A_IMG_128KB + ), + REG_WRAM_B_MAP_PACK(HW_WRAM_AREA_HALF + 0x00020000, + HW_WRAM_AREA_HALF + 0x00040000, + MI_WRAM_B_IMG_128KB + ), + REG_WRAM_C_MAP_PACK(MI_WRAM_MAP_NULL, + MI_WRAM_MAP_NULL, + MI_WRAM_C_IMG_128KB + ), + // WRAM Lock + { + 0, + 0, + 0, + }, + + // WRAM-0/1 + MI_WRAM_ARM7_ALL, + + // VRAM-C + 7, + // VRAM-D + 7, +}; diff --git a/build/tools/makegcdfirm/wram_regs.c b/build/tools/makegcdfirm/wram_regs.c new file mode 100644 index 0000000..fba20ce --- /dev/null +++ b/build/tools/makegcdfirm/wram_regs.c @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makegcdfirm + File: wram_regs.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include "format_rom.h" +//#define SDK_ASM +#define NITRO_TYPES_H_ +#include +#include +#include + + +MIHeader_WramRegs wram_regs_init = +{ + // ARM9 + { + REG_MI_MBK_A0_FIELD( 1, MI_WRAM_A_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_A1_FIELD( 1, MI_WRAM_A_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_A2_FIELD( 1, MI_WRAM_A_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_A3_FIELD( 1, MI_WRAM_A_OFFSET_192KB, MI_WRAM_ARM7 ), + }, + { + REG_MI_MBK_B0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM7 ), + }, + { + REG_MI_MBK_C0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM9 ), + }, + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, MI_WRAM_MAP_NULL ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, MI_WRAM_MAP_NULL ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, HW_WRAM_AREA_HALF + 0x00020000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, HW_WRAM_AREA_HALF ) + ), + + // ARM7 + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, HW_WRAM_AREA_HALF + 0x00020000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, HW_WRAM_AREA_HALF ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, HW_WRAM_AREA_HALF + 0x00040000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, HW_WRAM_AREA_HALF + 0x00020000 ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, MI_WRAM_MAP_NULL ) + ), + + // WRAM Lock + { + 0, + 0, + 0, + }, + + // WRAM-0/1 + 3, + + // VRAM-C + 7, + // VRAM-D + 7, +}; + diff --git a/build/tools/makenandfirm/Makefile b/build/tools/makenandfirm/Makefile new file mode 100644 index 0000000..11436d9 --- /dev/null +++ b/build/tools/makenandfirm/Makefile @@ -0,0 +1,151 @@ +#! make -f +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makenandfirm +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#--------------------------------------------------------------------------- + +TARGET_PLATFORM = TWL + +SUPPORT_ECC = 0 + +ifeq ($(SUPPORT_ECC),1) +ECC_SRCDIR = ../../libraries/acsign_ecc/common \ + ../../libraries/acsign_ecc/common/algae/common/ecc \ + ../../libraries/acsign_ecc/common/algae/cmp \ + ../../libraries/acsign_ecc/common/algae/ecsource \ + +ECC_INCDIR = ../../libraries/acsign_ecc/include \ + ../../libraries/acsign_ecc/common/algae/include \ + ../../libraries/acsign_ecc/common/algae/common/include \ + +ECC_SRCS = acsign_ecc.c acsign_cryptoc.c \ + \ + cmparith.c cmpbits.c cmpcnv.c cmpdiv.c cmpmem.c \ + cmpmod.c cmpmuldv.c cmpspprt.c cmpsqr.c cmpvectr.c \ + computem.c ecfpatbl.c ecfpsmul.c \ + spcprime.c secfpcom.c \ + \ + p224v1.c p224v1a.c \ + +ECC_DEFS = -DRSA_PROTOTYPES=RSA_ENABLED \ + -DRCOM_BUILD=RSA_ENABLED -DRSA_FAST_INVERSE=RSA_ENABLED \ + -DRSA_STD_MEM_FUNCS=RSA_ENABLED -DRSA_STD_ALLOC_FUNCS=RSA_ENABLED \ +else +ECC_SRCDIR = +ECC_INCDIR = +ECC_SRCS = +ECC_DEFS = +endif + +SRCDIR += ../acsign $(ECC_SRCDIR) +INCDIR += ../acsign/include $(ECC_INCDIR) $(ECC_SRCDIR) + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +TARGETS = makenandfirm.exe + +SOURCES_C = makenandfirm.c \ + out_nandfirm.c \ + misc.c \ + path.c \ + defval.c \ + compress.c \ + wram_regs.c \ + acsign.c \ + acsign_nand.c \ + aes2.c \ + $(ECC_SRCS) + +SOURCES = $(SORUCES_C) + +OBJECTS = $(SOURCES_C:.c=.o) + +HEADERS = format_nlist.h \ + makenandfirm.h \ + path.h \ + format_rom.h \ + misc.h \ + defval.h \ + compress.h \ + +MACROS += -DSMALL_CODE_SIZE \ + -DSTANDALONE \ + -DOPT_32_BIT \ + -DNO_SPLIT \ + -DNO_FP_API \ + -DNO_R_DIAG \ + $(ECC_DEFS) + +INSTALL_DIR = $(FIRM_INSTALL_TOOLSDIR)/bin +INSTALL_TARGETS = $(TARGETS) + +LDIRT_CLEAN = $(OBJECTS) $(TARGETS) version.h + + +VPATH = $(SRCDIR) +TWL_INCDIR := $(TWL_INCDIR) $(addprefix -I,$(INCDIR)) $(addprefix -I,$(FIRM_INCDIR)) + +include $(TWLSDK_ROOT)/build/buildtools/twl/modulerules.x86 + +#---------------------------------------------------------------------------- +# build +#---------------------------------------------------------------------------- +do-build: $(TARGETS) + +$(TARGETS): $(OBJECTS) + $(CC_X86) $+ -o $@ + +makenandfirm.o: makenandfirm.c makenandfirm.h format_rom.h path.h version.h +out_nandfirm.o: out_nandfirm.c misc.h format_rom.h format_nlist.h format_sign.h elf.h compress.h \ + $(FIRM_INCDIR)/firm/format/sign.h \ + $(FIRM_INCDIR)/firm/format/wram_regs.h \ + $(FIRM_INCDIR)/firm/format/nandfirm.h \ + +misc.o: misc.c misc.h +path.o: path.c path.h +compress.o: compress.c compress.h +wram_regs.o: wram_regs.c +acsign.o: acsign.c ../acsign/include/acsign.h +acsign_nand.o: acsign_nand.c format_sign.h \ + $(FIRM_INCDIR)/firm/format/sign.h \ + $(FIRM_INCDIR)/firm/format/wram_regs.h \ + $(FIRM_INCDIR)/firm/format/nandfirm.h \ + +aes2.o: aes2.c aes2.h + +$(FIRM_INCDIR)/firm/format/sign.h: +$(FIRM_INCDIR)/firm/format/wram_regs.h: +$(FIRM_INCDIR)/firm/format/nandfirm.h: +format_nlist.h: +format_rom.h: +makenandfirm.h: +acsign.h: +acsign_nand.h: +path.h: + +# avoid to warning message +misc.o:WARNING += -Wno-format-y2k + +# + +version.h: $(SOURCES) $(HEADERS) + @for i in $^ ; \ + do \ + date -r $$i +'#define SDK_DATE_OF_LATEST_FILE %Y%m%dUL'; \ + done | sort | tail -1 > $@ + +test: path.c misc.c + $(CC_X86) -DTEST $+ -o $@ diff --git a/build/tools/makenandfirm/compress.c b/build/tools/makenandfirm/compress.c new file mode 100644 index 0000000..71e468c --- /dev/null +++ b/build/tools/makenandfirm/compress.c @@ -0,0 +1,293 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenandfirm + File: compress.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include // atoi() +#include // strcmp() +#include // isprint() +#include // chdir() +#include +#include // UCHAR_MAX +#include +#include // stat() +#include "elf.h" +#include "misc.h" +#include "defval.h" +#include "format_rom.h" +#include "format_nlist.h" +#include "makenandfirm.h" + +//#define ADD_HEADER + +#define DIFF_CODE_HEADER (0x80) +#define RL_CODE_HEADER (0x30) +#define LZ_CODE_HEADER (0x10) +#define HUFF_CODE_HEADER (0x20) +#define CODE_HEADER_MASK (0xF0) + +//=========================================================================== +// LZ77k +//=========================================================================== +static u8 SearchLZ(const u8 *nextp, u32 remainSize, u16 *offset); + +static u16 windowPos; +static u16 windowLen; + +static s16 LZOffsetTable[4096]; +static s16 LZByteTable[256]; +static s16 LZEndTable[256]; + + +static void LZInitTable(void) +{ + u16 i; + + for (i = 0; i < 256; i++) + { + LZByteTable[i] = -1; + LZEndTable[i] = -1; + } + windowPos = 0; + windowLen = 0; +} + +static void SlideByte(const u8 *srcp) +{ + s16 offset; + u8 in_data = *srcp; + u16 insert_offset; + + if (windowLen == 4096) + { + u8 out_data = *(srcp - 4096); + if ((LZByteTable[out_data] = LZOffsetTable[LZByteTable[out_data]]) == -1) + { + LZEndTable[out_data] = -1; + } + insert_offset = windowPos; + } + else + { + insert_offset = windowLen; + } + + offset = LZEndTable[in_data]; + if (offset == -1) + { + LZByteTable[in_data] = insert_offset; + } + else + { + LZOffsetTable[offset] = insert_offset; + } + LZEndTable[in_data] = insert_offset; + LZOffsetTable[insert_offset] = -1; + + if (windowLen == 4096) + { + windowPos = (u16)((windowPos + 1) % 0x1000); + } + else + { + windowLen++; + } +} + +static void LZSlide(const u8 *srcp, u32 n) +{ + u32 i; + + for (i = 0; i < n; i++) + { + SlideByte(srcp++); + } +} + +/*---------------------------------------------------------------------------* + Name: MI_CompressLZ + + Description: LZ77ksȂ֐ + + Arguments: srcp kf[^ւ̃|C^ + size kf[^TCY + dstp kf[^ւ̃|C^ + kf[^傫TCỸobt@KvłB + + Returns: k̃f[^TCYB + k̃f[^kO傫Ȃꍇɂ͈k𒆒f0Ԃ܂B + *---------------------------------------------------------------------------*/ +u32 LZCompWrite(u8 *srcp, u32 size, u8 *dstp, int boundary) +{ + u32 LZDstCount; // kf[^̃oCg + u8 LZCompFlags; // k̗LtOn + u8 *LZCompFlagsp; // LZCompFlags i[郁̈|Cg + u16 lastOffset; // vf[^܂ł̃ItZbg (̎_ł̍Œvf[^) + u8 lastLength; // vf[^ (̎_ł̍Œvf[^) + u8 i; + u32 dstMax; + +#ifdef ADD_HEADER + *(u32 *)dstp = size << 8 | LZ_CODE_HEADER; // f[^Ewb_ + dstp += 4; +#endif + LZDstCount = 4; + dstMax = size; + LZInitTable(); + + while (size > 0) + { + LZCompFlags = 0; + LZCompFlagsp = dstp++; // tOn̊i[ + LZDstCount++; + + // tOn8rbgf[^ƂĊi[邽߁A8񃋁[v + for (i = 0; i < 8; i++) + { + LZCompFlags <<= 1; // (i=0) ͓ɈӖ͂Ȃ + if (size <= 0) + { + // I[ɗꍇ̓tOŌ܂ŃVtgĂI + continue; + } + + if ((lastLength = SearchLZ(srcp, size, &lastOffset))) + { + // k”\ȏꍇ̓tO𗧂Ă + LZCompFlags |= 0x1; + + // ItZbg͏4rbgƉ8rbgɕĊi[ + *dstp++ = (u8)((lastLength - 3) << 4 | (lastOffset - 1) >> 8); + *dstp++ = (u8)((lastOffset - 1) & 0xff); + LZDstCount += 2; + LZSlide(srcp, lastLength); + srcp += lastLength; + size -= lastLength; + } + else + { + // kȂ + LZSlide(srcp, 1); + *dstp++ = *srcp++; + size--; + LZDstCount++; + } + } // 8񃋁[vI + *LZCompFlagsp = LZCompFlags; // tOni[ + } + + // 16oCgEACg + // ACgpf[^0 ̓f[^TCYɊ܂߂ + i = 0; + while (LZDstCount & (boundary - 1)) +// while ((LZDstCount + i) & 0x3) + { + *dstp++ = 0; + LZDstCount++; + i++; + } + + return LZDstCount; +} + +//-------------------------------------------------------- +// LZ77kŃXCh̒Œv܂B +// Arguments: startp f[^̊Jnʒu|C^ +// nextp Jnf[^̃|C^ +// remainSize cf[^TCY +// offset vItZbgi[̈ւ̃|C^ +// Return : v񂪌‚ꍇ TRUE +// ‚Ȃꍇ FALSE +//-------------------------------------------------------- +static u8 SearchLZ(const u8 *nextp, u32 remainSize, u16 *offset) +{ + const u8 *searchp; + const u8 *headp, *searchHeadp; + u16 maxOffset; + u8 maxLength = 2; + u8 tmpLength; + s32 w_offset; + + if (remainSize < 3) + { + return 0; + } + + w_offset = LZByteTable[*nextp]; + + while (w_offset != -1) + { + if (w_offset < windowPos) + { + searchp = nextp - windowPos + w_offset; + } + else + { + searchp = nextp - windowLen - windowPos + w_offset; + } + + /* ĂǂA͂ɍ */ + if (*(searchp + 1) != *(nextp + 1) || *(searchp + 2) != *(nextp + 2)) + { + w_offset = LZOffsetTable[w_offset]; + continue; + } + + if (nextp - searchp < 2) + { + // VRAM2oCgANZXȂ̂ (VRAMf[^ǂݏoꍇ邽)A + // Ώۃf[^2oCgÕf[^ɂȂ΂ȂȂB + // + // ItZbg12rbgŊi[邽߁A4096ȉ + break; + } + tmpLength = 3; + searchHeadp = searchp + 3; + headp = nextp + 3; + + while (((u32)(headp - nextp) < remainSize) && (*headp == *searchHeadp)) + { + headp++; + searchHeadp++; + tmpLength++; + + // f[^4rbgŊi[邽߁A18ȉ (3̉ʂ͂) + if (tmpLength == (0xF + 3)) + { + break; + } + } + if (tmpLength > maxLength) + { + // ő咷ItZbgXV + maxLength = tmpLength; + maxOffset = (u16)(nextp - searchp); + if (maxLength == (0xF + 3)) + { + // vőȂ̂ŁAIB + break; + } + } + w_offset = LZOffsetTable[w_offset]; + } + + if (maxLength < 3) + { + return 0; + } + *offset = maxOffset; + return maxLength; +} + diff --git a/build/tools/makenandfirm/compress.h b/build/tools/makenandfirm/compress.h new file mode 100644 index 0000000..f8fd899 --- /dev/null +++ b/build/tools/makenandfirm/compress.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenandfirm + File: compress.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef COMPRESS_H_ +#define COMPRESS_H_ + +#include "misc.h" + + +/*---------------------------------------------------------------------------* + Name: MI_CompressLZ + + Description: LZ77ksȂ֐ + + Arguments: srcp kf[^ւ̃|C^ + size kf[^TCY + dstp kf[^ւ̃|C^ + kf[^傫TCỸobt@KvłB + + Returns: k̃f[^TCYB + *---------------------------------------------------------------------------*/ +u32 LZCompWrite(u8 *srcp, u32 size, u8 *dstp, int boundary); + + +#endif //COMPRESS_H_ diff --git a/build/tools/makenandfirm/defval.c b/build/tools/makenandfirm/defval.c new file mode 100644 index 0000000..679fb0e --- /dev/null +++ b/build/tools/makenandfirm/defval.c @@ -0,0 +1,315 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makerom + File: defval.c + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: defval.c,v $ + Revision 1.10 2006/01/18 02:11:19 kitase_hirotake + do-indent + + Revision 1.9 2005/02/28 05:26:03 yosizaki + do-indent. + + Revision 1.8 2004/08/05 13:50:13 yasu + Support -M option + + Revision 1.7 2004/06/29 04:55:40 yasu + Use VBuffer to resolve variables + + Revision 1.6 2004/06/23 07:51:02 yasu + fix a bug as illegal memory freeing at ResolveDefVal() + + Revision 1.5 2004/05/27 00:40:49 yasu + care also about current directory (dot ".") + + Revision 1.4 2004/05/27 00:25:46 yasu + care about double-dots ".." for defvalue option :r, :e + + Revision 1.3 2004/05/27 00:11:19 yasu + fix a error when searching a "dot" of file extension + + Revision 1.2 2004/05/26 12:02:47 yasu + support :h, :t, :r, :e option for variable name + + Revision 1.1 2004/03/26 05:06:45 yasu + support variables like as -DNAME=VALUE + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +#include // getenv() +#include // strcasecmp() +#include // getopt() +#include "misc.h" +#include "defval.h" + +typedef struct tValdef +{ + struct tValdef *next; + char *name; + char *value; +} +tValdef; + +tValdef *valdef_top = NULL; + + +// +// Add new define value via file +// +// opt : "DEFINE=VALUE" +// +BOOL AddDefValFromFile(char *filename) +{ + char *buffer; + int buffer_size; + int read_size; + FILE *fp; + + if (filename[0] == '-' && filename[1] == '\0') + { + fp = stdin; + } + else if (NULL == (fp = fopen(filename, "rb"))) + { + fprintf(stderr, "Cannot open file \"%s\".\n", filename); + return FALSE; + } + + buffer_size = DEFVAL_DEFAULT_BUFFER_SIZE; + + if (NULL == (buffer = malloc(buffer_size))) + { + fprintf(stderr, "Cannot allocate memory.\n"); + return FALSE; + } + + read_size = 0; + + while (NULL != fgets(buffer + read_size, buffer_size - read_size, fp)) + { + read_size = strlen(buffer); + + if (read_size == buffer_size - 1 && buffer[read_size - 1] != '\n') + { + buffer_size *= 2; + + if (NULL == (buffer = realloc(buffer, buffer_size))) + { + fprintf(stderr, "Cannot allocate memory.\n"); + return FALSE; + } + continue; + } + + AddDefVal(buffer); + read_size = 0; + } + + if (fp != stdin) + { + fclose(fp); + } + free(buffer); + + return TRUE; +} + + +// +// Add new define value +// +// opt : "DEFINE=VALUE" +// +void AddDefVal(char *opt) +{ + int i; + tValdef *t; + + for (i = 0;; i++) + { + if ('=' == opt[i] || '\0' == opt[i]) + { + break; + } + } + + if (i > 0) + { + t = Alloc(sizeof(tValdef)); + t->name = strncpy(Alloc(i + 1), opt, i); + t->name[i] = '\0'; + + if (opt[i] == '=') + { + i++; + } + t->value = strdup(opt + i); + + t->next = valdef_top; + valdef_top = t; + + debug_printf("DEFINE:$(%s)=\"%s\"\n", t->name, t->value); + } + return; +} + +// +// Search define value +// +// Return: value of specified name +// +char *SearchDefVal(char *name) +{ + tValdef *t; + + for (t = valdef_top; t; t = t->next) + { + if (!strcmp(t->name, name)) + { + return t->value; + } + } + + return getenv(name); +} + + +// +// Search define value and Modify it by : option +// +// Return: duplicated value of specified name modified by :x option +// +char *SearchDefValWithOption(char *name) +{ + int len_name = strlen(name); + char *value; + char option = '\0'; + + if (len_name > 2 && name[len_name - 2] == ':') + { + name[len_name - 2] = '\0'; + option = name[len_name - 1]; + } + + value = SearchDefVal(name); + + if (value) + { + int value_len = strlen(value); + int col_dot = value_len; + int col_filename = 0; + int i; + + for (i = 0; i < value_len; i++) + { + switch (value[i]) + { + case '.': + if (col_filename == i && + (value[i + 1] == '\0' || (value[i + 1] == '.' && value[i + 2] == '\0'))) + { + i = value_len; // exit loop if last entry is . or .. + } + else + { + col_dot = i; // Save the last dot column + } + break; + + case '/': + case '\\': + case ':': + col_filename = i + 1; // Save the last filename + col_dot = value_len; // Reset dot position + break; + + default: + ; + } + } + + switch (option) + { + case 'h': // Dirname with the last slash + value = strdup(value); + value[col_filename] = '\0'; + break; + + case 't': // Filename + value = strdup(value + col_filename); + break; + + case 'r': // All without . file extension + value = strdup(value); + value[col_dot] = '\0'; + break; + + case 'e': // File extension + value = strdup(value + col_dot + 1); + break; + + default: + value = strdup(value); + } + } + return value; +} + + +// +// Resolve define value +// +// Return: new string +// +char *ResolveDefVal(char *str) +{ + int i, j; + char *val; + VBuffer buf; + + InitVBuffer(&buf); + + for (i = 0; '\0' != str[i]; i++) + { + // search $(XXX) + if ('$' == str[i] && '(' == str[i + 1]) + { + for (j = i + 2; '\0' != str[j]; j++) + { + if (')' == str[j]) + { + str[j] = '\0'; + + // get value of XXX + val = SearchDefValWithOption(&str[i + 2]); + + // copy value of XXX + if (val) + { + char *s = val; + + while (*s) + { + PutVBuffer(&buf, *s); + s++; + } + free(val); + } + i = j; + goto next; + } + } + } + PutVBuffer(&buf, str[i]); + next:; + } + return GetVBuffer(&buf); // pass allocated buffer, should be freed by caller +} diff --git a/build/tools/makenandfirm/defval.h b/build/tools/makenandfirm/defval.h new file mode 100644 index 0000000..7135510 --- /dev/null +++ b/build/tools/makenandfirm/defval.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makerom + File: defval.h + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: defval.h,v $ + Revision 1.4 2006/01/18 02:11:19 kitase_hirotake + do-indent + + Revision 1.3 2005/02/28 05:26:03 yosizaki + do-indent. + + Revision 1.2 2004/08/05 13:50:13 yasu + Support -M option + + Revision 1.1 2004/03/26 05:06:45 yasu + support variables like as -DNAME=VALUE + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef DEFVAL_H_ +#define DEFVAL_H_ + +#define DEFVAL_DEFAULT_BUFFER_SIZE (1024) + +BOOL AddDefValFromFile(char *filename); +void AddDefVal(char *opt); +char *SearchDefVal(char *name); +char *ResolveDefVal(char *str); + +#endif //DEFVAL_H_ diff --git a/build/tools/makenandfirm/elf.h b/build/tools/makenandfirm/elf.h new file mode 100644 index 0000000..c360cd3 --- /dev/null +++ b/build/tools/makenandfirm/elf.h @@ -0,0 +1,431 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - ELF + File: elf.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + *---------------------------------------------------------------------------*/ + +#ifndef ELF_H_ +#define ELF_H_ + +#include "misc.h" + +/*--------------------------------------------------------- + ^` + --------------------------------------------------------*/ +typedef u32 Elf32_Addr; /* size:4, align:4 Unsigned program address */ +typedef u16 Elf32_Half; /* size:2, align:2 Unsigned medium int */ +typedef u32 Elf32_Off; /* size:4, align:4 Unsigned file offset */ +typedef s32 Elf32_Sword; /* size:4, align:4 Signed large int */ +typedef u32 Elf32_Word; /* size:4, align:4 Unsigned large int */ + +/*--------------------------------------------------------- + ELF Header + --------------------------------------------------------*/ +/* e_ident̃CfbNX */ +#define EI_MAG0 0 /* File identification */ +#define EI_MAG1 1 /* File identification */ +#define EI_MAG2 2 /* File identification */ +#define EI_MAG3 3 /* File identification */ +#define EI_CLASS 4 /* File class 0=invalid, 1=32bit, 2=64bit */ +#define EI_DATA 5 /* Data encoding 0=invalid, 1=LSB, 2=MSB */ +#define EI_VERSION 6 /* File version ݂1 */ +#define EI_PAD 7 /* Start of padding bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; /* ELF̌`(Ĕzu”\, s”\Ȃ) */ + Elf32_Half e_machine; /* t@CŗvA[LeN` */ + Elf32_Word e_version; /* ELFtH[}bg̃o[Wi݂1j */ + Elf32_Addr e_entry; /* vÕGg|CgBw薳Ȃ0B */ + Elf32_Off e_phoff; /* vOwb_e[ũt@C擪̃ItZbg */ + Elf32_Off e_shoff; /* ZNVwb_e[ũt@C擪̃ItZbg */ + Elf32_Word e_flags; /* vZbTŗL̃tO */ + Elf32_Half e_ehsize; /* ELFwb_̃TCY */ + Elf32_Half e_phentsize; /* 1vOwb_̃TCY */ + Elf32_Half e_phnum; /* vOwb_̐ */ + Elf32_Half e_shentsize; /* 1ZNVwb_̃TCY */ + Elf32_Half e_shnum; /* ZNVwb_̐ */ + Elf32_Half e_shstrndx; /* ZNVe[uZNVւ̃CfbNX */ +} Elf32_Ehdr; + +/* e_ident[EI_*]̒g` */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFCLASSNONE 0 /* invalid */ +#define ELFCLASS32 1 /* ARM and Thumb processors use 32-bit ELF. */ +#define ELFCLASS64 2 +#define ELFDATANONE 0 /* invalid */ +#define ELFDATA2LSB 1 /* little-endian */ +#define ELFDATA2MSB 2 /* big-endian */ + + +/* [e_type] */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Re-locatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOPROC 0xff00 /* Processor-specific */ +#define ET_HIPROC 0xffff /* Processor-specific */ + +/* [e_machine] */ +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_860 7 +#define EM_MIPS 8 +#define EM_MIPS_RS4_BE 10 +#define EM_ARM 40 /* ARM/Thumb Architecture */ + + +/* [e_version] This member identifies the object file version.*/ +#define EV_NONE 0 /* Invalid version */ +#define EV_CURRENT 1 /* Current version */ + + +/* + ARM-specific e_flags + e_flags Field Value Meaning + EF_ARM_HASENTRY (0x02) e_entry contains a program-loader entry point + (see section 4.1.1, Entry points, below). + EF_ARM_SYMSARESORTED (0x04) Each subsection of the symbol table is sorted by symbol value + (see section 4.4.8, Symbol table order, below) + EF_ARM_DYNSYMSUSESEGIDX (0x8) Symbols in dynamic symbol tables that are defined in sections + included in program segment n have st_shndx = n + 1. + (see section 4.4.9, Dynamic symbol table entries, below). + EF_ARM_MAPSYMSFIRST (0x10) Mapping symbols precede other local symbols in the symbol table + (see section 4.4.8, Symbol table order, below). + + EF_ARM_EABIMASK (0xFF000000)(current version is 0x02000000) + This masks an 8-bit version number, the version of the ARM + EABI to which this ELF file conforms. This EABI is version 2. A + value of 0 denotes unknown conformance. +*/ +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x8 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0xFF000000 + + +/*--------------------------------------------------------- + Program headers + --------------------------------------------------------*/ +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* [p_type] */ +#define PT_NULL 0 /* gȂGgŁÃo̒l̈Ӗ͖` */ +#define PT_LOAD 1 /* sɃ[hZOg */ +#define PT_DYNAMIC 2 /* I\̔zێZOg */ +#define PT_INTERP 3 /* t@C̉߂ɎgC^v^̃pXێZOg */ +#define PT_NOTE 4 /* t@C̉߂ɂ͎gȂێZOg */ +#define PT_SHLIB 5 /* \ */ +#define PT_PHDR 6 /* vOwb_e[uivÕC[Ẅꕔłꍇ̂ݑ݁j */ +//#define PT_TLS ? /* XbhǏL̈̃ev[g */ + +#define PT_LOOS 0x60000000 /* OSŗLɗ\񂳂ꂽ̈ */ +#define PT_HIOS 0x6fffffff + +#define PT_LOPROC 0x70000000 /* vZbTŗLɗ\񂳂ꂽ̈ */ +#define PT_HIPROC 0x7fffffff + +/* [p_flags]*/ +#define PF_X 1 /*s”\*/ +#define PF_W 2 /*݉”\*/ +#define PF_R 4 /*ǂݏo”\*/ +#define PF_ARM_SB 0x10000000 /*The segment contains the location addressed by the static base*/ +#define PF_ARM_PI 0x20000000 /*The segment is position-independent*/ +#define PF_ARM_ENTRY 0x80000000 /*The segment contains the entry point*/ +#define PF_MASKPROC 0xf0000000 + + +/*--------------------------------------------------------- + Section headers + --------------------------------------------------------*/ +typedef struct { + Elf32_Word sh_name; /*ZNVwb_e[uZNṼCfbNX*/ + Elf32_Word sh_type; /* ^CviL`QƁj */ + Elf32_Word sh_flags; + Elf32_Addr sh_addr; /* */ + Elf32_Off sh_offset; /* t@C̐擪̃ItZbg */ + Elf32_Word sh_size; /* oCgPʂ̃TCY */ + Elf32_Word sh_link; /* sh_typeɂĒl̈Ӗς */ + Elf32_Word sh_info; /* sh_typeɂĒl̈Ӗς */ + Elf32_Word sh_addralign; /* ACg(0or1ŐȂ,44ByteAlign) */ + Elf32_Word sh_entsize; /* ŒTCỸGge[uꍇA1vf̃TCY */ +} Elf32_Shdr; + +/* sh_addr mod sh_addralign = 0 łȂ΂ȂȂ */ + +/* Section Types, [sh_type] */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + + +/* [sh_flags] */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 +/* ARM-EABI-specific */ +#define SHF_ENTRYSECT 0x10000000 /* The section contains an entry point. */ +#define SHF_COMDEF 0x80000000 /* The section may be multiply defined in the input to a link step. */ +/* others */ +#define SHF_LINK_ORDER 0x80 + +/*ZNVCfbNX*/ +//Sym->st_shndxȂ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + + +//̓wb_łȂ̃f[^\ + +/*--------------------------------------------------------- + Symbol Table Entry + --------------------------------------------------------*/ +typedef struct { + Elf32_Word st_name; /* V{e[ũCfbNX */ + Elf32_Addr st_value; /* 炭֘AZNVł̃ItZbgl */ + Elf32_Word st_size; /* TCYȂAsȏꍇ 0 */ + unsigned char st_info; /* oCh ^Cv */ + unsigned char st_other; /* ݂ 0 */ + Elf32_Half st_shndx; /* ֘AZNVwb_e[ũCfbNX */ +} Elf32_Sym; + + +/* st_info */ +#define ELF32_ST_BIND(i) ((i)>>4) +#define ELF32_ST_TYPE(i) ((i)&0xf) +#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + +/* st_info BIND */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +/* st_info TYPE */ +#define STT_NOTYPE 0 /*`*/ +#define STT_OBJECT 1 /*f[^IuWFNg*/ +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + + +/*--------------------------------------------------------- + Relocation Entry + --------------------------------------------------------*/ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) + + +/* r_info TYPE */ +#define R_ARM_NONE 0 /* Any No relocation. Encodes dependencies between sections. */ +#define R_ARM_PC24 1 /* ARM B/BL S . P + A */ +#define R_ARM_ABS32 2 /* 32-bit word S + A */ +#define R_ARM_REL32 3 /* 32-bit word S . P + A */ +#define R_ARM_PC13 4 /* ARM LDR r, [pc,c] S . P + A */ +#define R_ARM_ABS16 5 /* 16-bit half-word S + A */ +#define R_ARM_ABS12 6 /* ARM LDR/STR S + A */ +#define R_ARM_THM_ABS5 7 /* Thumb LDR/STR S + A */ +#define R_ARM_ABS8 8 /* 8-bit byte S + A */ +#define R_ARM_SBREL32 9 /* 32-bit word S . B + A */ +#define R_ARM_THM_PC22 10 /* Thumb BL pair S . P+ A */ +#define R_ARM_THM_PC8 11 /* Thumb LDR r, [pc,c] S . P + A */ +#define R_ARM_AMP_VCALL9 12 /* AMP VCALL Obsolete.SA-1500 only. */ +#define R_ARM_SWI24 13 /* ARM SWI S + A */ +#define R_ARM_THM_SWI8 14 /* Thumb SWI S + A */ +#define R_ARM_XPC25 15 /* ARM BLX S . P+ A */ +#define R_ARM_THM_XPC22 16 /* Thumb BLX pair S . P+ A */ + +/* 17-31, reserved to ARM Linux */ +//17-19 Reserved to ARM LINUX +#define R_ARM_COPY 20 /* 32 bit word Copy symbol at dynamic link time. */ +#define R_ARM_GLOB_DAT 21 /* 32 bit word Create GOT entry. */ +#define R_ARM_JUMP_SLOT 22 /* 32 bit word Create PLT entry. */ +#define R_ARM_RELATIVE 23 /* 32 bit word Adjust by program base. */ +#define R_ARM_GOTOFF 24 /* 32 bit word Offset relative to start of GOT. */ +#define R_ARM_GOTPC 25 /* 32 bit word Insert address of GOT. */ +#define R_ARM_GOT32 26 /* 32 bit word Entry in GOT. */ +#define R_ARM_PLT32 27 /* ARM BL Entry in PLT. */ + +/* 28-31 Reserved to ARM LINUX */ +#define R_ARM_ALU_PCREL_7_0 32 /* ARM ADD/SUB (S . P + A) & 0x000000FF */ +#define R_ARM_ALU_PCREL_15_8 33 /* ARM ADD/SUB (S . P + A) & 0x0000FF00 */ +#define R_ARM_ALU_PCREL_23_15 34 /* ARM ADD/SUB (S . P + A) & 0x00FF0000 */ +#define R_ARM_LDR_SBREL_11_0 35 /* ARM LDR/STR (S . B + A) & 0x00000FFF */ +#define R_ARM_ALU_SBREL_19_12 36 /* ARM ADD/SUB (S . B + A) & 0x000FF000 */ +#define R_ARM_ALU_SBREL_27_20 37 /* ARM ADD/SUB (S . B + A) & 0x0FF00000 */ + +#define R_ARM_TARGET1 38 +#define R_ARM_ROSEGREL32 39 +#define R_ARM_V4BX 40 +#define R_ARM_TARGET2 41 +#define R_ARM_PREL31 42 + +/* 96-111, reserved to ARM g++ */ +#define R_ARM_GNU_VTENTRY 100 /* 32 bit word Record C++ vtable entry. */ +#define R_ARM_GNU_VTINHERIT 101 /* 32 bit word Record C++ member usage. */ +#define R_ARM_THM_PC11 102 /* Thumb B S . P + A */ +#define R_ARM_THM_PC9 103 /* Thumb B S . P + A */ + +/* 112-127, reserved for private experiments */ + +/* 128-248, reserved to ARM */ +#define R_ARM_RXPC25 249 /* ARM BLX (S . P) + A #define For calls between program segments. */ +#define R_ARM_RSBREL32 250 /* Word (S . SB) + A For an offset from SB, the static base. */ +#define R_ARM_THM_RPC22 251 /* Thumb BL/BLX pair (S . P) + A For calls between program segments. */ +#define R_ARM_RREL32 252 /* Word (S . P) + A For on offset between two segments. */ +#define R_ARM_RABS32 253 /* Word S + A For the address of a location in the target segment. */ +#define R_ARM_RPC24 254 /* ARM B/BL (S . P) + A For calls between program segments. */ +#define R_ARM_RBASE 255 /* None None.Identifies the segment being relocated by the following + relocation directives. The ARM EABI poses two problems for relocating + executables and shared objects encoded in */ + + +// shirait +#define R_ARM_LDR_PC_G0 4 //LDR + +#define R_ARM_ABS12 6 //LDR, STR + +#define R_ARM_THM_CALL 10 //R_ARM_THM_PC22Ɠ + +#define R_ARM_CALL 28 //BL/BLX +#define R_ARM_JUMP24 29 //B/BL +#define R_ARM_THM_JUMP24 30 + +#define R_ARM_MOVW_ABS_NC 43 //MOVW +#define R_ARM_MOVT_ABS 44 //MOVT +#define R_ARM_MOVW_PREL_NC 45 //MOVW +#define R_ARM_MOVT_PREL 46 //MOVT + +#define R_ARM_ALU_PC_G0_NC 57 //ADD, SUB +#define R_ARM_ALU_PC_G0 58 //ADD, SUB +#define R_ARM_ALU_PC_G1_NC 59 //ADD, SUB +#define R_ARM_ALU_PC_G1 60 //ADD, SUB +#define R_ARM_ALU_PC_G2 61 //ADD, SUB +#define R_ARM_LDR_PC_G1 62 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_PC_G2 63 //LDR, STR, LDRB, STRB +#define R_ARM_LDRS_PC_G0 64 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_PC_G1 65 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_PC_G2 66 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDC_PC_G0 67 //LDC, STC +#define R_ARM_LDC_PC_G1 68 //LDC, STC +#define R_ARM_LDC_PC_G2 69 //LDC, STC +#define R_ARM_ALU_SB_G0_NC 70 //ADD, SUB +#define R_ARM_ALU_SB_G0 71 //ADD, SUB +#define R_ARM_ALU_SB_G1_NC 72 //ADD, SUB +#define R_ARM_ALU_SB_G1 73 //ADD, SUB +#define R_ARM_ALU_SB_G2 74 //ADD, SUB +#define R_ARM_LDR_SB_G0 75 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_SB_G1 76 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_SB_G2 77 //LDR, STR, LDRB, STRB +#define R_ARM_LDRS_SB_G0 78 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_SB_G1 79 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_SB_G2 80 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDC_SB_G0 81 //LDC, STC +#define R_ARM_LDC_SB_G1 82 //LDC, STC +#define R_ARM_LDC_SB_G2 83 //LDC, STC +#define R_ARM_MOVW_BREL_NC 84 //MOVW +#define R_ARM_MOVT_BREL 85 //MOVT +#define R_ARM_MOVW_BREL 86 //MOVW + +#define R_ARM_GOT_BREL12 97 //LDR +#define R_ARM_GOTOFF12 98 //LDR, STR + +#define R_ARM_TLS_LDO12 109 //LDR, STR +#define R_ARM_TLS_LE12 110 //LDR, STR +#define R_ARM_TLS_TE12GP 111 //LDR + + + +/*--------------------------------------------------------- + Dynamic Section elf_v1.2 + --------------------------------------------------------*/ +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + + +/* Additional symbol types for Thumb. */ +#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ +#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ + + + + + + + + + +/*--------------------------------------------------------- + ELFwb_ǂݏo + --------------------------------------------------------*/ +void *ELF_LoadELFHeader(const void *buf, Elf32_Ehdr *ehdr); + + + +#endif /* ELF_H_ */ + diff --git a/build/tools/makenandfirm/format_nlist.h b/build/tools/makenandfirm/format_nlist.h new file mode 100644 index 0000000..a1ac95f --- /dev/null +++ b/build/tools/makenandfirm/format_nlist.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenandfirm + File: format_nlist.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FORMAT_NLIST_H_ +#define FORMAT_NLIST_H_ + +#include +#include "misc.h" +#include "path.h" + +#define SPECFILE_MAGIC_ID "#NANDSF" + +#define CRC16_INIT_VALUE 0xffff + +//--------------------------------------------------------------------------- +// Banner Spec File +//--------------------------------------------------------------------------- + +// Command List +typedef struct +{ + char *string; + BOOL (*funcp) (char *, int num); + +} +tCommandDesc; + + +// F Command +typedef struct +{ + u32 offsetStart; + u32 offsetEnd; + u32 padding; + char fullPathSrc[FILENAME_MAX]; + +} +tFileDesc; + + +#endif // FORMAT_NLIST_H_ diff --git a/build/tools/makenandfirm/format_rom.h b/build/tools/makenandfirm/format_rom.h new file mode 100644 index 0000000..e7195c1 --- /dev/null +++ b/build/tools/makenandfirm/format_rom.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenandfirm + File: format_rom.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FORMAT_ROM_H_ +#define FORMAT_ROM_H_ + +#include "misc.h" +#include + + +#define DEFAULT_ALIGN 0x200 +#define FIRM_ALIGN DEFAULT_ALIGN +#define FIRM_ALIGN_MASK (FIRM_ALIGN - 1) + +#define DEFAULT_HOSTROOT "." +#define DEFAULT_ROOT "/" + +#define DEFAULT_REJECT_1 "CVS" +#define DEFAULT_REJECT_2 "vssver.scc" + +#define FORMAT_VERSION "1.0" + +#define ENTRYNAME_MAX 127 + +#define DEFAULT_LISTFILE "default.nlf" + +#define DEFAULT_NANDFIRM_SUFFIX ".nand" +#define DEFAULT_SPECFILE_SUFFIX ".nandsf" + +/*===========================================================================* + * ROM FORMAT + *===========================================================================*/ + +//--------------------------------------------------------------------------- +// ROM HEADER +//--------------------------------------------------------------------------- + +#endif //FORMAT_ROM_H_ diff --git a/build/tools/makenandfirm/format_sign.h b/build/tools/makenandfirm/format_sign.h new file mode 100644 index 0000000..6d3d277 --- /dev/null +++ b/build/tools/makenandfirm/format_sign.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - SS + File: format_sign.h + + Copyright 2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_MAKENANDFIRM_ACSIGN_FORMAT_H_ +#define FIRM_MAKENANDFIRM_ACSIGN_FORMAT_H_ + +#include "format_rom.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_MAKENANDFIRM_ACSIGN_FORMAT_H_ */ +#endif diff --git a/build/tools/makenandfirm/makenandfirm.c b/build/tools/makenandfirm/makenandfirm.c new file mode 100644 index 0000000..abdb1c5 --- /dev/null +++ b/build/tools/makenandfirm/makenandfirm.c @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenandfirm + File: makenandfirm.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include +#include // strcasecmp() +#include // getopt() +#include "makenandfirm.h" +#include "format_rom.h" +#include "path.h" +#include "defval.h" +#include "version.h" + +static int makenandfirm(const char *specFile, const char *nandFile); + +//--------------------------------------------------------------------------- +// Main +//--------------------------------------------------------------------------- + +int main(int argc, char *argv[]) +{ + int n; + int narg; + char *nandfirmFile; + + InitAppName(argv[0]); + + while ((n = getopt(argc, argv, "D:hvpd")) != -1) + { + switch (n) + { + case 'h': + case 'v': + goto usage; + + case 'D': + AddDefVal(optarg); + break; + + case 'p': + PrintMode = TRUE; + break; + + case 'd': + DebugMode = TRUE; + break; + + default: + break; + } + } + + narg = argc - optind; + if (narg > 0) + { + // Make SpecFile->NandfirmFile + nandfirmFile = + strdup(narg > + 1 ? argv[optind + 1] : ChangeSuffix(argv[optind], DEFAULT_NANDFIRM_SUFFIX)); + return makenandfirm(argv[optind], nandfirmFile); + } + + usage: + { + char *makenandfirm = GetAppName(); + + fprintf(stderr, + "NITRO-SDK Development Tool - %s - Make nandfirm file \n" + "Build %lu\n\n" + "Usage: %s [-phv] [-DNAME=VALUE ...] SPECFILE [NANDFIRMFILE]\n\n", + makenandfirm, SDK_DATE_OF_LATEST_FILE, makenandfirm); + } + return 1; +} + + +//--------------------------------------------------------------------------- +// makenandfirm +//--------------------------------------------------------------------------- + +static int makenandfirm(const char *specFile, const char *nandFile) +{ + debug_printf("makenandfirm(): '%s' -> '%s'\n", specFile, nandFile); + + // Check identical + if (specFile && nandFile && !strcasecmp(specFile, nandFile)) + { + error("nandfirm spec file is identical '%s'", nandFile); + return 1; + } + + return OutputNandfirmFile(specFile, nandFile) ? 0 : 1; +} diff --git a/build/tools/makenandfirm/makenandfirm.h b/build/tools/makenandfirm/makenandfirm.h new file mode 100644 index 0000000..21ac7e0 --- /dev/null +++ b/build/tools/makenandfirm/makenandfirm.h @@ -0,0 +1,24 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenandfirm + File: makenandfirm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef MAKENANDFIRM_H_ +#define MAKENANDFIRM_H_ + +#include "misc.h" + +BOOL OutputNandfirmFile(const char *specFile, const char *nandFile); + +#endif //MAKENANDFIRM_H_ diff --git a/build/tools/makenandfirm/misc.c b/build/tools/makenandfirm/misc.c new file mode 100644 index 0000000..7326f41 --- /dev/null +++ b/build/tools/makenandfirm/misc.c @@ -0,0 +1,628 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenandfirm + File: misc.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include // calloc() +#include // free(), exit() +#include // setmode() +#include // stat() +#include // setmode() +#include // strlen() +#include // va_start(),va_end() +#include // localtime() + +#include +#include "misc.h" + +BOOL DebugMode = FALSE; +BOOL PrintMode = FALSE; +char *PubkeyFileName = NULL; + +/*---------------------------------------------------------------------------* + * File Output Utilities + * + * BOOL OpenFile( const char* filename ) + * void CloseFile( void ) + * BOOL CheckResult( void ) + * void PutBuffer( const void* ptr, int len ) + * void PutByte( u8 c ) + * void PutWord( u16 c ) + * void PutWord( u32 c ) + * void PutString( const char *str ) + *---------------------------------------------------------------------------*/ + +static FILE *OutFile = NULL; +static const char *FileName = NULL; +static BOOL Status = FALSE; + + +// +// File Open +// + +BOOL OpenFile(const char *filename) +{ + if (OutFile) + CloseFile(); + + if (filename) + { + if (NULL == (OutFile = fopen(filename, "wb+"))) + { + error("Can't write '%s'", filename); + Status = FALSE; + return FALSE; + } + } + else + { + setmode(1, O_BINARY); + OutFile = stdout; // out to console if filename == NULL + } + FileName = filename; + Status = TRUE; + + return TRUE; +} + + +// +// File Close +// + +BOOL CloseFile(void) +{ + if (OutFile) + { + if (FileName) + { + if (fclose(OutFile) == -1) + { + error("Can't close '%s'", FileName); + Status = FALSE; + } + } + else + { + setmode(1, O_TEXT); + } + } + OutFile = NULL; + + return Status; +} + + +// +// File Seek +// + +void SeekFile(long pos) +{ + if (OutFile && fseek(OutFile, pos, SEEK_SET)) + { + error("Can't seek '%s'", FileName ? FileName : ""); + CloseFile(); + Status = FALSE; + } +} + + +// +// Error Check +// + +BOOL CheckResult(void) +{ + return Status; +} + + +// +// Delete outfile +// + +void DeleteOutFile(void) +{ + // Delete outfile + if (FileName) + { + debug_printf("Delete '%s'\n", FileName); + (void)unlink(FileName); + FileName = NULL; + } + return; +} + + +// +// Buffer Output +// + +void PutBuffer(const void *ptr, int len) /* If error, close file */ +{ + if (OutFile && len != fwrite(ptr, 1, len, OutFile)) + { + error("Can't write buffer to '%s'", FileName ? FileName : ""); + CloseFile(); + Status = FALSE; + } +} + +// +// Buffer Input +// + +void GetBuffer(void *ptr, int len) /* If error, close file */ +{ + if (OutFile && len != fread(ptr, 1, len, OutFile)) + { + error("Can't read '%s'", FileName ? FileName : ""); + CloseFile(); + Status = FALSE; + } +} + +// +// Byte/Half/Word Output +// + +void PutByte(u8 c) +{ + PutBuffer(&c, 1); +} +void PutHalf(u16 c) +{ + PutBuffer(&c, 2); +} +void PutWord(u32 c) +{ + PutBuffer(&c, 4); +} +void PutString(const char *str) +{ + PutBuffer(str, strlen(str)); +} + + +// +// Printf +// + +void PrintString(const char *fmt, ...) +{ + char *buffer; + va_list va; + int nchars; + int bufsize = FILENAME_MAX; + + while (1) + { + buffer = Alloc(bufsize); + va_start(va, fmt); + nchars = vsnprintf(buffer, bufsize, fmt, va); + va_end(va); + + if (0 <= nchars && nchars < bufsize) + { + break; + } + + Free(&buffer); + bufsize *= 2; + } + + if (nchars > 0) + { + PutBuffer(buffer, nchars); + } + Free(&buffer); +} + + +/*---------------------------------------------------------------------------* + * File Read/Write Utilities + * + * int ReadFile( const char* filename, void** buffer ) + * + * Read a file to buffer allocated internally + * Return read size + * Add '\0' at tail of file for help to handle text file + * + * BOOL WriteFile( const char* filename, void** buffer, int size ) + *---------------------------------------------------------------------------*/ + +int ReadFile(const char *filename, void *filebuffer, int size) +{ + FILE *fp; + struct stat fileStat; + int fileSize, readSize; + void **buffer = (void **)filebuffer; + + /* Check file */ + if (stat(filename, &fileStat) || !S_ISREG(fileStat.st_mode)) + { + goto error; + } + fileSize = fileStat.st_size; + if (fileSize < 0) + { + goto error; + } + + /* Open file */ + fp = fopen(filename, "rb"); + if (!fp) + { + goto error; + } + + if (size && (size < fileSize)) + { + readSize = size; + } + else + { + readSize = fileSize; + } + + /* Read file */ + *buffer = Alloc(readSize + 1); /* error handle is done in Alloc() */ + /* size+1 for '\0' to handle text file */ + if (readSize != fread(*buffer, sizeof(char), readSize, fp)) + { + goto error_free_close; + } + + (*(char **)buffer)[readSize] = '\0'; /* Works as terminater if file is text file */ + + /* Close file */ + fclose(fp); + return readSize; + + error_free_close: + Free(buffer); + fclose(fp); + error: + error("Can't read '%s'", filename); + return -1; +} + + +int ReadFileWithPadding(const char *filename, void *filebuffer, int size, int boundary) +{ + FILE *fp; + struct stat fileStat; + int fileSize, readSize, padSize; + void **buffer = (void **)filebuffer; + + if (!boundary) + { + return ReadFile(filename, buffer, size); + } + + /* Check file */ + if (stat(filename, &fileStat) || !S_ISREG(fileStat.st_mode)) + { + goto error; + } + fileSize = fileStat.st_size; + if (fileSize < 0) + { + goto error; + } + + /* Open file */ + fp = fopen(filename, "rb"); + if (!fp) + { + goto error; + } + + if (size && (size < fileSize)) + { + readSize = size; + } + else + { + readSize = fileSize; + } + + padSize = (boundary - (readSize & (boundary-1))) & (boundary-1); + + /* Read file */ + *buffer = Alloc(readSize + padSize); /* error handle is done in Alloc() */ + /* size+1 for '\0' to handle text file */ + if (readSize != fread(*buffer, sizeof(char), readSize, fp)) + { + goto error_free_close; + } + + memset((char*)*buffer + readSize, 0, padSize); + + /* Close file */ + fclose(fp); + return readSize + padSize; + + error_free_close: + Free(buffer); + fclose(fp); + error: + error("Can't read '%s'", filename); + return -1; +} + + +BOOL WriteFile(const char *filename, void *buffer, int size) +{ + debug_printf("WriteFile %s\n", filename); + + (void)OpenFile(filename); + PutBuffer(buffer, size); + CloseFile(); + Free(&buffer); + return CheckResult(); +} + + +/*---------------------------------------------------------------------------* + * Time Format Utilities + * + * char* GetGMTime( const time_t time ) Show GMT + * char* GetTime( const time_t time ) Show local Time + *---------------------------------------------------------------------------*/ + +char *GetGMTime(const time_t time) +{ + static char timebuffer[32]; + strftime(timebuffer, sizeof(timebuffer), "%y/%m/%d-%H:%M:%S", gmtime(&time)); + return timebuffer; +} + + +char *GetTime(const time_t time) +{ + static char timebuffer[32]; + strftime(timebuffer, sizeof(timebuffer), "%y/%m/%d-%H:%M:%S", localtime(&time)); + return timebuffer; +} + + +/*---------------------------------------------------------------------------* + * Memory Allocation Utilities + * + * void* Alloc( size_t size ) + *---------------------------------------------------------------------------*/ + +void *Alloc(size_t size) +{ + void *t = calloc(1, size); + + if (t == NULL) + { + error("Can't allocate memory."); + exit(10); + } + return t; +} + + +void Free(void *p) +{ + void **ptr = (void **)p; + + if (*ptr) + { + free(*ptr); + (*ptr) = NULL; + } +} + + +/*---------------------------------------------------------------------------* + * VBuffer + * + * void PutVBuffer( VBuffer* vbuf, char c ) + *---------------------------------------------------------------------------*/ + +void PutVBuffer(VBuffer * vbuf, char c) +{ + int size; + char *tmp_buffer; + + if (vbuf->buffer == 0) + { + vbuf->size = VBUFFER_INITIAL_SIZE; + vbuf->buffer = Alloc(vbuf->size); // buffer is CALLOCed + } + size = strlen(vbuf->buffer); + + if (size >= vbuf->size - 1) + { + // Need buffer expansion + vbuf->size *= 2; + tmp_buffer = Alloc(vbuf->size); // buffer is CALLOCed + strcpy(tmp_buffer, vbuf->buffer); + Free(&vbuf->buffer); + vbuf->buffer = tmp_buffer; + } + vbuf->buffer[size] = c; + return; +} + +char *GetVBuffer(VBuffer * vbuf) +{ + return vbuf->buffer; +} + +void InitVBuffer(VBuffer * vbuf) +{ + vbuf->buffer = 0; + vbuf->size = 0; +} + +void FreeVBuffer(VBuffer * vbuf) +{ + Free(&vbuf->buffer); +} + + +/*---------------------------------------------------------------------------* + * File Path Utilities + * + * char* ChangeBackSlash( char* path ) + *---------------------------------------------------------------------------*/ + +char *ChangeBackSlash(char *path) +{ + char *p = path; + + while (*p) + { + if (*p == '\\') + { + *p = '/'; + } + p++; + } + return path; +} + + +/*---------------------------------------------------------------------------* + * Math + * + * u16 CalcCRC16( u16 start, u8 *data, int size ) + *---------------------------------------------------------------------------*/ + +static u16 crc16_table[16] = { + 0x0000, 0xCC01, 0xD801, 0x1400, + 0xF001, 0x3C00, 0x2800, 0xE401, + 0xA001, 0x6C00, 0x7800, 0xB401, + 0x5000, 0x9C01, 0x8801, 0x4400 +}; + +u16 CalcCRC16(u16 start, u8 *data, int size) +{ + u16 r1; + u16 total = start; + + while (size-- > 0) + { + // 4bit + r1 = crc16_table[total & 0xf]; + total = (total >> 4) & 0x0fff; + total = total ^ r1 ^ crc16_table[*data & 0xf]; + + // 4bit + r1 = crc16_table[total & 0xf]; + total = (total >> 4) & 0x0fff; + total = total ^ r1 ^ crc16_table[(*data >> 4) & 0xf]; + + data++; + } + return total; +} + + +/*---------------------------------------------------------------------------* + * for firm header + * + *---------------------------------------------------------------------------*/ + +static u8 ConvertAlign( u32 ofs ) +{ + u8 i; + + ofs /= 4; + for (i=0; i<7; i++) + { + if ( ofs & 1 ) + { + break; + } + ofs >>= 1; + } + + return i; +} + +tROMAddrConvType ConvertHeaderRamAddr( s32 p ) +{ + tROMAddrConvType retval; + + retval.align = ConvertAlign( p ); + retval.address = (u16)((p - HW_WRAM)/(4< + +typedef enum +{ + FALSE = 0, + TRUE = 1 +} +BOOL; + +typedef unsigned char u8; +typedef unsigned short int u16; +typedef unsigned long int u32; +typedef unsigned long long u64; +typedef signed char s8; +typedef signed short int s16; +typedef signed long int s32; +typedef signed long long s64; +typedef volatile u8 vu8; +typedef volatile u32 vu32; +typedef vu32 REGType32v; + +#define error(...) do { fprintf(stderr, "Error: "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); } while(0) + +#define warning(...) do { fprintf(stderr, "Warning: "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); } while(0) + +BOOL OpenFile(const char *filename); +BOOL CloseFile(void); +void SeekFile(long pos); +BOOL CheckResult(void); +void DeleteOutFile(void); +void PutBuffer(const void *ptr, int len); +void GetBuffer(void *ptr, int len); +void PutByte(u8 c); +void PutHalf(u16 c); +void PutWord(u32 c); +void PutString(const char *str); +void PrintString(const char *fmt, ...); + +#define READ_ALL 0 +int ReadFile(const char *filename, void *filebuffer, int size); +int ReadFileWithPadding(const char *filename, void *filebuffer, int size, int boundary); +BOOL WriteFile(const char *filename, void *buffer, int size); + +char *GetGMTime(const time_t time); +char *GetTime(const time_t time); + +void *Alloc(size_t size); +void Free(void *p); + +typedef struct +{ + char *buffer; + int size; +} +VBuffer; + +#define VBUFFER_INITIAL_SIZE 1024 +void InitVBuffer(VBuffer * vbuf); +void FreeVBuffer(VBuffer * vbuf); +void PutVBuffer(VBuffer * vbuf, char c); +char *GetVBuffer(VBuffer * vbuf); + +char *ChangeBackSlash(char *path); + +u16 CalcCRC16(u16 start, u8 *data, int size); +const char *WrapNull(const char *str); + +typedef struct +{ + u16 address; + u8 align; +} +tROMAddrConvType; + +tROMAddrConvType ConvertHeaderRamAddr( s32 p ); +tROMAddrConvType ConvertHeaderRomOffset( s32 p ); +u16 ConvertHeaderRomOffsetAlign( s32 p, u32 align ); + +typedef union +{ + struct + { + u32 sign:1; + u32 header_hash:1; + u32 arm9_hash:1; + u32 arm7_hash:1; + u32 hash_table_hash:1; + u32 final_hash:1; + u32 header_footer:1; + } + e; + u32 raw; +} +tErrorFlags; + +extern BOOL DebugMode; +extern BOOL PrintMode; +extern char *PubkeyFileName; +void debug_printf(const char *str, ...); +void debug_printf2(const char *str, ...); + +#endif //MISC_H_ diff --git a/build/tools/makenandfirm/out_nandfirm.c b/build/tools/makenandfirm/out_nandfirm.c new file mode 100644 index 0000000..ad1e69a --- /dev/null +++ b/build/tools/makenandfirm/out_nandfirm.c @@ -0,0 +1,979 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenandfirm + File: out_nandfirm.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include // atoi() +#include // strcmp() +#include // isprint() +#include // chdir() +#include +#include // UCHAR_MAX +#include +#include // stat() +#include "elf.h" +#include "misc.h" +#include "defval.h" +#include "format_rom.h" +#include "format_nlist.h" +#include "makenandfirm.h" +#include "format_sign.h" +#include "acsign_nand.h" +#include "compress.h" + +#define SDK_ASM + +#include +#include "../acsign/aes2.h" + +#define SBIN9CMD "ARM9_SBIN" +#define SBIN7CMD "ARM7_SBIN" +#define ELF9CMD "ARM9_ELF" +#define ELF7CMD "ARM7_ELF" +#define COMP9CMD "ARM9_COMP" +#define COMP7CMD "ARM7_COMP" +#define DECOMPCMD "DECOMP_PROC" +#define ARM9X2CMD "ARM9_X2" +#define VERCMD "VERSION" +#define RSAKEYCMD "RSA_KEY" +#define OUTKEYCMD "OUT_KEY" +#define WREGCMD "WRAM_RBIN" +#define ENDKEYCMD "ENC_KEYINFO" +#define NCDCMD "NCD_ROMOFS" +#define MIRRORCMD "MIRROR_OFS" +#define ERRCMD "ERROR" + +static BOOL ConstructNandfirmFile(char * specFile); +static BOOL ReadSbinFile(const char *fileName, void* minfo, void* minfo2, void* hash, BOOL comp); +static BOOL ReadKeyFile(const char *fileName); +static BOOL ReadWramRegFile(const char *fileName); +static s32 GetRamAddr(const char *fileName); + +static BOOL EncryptBuffer(char *buffer, int length); + +static BOOL Sbin9_Command(char * line, int num); +static BOOL Sbin7_Command(char * line, int num); +static BOOL Elf9_Command(char * line, int num); +static BOOL Elf7_Command(char * line, int num); +static BOOL Comp9_Command(char * line, int num); +static BOOL Comp7_Command(char * line, int num); +static BOOL Decomp_Command(char * line, int num); +static BOOL ARM9X2_Command(char * line, int num); +static BOOL VERSION_Command(char * line, int num); +static BOOL RSAKEY_Command(char * line, int num); +static BOOL OUTKEY_Command(char * line, int num); +static BOOL WramRegs_Command(char * line, int num); +static BOOL ENCKEY_Command(char * line, int num); +static BOOL NcdOffset_Command(char * line, int num); +static BOOL MirrorOffset_Command(char * line, int num); +static BOOL ERROR_Command(char * line, int num); + +static BOOL InitializeAesKey(void); +static BOOL InitializeNandfirmFile(void); +static BOOL FinalizeNandfirmFile(const char *nandFile); + +static s32 Offset; // Current offset +static int LineNum; // Line number for error message +static const char *specFileName; // specFile name for error message + +NANDHeaderEx nandHeader; // Nandfirm Header Shadow +FIRMSignedContext signedContext; +u8 *keyFileBuf; +BOOL compArm9 = TRUE; +BOOL compArm7 = TRUE; +u32 mirrorOfs = 0; +tErrorFlags errFlags; + +//--------------------------------------------------------------------------- +// Output - nandfirm File +//--------------------------------------------------------------------------- + +BOOL OutputNandfirmFile(const char *specFile, const char *nandFile) +{ + char *buffer; + BOOL state; + + if (ReadFile(specFile, &buffer, READ_ALL) <= 0) + { + return FALSE; + } + + if (!OpenFile(nandFile)) + { + return FALSE; + } + + specFileName = specFile; + + state = InitializeNandfirmFile() && ConstructNandfirmFile(buffer) && + FinalizeNandfirmFile(nandFile) && CloseFile(); + + if (!state) + { + DeleteOutFile(); + } + + return state; +} + + +//--------------------------------------------------------------------------- +// Output - Nandfirm File +//--------------------------------------------------------------------------- + +static const tCommandDesc command[] = { + {SBIN9CMD, Sbin9_Command}, {SBIN7CMD, Sbin7_Command}, + {ELF9CMD, Elf9_Command},{ELF7CMD, Elf7_Command}, + {COMP9CMD, Comp9_Command},{COMP7CMD, Comp7_Command}, + {DECOMPCMD, Decomp_Command}, + {VERCMD, VERSION_Command}, + {ARM9X2CMD, ARM9X2_Command}, + {RSAKEYCMD, RSAKEY_Command}, + {OUTKEYCMD, OUTKEY_Command}, + {WREGCMD, WramRegs_Command}, + {ENDKEYCMD, ENCKEY_Command}, + {NCDCMD, NcdOffset_Command}, + {MIRRORCMD, MirrorOffset_Command}, + {ERRCMD, ERROR_Command}, +}; + +BOOL ConstructNandfirmFile(char * specFile) +{ + char *line; + char *line_top; + char *p; + int i; + + LineNum = 0; + Offset = 0x00000000; + + line = specFile++; + + while (*line != '\0') + { + LineNum++; + + // Get command line + line_top = line; + while (*line != '\0') + { + if (*line++ == '\n') + { + break; + } + } + + // Print for debug + debug_printf("NANDSF Line%4d [", LineNum, line); + for (p = line_top; p != line; p++) + { + if (isprint(*p)) + { + debug_printf("%c", *p); + } + } + debug_printf("]\n"); + + if (*line_top == '#') + { + } + else + { + for (i = 0; i < (sizeof(command) / sizeof(command[0])); i++) + { + if (!strncmp(line_top, command[i].string, strlen(command[i].string))) + { + if (command[i].funcp != NULL) + { + char line_cmd[FILENAME_MAX]; + char line_scan[FILENAME_MAX]; + char* line_conv; + int num; + + num = sscanf( line_top, + "%1024[^ :] : %1024[^ \x0d:#\n]", + line_cmd, line_scan + ); + line_conv = ResolveDefVal(line_scan); + + debug_printf("line_cmd = %s, line_conv = %s\n", line_cmd, line_conv); + + if (!command[i].funcp(line_conv, num - 1)) + return FALSE; + } + } + } + } + + } + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - 'WramRegs' Command +//--------------------------------------------------------------------------- + +extern MIHeader_WramRegs wram_regs_init; +MIHeader_WramRegs* wram_regs; + +static BOOL WramRegs_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("wram regs file = %s\n", line); + + return ReadWramRegFile(line); +} + +static BOOL ReadWramRegFile(const char *fileName) +{ + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &wram_regs, READ_ALL)) < 0) + return FALSE; + + nandHeader.o.h.w = *wram_regs; + nandHeader.m.h.w = *wram_regs; + + return CheckResult(); +} + +//--------------------------------------------------------------------------- +// Output - 'RSAKEY' Command +//--------------------------------------------------------------------------- + +static BOOL RSAKEY_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("rsa key = %s\n", line); + + return ReadKeyFile(line); +} + +static BOOL ReadKeyFile(const char *fileName) +{ + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &keyFileBuf, READ_ALL)) < 0) + return FALSE; + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'OUTKEY' Command +//--------------------------------------------------------------------------- + +static BOOL OUTKEY_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("out key = %s\n", line); + + PubkeyFileName = line; + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'VERSION' Command +//--------------------------------------------------------------------------- + +static u8 ConvToBCD8(int x) +{ + u8 bcd = 0; + + x %= 100; + bcd |= (x / 10)<<4; + bcd |= (x % 10); + + return bcd; +} + +static BOOL VERSION_Command(char * line, int num) +{ + char scan[FILENAME_MAX]; + u64 version = -1; + + // rescan + num = sscanf( line, + "0x%1024[^\x0d\n]", + scan + ); + + if (num == 1) + { + // convert version info + version = strtoull(scan, NULL, 16); + } + else if (num == 0) + { + // generate version info + u8* ver8 = (u8*)&version; + time_t timer; + struct tm *t_st; + + time(&timer); + t_st = localtime(&timer); + + ver8[0] = ConvToBCD8(t_st->tm_min); + ver8[1] = ConvToBCD8(t_st->tm_hour); + ver8[2] = ConvToBCD8(t_st->tm_mday); + ver8[3] = ConvToBCD8(t_st->tm_mon+1); + ver8[4] = ConvToBCD8(t_st->tm_year); + ver8[5] = 0xff; + ver8[6] = 0xff; + ver8[7] = 0xff; + } + + debug_printf2("version = %08llx\n", version); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Decomp' Command +//--------------------------------------------------------------------------- + +static BOOL Decomp_Command(char * line, int num) +{ + char* dbg_str = "ARM7"; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + if (!strcmp(line, "ARM9")) + { + nandHeader.o.l.arm9_decomp = TRUE; + nandHeader.m.l.arm9_decomp = TRUE; + dbg_str = "ARM9"; + } + + debug_printf2("decompress processor = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'ARM9_X2' Command +//--------------------------------------------------------------------------- + +static BOOL ARM9X2_Command(char * line, int num) +{ + char* dbg_str = "FALSE"; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + if (!strcmp(line, "TRUE")) + { + nandHeader.o.l.arm9_x2 = TRUE; + nandHeader.m.l.arm9_x2 = TRUE; + dbg_str = "TRUE"; + } + + debug_printf2("arm9 x2 = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Comp9' Command +//--------------------------------------------------------------------------- + +static BOOL Comp9_Command(char * line, int num) +{ + char* dbg_str = "FALSE"; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + compArm9 = FALSE; + + if (!strcmp(line, "TRUE")) + { + nandHeader.o.l.comp_arm9_boot_area = TRUE; + nandHeader.m.l.comp_arm9_boot_area = TRUE; + compArm9 = TRUE; + dbg_str = "TRUE"; + } + + debug_printf2("arm9 compress = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Comp7' Command +//--------------------------------------------------------------------------- + +static BOOL Comp7_Command(char * line, int num) +{ + char* dbg_str = "FALSE"; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + compArm7 = FALSE; + + if (!strcmp(line, "TRUE")) + { + nandHeader.o.l.comp_arm7_boot_area = TRUE; + nandHeader.m.l.comp_arm7_boot_area = TRUE; + compArm7 = TRUE; + dbg_str = "TRUE"; + } + + debug_printf2("arm7 compress = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Elf9' Command +//--------------------------------------------------------------------------- + +static BOOL Elf9_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm9 elf = %s\n", line); + + { + s32 ramAddr = GetRamAddr(line); + nandHeader.o.l.main_ram_address = (void*)ramAddr; + nandHeader.m.l.main_ram_address = (void*)ramAddr; + } + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Elf7' Command +//--------------------------------------------------------------------------- + +static BOOL Elf7_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm7 elf = %s\n", line); + + { + s32 ramAddr = GetRamAddr(line); + nandHeader.o.l.sub_ram_address = (void*)ramAddr; + nandHeader.m.l.sub_ram_address = (void*)ramAddr; + } + + return CheckResult(); +} + + +static s32 GetRamAddr(const char *fileName) +{ + Elf32_Ehdr *ehdr; + s32 ramAddr; + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &ehdr, sizeof(Elf32_Ehdr))) < 0) + return FALSE; + + ramAddr = ehdr->e_entry; + + Free(&ehdr); + + debug_printf2("ramaddr = 0x%08x\n", ramAddr); + + return ramAddr; +} + + +//--------------------------------------------------------------------------- +// Output - 'Sbin9' Command +//--------------------------------------------------------------------------- + +static BOOL Sbin9_Command(char * line, int num) +{ + FIRMSignedContext* sc = &signedContext; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm9 sbin = %s\n", line); + + // Set ARM9 ROM Offset + if (!Offset) + { + Offset = (sizeof(NANDHeader) + FIRM_ALIGN_MASK) & ~FIRM_ALIGN_MASK; + if (mirrorOfs) + { + Offset += sizeof(NANDHeaderCore) * 2; + } + SeekFile(Offset); + } + debug_printf2("romoffset = %#x\n", Offset); + { + nandHeader.o.l.main_rom_offset = Offset; + nandHeader.m.l.main_rom_offset = Offset + mirrorOfs - sizeof(NANDHeaderCore) * 2; + } + + return ReadSbinFile(line, &nandHeader.o.l.main_rom_offset, &nandHeader.m.l.main_rom_offset, &sc->hash[FIRM_SIGNED_HASH_IDX_ARM9], compArm9); +} + +//--------------------------------------------------------------------------- +// Output - 'Sbin7' Command +//--------------------------------------------------------------------------- + +static BOOL Sbin7_Command(char * line, int num) +{ + FIRMSignedContext* sc = &signedContext; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm7 sbin = %s\n", line); + + // Set ARM7 ROM Offset + if (!Offset) + { + Offset = (sizeof(NANDHeader) + FIRM_ALIGN_MASK) & ~FIRM_ALIGN_MASK; + if (mirrorOfs) + { + Offset += sizeof(NANDHeaderCore) * 2; + } + SeekFile(Offset); + } + debug_printf2("romoffset = %#x\n", Offset); + { + nandHeader.o.l.sub_rom_offset = Offset; + nandHeader.m.l.sub_rom_offset = Offset + mirrorOfs - sizeof(NANDHeaderCore) * 2; + } + + return ReadSbinFile(line, &nandHeader.o.l.sub_rom_offset, &nandHeader.m.l.sub_rom_offset, &sc->hash[FIRM_SIGNED_HASH_IDX_ARM7], compArm7); +} + + +static BOOL ReadSbinFile(const char *fileName, void* minfo, void* minfo2, void* hash, BOOL comp) +{ + const NANDHeader_ModuleInfo *m = minfo; + u32 *size = (void*)&m->size; + u32 *orig_size = (void*)&m->decomp_size; + const NANDHeader_ModuleInfo *m2 = minfo2; + u32 *size2 = (void*)&m2->size; + u32 *orig_size2 = (void*)&m2->decomp_size; + char *buffer; + char *file; + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &file, READ_ALL)) < 0) + return FALSE; + + *orig_size = *orig_size2 = file_size; + + // Digest file image + if (hash) + { + ACSign_DigestUnit(hash, file, file_size); + } + + // Compress file image with fitting region + buffer = Alloc(file_size * 2); + if ( comp ) + { + file_size = LZCompWrite(file, file_size, buffer, FIRM_ALIGN); + } + else + { + memcpy(&buffer[0], file, file_size); + { + u32 pad_size = (FIRM_ALIGN - (file_size % FIRM_ALIGN)) % FIRM_ALIGN; + if (pad_size) + memset(&buffer[file_size], 0, pad_size); + file_size += pad_size; + } + } + Free(&file); + file = buffer; + + if (size) + { + *size = *size2 = file_size; + } + Offset += file_size; + + // Encrypt file image + EncryptBuffer(file, file_size); + + // Output file image with fitting region + PutBuffer(file, file_size); + + Free(&file); + + if (mirrorOfs && mirrorOfs < Offset + sizeof(NANDHeaderCore) * 2) + { + error("mirrorOfs is too small (%ld < %ld).\n", mirrorOfs, Offset + sizeof(NANDHeaderCore) * 2); + return FALSE; + } + + return CheckResult(); +} + +typedef struct +{ + unsigned long e[4]; +} u128; + +static BOOL EncryptBuffer(char *buffer, int length) +{ + const u128 id = {{ AES_IDS_ID2_A, AES_IDS_ID2_B, AES_IDS_ID2_C, AES_IDS_ID2_D }}; + u128 iv = {{ length, -length, ~length, 0 }}; + FIRMSignedContext* sc = &signedContext; + char *buffer2 = Alloc(length); + AES_KEY key; + if (!buffer2) + return FALSE; + AES_SetKey(&key, sc->aes_key, (unsigned char*)&id); + AES_Ctr(&key, buffer2, buffer, length, (unsigned char*)&iv); + memcpy(buffer, buffer2, length); + memset(buffer2, 0, length); + Free(buffer2); + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - 'ENC_KEYINFO' Command +//--------------------------------------------------------------------------- + +static BOOL ENCKEY_Command(char * line, int num) +{ + u32 key; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + key = strtoul(line, NULL, 0); + nandHeader.g.d.ds_key = key; + + debug_printf2("keyinfo = %#x\n", key); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'NcdOffset' Command +//--------------------------------------------------------------------------- + +static BOOL NcdOffset_Command(char * line, int num) +{ + u32 ofs; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + ofs = strtoul(line, NULL, 0); + { + nandHeader.g.d.ncd_romAdr = ConvertHeaderRomOffsetAlign(ofs, 8); + } + + debug_printf2("ncd romoffset = %#x\n", ofs); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'MirrorOffset' Command +//--------------------------------------------------------------------------- + +static BOOL MirrorOffset_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + mirrorOfs = strtoul(line, NULL, 0); + + debug_printf2("mirrored image offset = %#x\n", mirrorOfs); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'ERROR' Command +//--------------------------------------------------------------------------- +static char* error_type[] = +{ + "SIGN", + "HEADER_HASH", + "ARM9_HASH", + "ARM7_HASH", + "HASH_TABLE_HASH", + "FINAL_HASH", + "HEADER_FOOTER", +}; + +static BOOL ERROR_Command(char * line, int num) +{ + char* dbg_str = "UNKNOWN"; + int i; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + for (i=0; ihash[FIRM_SIGNED_HASH_IDX_HEADER][0] ^= 1; + } + if ( errFlags.e.arm9_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_ARM9][0] ^= 1; + } + if ( errFlags.e.arm7_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_ARM7][0] ^= 1; + } + if ( errFlags.e.hash_table_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_HASH_TABLE][0] ^= 1; + } +} + +static void SetFinalHashError(FIRMSignedContext* sc) +{ + if ( errFlags.e.final_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_FINAL][0] ^= 1; + } +} + +static void SetSignError(NANDHeader* nh) +{ + if ( errFlags.e.sign ) + { + nh->sign.raw[0] ^= 1; + } + +} + +static void SetFooterError(NANDHeader* nh) +{ + if ( errFlags.e.header_footer ) + { + nh->h.reserved_footer[sizeof(nh->h.reserved_footer)-1] ^= 1; + } + +} + +//--------------------------------------------------------------------------- +// Output - Initialize AES Key +//--------------------------------------------------------------------------- +static BOOL InitializeAesKey(void) +{ + FIRMSignedContext* sc = &signedContext; + struct stat specstat; + time_t spectime; + if (stat(specFileName, &specstat) != 0) + return FALSE; + time(&spectime); + memcpy(&sc->aes_key[0], &specstat.st_atime, 4); + memcpy(&sc->aes_key[4], &specstat.st_mtime, 4); + memcpy(&sc->aes_key[8], &specstat.st_ctime, 4); + memcpy(&sc->aes_key[12], &spectime, 4); + ACSign_GetKey(sc->aes_key, sizeof(sc->aes_key), sc->aes_key, sizeof(sc->aes_key)); + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - Initialize Nandfirm File +//--------------------------------------------------------------------------- + +static BOOL InitializeNandfirmFile(void) +{ + memset(&signedContext.hash[FIRM_SIGNED_HASH_IDX_HASH_TABLE], 0xff, sizeof(signedContext.hash[0])); + nandHeader.o.h.w = wram_regs_init; + nandHeader.m.h.w = wram_regs_init; + InitializeAesKey(); + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - Finalize Nandfirm File +//--------------------------------------------------------------------------- + +static void FinalizeNandfirmFileCore(NANDHeaderCore* master) +{ + NANDHeader *nh = &nandHeader.g; + FIRMSignedContext* sc = &signedContext; + u8* key = keyFileBuf; + + memcpy(&nh->l, &master->l, sizeof(NANDHeaderLow)); + memcpy(&nh->h, &master->h, sizeof(NANDHeaderHigh)); + + ACSign_DigestHeader(&sc->hash[FIRM_SIGNED_HASH_IDX_HEADER], nh); + + SetUnitHashErrors(sc); + + ACSign_DigestUnit(&sc->hash[FIRM_SIGNED_HASH_IDX_FINAL], sc, FIRM_HEADER_2ND_HASH_AREA_LEN); + + SetFinalHashError(sc); + + if (key) + { + ACSign_Final(nh, sc, key); + } + + SetFooterError(nh); + + SetSignError(nh); + + memcpy(&master->sign, &nh->sign, sizeof(FIRMPaddedSign)); +} + +static BOOL FinalizeNandfirmFile(const char *nandFile) +{ + // for m header (copy to g) + FinalizeNandfirmFileCore(&nandHeader.m); + + // for o header (copy to g) + FinalizeNandfirmFileCore(&nandHeader.o); + + // Output file image + SeekFile(0L); + if (mirrorOfs) + { + PutBuffer(&nandHeader, sizeof(nandHeader)); + } + else + { + PutBuffer(&nandHeader.g, sizeof(nandHeader.g)); + } + + // Output public key (modulus) + if (PubkeyFileName) + { + WriteFile(PubkeyFileName, &keyFileBuf[ACS_RSA_PRVMOD_OFFSET], ACS_RSA_PRVMOD_LEN); + } + + return TRUE; +} diff --git a/build/tools/makenandfirm/path.c b/build/tools/makenandfirm/path.c new file mode 100644 index 0000000..eeeb989 --- /dev/null +++ b/build/tools/makenandfirm/path.c @@ -0,0 +1,931 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makebanner + File: path.c + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: path.c,v $ + Revision 1.3 2006/01/18 02:11:20 kitase_hirotake + do-indent + + Revision 1.2 2005/02/28 05:26:13 yosizaki + do-indent. + + Revision 1.1 2004/08/30 08:41:14 yasu + makebanner moves into CVS tree + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +#include // free() +#include // strcasecmp() +#include // stat() +#include // opendir()/readdir()/closedir() +#include // getcwd() +#ifdef __CYGWIN__ +#include // cygwin_conv_to_win32_path() +#endif +#include "path.h" + +//--------------------------------------------------------------------------- +// Get File Statue +//--------------------------------------------------------------------------- + +tFileStatus GetFileStatus(struct stat *s, const char *filename) +{ + // Get file status + if (stat(filename, s)) + { + error("Can't get status %s", filename); + return FILESTATUS_ERROR; + } + + if (S_ISREG(s->st_mode)) + { + return FILESTATUS_FILE; + } + else if (S_ISDIR(s->st_mode)) + { + return FILESTATUS_DIR; + } + + error("Unknown file type %s", filename); + return FILESTATUS_ERROR; +} + + +//--------------------------------------------------------------------------- +// File Globbing & Dir Listing +//--------------------------------------------------------------------------- + +typedef struct +{ + tCallBack callBack; + void *param; + tWildCard *accept; + tWildCard *reject; + +} +tForeachEntryParam; + + +static BOOL isAcceptEntryName(char *pathName, tWildCard * accept, tWildCard * reject) +{ + char *p = pathName; + + while (*p) + { + if (*p == '/') + pathName = p + 1; + p++; + } + + if (accept) + { + while (accept) + { + if (WildCardCmp(accept->name, pathName)) + { + goto accepted; + } + accept = accept->next; + } + return FALSE; + } + accepted: + + while (reject) + { + if (WildCardCmp(reject->name, pathName)) + { + return FALSE; + } + reject = reject->next; + } + return TRUE; +} + + +static BOOL ForeachEntry_CallBack(char *pathName, void *param) +{ + tForeachEntryParam *t = (tForeachEntryParam *) param; + struct stat fstat; + + if (!isAcceptEntryName(pathName, t->accept, t->reject)) + { + // Reject!!! ignored + return TRUE; + } + + switch (GetFileStatus(&fstat, pathName)) + { + case FILESTATUS_FILE: + return t->callBack(pathName, t->param); + + case FILESTATUS_DIR: + return ForeachDirList(pathName, ForeachEntry_CallBack, param); + + default: + break; + } + return FALSE; +} + + +BOOL ForeachEntry(const char *pathName, tWildCard * reject, tCallBack callBack, void *param) +{ + tForeachEntryParam t; + + t.callBack = callBack; + t.param = param; + t.accept = NULL; + t.reject = reject; + + return ForeachPathGlobbing(pathName, ForeachEntry_CallBack, &t); +} + + +typedef struct +{ + tCallBack callBack; + void *param; + char *baseName; + +} +tForeachFileParam; + + +static BOOL ForeachFile_CallBack(char *pathName, void *param) +{ + tForeachFileParam *t = (tForeachFileParam *) param; + + int len = strlen(t->baseName); + + debug_printf(" ForeachFile_CallBack path[%s] base[%s]\n", pathName, t->baseName); + + if (strncmp(pathName, t->baseName, len)) + { + error("Wildcard in Root is not supported"); + return FALSE; + } + + return t->callBack(pathName + len, t->param); +} + + +BOOL ForeachFile(const char *baseName, const char *fileName, tWildCard * reject, tCallBack callBack, + void *param) +{ + char *cBaseName; + char *cPathName; + BOOL state; + tForeachFileParam t; + + debug_printf("ForeachFile : baseName[%s] fileName[%s]\n", baseName, fileName); + + cBaseName = GetSrcPath(baseName, ""); + cPathName = GetSrcPath(baseName, fileName); + + debug_printf("ForeachFile : cBaseName[%s] cPathName[%s]\n", cBaseName, cPathName); + + t.callBack = callBack; + t.param = param; + t.baseName = cBaseName; + + state = ForeachEntry(cPathName, reject, ForeachFile_CallBack, &t); + + free(cBaseName); + free(cPathName); + + return state; +} + + +//--------------------------------------------------------------------------- +// FilePath Globbing +//--------------------------------------------------------------------------- + +typedef struct +{ + char *baseName; + char *pathName; + tCallBack callBack; + void *param; + +} +tGlobParam; + + +static int CountFile; +static BOOL ForeachPathGlobbing_Entry(tGlobParam * pg); +static BOOL ForeachPathGlobbing_WildCard(char *pathName, void *param); + +BOOL ForeachPathGlobbing(const char *pathName, tCallBack callBack, void *param) +{ + tGlobParam g; + BOOL ret; + + g.baseName = NULL; + g.pathName = PathNormalize(pathName, TRUE); + g.callBack = callBack; + g.param = param; + CountFile = 0; + + debug_printf("PathGlobbing : Name [%s]->[%s]\n", pathName, g.pathName); + + ret = ForeachPathGlobbing_Entry(&g); + + free(g.pathName); + + if (ret && CountFile == 0) + { + error("No file or directory matched %s", pathName); + return FALSE; + } + return ret; +} + + +static BOOL ForeachPathGlobbing_Entry(tGlobParam * pg) +{ + tGlobParam g; + char *entryName; + struct stat s; + BOOL state; + + if (pg->pathName) + { + entryName = PathDup(pg->pathName); + + g = *pg; + g.pathName = PathGetDirLevelDown(pg->pathName); + + if (pg->baseName) + { + g.baseName = Alloc(strlen(pg->baseName) + strlen(entryName) + 2); + sprintf(g.baseName, "%s/%s", pg->baseName, entryName); + } + else + { + g.baseName = strdup(entryName); + } + + // Check if wildcard ? + if (isPathWildCard(entryName)) + { + state = ForeachDirList(pg->baseName, ForeachPathGlobbing_WildCard, &g); + } + else + { + state = ForeachPathGlobbing_Entry(&g); + } + + Free(&entryName); + Free(&g.baseName); + } + else + { + // Check if file exists + if (!stat(pg->baseName, &s)) + { + debug_printf(" File Found [%s]\n", pg->baseName); + + // Globbing done, exec callback + + state = pg->callBack(pg->baseName, pg->param); + CountFile++; + } + else + { + debug_printf(" File Not Found [%s]\n", pg->baseName); + state = TRUE; // Ignored + } + } + return state; +} + + +static BOOL ForeachPathGlobbing_WildCard(char *pathName, void *param) +{ + tGlobParam g; + tGlobParam *pg = (tGlobParam *) param; + + debug_printf(" WildCardCmp: [%s] [%s]\n", pg->baseName, pathName); + + if (WildCardCmp(pg->baseName, pathName)) + { + g = *pg; + g.baseName = pathName; + return ForeachPathGlobbing_Entry(&g); + } + + return TRUE; // Ignored +} + + +//--------------------------------------------------------------------------- +// Directory Listing +// Listing directory & Exec CallBack +//--------------------------------------------------------------------------- + +BOOL ForeachDirList(const char *dirName, tCallBack callBack, void *param) +{ + DIR *dir; + struct dirent *entry; + char *pathName; + BOOL state = TRUE; + + if (!dirName) + { + dirName = "."; + } + + debug_printf("DirectoryList: Name [%s]\n", dirName); + + // Open directory + if (NULL == (dir = opendir(dirName))) + { + error("Can't read directory %s", dirName); + return FALSE; + } + + // Store new files + while (NULL != (entry = readdir(dir))) + { + pathName = entry->d_name; + + if (!strcmp(pathName, ".") || !strcmp(pathName, "..")) + { + continue; + } + + debug_printf(" :%s\n", pathName); + pathName = GetSrcPath(dirName, pathName); + state = callBack(pathName, param); + free(pathName); + + if (!state) + break; + } + + closedir(dir); + return state; +} + + +//--------------------------------------------------------------------------- +// +// PathName Utilities +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// StrCmp/StrCpy entry name terminated / or \0 +//--------------------------------------------------------------------------- + +int PathCmp(const char *path, const char *cmp) +{ + char c; + + do + { + c = *path; + if (c == '/') + c = '\0'; // end of string if '/' + if (c != *cmp) + return 1; + path++; + cmp++; + } + while (c); + + return 0; +} + + +char *PathCpy(char *dest, const char *src) +{ + while (*src != '\0' && *src != '/') + { + *dest++ = *src++; + } + return dest; // Don't set '\0' +} + + +int PathLen(const char *path) +{ + int n = 0; + + while (*path != '\0' && *path != '/') + { + n++; + path++; + } + return n; +} + + +char *PathDup(const char *src) +{ + int n = PathLen(src); + char *dest = Alloc(n + 2); + + PathCpy(dest, src); + dest[n] = '\0'; + + return dest; +} + + +BOOL WildCardCmp(const char *wildcard, const char *path) +{ + if (*wildcard == '*') + { + if (*path != '\0' && WildCardCmp(wildcard, path + 1)) + return TRUE; + if (WildCardCmp(wildcard + 1, path)) + return TRUE; + } + + else if (*wildcard == '?') + { + return *path != '\0' && WildCardCmp(wildcard + 1, path + 1); + } + + else if (*wildcard == *path) + { + return *path == '\0' || WildCardCmp(wildcard + 1, path + 1); + } + + return FALSE; +} + + +BOOL isPathWildCard(const char *path) +{ + while (*path != '\0' && *path != '/') + { + if (*path == '*' || *path == '?') + { + return TRUE; + } + path++; + } + return FALSE; +} + + +//--------------------------------------------------------------------------- +// Go up/down directory level +//--------------------------------------------------------------------------- + +char *PathGetDirLevelDown(const char *path) +{ + while (*path) + { + if (*path == '/') + return (char *)path + 1; + path++; + } + return NULL; +} + + +//--------------------------------------------------------------------------- +// Get Basename +//--------------------------------------------------------------------------- + +char *GetBaseName(const char *path) +{ + int i; + char *new_path; + + for (i = strlen(path) - 1; i >= 0; i--) + { + if (path[i] == '/') + { + new_path = strdup(path); + new_path[i] = '\0'; + return new_path; + } + if (path[i] == ':') + { + new_path = Alloc(i + 3); + strncpy(new_path, path, i); + strcpy(new_path + i, ":."); + return new_path; + } + } + + new_path = strdup("."); + return new_path; +} + + +//--------------------------------------------------------------------------- +// Get Filename +//--------------------------------------------------------------------------- + +char *GetFileName(const char *path) +{ + int i; + char *new_file; + + for (i = strlen(path) - 1; i >= 0; i--) + { + if (path[i] == '/' || path[i] == ':') + { + new_file = strdup(path + i + 1); + return new_file; + } + } + new_file = strdup(path); + return new_file; +} + + +//--------------------------------------------------------------------------- +// Reconstruct path name +// +// - Resolve '.' or '..' in path name +// - Work around . and / to translate regular form +// +// Regular form of path: +// Absolute Path [Drive:]/.[/Entry...] +// Relative Path [Drive:].[/Entry]... +// +// ex) +// abc/def -> ./abc/def +// /aaa -> /./aaa +// D:/aaa -> D:/./aaa +// / -> /. +// . -> . +// ../aa -> ./../aa +//--------------------------------------------------------------------------- + +char *PathNormalize(const char *pathName, BOOL isTreatDotDot) +{ + int i, level, level_root, n; + BOOL isAbsolute; + const char *entry[DIRLEVEL_MAX]; + + char *pathNormal = Alloc(strlen(pathName) + 4); + const char *p_org; + char *p_new; + + // + // Check if drive letter C: D: E: + // Check if absolute path + // + p_new = pathNormal; + p_org = SkipDriveName(pathName); + n = (int)p_org - (int)pathName; + + if (n > 0) + { + strncpy(p_new, pathName, n); + p_new += n; + } + isAbsolute = isAbsolutePath(p_org); + + // + // Resolve '.' and '..' + // + // Slice the path at point of / , put them into entry[] + // + + level = level_root = 0; + + for (; p_org; p_org = PathGetDirLevelDown(p_org)) + { + if (!PathCmp(p_org, "") || !PathCmp(p_org, ".")) + { + // skip it + continue; + } + else if (!PathCmp(p_org, "..") && isTreatDotDot) + { + if (level > level_root) + { + // Back to parent dir + level--; + continue; + } + + // if pathname starts with '/', no directory to go up + if (isAbsolute) + { + error("Can't go up directory, '..' Ignored. %s", pathName); + continue; + } + + // keep '..' + level_root = level + 1; + } + + // name entry + entry[level] = p_org; + level++; + } + + // Reconstruct pathname + if (isAbsolute) + { + *p_new++ = '/'; + } + *p_new++ = '.'; + + for (i = 0; i < level; i++) + { + *p_new++ = '/'; + p_new = PathCpy(p_new, entry[i]); + } + *p_new = '\0'; + +#if 0 + if (strcmp(pathNormal, pathName)) + { + debug_printf(" PathNormal: [%s] -> [%s]\n", pathName, pathNormal); + } +#endif + return pathNormal; +} + + +//--------------------------------------------------------------------------- +// Get Src Path +// Normalize BASENAME +// Normalize FILENAME +// Concat both +//--------------------------------------------------------------------------- + +char *GetSrcPath(const char *baseName, const char *fileName) +{ + char *base; + char *file; + char *t; + char *path; + + base = PathNormalize(baseName, TRUE); + file = PathNormalize(fileName, TRUE); + t = Alloc(strlen(base) + strlen(file) + 2); + + // Concat base + '/' + file + sprintf(t, "%s/%s", base, file); + path = PathNormalize(t, FALSE); + + free(base); + free(file); + free(t); + + debug_printf(" GetSrcPath: [%s]\n", path); + return path; +} + + +//--------------------------------------------------------------------------- +// Get Dest Path +// Concat BASENAME + FILENAME +// Normalize it +//--------------------------------------------------------------------------- + +char *GetDestPath(const char *baseName, const char *fileName) +{ + char *t; + char *path; + + t = Alloc(strlen(baseName) + strlen(fileName) + 2); + + // Concat base + '/' + file + sprintf(t, "%s/%s", baseName, fileName); + path = PathNormalize(t, TRUE); + + free(t); + + debug_printf(" GetDestPath: [%s]\n", path); + return path; +} + + +//--------------------------------------------------------------------------- +// Remake the path into familier shape +// Delete ./ +//--------------------------------------------------------------------------- + +char *PathDenormalize(char *path) +{ + char *p; + + p = (char *)SkipDriveName(path); + if (*p == '/') + { + p++; + } + + // Cut './' + if (*p == '.' && *(p + 1) == '/') + { + while ('\0' != (*p = *(p + 2))) + { + p++; + } + + if (p == path) + { + + } + } + + + + return path; +} + + +//--------------------------------------------------------------------------- +// Get PC Path +//--------------------------------------------------------------------------- + +char *GetWin32Path(char *cygpath) +{ + static char buffer[FILENAME_MAX]; + +#ifdef __CYGWIN__ + if (*cygpath == '/') + { + cygwin_conv_to_win32_path(cygpath, buffer); + } + else +#endif + { + strcpy(buffer, cygpath); + } + + return ChangeBackSlash(buffer); +} + +char *ChangeWin32Path(char *cygpath) +{ + char *win32path = strdup(GetWin32Path(cygpath)); + + free(cygpath); + return win32path; +} + +//--------------------------------------------------------------------------- +// Change suffix +//--------------------------------------------------------------------------- +char *ChangeSuffix(const char *file, const char *suffix) +{ + int i, n; + char *path; + + n = strlen(file); + + for (i = n; file[i] != '.'; i--) + { + if (file[i] == '/' || i == 0) + { + i = n; + break; + } + } + + path = Alloc(i + strlen(suffix) + 1); + strncpy(path, file, i); + strcpy(path + i, suffix); + + return path; +} + + +//--------------------------------------------------------------------------- +// Get Current Dir +//--------------------------------------------------------------------------- + +char *GetCurrentDirectory(void) +{ + static char buffer[FILENAME_MAX]; + char *cwd; + + cwd = getcwd(buffer, FILENAME_MAX); + if (!cwd) + { + error("Can't access current directory"); + exit(10); + } + return cwd; +} + + +//--------------------------------------------------------------------------- +// Check if absolute path +// +// Return True in case of ... +// +// /dirA/dirB/fileC +// D:/dirA/dirB/fileC +// +// Return False in case of ... +// +// dirX/dirY/fileZ +// D:dirX/dirY/fileZ +//--------------------------------------------------------------------------- + +BOOL isAbsolutePath(const char *path) +{ + const char *p = path; + + while (*p != '\0') + { + if (*p == '/' || *p == '\\') + { + if (p == path || p[-1] == ':') + { + return TRUE; + } + } + p++; + } + return FALSE; +} + +//--------------------------------------------------------------------------- +// Check if drive name +// +// Return next character of ':' if drive name +// Return head of path if no drive name +//--------------------------------------------------------------------------- + +const char *SkipDriveName(const char *path) +{ + const char *p = path; + + while (*p != '\0' && *p != '/' && *p != '\\') + { + if (*p == ':') + { + return p + 1; + } + p++; + } + return path; +} + + +//--------------------------------------------------------------------------- +// App Name Utilities +//--------------------------------------------------------------------------- +static char *appName; +static char *appBaseName; +static char *appFileName; + +void InitAppName(const char *path) +{ + char *slash_path = ChangeBackSlash(strdup(path)); + + appBaseName = GetBaseName(slash_path); + appFileName = GetFileName(slash_path); + appName = ChangeSuffix(appFileName, ""); + + free(slash_path); +} + +char *GetAppName(void) +{ + return appName; +} + +char *GetAppBaseName(void) +{ + return appBaseName; +} + +char *GetAppFileName(void) +{ + return appFileName; +} + + +#ifdef TEST +int main(int argc, char *argv[]) +{ + int i; + char *s; + + for (i = 1; i < argc; i++) + { + s = PathNormalize(argv[i], TRUE); + printf("[%s] -> [%s]\n", argv[i], s); + free(s); + } + return 0; +} +#endif diff --git a/build/tools/makenandfirm/path.h b/build/tools/makenandfirm/path.h new file mode 100644 index 0000000..e9956dc --- /dev/null +++ b/build/tools/makenandfirm/path.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makebanner + File: path.h + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: path.h,v $ + Revision 1.3 2006/01/18 02:11:20 kitase_hirotake + do-indent + + Revision 1.2 2005/02/28 05:26:13 yosizaki + do-indent. + + Revision 1.1 2004/08/30 08:41:14 yasu + makebanner moves into CVS tree + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef PATH_H_ +#define PATH_H_ + +#include // struct tat +#include "misc.h" + +#define DIRLEVEL_MAX 256 +#ifndef FILENAME_MAX +#define FILENAME_MAX 1024 +#endif + +typedef enum +{ + FILESTATUS_ERROR = -1, + FILESTATUS_FILE = 0, + FILESTATUS_DIR = 1 +} +tFileStatus; + + +// Item Reject Control + +typedef struct tWildCard +{ + struct tWildCard *next; + char *name; + +} +tWildCard; + + +// CallBacks + +typedef BOOL (*tCallBack) (char *, void *); + + +// Prototypes + +tFileStatus GetFileStatus(struct stat *s, const char *filename); +BOOL ForeachEntry(const char *pathName, tWildCard * reject, tCallBack callBack, void *param); +BOOL ForeachFile(const char *baseName, const char *fileName, tWildCard * reject, + tCallBack callBack, void *param); +BOOL ForeachPathGlobbing(const char *pathName, tCallBack callBack, void *param); +BOOL ForeachDirList(const char *dirName, tCallBack callBack, void *param); +int PathCmp(const char *path, const char *cmp); +char *PathCpy(char *dest, const char *src); +int PathLen(const char *path); +char *PathDup(const char *src); +char *PathGetDirLevelDown(const char *path); +char *GetBaseName(const char *path); +char *GetFileName(const char *path); +BOOL WildCardCmp(const char *wildcard, const char *path); +BOOL isPathWildCard(const char *path); +char *PathNormalize(const char *pathName, BOOL isTreatDotDot); +char *PathDenormalize(char *path); +char *GetSrcPath(const char *base, const char *file); +char *GetDestPath(const char *base, const char *file); +char *GetWin32Path(char *cygpath); +char *ChangeWin32Path(char *cygpath); +char *ChangeSuffix(const char *file, const char *suffix); +char *GetCurrentDirectory(void); +BOOL isAbsolutePath(const char *path); +const char *SkipDriveName(const char *path); +void InitAppName(const char *path); +char *GetAppName(void); +char *GetAppBaseName(void); +char *GetAppFileName(void); + +#endif //PATH_H_ diff --git a/build/tools/makenandfirm/test/Makefile b/build/tools/makenandfirm/test/Makefile new file mode 100644 index 0000000..7ed8894 --- /dev/null +++ b/build/tools/makenandfirm/test/Makefile @@ -0,0 +1,56 @@ +#! make -f +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makenandfirm +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#--------------------------------------------------------------------------- + +SUBDIRS = wram_rbin \ + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +MAKENANDFIRM = ../makenandfirm.exe + +MAKEFIRM_ARM9 = ./twl_nandfirm9_print.axf +MAKEFIRM_ARM7 = ./twl_nandfirm7_print.axf +SDEPENDS_BIN += $(MAKEFIRM_ARM9) $(MAKEFIRM_ARM7) +MAKEFIRM_FLAGS += -d +MAKEFIRM_DEFS += -DFIRM_ROOT='$(FIRM_ROOT)' \ + -DMAKEFIRM_ARM9='$(basename $(MAKEFIRM_ARM9))' \ + -DMAKEFIRM_ARM7='$(basename $(MAKEFIRM_ARM7))' \ + -DMAKEFIRM_RSA_PRVKEY='$(MAKEFIRM_RSA_PRVKEY)' \ + +TARGET = test.srl + +%.srl: %.nandsf $(MAKENANDFIRM) + $(MAKENANDFIRM) $(MAKEFIRM_FLAGS) $(MAKEFIRM_DEFS) $< $@ + +.PHONY: build install do-autotest clean clobber + +define ECHO_CURDIR + echo "==== $(CURDIR)"; +endef + +build: + @$(ECHO_CURDIR) + @$(MAKE) $(TARGET) + +install do-autotest: + @$(ECHO_CURDIR) + +clean clobber super-clobber: + @$(ECHO_CURDIR) + -rm -f $(TARGET) *~ + +test-utf16.bsf: icon.nbfc icon.nbfp diff --git a/build/tools/makenandfirm/test/rsa_private.der b/build/tools/makenandfirm/test/rsa_private.der new file mode 100644 index 0000000000000000000000000000000000000000..06f5f4ccbac2e2f50ebc312c9d601a422754c370 GIT binary patch literal 607 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
U4<#z|> zvnw~zljzpn6xF(4+lc|UyhR_t1C%r}%$?mkOQJ)}(yVtEx{cw5)aO79?b_+u5PLJE zegm9g*IF!+pI@x$wb%2By)x;C-d?#_i>Z$P6|8sH4qn`G!J4VMYu>#cVqUD}esRY? z>jzxBR(dgqXZ5n|B076f57F+#NVb^FjlOrW(-*%*R6e}wO9_i|#p%69hwORdo*z_( z*X(VD%kEdb>cNV=#T8-6TEX>u!(>&sl%f zhQTJ#IqP@ufAg}dwyhs*4qm(Us%_hwLsxIr-*Yx?-16$?#-R=8Y#ZD(xNd0hob5yB ztS7rd*Cb)GMN{pl%O|FH4Nr(K6-#gTbz|ThX-=D9w0OO1Zt81;UpyhN8tgmCRY&7LPt)ct}~uHoF$R& zOpcDhRS;pS#gWk67wayGb$7)UxvRy~F-mZ4@}8f%!PmExqtMdj`)@QZcwk~|zvL!j z;*B|gHIb8W5=Vgx{Q;pYwJLyXf;@~xwSQ!6CLAFo7zAJ-E=!u$)pCGAR5qj^ZURhV zHE>c+07uCiu$0L~H4~3gwafKLL4_IsdERsdNS9fGkje=<2g25wb6g-hCNnR6n3NY* z-1yX{X|9K}Hbi{~5v3-CV2i2*Om+$<5PX9XW|RB11lxVXGh_@@6YL1ryo?D4|6`!! zfsP;?9n%H6J1S7}VFz}{b^v#ESMvRv%~{2Z^)(w9lI%QBAPJTv@wzoj6zSq)mk@-{ zt=y+Z$A{&Z0bKX)4>WM?N*ldr3FcD+1kxGEd@NE`#FdsjS>*B|N}ox|oj0mvpsAh5 z%*QnI(am(4GoSBlIrv#S720xQbYVUoB~7PG9YC@!j-eu4!{AVBpLc#_RT8@)<5@M2 z4{eDK&~_LWiqZvxlunhjHd^mVPDD6RLHFeYxD(-#nS4H%qlx*z!Zhmw2VF^DJ}?t9 z;_P1S3~>FSn(Q=EJ5ZbzHg@2^8y3$aGZU@$U|AF633mI7Z%I7U%z5G3ac9m=?wIhC z&>RikF@XyY85kJPOucem`Qc5jDYD?!;IvJEJv5)?=2)@9bDE5} zdHDXB<^~6e9g}7j4iAor6EGp>d>W>3cqb`^tq2`y4MQUyOo270Y{p7B9}g7XXu^{q zKHLNtqJjKGJwVvhbyT!?4T=bVBnrTN#S(BbQ6?i&B5>hg##ZRHV6OXn)u*Vc@y)9I zq&4W|%$8l;PKCJc2^S`B%NfF#rb-_IPGoY#c##8^)v{0NwBmkg6uyKG zL|0UubRvo&?vm0Q6epR&Bj3WM3%*Q=gL((kHCm`s29~c_waRrZW@cW=rB$Y%I+JYr z8z-N>a-jbxC9;!`QaPP?{&A*yI`Mo6v8IPik3=0}hVvIOb^EHnVcA`rMq^3CFgoV; zBlIcXf*OVce7~q0vWdNONe$6m8&~hKCAGz?lYY_1(30As(;*Mr85X4$@f1jX|B7l0 z|Dw+ay@XUA&PeQZy@XZG8HfNLg8kiZVv$n~Iit>K)igLNYZ?f*YZ_2iWbYa%f~Fy4 zmoyC_oHY#~N=<`;QPTh%Gz~zmX#mKY1_Cur1L34;0FIglz?!CkaMm>BG_Gl&89~#4 z4#LFNASXo=a1b*Iy0l=Lh7>YQLkhX3Aq8F2kbb^ z04y~PqH;|G&1u&(Akr6_1_@!(gdpc+O+zXtXc`FDH4XBF*o*yEJhv5>G!2BJrU9_j zG!SgjG=RyP1_EISp!7(Z2H>D+0IF#k2-h?XgoBU>lr#+p^HIq~I`> z0_0%^!GZ@7g0Dd!saAo5)&VF;>UO6Sb0KOSlz4b%eqmNpH-Vsa018?MAlEtoxYj|K zQtLoCYaIxbS_gtb>j31+1}c6~tpoANuZ6MNrgcz1*?|vt5uq)ev<{?nD%Uzd6|@dS z1Z4qTX<7#|)N)7r(I|A%IzZ4t>tM<3YP)Yx>%e5PE6>O4(MudQ{U zHmXH8^@EeS@S5h%H%${kjZ724U)Mwc1XTl2ubPP7)DO~A#KizOsvjuF)ei;)^#kgO zpnd?G)eoRu{Qx$rA5QV%DRTq(QWHTiOzsv<1R9G&$EipY(RYxNXr7d)Qml+r=s+re zAoGDwpo{oJQ!?Oiah!X}d<^|zU-e>scTfp*av+Q%km4j)cB2W_9YQ^3x}I2?$05%u2L ztA7jgZZX*|&H-bw?j1`PGqhiBu~_}sqV;e4)4`pdmeoV==+yJg2}x~yh<)%7*Yg`i ztj~uy`}M{@)k-+nZq$t*@cqZnWp&D@)!ET{jV7{Sr_%@+tj6|lm>h=rf(I&`QRd+u z=XTqbx~MbiwnPxw(kNwz+rv?F4A0Gt&B{{&I7k}8j)}RWD3eM6QG-MftVG}D@Gkiq zP=~s(jRatbARf2qPom>SlKK>1H)UlrnAz@-w4)8LP+Y)h79j~<@xTSbNXUVd2@8es z-Qc1nuq+mI>`B1P=}OOF21Br!D@GDdb~}TEVj*(a5c|SR|42~Zqy9~RR8B z9JLM!ku(kolUjtq+%ln}l$Ol7NTW4b3o(7;bV`UX-rge^b)IJVf@VlaAu}?hkYA~of_|kU!C<&}Ih8MO$2?QL7LRkC zMYoxkC@Y}WAi~j30vOU6x@KA-F56uQxHSeK7-*C>nr#FZC$tIHPiO~3G6@k5#v-6> zLn6>_Wuh&$6WSrK@`N@hE8ZIivjuRrK3X{6d5&OPN?J5k-%Z5q{JCh3&aF@iJt8lb z>P9q2ue1l>BF|3&}`5h}(Wg|na$1xj;+8CcPGv`*<*G0&)& zza_U7N*8|Fxg}~M2148xKR;o=OU%dHFmHj&(@##d01u>}m-5f^`OYJ%>IOnr4UIQ9 z&c0#0*+^cqFt#uzy6OV{IpLWMtB(;1gqjXow=^}Y&l|qEaocOQ5AT}rl)2EqVEpUn z75wwOPKRS!Af&u5W7*n1Haj^!H9S97ebBJYtqb!*ro1Cq*8lBPqK^44SW*3am4BZ3 zcd(iLC?REzOWMeFmrc)Z7-OMc7@41*tsV(c+s5YLyhax$#@0_SOwCuXB_m5>OIU8+ z(7y5ck-gq8)$M_3{le@lYnx-Y&d*k#4iOvY9JdiZZhUxxi7;CAQ!nKlW9YC`18U>w z#F(S4rqz{g`0BcV+B8f@?H!wSavD+g%kMx`$DA2DJ%5J(4Ogxoc#hChcf;82BSht{ z7#p6kPbrF==G3jPtJK3Ub&7r90snA`SUQGa;nSPy5LQ1 zm>1Fo`uRapd#C)9-eUnX-n0|sddaA{dupV*3!Gy{wZ6^HPEA+eNvfHJ`K{ZVw&hnB z65ca5KeT<__Ubh$?$S-Kt|mPON`-Dqp-t6~C%R45FDH2J28#TXL}tPN9fQ@2sH&A) zo$k>3%^Rvq0GrLR`SU`>=jMm!tC1Gu$mHnkXmv|FcHit=b$<(*E9QqsXPbMg-*1VS z+dIB{zBya{pN{y6>Lk8$SryNy+5kFsE47=Qw~kf!=Z|)D80#7HU&FY~m{Y=Vcr_`h z0YCqn!Kk%xZiwm4qAO(?p9-f;Yo83A*RsDj3SIzDb{JR0ZW_n^_a*RM# zUBW-lZXK1-qKx14c$2Kg@s%BV!vc(yuaZh!#&udd_aH*)Cs+H3m$qUqY@-=ND$JQ9IfnGHtZBKIrXCiP|{ z-a5_qw_$#zZE?7%ZG8MoSY$@X%o5DW?Twc~48`0NqA#5opSms-v}L;bjSlDy!}G(S z%Z2^#Xt1`x_1m{?xO}{s%E(LqFR{x02oxi}ku|R$-=!>yj(rR!sE*kdI_)&jUQ?|= zGlcYEn1`FEwVj%nKi87>_n_2I9>-q|!{V2~dTyVi*4jv#uiL(HXnxHr7!>0p;UvVa zh20xRK(0adoNc1!8lRurI5Id`{eDhx9(%mYV^CNB=n+FCsz|_2Gb9 z#Ao@llua=-8a_07Umq?B2`ISB$Jl?6toOApJ^L8szmT&ozTUI{6fgF1vvJFsb2pEn zVca)1d)?fc3(zslO;3#Rk^#)xf!4vnYPe(SH6*|uFgB`$omw$i-PbW;d$FBUKOIst z(|x^W73#cFpXDRBrFj>|=1nimhxT>XW?|)M-N*to|j;uyXjWKFo)7 z{nOMsw{vEDLPEyR`Ll?bh(+T1kwf3(G4&<#Q;uYb?ADuq)rqoWcbp76Ve`4I3RilJ zO3S;|WJ0#q_HNPsCVBR=Wit$$tuo`)?g-LCAB5A+2Xq|q)sMH4 zb81aj`*bFM!pZfax{UB+(ffH%7nB{p$<{#GeO0-TOE_v%I%y`4DFGyC$MS!JoPeHI?#j`G3TJd!S9hYBwp7q^-DC5s#WH+aGH!{`36J z2TeJy`Y}|_tBs-e#%x^wvgX2F!zkmirsxiprp(-f)o-Tq>*MUHn6|9Knse1qAvt{I<9DH{Rc}C7dgDCfUgDS#!36xDVUL| zpHb0#-0AlU{yv8%1Y^%qo-=}9;qbiR5r_8+{%MEbB=|UoZxs9^4&MjdH^ux_S#Jlv z%i+C(FL!t%z&Aqk0pP}ip7x=DzXbfl0p0-oNPw>ZeoFMnhN|bqH)Z&}1-$7Ux!kRS zf5yw5xfwXrZC>z;9l!OHz-KtTserF2;0*}_X78=cl>?AU+MS<1i#hcCk4OD z;im*2>+mtRX8IEZ2l}%F|B%yMD>$Tmz2J~`zhG3^nzOeHUhDJsZs5NE;PrVx_;rqd zNbswi{!!7K?=;&rZa?e&cCFyej($@no-Am-QqVjjnozf+-UYnZ^E^Xv$bUnD9|i6k z^s@E}4&_b=4&}}W-sCi={wMNT@I0S+ANZg2{yFk4@EaX}l;GGuf-iCW_>dj)^c z+jU<-^BLgSu46w09NKjSaLn^s;XmSK-6)uRG`1fR9P03x=-=w)J|ldr^N#|Dbz?Pf z-+ywND})bu?iU=tsbHiA<$uZD8QugO)7~ijhrAB&5FEbsy@ErY4+?&}=ku`O(5^24 z_uc4qcvSG)9DZChA)l`n^lLv1KGbKE;E>O?z_C8B7yhR3-35pC-Xl2F=L>>kyLh)L z)@{4sfZq!o^Snd&hrEq<3;z+X=RJbu3&77~q6z)*L_zbUU zJOdotyOsBy8d%xY=dTwW#@K}5@O@_lk2}qMg0WYN{tJRbpL`j(?|v`q3Bez8_$k2` zdbt&^JjHU)6&%uD3>@hv3Yr@WnmY>k$%5wT0)OO3bDnzzf7HLrn}B2f4{9y_jMwd< z0)DuFA1UC^7w{Jf_|XD>tbo5gR36N3L=FZc7R+b?_Fo+#k23jTA)FZ)=gIYw~6 zpH<*5F7TTQ{I!Dr(({=q@NX*cw+sGnPIF%YKPVUnB>TPv{_z6;bb(*SZS|4<7{MXW z)q?T7P(Eu5{3QkcY2dyGy-)7v8v6)8@e{y*;rJ&72bv>)k~}}{d43Hz(mW&h=bgU# zIIvU={45h3(+d7M#~&s5vkos8{EH4BBUm1V{2VLz&m2BM@c(dlwcxKfe5&9l96m$v zlMbIH_`f@Ru3-5c@v~O&0}fv#_-7s70Nl9G=hUe1q0Wy8AJ(O>3H|}6Ir2W>H#mHj zV03-z=Zge~xp{@)ZI0h6ILx(C!6BdhfL`1b<${hhbv zUcpZ}e4k+UW&PZLBWeHHzui}W`!03-R|UV?;im=5-GrZeehT_gug`}2frlNwSny$u z>P<$~+b`wVUy`0*nafN>DPI5H$-k2BlC@R!D=Q+E(}?cf{OikTb3B{DH%B-*G>AsN zM_PIXBf>40bN4X>o(#M*XyZ8)|A_z#r=NT9V>tm;y6PgnL_g@$s$b(@$gg^m_2g@T z?^V2hM63A6!e7d@p99fpITF3fx#+V8&aVMcFLcNCNcYk}XZ53B4pcvENLDU?>}O^a zepVF;KLYjd72$6{SNDwJ%=ceo$Z15ku7z&(V555Km5T8nLHf5R{BFAO%OMV zIa6iT_Uta)<^tZLkdOr3M$Lue{9{1kS>&t?2p;iBvLKvjV$wZrAM9@GLQ=_PHJZK8 zw`UrMjaHJos=K7DC)n$H-_ew?_=yf z`Y*h^P&Vv=R}H)Hs^I(0`1q1Fj9J$2_UGx(m;<3{4V~*#nKCY1|D_gHi4p5GYe&S4t_m8-da=#{r5ua_3?2%m76tO4?iZn zH0x?KL(PQIRPLEG0<#8s>nQ?ve^QNps$PxWs;SW=bB@zqS*J#4P=AR2cup1^%5nq4 za*%<1JCs5w_+H)9ow(+WaeeIiS;M=EjCt(UfE&0r`&M%ODJ~`N`jc|hU6fAOPdb`c zuU7hoqr5t`QfpEwol>6+GLGvbfc=yCPB|Yxp6clxN-6bng0}S6QEScvQ9m+xS<$}6 z8B9)@_N8|zwK6b_{+850e{;s|Z{7(mSGj&+s^h0j*VnuU%2xpY6ZB>5`id;JBZr^D z|JuFX2@`qb;92Ed-)QVTJ(ur<>MLvPLj!nZKa7iePn*ceLLSm@G&-jZ-SMI^(+SP0 zjAw$+rp%#aEN}u_RL6bUN0C`dSH@iEDdeI-?^omFqjNmq>_@_s_3?7j?1kO~VXE{9 zeZ7HUZek4&ghlf>{hPpb5IMR2+$ueD0zMyn*MKi+dAgi1Z7Rp`ZwF&3r)*f8!juV*+LqG>yqd^c z_IY_&< z?0wNZ>L1~|X#NPej=(tkuo3Mu{l}q^z#pZoO=V?17_Ieb<5&YetZAvar5QVIl{sR^ z4_0BB|Ed9P`u*2fZ^oAI8$|EZ33Jx)RL}LBSWCiu<_!9P{ax>4lVL_ZGn`TGa3=rE z@EhIUF#0?ELKP?D!wZMDgfTzL+7s$$@9=ZpmTz z4~BE?`DH^n$f*au9|Ep`F7^b<>J1Gw5GEV9fGf|QcO*n627HMuKZ3r+y4Y8>)wA$9 zhQItJwSoMFr#9%_zoF7bhtF%{FVAaZH|MpXbzVC;p4{AG(lrE@bVp&yGD1 zYN}9<*2&&!>|MNX?Z8E{Fz1)iY1WD?)D}u1jQyHJ?NG zEOZ#zh!1|sJmhP)NNiLi@a<2*H|^U^DRtrJRpLe|LVrOt`X zpd;#EsBb*C{tLk={Yw1}YgrM<{=#$m3)Q)6quLF|s{U+j!K~p#XVF&!z&Wn3!-v4% zUWLC!YIvCh9`WtViCHRFWPQTdP3P#o3%dITjzqkOd<4g;Dvs-^g^#fXl~^GDU--W# zrAD*JEz5pId}2%AMh|1(eg-+6>aWBL3pfin@kPgg5gw35>#g9BxwUgnFh^`l%04v| z)o~1XzwiWY!6i6_SA+N}y3+`};JO5u*cRHqh(AM5VxBidYsw>6l@{3dKp!26=AA+| zF&|UatYOjFl-gWQn57_PJ&aE)l-m_+Xmf+VK!4g~?X(SZOGIC6S@hE!+FTai9rQ(L z|2|xo{gJq0S>RiI9OJ0yep1$8x&9EcZK?7s{IhFG-ITTw^j_CKYV7IQ)L*`5V zxYEj&vdTMEu6zwPM=ZHi^iP>bnzey1mWR|!zSgyA1@-8xp6d%n$HzxB>S5{>^=WF8I;6godBosW(HU8rVfB;^ zw~_P8X5@Qwpxn>wWzLh}9!XnrJ_mpPCGTs?rhB$~ZFwmFk}tHe!TleiCa%6LGQJ%8 z&EP#|z2>W;8(doD=R7*an9ePMDtf;|AjPD;ZcRFp>_xulNzesx} zZ4RdC6MV0$jy*wpi1uC9{PHCF^q>FTz){+AzQKQwe3x>BvWW5=1)Uf#YIjOK9Hvwjp5<(0^1V4k-f2xOK_}5w3tdD< zML$JP-_Ngvd8jlI{@GPy5ZEqIvE`K{k;fvyQHn>z}y z36()tO`+2fn}aK=vP`qy^dBNi)|*C-(_%SV$kB2W z`b^o6n}hk(ldCd}aMti6GOXoA_C|OSeE*Ymh^#-0tQE4>GRQ_P_QYOu$O$>7QzkKl zeM{jd4YMIEsslcDGU6~UwkG4HEAZnrFiBN7BephiuAEbZ-u2LvbJQgE2O3dKkMxwW z*e6~mFu9Mgw&lSB4ZR{x7|5A;QILIC*o5fp3u+5@CHBbf<-UAFv`0E}F_6m#1qb$I zMmm!X%-kWaqWBoomG8&2qWffqb!q8ra3yPz_1CW1$aiqp!2ba+es`iw_T@V`pH#-t zqev$4{8UvQseD5uw_14^^u_ZMxkIcY8(a^46Me+LA`fg*tw=1PZ<^IxHm&c4w#7Y_ zTBpw7lNX45fu9Gwj0ucZ9lM6HiEBAg<@NAIuK#vx`DM-ce`hU%S3zHO>iB~j1AVn7 zbpl&WC-WYDf|B1>*3F$>%;&5s-^8#H$Yz~vjm5MZtH}@W~C_$;7v<(6r8t<&aOEi-8h)KUTM_Bd69>sr*_+D}Be%6V zo~sr80bTPn^IA{Nv^IKQr=C46xc(Dd(`)#;7{26eD04->ujXtg-vd|ncnNC-{PmP0 zzTvT=Bl(2j6kMF~TN`U|O_ep4HkUaU1yih~H+`AwPt$>AJ!!EY)?}-my$RLh)~Tc5 zgC_D}9nm^}4!%s}fAivRUmnt40X{GG0iDfd8=I&zOVPXxF-Lfi*iffF>dC%k@C$X; z64pK6le>kc+&$7Kz6$?asxu3oh96Fu*>XjGH=pyx6Mdi9x$N~j`M-=Mc$Y=kHydh{oZYD6oKGHT zB)+5mj615pJk9yuA}=d)`v7Zug1dmmepuX(+axE49?ooV*jw_cvz^eI=7jCk{nlV8 zxnY~{nZV7Uh>nmOK1pu)F!f1x!S|K#7 zM7VU?mT+-tFkEbN=P31rtLR@z*{2`y=Yr!YYGwD3vw17G>X38UMNug6%6-%hMOR94 z#lL>@!!LgOs#ks^d6~z#cgA<5uOkn+quRMGp`9;;J7~+jFTNiNPT@`DE4eUi3wu5m z$`HBDq`#7X$V;4VjbMnse2>-x4?ClB&V-e7dEhtTFTQhf4jDBXT>pv-3+3_F zLix}I$N(PNC-l4Y$M;X{Jo4G~)mr>9bnwAyL~hwy0=_H8jV<@}IB z|8gaHV{phR9*x$&*Ieo!KyPIqiuO@|`s?G-o(TLpz9qLW-v)Ey9FhTDT~o%wuXZQo z%|i4(#hZn^U1-*W<&@;^&7EbTV^r-Xi5%pu;Q+Xb_CbHIJwM7-8@3Z>;Ys+Fbte67XxFK#LLrHcx_ zo^t#QeoIyJNNlVC^qhkOCQb4bZTan?mD?U-i(Zm_ zHEhl+<^gXy{#LUFh)+Aq+pa8l+stX+*2ZaGqU$T3*7^5drmH{PrO2yy_J`<0VB`lv z9sez7#*DoUUblsb+)bXcpChg>_jL7whripMr9Z3s!>qF*Y{^r@v+&#EIL*v$6}hA5 zzTp(Yhv1p>$w*6n8!#&Za&E06E78LiaHPnarhpTCF%BGFtMtVh5qturp9L!IPz2uSmUtQz|pZLxA=sa{y_Mpw&NQ~JSs;-S;i^NOj z8nkoJQ1&)YvmWOi3!KQ|tMuVN{i~QeR@K8Ua!dD9V*hR%~7q&pYV02s&Are@=o;`^#7FfN&cRkwK*YYtwHOb88>qBzOg)*0e!I} zu_w91XH;H8zL!c&xCmHF)@EX7;5X1^Sw~9sB(to=Qd{9y#yI=sD=>_+C4EWRf7vGk zn5mxYH{+MjgBLi~Ec++4Gz*#L`@*ZBDY-v+Ux@HB{$`CF#2zKjF7gmtl>EHB(Fv@` zR(!u^bC(i%;1h4EiGvn%9)F}VuRFs%#=r*2ugm?6x51=lx{1AJNfVwVmnymBSK#qb zjr|Ia9q7a^N_?gn1E<*ZV{eX+4vD_!T;fS3cFcsQ61Z4j6g$NBHeEujpik^iZ*Wda zUdG}K!`*-X4tp@%0bQ-W!heSS9H_QMUJs6qkII;Q|B&xrKvUMhmOiXf`it4)&-4B4XNFG_sRA^pGTi!F!n-SIdl~8qV4yV(Xq%Va{$$d3V zO@21L@dDnrFDUx|&bOMq75UsCaWh>v%k|&a-aHfym`^Yt)d#8wDya_Nrrd_)SG2FjRfICrxOKki5 zw6zMY^bh#9$VC!{&+#NMhihP-<2&Y8#tzAtrpmQ*V%pCzrt5F5r`L?~(oR{f899miMnADuTbg7YNf_@{vp={(9 z^47aNKrb(qxKIyXd?M$9x87hhb@){aAEM=!m+@7tUDY`BG`>*c^sX9SiM5hLA4#Z~ z$9!a;5szKlA|CgeC-FxoeeFIc;xS>J40Uxf)J*Dj2cJ%zE%@4c$IqHy=FC&E4SCzD z<(YSmh-Z9UT6isiu6)w$a;jP$b368mv^s;JoMB5XW*OcNWN5!w7(6GwrZ>u-AGwmkuiBN z_!S!R9$DXcomcPvttYvSQ}Aq8X~pY|-`pnBmiOBDzc;(^F(S9Uk1QA$-Bp^r;r%YZ zqr~i~DOIjdf{XWHtpPNj#z`?5nv<-z_}?b(Js-R z!g@t6PuI*RCN>Yyx2tBp3%px1e>?5%G6#He*J4h%iaDF;%g`rxH#uj->leNx_Rj^z zs_B0xx#+}|*j7a@?xWp_+rL?n&mq3e$M~NTwN2emeQGEF8KW%byPdL@a)|a)#>XhJ z-x2>IdMhz_MvdOa{z>GoLA&-|EC1tC`J%itVE&b}DE830kZ+AQlZE(&T=g6(KBLml zfAjKguf*tU)HcFYz6qUe{TyfLL-Wu>Y(dU%I&yh8{n$uQ{2cMNV=zp2;s?-ig7S#i z*HxTF9LMB6Me)D36Mj2wktaIcYIOF6lU>dporlqL{_jxkzrpB4#5Oc(4_f>J!&KEjQ(7zKK(;7B- z?d+9X#WfV+s>ojO$-Rg(TByUvL>#x*;K+buRTal~Cg2diEbj<2fR{CY=hvJuz$b67B}LKNG^L(W~p+Ch?_JXP@qj?oU~A0d7Nyw~cs?tQ#D=mFgmQ;FslG7PYOr z%gPSQD!;|QPHYR`u62scZV)|Q0-dsMJ?JIuCq3kLa}s)ji+$P8y*=_LmAvr)IrBXp zZPKZ5(F;1`_F z1s>oU_-_I~0Q?@{zj+=!F?~04Mk?dH({yFa+>f-$rmLY(X{&2Rd3L?K6CK@cb=_9B zlfCf3)|%C9{gG-f9C=g(D|^4o>z<%uERI2`NuDr>mIvA=WS2E=eWn@zH7+$mF_Wc&dki}T2D?K%Ck|Fq}-|MgV%T=rQ0+ge+q zHvxiAdfu{+U1i;~e)Zk!@3~x@VAQ^C-I}PSR7y?4F-}(UIFnR(etwT{Bis zUQg+xY_0aUQ_rC+q%5!Y#qj^vwfZu0;D3lLRZYL=>gj8&{OWag+#ln~wR-L9 zyYIaGR;8j3>(;yOUAxBm^ljGawRhjPdd(NCd+)hz&E-|tyKlSaw)Fyg@4C;fyX&vl V0e$D4tJkd|WOOI~ka7)h{{^{CZ=wJI literal 0 HcmV?d00001 diff --git a/build/tools/makenandfirm/test/twl_nandfirm9_print.axf b/build/tools/makenandfirm/test/twl_nandfirm9_print.axf new file mode 100644 index 0000000000000000000000000000000000000000..3d064b38a5509e8ea9e4ce4cc5302e3f0684d513 GIT binary patch literal 288636 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 literal 0 HcmV?d00001 diff --git a/build/tools/makenandfirm/test/wram_rbin/Makefile b/build/tools/makenandfirm/test/wram_rbin/Makefile new file mode 100644 index 0000000..217e8b4 --- /dev/null +++ b/build/tools/makenandfirm/test/wram_rbin/Makefile @@ -0,0 +1,48 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - tools - nandfirm-print +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = wram_regs.rbin + +SRCS = \ + wram_regs.c \ + +#SRCDIR = # using default +#LCFILE = # using default + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_DIR = . +INSTALL_TARGETS = $(BINDIR)/$(TARGET_BIN) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/tools/makenandfirm/test/wram_rbin/wram_regs.c b/build/tools/makenandfirm/test/wram_rbin/wram_regs.c new file mode 100644 index 0000000..88332ab --- /dev/null +++ b/build/tools/makenandfirm/test/wram_rbin/wram_regs.c @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenandfirm + File: wram_regs.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include + +MIHeader_WramRegs wram_regs = +{ + // ARM9 + { + REG_WRAM_A_BNK_PACK(0, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_0KB, TRUE), + REG_WRAM_A_BNK_PACK(1, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_64KB, TRUE), + REG_WRAM_A_BNK_PACK(2, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_128KB, TRUE), + REG_WRAM_A_BNK_PACK(3, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_192KB, TRUE), + }, + { + REG_WRAM_B_BNK_PACK(0, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_0KB, TRUE), + REG_WRAM_B_BNK_PACK(1, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_32KB, TRUE), + REG_WRAM_B_BNK_PACK(2, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_64KB, TRUE), + REG_WRAM_B_BNK_PACK(3, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_96KB, TRUE), + REG_WRAM_B_BNK_PACK(4, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_128KB, TRUE), + REG_WRAM_B_BNK_PACK(5, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_160KB, TRUE), + REG_WRAM_B_BNK_PACK(6, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_192KB, TRUE), + REG_WRAM_B_BNK_PACK(7, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_224KB, TRUE), + }, + { + REG_WRAM_C_BNK_PACK(0, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_0KB, TRUE), + REG_WRAM_C_BNK_PACK(1, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_32KB, TRUE), + REG_WRAM_C_BNK_PACK(2, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_64KB, TRUE), + REG_WRAM_C_BNK_PACK(3, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_96KB, TRUE), + REG_WRAM_C_BNK_PACK(4, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_128KB, TRUE), + REG_WRAM_C_BNK_PACK(5, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_160KB, TRUE), + REG_WRAM_C_BNK_PACK(6, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_192KB, TRUE), + REG_WRAM_C_BNK_PACK(7, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_224KB, TRUE), + }, + REG_WRAM_A_MAP_PACK(MI_WRAM_MAP_NULL, + MI_WRAM_MAP_NULL, + MI_WRAM_A_IMG_128KB + ), + REG_WRAM_B_MAP_PACK(MI_WRAM_MAP_NULL, + MI_WRAM_MAP_NULL, + MI_WRAM_B_IMG_128KB + ), + REG_WRAM_C_MAP_PACK(HW_WRAM_AREA_HALF, + HW_WRAM_AREA_HALF + 0x00020000, + MI_WRAM_C_IMG_128KB + ), + + // ARM7 + REG_WRAM_A_MAP_PACK(HW_WRAM_AREA_HALF, + HW_WRAM_AREA_HALF + 0x00020000, + MI_WRAM_A_IMG_128KB + ), + REG_WRAM_B_MAP_PACK(HW_WRAM_AREA_HALF + 0x00020000, + HW_WRAM_AREA_HALF + 0x00040000, + MI_WRAM_B_IMG_128KB + ), + REG_WRAM_C_MAP_PACK(MI_WRAM_MAP_NULL, + MI_WRAM_MAP_NULL, + MI_WRAM_C_IMG_128KB + ), + // WRAM Lock + { + 0, + 0, + 0, + }, + + // WRAM-0/1 + MI_WRAM_ARM7_ALL, + + // VRAM-C + 7, + // VRAM-D + 7, +}; diff --git a/build/tools/makenandfirm/wram_regs.c b/build/tools/makenandfirm/wram_regs.c new file mode 100644 index 0000000..5f09a86 --- /dev/null +++ b/build/tools/makenandfirm/wram_regs.c @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenandfirm + File: wram_regs.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include "format_rom.h" +//#define SDK_ASM +#define NITRO_TYPES_H_ +#include +#include +#include + + +MIHeader_WramRegs wram_regs_init = +{ + // ARM9 + { + REG_MI_MBK_A0_FIELD( 1, MI_WRAM_A_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_A1_FIELD( 1, MI_WRAM_A_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_A2_FIELD( 1, MI_WRAM_A_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_A3_FIELD( 1, MI_WRAM_A_OFFSET_192KB, MI_WRAM_ARM7 ), + }, + { + REG_MI_MBK_B0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM7 ), + }, + { + REG_MI_MBK_C0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM9 ), + }, + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, MI_WRAM_MAP_NULL ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, MI_WRAM_MAP_NULL ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, HW_WRAM_AREA_HALF + 0x00020000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, HW_WRAM_AREA_HALF ) + ), + + // ARM7 + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, HW_WRAM_AREA_HALF + 0x00020000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, HW_WRAM_AREA_HALF ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, HW_WRAM_AREA_HALF + 0x00040000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, HW_WRAM_AREA_HALF + 0x00020000 ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, MI_WRAM_MAP_NULL ) + ), + + // WRAM Lock + { + 0, + 0, + 0, + }, + + // WRAM-0/1 + 3, + + // VRAM-C + 7, + // VRAM-D + 7, +}; + diff --git a/build/tools/makenorfirm/Makefile b/build/tools/makenorfirm/Makefile new file mode 100644 index 0000000..60b4ecd --- /dev/null +++ b/build/tools/makenorfirm/Makefile @@ -0,0 +1,151 @@ +#! make -f +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makenorfirm +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#--------------------------------------------------------------------------- + +TARGET_PLATFORM = TWL + +SUPPORT_ECC = 0 + +ifeq ($(SUPPORT_ECC),1) +ECC_SRCDIR = ../../libraries/acsign_ecc/common \ + ../../libraries/acsign_ecc/common/algae/common/ecc \ + ../../libraries/acsign_ecc/common/algae/cmp \ + ../../libraries/acsign_ecc/common/algae/ecsource \ + +ECC_INCDIR = ../../libraries/acsign_ecc/include \ + ../../libraries/acsign_ecc/common/algae/include \ + ../../libraries/acsign_ecc/common/algae/common/include \ + +ECC_SRCS = acsign_ecc.c acsign_cryptoc.c \ + \ + cmparith.c cmpbits.c cmpcnv.c cmpdiv.c cmpmem.c \ + cmpmod.c cmpmuldv.c cmpspprt.c cmpsqr.c cmpvectr.c \ + computem.c ecfpatbl.c ecfpsmul.c \ + spcprime.c secfpcom.c \ + \ + p224v1.c p224v1a.c \ + +ECC_DEFS = -DRSA_PROTOTYPES=RSA_ENABLED \ + -DRCOM_BUILD=RSA_ENABLED -DRSA_FAST_INVERSE=RSA_ENABLED \ + -DRSA_STD_MEM_FUNCS=RSA_ENABLED -DRSA_STD_ALLOC_FUNCS=RSA_ENABLED \ +else +ECC_SRCDIR = +ECC_INCDIR = +ECC_SRCS = +ECC_DEFS = +endif + +SRCDIR += ../acsign $(ECC_SRCDIR) +INCDIR += ../acsign/include $(ECC_INCDIR) $(ECC_SRCDIR) + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +TARGETS = makenorfirm.exe + +SOURCES_C = makenorfirm.c \ + out_norfirm.c \ + misc.c \ + path.c \ + defval.c \ + compress.c \ + wram_regs.c \ + acsign.c \ + acsign_nor.c \ + aes2.c \ + $(ECC_SRCS) + +SOURCES = $(SORUCES_C) + +OBJECTS = $(SOURCES_C:.c=.o) + +HEADERS = format_nlist.h \ + makenorfirm.h \ + path.h \ + format_rom.h \ + misc.h \ + defval.h \ + compress.h \ + +MACROS += -DSMALL_CODE_SIZE \ + -DSTANDALONE \ + -DOPT_32_BIT \ + -DNO_SPLIT \ + -DNO_FP_API \ + -DNO_R_DIAG \ + $(ECC_DEFS) + +INSTALL_DIR = $(FIRM_INSTALL_TOOLSDIR)/bin +INSTALL_TARGETS = $(TARGETS) + +LDIRT_CLEAN = $(OBJECTS) $(TARGETS) version.h + + +VPATH = $(SRCDIR) +TWL_INCDIR := $(TWL_INCDIR) $(addprefix -I,$(INCDIR)) $(addprefix -I,$(FIRM_INCDIR)) + +include $(TWLSDK_ROOT)/build/buildtools/twl/modulerules.x86 + +#---------------------------------------------------------------------------- +# build +#---------------------------------------------------------------------------- +do-build: $(TARGETS) + +$(TARGETS): $(OBJECTS) + $(CC_X86) $+ -o $@ + +makenorfirm.o: makenorfirm.c makenorfirm.h format_rom.h path.h version.h +out_norfirm.o: out_norfirm.c misc.h format_rom.h format_nlist.h format_sign.h elf.h compress.h \ + $(FIRM_INCDIR)/firm/format/sign.h \ + $(FIRM_INCDIR)/firm/format/wram_regs.h \ + $(FIRM_INCDIR)/firm/format/norfirm.h \ + +misc.o: misc.c misc.h +path.o: path.c path.h +compress.o: compress.c compress.h +wram_regs.o: wram_regs.c +acsign.o: acsign.c ../acsign/include/acsign.h +acsign_nor.o: acsign_nor.c format_sign.h \ + $(FIRM_INCDIR)/firm/format/sign.h \ + $(FIRM_INCDIR)/firm/format/wram_regs.h \ + $(FIRM_INCDIR)/firm/format/norfirm.h \ + +aes2.o: aes2.c aes2.h + +$(FIRM_INCDIR)/firm/format/sign.h: +$(FIRM_INCDIR)/firm/format/wram_regs.h: +$(FIRM_INCDIR)/firm/format/norfirm.h: +format_nlist.h: +format_rom.h: +makenorfirm.h: +acsign.h: +acsign_nor.h: +path.h: + +# avoid to warning message +misc.o:WARNING += -Wno-format-y2k + +# + +version.h: $(SOURCES) $(HEADERS) + @for i in $^ ; \ + do \ + date -r $$i +'#define SDK_DATE_OF_LATEST_FILE %Y%m%dUL'; \ + done | sort | tail -1 > $@ + +test: path.c misc.c + $(CC_X86) -DTEST $+ -o $@ diff --git a/build/tools/makenorfirm/compress.c b/build/tools/makenorfirm/compress.c new file mode 100644 index 0000000..0d7a555 --- /dev/null +++ b/build/tools/makenorfirm/compress.c @@ -0,0 +1,293 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: compress.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include // atoi() +#include // strcmp() +#include // isprint() +#include // chdir() +#include +#include // UCHAR_MAX +#include +#include // stat() +#include "elf.h" +#include "misc.h" +#include "defval.h" +#include "format_rom.h" +#include "format_nlist.h" +#include "makenorfirm.h" + +//#define ADD_HEADER + +#define DIFF_CODE_HEADER (0x80) +#define RL_CODE_HEADER (0x30) +#define LZ_CODE_HEADER (0x10) +#define HUFF_CODE_HEADER (0x20) +#define CODE_HEADER_MASK (0xF0) + +//=========================================================================== +// LZ77k +//=========================================================================== +static u8 SearchLZ(const u8 *nextp, u32 remainSize, u16 *offset); + +static u16 windowPos; +static u16 windowLen; + +static s16 LZOffsetTable[4096]; +static s16 LZByteTable[256]; +static s16 LZEndTable[256]; + + +static void LZInitTable(void) +{ + u16 i; + + for (i = 0; i < 256; i++) + { + LZByteTable[i] = -1; + LZEndTable[i] = -1; + } + windowPos = 0; + windowLen = 0; +} + +static void SlideByte(const u8 *srcp) +{ + s16 offset; + u8 in_data = *srcp; + u16 insert_offset; + + if (windowLen == 4096) + { + u8 out_data = *(srcp - 4096); + if ((LZByteTable[out_data] = LZOffsetTable[LZByteTable[out_data]]) == -1) + { + LZEndTable[out_data] = -1; + } + insert_offset = windowPos; + } + else + { + insert_offset = windowLen; + } + + offset = LZEndTable[in_data]; + if (offset == -1) + { + LZByteTable[in_data] = insert_offset; + } + else + { + LZOffsetTable[offset] = insert_offset; + } + LZEndTable[in_data] = insert_offset; + LZOffsetTable[insert_offset] = -1; + + if (windowLen == 4096) + { + windowPos = (u16)((windowPos + 1) % 0x1000); + } + else + { + windowLen++; + } +} + +static void LZSlide(const u8 *srcp, u32 n) +{ + u32 i; + + for (i = 0; i < n; i++) + { + SlideByte(srcp++); + } +} + +/*---------------------------------------------------------------------------* + Name: MI_CompressLZ + + Description: LZ77ksȂ֐ + + Arguments: srcp kf[^ւ̃|C^ + size kf[^TCY + dstp kf[^ւ̃|C^ + kf[^傫TCỸobt@KvłB + + Returns: k̃f[^TCYB + k̃f[^kO傫Ȃꍇɂ͈k𒆒f0Ԃ܂B + *---------------------------------------------------------------------------*/ +u32 LZCompWrite(u8 *srcp, u32 size, u8 *dstp, int boundary) +{ + u32 LZDstCount; // kf[^̃oCg + u8 LZCompFlags; // k̗LtOn + u8 *LZCompFlagsp; // LZCompFlags i[郁̈|Cg + u16 lastOffset; // vf[^܂ł̃ItZbg (̎_ł̍Œvf[^) + u8 lastLength; // vf[^ (̎_ł̍Œvf[^) + u8 i; + u32 dstMax; + +#ifdef ADD_HEADER + *(u32 *)dstp = size << 8 | LZ_CODE_HEADER; // f[^Ewb_ + dstp += 4; +#endif + LZDstCount = 4; + dstMax = size; + LZInitTable(); + + while (size > 0) + { + LZCompFlags = 0; + LZCompFlagsp = dstp++; // tOn̊i[ + LZDstCount++; + + // tOn8rbgf[^ƂĊi[邽߁A8񃋁[v + for (i = 0; i < 8; i++) + { + LZCompFlags <<= 1; // (i=0) ͓ɈӖ͂Ȃ + if (size <= 0) + { + // I[ɗꍇ̓tOŌ܂ŃVtgĂI + continue; + } + + if ((lastLength = SearchLZ(srcp, size, &lastOffset))) + { + // k”\ȏꍇ̓tO𗧂Ă + LZCompFlags |= 0x1; + + // ItZbg͏4rbgƉ8rbgɕĊi[ + *dstp++ = (u8)((lastLength - 3) << 4 | (lastOffset - 1) >> 8); + *dstp++ = (u8)((lastOffset - 1) & 0xff); + LZDstCount += 2; + LZSlide(srcp, lastLength); + srcp += lastLength; + size -= lastLength; + } + else + { + // kȂ + LZSlide(srcp, 1); + *dstp++ = *srcp++; + size--; + LZDstCount++; + } + } // 8񃋁[vI + *LZCompFlagsp = LZCompFlags; // tOni[ + } + + // 16oCgEACg + // ACgpf[^0 ̓f[^TCYɊ܂߂ + i = 0; + while (LZDstCount & (boundary - 1)) +// while ((LZDstCount + i) & 0x3) + { + *dstp++ = 0; + LZDstCount++; + i++; + } + + return LZDstCount; +} + +//-------------------------------------------------------- +// LZ77kŃXCh̒Œv܂B +// Arguments: startp f[^̊Jnʒu|C^ +// nextp Jnf[^̃|C^ +// remainSize cf[^TCY +// offset vItZbgi[̈ւ̃|C^ +// Return : v񂪌‚ꍇ TRUE +// ‚Ȃꍇ FALSE +//-------------------------------------------------------- +static u8 SearchLZ(const u8 *nextp, u32 remainSize, u16 *offset) +{ + const u8 *searchp; + const u8 *headp, *searchHeadp; + u16 maxOffset; + u8 maxLength = 2; + u8 tmpLength; + s32 w_offset; + + if (remainSize < 3) + { + return 0; + } + + w_offset = LZByteTable[*nextp]; + + while (w_offset != -1) + { + if (w_offset < windowPos) + { + searchp = nextp - windowPos + w_offset; + } + else + { + searchp = nextp - windowLen - windowPos + w_offset; + } + + /* ĂǂA͂ɍ */ + if (*(searchp + 1) != *(nextp + 1) || *(searchp + 2) != *(nextp + 2)) + { + w_offset = LZOffsetTable[w_offset]; + continue; + } + + if (nextp - searchp < 2) + { + // VRAM2oCgANZXȂ̂ (VRAMf[^ǂݏoꍇ邽)A + // Ώۃf[^2oCgÕf[^ɂȂ΂ȂȂB + // + // ItZbg12rbgŊi[邽߁A4096ȉ + break; + } + tmpLength = 3; + searchHeadp = searchp + 3; + headp = nextp + 3; + + while (((u32)(headp - nextp) < remainSize) && (*headp == *searchHeadp)) + { + headp++; + searchHeadp++; + tmpLength++; + + // f[^4rbgŊi[邽߁A18ȉ (3̉ʂ͂) + if (tmpLength == (0xF + 3)) + { + break; + } + } + if (tmpLength > maxLength) + { + // ő咷ItZbgXV + maxLength = tmpLength; + maxOffset = (u16)(nextp - searchp); + if (maxLength == (0xF + 3)) + { + // vőȂ̂ŁAIB + break; + } + } + w_offset = LZOffsetTable[w_offset]; + } + + if (maxLength < 3) + { + return 0; + } + *offset = maxOffset; + return maxLength; +} + diff --git a/build/tools/makenorfirm/compress.h b/build/tools/makenorfirm/compress.h new file mode 100644 index 0000000..e3dc58f --- /dev/null +++ b/build/tools/makenorfirm/compress.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: compress.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef COMPRESS_H_ +#define COMPRESS_H_ + +#include "misc.h" + + +/*---------------------------------------------------------------------------* + Name: MI_CompressLZ + + Description: LZ77ksȂ֐ + + Arguments: srcp kf[^ւ̃|C^ + size kf[^TCY + dstp kf[^ւ̃|C^ + kf[^傫TCỸobt@KvłB + + Returns: k̃f[^TCYB + *---------------------------------------------------------------------------*/ +u32 LZCompWrite(u8 *srcp, u32 size, u8 *dstp, int boundary); + + +#endif //COMPRESS_H_ diff --git a/build/tools/makenorfirm/defval.c b/build/tools/makenorfirm/defval.c new file mode 100644 index 0000000..679fb0e --- /dev/null +++ b/build/tools/makenorfirm/defval.c @@ -0,0 +1,315 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makerom + File: defval.c + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: defval.c,v $ + Revision 1.10 2006/01/18 02:11:19 kitase_hirotake + do-indent + + Revision 1.9 2005/02/28 05:26:03 yosizaki + do-indent. + + Revision 1.8 2004/08/05 13:50:13 yasu + Support -M option + + Revision 1.7 2004/06/29 04:55:40 yasu + Use VBuffer to resolve variables + + Revision 1.6 2004/06/23 07:51:02 yasu + fix a bug as illegal memory freeing at ResolveDefVal() + + Revision 1.5 2004/05/27 00:40:49 yasu + care also about current directory (dot ".") + + Revision 1.4 2004/05/27 00:25:46 yasu + care about double-dots ".." for defvalue option :r, :e + + Revision 1.3 2004/05/27 00:11:19 yasu + fix a error when searching a "dot" of file extension + + Revision 1.2 2004/05/26 12:02:47 yasu + support :h, :t, :r, :e option for variable name + + Revision 1.1 2004/03/26 05:06:45 yasu + support variables like as -DNAME=VALUE + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +#include // getenv() +#include // strcasecmp() +#include // getopt() +#include "misc.h" +#include "defval.h" + +typedef struct tValdef +{ + struct tValdef *next; + char *name; + char *value; +} +tValdef; + +tValdef *valdef_top = NULL; + + +// +// Add new define value via file +// +// opt : "DEFINE=VALUE" +// +BOOL AddDefValFromFile(char *filename) +{ + char *buffer; + int buffer_size; + int read_size; + FILE *fp; + + if (filename[0] == '-' && filename[1] == '\0') + { + fp = stdin; + } + else if (NULL == (fp = fopen(filename, "rb"))) + { + fprintf(stderr, "Cannot open file \"%s\".\n", filename); + return FALSE; + } + + buffer_size = DEFVAL_DEFAULT_BUFFER_SIZE; + + if (NULL == (buffer = malloc(buffer_size))) + { + fprintf(stderr, "Cannot allocate memory.\n"); + return FALSE; + } + + read_size = 0; + + while (NULL != fgets(buffer + read_size, buffer_size - read_size, fp)) + { + read_size = strlen(buffer); + + if (read_size == buffer_size - 1 && buffer[read_size - 1] != '\n') + { + buffer_size *= 2; + + if (NULL == (buffer = realloc(buffer, buffer_size))) + { + fprintf(stderr, "Cannot allocate memory.\n"); + return FALSE; + } + continue; + } + + AddDefVal(buffer); + read_size = 0; + } + + if (fp != stdin) + { + fclose(fp); + } + free(buffer); + + return TRUE; +} + + +// +// Add new define value +// +// opt : "DEFINE=VALUE" +// +void AddDefVal(char *opt) +{ + int i; + tValdef *t; + + for (i = 0;; i++) + { + if ('=' == opt[i] || '\0' == opt[i]) + { + break; + } + } + + if (i > 0) + { + t = Alloc(sizeof(tValdef)); + t->name = strncpy(Alloc(i + 1), opt, i); + t->name[i] = '\0'; + + if (opt[i] == '=') + { + i++; + } + t->value = strdup(opt + i); + + t->next = valdef_top; + valdef_top = t; + + debug_printf("DEFINE:$(%s)=\"%s\"\n", t->name, t->value); + } + return; +} + +// +// Search define value +// +// Return: value of specified name +// +char *SearchDefVal(char *name) +{ + tValdef *t; + + for (t = valdef_top; t; t = t->next) + { + if (!strcmp(t->name, name)) + { + return t->value; + } + } + + return getenv(name); +} + + +// +// Search define value and Modify it by : option +// +// Return: duplicated value of specified name modified by :x option +// +char *SearchDefValWithOption(char *name) +{ + int len_name = strlen(name); + char *value; + char option = '\0'; + + if (len_name > 2 && name[len_name - 2] == ':') + { + name[len_name - 2] = '\0'; + option = name[len_name - 1]; + } + + value = SearchDefVal(name); + + if (value) + { + int value_len = strlen(value); + int col_dot = value_len; + int col_filename = 0; + int i; + + for (i = 0; i < value_len; i++) + { + switch (value[i]) + { + case '.': + if (col_filename == i && + (value[i + 1] == '\0' || (value[i + 1] == '.' && value[i + 2] == '\0'))) + { + i = value_len; // exit loop if last entry is . or .. + } + else + { + col_dot = i; // Save the last dot column + } + break; + + case '/': + case '\\': + case ':': + col_filename = i + 1; // Save the last filename + col_dot = value_len; // Reset dot position + break; + + default: + ; + } + } + + switch (option) + { + case 'h': // Dirname with the last slash + value = strdup(value); + value[col_filename] = '\0'; + break; + + case 't': // Filename + value = strdup(value + col_filename); + break; + + case 'r': // All without . file extension + value = strdup(value); + value[col_dot] = '\0'; + break; + + case 'e': // File extension + value = strdup(value + col_dot + 1); + break; + + default: + value = strdup(value); + } + } + return value; +} + + +// +// Resolve define value +// +// Return: new string +// +char *ResolveDefVal(char *str) +{ + int i, j; + char *val; + VBuffer buf; + + InitVBuffer(&buf); + + for (i = 0; '\0' != str[i]; i++) + { + // search $(XXX) + if ('$' == str[i] && '(' == str[i + 1]) + { + for (j = i + 2; '\0' != str[j]; j++) + { + if (')' == str[j]) + { + str[j] = '\0'; + + // get value of XXX + val = SearchDefValWithOption(&str[i + 2]); + + // copy value of XXX + if (val) + { + char *s = val; + + while (*s) + { + PutVBuffer(&buf, *s); + s++; + } + free(val); + } + i = j; + goto next; + } + } + } + PutVBuffer(&buf, str[i]); + next:; + } + return GetVBuffer(&buf); // pass allocated buffer, should be freed by caller +} diff --git a/build/tools/makenorfirm/defval.h b/build/tools/makenorfirm/defval.h new file mode 100644 index 0000000..7135510 --- /dev/null +++ b/build/tools/makenorfirm/defval.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makerom + File: defval.h + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: defval.h,v $ + Revision 1.4 2006/01/18 02:11:19 kitase_hirotake + do-indent + + Revision 1.3 2005/02/28 05:26:03 yosizaki + do-indent. + + Revision 1.2 2004/08/05 13:50:13 yasu + Support -M option + + Revision 1.1 2004/03/26 05:06:45 yasu + support variables like as -DNAME=VALUE + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef DEFVAL_H_ +#define DEFVAL_H_ + +#define DEFVAL_DEFAULT_BUFFER_SIZE (1024) + +BOOL AddDefValFromFile(char *filename); +void AddDefVal(char *opt); +char *SearchDefVal(char *name); +char *ResolveDefVal(char *str); + +#endif //DEFVAL_H_ diff --git a/build/tools/makenorfirm/elf.h b/build/tools/makenorfirm/elf.h new file mode 100644 index 0000000..c360cd3 --- /dev/null +++ b/build/tools/makenorfirm/elf.h @@ -0,0 +1,431 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - ELF + File: elf.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + *---------------------------------------------------------------------------*/ + +#ifndef ELF_H_ +#define ELF_H_ + +#include "misc.h" + +/*--------------------------------------------------------- + ^` + --------------------------------------------------------*/ +typedef u32 Elf32_Addr; /* size:4, align:4 Unsigned program address */ +typedef u16 Elf32_Half; /* size:2, align:2 Unsigned medium int */ +typedef u32 Elf32_Off; /* size:4, align:4 Unsigned file offset */ +typedef s32 Elf32_Sword; /* size:4, align:4 Signed large int */ +typedef u32 Elf32_Word; /* size:4, align:4 Unsigned large int */ + +/*--------------------------------------------------------- + ELF Header + --------------------------------------------------------*/ +/* e_ident̃CfbNX */ +#define EI_MAG0 0 /* File identification */ +#define EI_MAG1 1 /* File identification */ +#define EI_MAG2 2 /* File identification */ +#define EI_MAG3 3 /* File identification */ +#define EI_CLASS 4 /* File class 0=invalid, 1=32bit, 2=64bit */ +#define EI_DATA 5 /* Data encoding 0=invalid, 1=LSB, 2=MSB */ +#define EI_VERSION 6 /* File version ݂1 */ +#define EI_PAD 7 /* Start of padding bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; /* ELF̌`(Ĕzu”\, s”\Ȃ) */ + Elf32_Half e_machine; /* t@CŗvA[LeN` */ + Elf32_Word e_version; /* ELFtH[}bg̃o[Wi݂1j */ + Elf32_Addr e_entry; /* vÕGg|CgBw薳Ȃ0B */ + Elf32_Off e_phoff; /* vOwb_e[ũt@C擪̃ItZbg */ + Elf32_Off e_shoff; /* ZNVwb_e[ũt@C擪̃ItZbg */ + Elf32_Word e_flags; /* vZbTŗL̃tO */ + Elf32_Half e_ehsize; /* ELFwb_̃TCY */ + Elf32_Half e_phentsize; /* 1vOwb_̃TCY */ + Elf32_Half e_phnum; /* vOwb_̐ */ + Elf32_Half e_shentsize; /* 1ZNVwb_̃TCY */ + Elf32_Half e_shnum; /* ZNVwb_̐ */ + Elf32_Half e_shstrndx; /* ZNVe[uZNVւ̃CfbNX */ +} Elf32_Ehdr; + +/* e_ident[EI_*]̒g` */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFCLASSNONE 0 /* invalid */ +#define ELFCLASS32 1 /* ARM and Thumb processors use 32-bit ELF. */ +#define ELFCLASS64 2 +#define ELFDATANONE 0 /* invalid */ +#define ELFDATA2LSB 1 /* little-endian */ +#define ELFDATA2MSB 2 /* big-endian */ + + +/* [e_type] */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Re-locatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOPROC 0xff00 /* Processor-specific */ +#define ET_HIPROC 0xffff /* Processor-specific */ + +/* [e_machine] */ +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_860 7 +#define EM_MIPS 8 +#define EM_MIPS_RS4_BE 10 +#define EM_ARM 40 /* ARM/Thumb Architecture */ + + +/* [e_version] This member identifies the object file version.*/ +#define EV_NONE 0 /* Invalid version */ +#define EV_CURRENT 1 /* Current version */ + + +/* + ARM-specific e_flags + e_flags Field Value Meaning + EF_ARM_HASENTRY (0x02) e_entry contains a program-loader entry point + (see section 4.1.1, Entry points, below). + EF_ARM_SYMSARESORTED (0x04) Each subsection of the symbol table is sorted by symbol value + (see section 4.4.8, Symbol table order, below) + EF_ARM_DYNSYMSUSESEGIDX (0x8) Symbols in dynamic symbol tables that are defined in sections + included in program segment n have st_shndx = n + 1. + (see section 4.4.9, Dynamic symbol table entries, below). + EF_ARM_MAPSYMSFIRST (0x10) Mapping symbols precede other local symbols in the symbol table + (see section 4.4.8, Symbol table order, below). + + EF_ARM_EABIMASK (0xFF000000)(current version is 0x02000000) + This masks an 8-bit version number, the version of the ARM + EABI to which this ELF file conforms. This EABI is version 2. A + value of 0 denotes unknown conformance. +*/ +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x8 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0xFF000000 + + +/*--------------------------------------------------------- + Program headers + --------------------------------------------------------*/ +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* [p_type] */ +#define PT_NULL 0 /* gȂGgŁÃo̒l̈Ӗ͖` */ +#define PT_LOAD 1 /* sɃ[hZOg */ +#define PT_DYNAMIC 2 /* I\̔zێZOg */ +#define PT_INTERP 3 /* t@C̉߂ɎgC^v^̃pXێZOg */ +#define PT_NOTE 4 /* t@C̉߂ɂ͎gȂێZOg */ +#define PT_SHLIB 5 /* \ */ +#define PT_PHDR 6 /* vOwb_e[uivÕC[Ẅꕔłꍇ̂ݑ݁j */ +//#define PT_TLS ? /* XbhǏL̈̃ev[g */ + +#define PT_LOOS 0x60000000 /* OSŗLɗ\񂳂ꂽ̈ */ +#define PT_HIOS 0x6fffffff + +#define PT_LOPROC 0x70000000 /* vZbTŗLɗ\񂳂ꂽ̈ */ +#define PT_HIPROC 0x7fffffff + +/* [p_flags]*/ +#define PF_X 1 /*s”\*/ +#define PF_W 2 /*݉”\*/ +#define PF_R 4 /*ǂݏo”\*/ +#define PF_ARM_SB 0x10000000 /*The segment contains the location addressed by the static base*/ +#define PF_ARM_PI 0x20000000 /*The segment is position-independent*/ +#define PF_ARM_ENTRY 0x80000000 /*The segment contains the entry point*/ +#define PF_MASKPROC 0xf0000000 + + +/*--------------------------------------------------------- + Section headers + --------------------------------------------------------*/ +typedef struct { + Elf32_Word sh_name; /*ZNVwb_e[uZNṼCfbNX*/ + Elf32_Word sh_type; /* ^CviL`QƁj */ + Elf32_Word sh_flags; + Elf32_Addr sh_addr; /* */ + Elf32_Off sh_offset; /* t@C̐擪̃ItZbg */ + Elf32_Word sh_size; /* oCgPʂ̃TCY */ + Elf32_Word sh_link; /* sh_typeɂĒl̈Ӗς */ + Elf32_Word sh_info; /* sh_typeɂĒl̈Ӗς */ + Elf32_Word sh_addralign; /* ACg(0or1ŐȂ,44ByteAlign) */ + Elf32_Word sh_entsize; /* ŒTCỸGge[uꍇA1vf̃TCY */ +} Elf32_Shdr; + +/* sh_addr mod sh_addralign = 0 łȂ΂ȂȂ */ + +/* Section Types, [sh_type] */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + + +/* [sh_flags] */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 +/* ARM-EABI-specific */ +#define SHF_ENTRYSECT 0x10000000 /* The section contains an entry point. */ +#define SHF_COMDEF 0x80000000 /* The section may be multiply defined in the input to a link step. */ +/* others */ +#define SHF_LINK_ORDER 0x80 + +/*ZNVCfbNX*/ +//Sym->st_shndxȂ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + + +//̓wb_łȂ̃f[^\ + +/*--------------------------------------------------------- + Symbol Table Entry + --------------------------------------------------------*/ +typedef struct { + Elf32_Word st_name; /* V{e[ũCfbNX */ + Elf32_Addr st_value; /* 炭֘AZNVł̃ItZbgl */ + Elf32_Word st_size; /* TCYȂAsȏꍇ 0 */ + unsigned char st_info; /* oCh ^Cv */ + unsigned char st_other; /* ݂ 0 */ + Elf32_Half st_shndx; /* ֘AZNVwb_e[ũCfbNX */ +} Elf32_Sym; + + +/* st_info */ +#define ELF32_ST_BIND(i) ((i)>>4) +#define ELF32_ST_TYPE(i) ((i)&0xf) +#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + +/* st_info BIND */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +/* st_info TYPE */ +#define STT_NOTYPE 0 /*`*/ +#define STT_OBJECT 1 /*f[^IuWFNg*/ +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + + +/*--------------------------------------------------------- + Relocation Entry + --------------------------------------------------------*/ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) + + +/* r_info TYPE */ +#define R_ARM_NONE 0 /* Any No relocation. Encodes dependencies between sections. */ +#define R_ARM_PC24 1 /* ARM B/BL S . P + A */ +#define R_ARM_ABS32 2 /* 32-bit word S + A */ +#define R_ARM_REL32 3 /* 32-bit word S . P + A */ +#define R_ARM_PC13 4 /* ARM LDR r, [pc,c] S . P + A */ +#define R_ARM_ABS16 5 /* 16-bit half-word S + A */ +#define R_ARM_ABS12 6 /* ARM LDR/STR S + A */ +#define R_ARM_THM_ABS5 7 /* Thumb LDR/STR S + A */ +#define R_ARM_ABS8 8 /* 8-bit byte S + A */ +#define R_ARM_SBREL32 9 /* 32-bit word S . B + A */ +#define R_ARM_THM_PC22 10 /* Thumb BL pair S . P+ A */ +#define R_ARM_THM_PC8 11 /* Thumb LDR r, [pc,c] S . P + A */ +#define R_ARM_AMP_VCALL9 12 /* AMP VCALL Obsolete.SA-1500 only. */ +#define R_ARM_SWI24 13 /* ARM SWI S + A */ +#define R_ARM_THM_SWI8 14 /* Thumb SWI S + A */ +#define R_ARM_XPC25 15 /* ARM BLX S . P+ A */ +#define R_ARM_THM_XPC22 16 /* Thumb BLX pair S . P+ A */ + +/* 17-31, reserved to ARM Linux */ +//17-19 Reserved to ARM LINUX +#define R_ARM_COPY 20 /* 32 bit word Copy symbol at dynamic link time. */ +#define R_ARM_GLOB_DAT 21 /* 32 bit word Create GOT entry. */ +#define R_ARM_JUMP_SLOT 22 /* 32 bit word Create PLT entry. */ +#define R_ARM_RELATIVE 23 /* 32 bit word Adjust by program base. */ +#define R_ARM_GOTOFF 24 /* 32 bit word Offset relative to start of GOT. */ +#define R_ARM_GOTPC 25 /* 32 bit word Insert address of GOT. */ +#define R_ARM_GOT32 26 /* 32 bit word Entry in GOT. */ +#define R_ARM_PLT32 27 /* ARM BL Entry in PLT. */ + +/* 28-31 Reserved to ARM LINUX */ +#define R_ARM_ALU_PCREL_7_0 32 /* ARM ADD/SUB (S . P + A) & 0x000000FF */ +#define R_ARM_ALU_PCREL_15_8 33 /* ARM ADD/SUB (S . P + A) & 0x0000FF00 */ +#define R_ARM_ALU_PCREL_23_15 34 /* ARM ADD/SUB (S . P + A) & 0x00FF0000 */ +#define R_ARM_LDR_SBREL_11_0 35 /* ARM LDR/STR (S . B + A) & 0x00000FFF */ +#define R_ARM_ALU_SBREL_19_12 36 /* ARM ADD/SUB (S . B + A) & 0x000FF000 */ +#define R_ARM_ALU_SBREL_27_20 37 /* ARM ADD/SUB (S . B + A) & 0x0FF00000 */ + +#define R_ARM_TARGET1 38 +#define R_ARM_ROSEGREL32 39 +#define R_ARM_V4BX 40 +#define R_ARM_TARGET2 41 +#define R_ARM_PREL31 42 + +/* 96-111, reserved to ARM g++ */ +#define R_ARM_GNU_VTENTRY 100 /* 32 bit word Record C++ vtable entry. */ +#define R_ARM_GNU_VTINHERIT 101 /* 32 bit word Record C++ member usage. */ +#define R_ARM_THM_PC11 102 /* Thumb B S . P + A */ +#define R_ARM_THM_PC9 103 /* Thumb B S . P + A */ + +/* 112-127, reserved for private experiments */ + +/* 128-248, reserved to ARM */ +#define R_ARM_RXPC25 249 /* ARM BLX (S . P) + A #define For calls between program segments. */ +#define R_ARM_RSBREL32 250 /* Word (S . SB) + A For an offset from SB, the static base. */ +#define R_ARM_THM_RPC22 251 /* Thumb BL/BLX pair (S . P) + A For calls between program segments. */ +#define R_ARM_RREL32 252 /* Word (S . P) + A For on offset between two segments. */ +#define R_ARM_RABS32 253 /* Word S + A For the address of a location in the target segment. */ +#define R_ARM_RPC24 254 /* ARM B/BL (S . P) + A For calls between program segments. */ +#define R_ARM_RBASE 255 /* None None.Identifies the segment being relocated by the following + relocation directives. The ARM EABI poses two problems for relocating + executables and shared objects encoded in */ + + +// shirait +#define R_ARM_LDR_PC_G0 4 //LDR + +#define R_ARM_ABS12 6 //LDR, STR + +#define R_ARM_THM_CALL 10 //R_ARM_THM_PC22Ɠ + +#define R_ARM_CALL 28 //BL/BLX +#define R_ARM_JUMP24 29 //B/BL +#define R_ARM_THM_JUMP24 30 + +#define R_ARM_MOVW_ABS_NC 43 //MOVW +#define R_ARM_MOVT_ABS 44 //MOVT +#define R_ARM_MOVW_PREL_NC 45 //MOVW +#define R_ARM_MOVT_PREL 46 //MOVT + +#define R_ARM_ALU_PC_G0_NC 57 //ADD, SUB +#define R_ARM_ALU_PC_G0 58 //ADD, SUB +#define R_ARM_ALU_PC_G1_NC 59 //ADD, SUB +#define R_ARM_ALU_PC_G1 60 //ADD, SUB +#define R_ARM_ALU_PC_G2 61 //ADD, SUB +#define R_ARM_LDR_PC_G1 62 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_PC_G2 63 //LDR, STR, LDRB, STRB +#define R_ARM_LDRS_PC_G0 64 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_PC_G1 65 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_PC_G2 66 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDC_PC_G0 67 //LDC, STC +#define R_ARM_LDC_PC_G1 68 //LDC, STC +#define R_ARM_LDC_PC_G2 69 //LDC, STC +#define R_ARM_ALU_SB_G0_NC 70 //ADD, SUB +#define R_ARM_ALU_SB_G0 71 //ADD, SUB +#define R_ARM_ALU_SB_G1_NC 72 //ADD, SUB +#define R_ARM_ALU_SB_G1 73 //ADD, SUB +#define R_ARM_ALU_SB_G2 74 //ADD, SUB +#define R_ARM_LDR_SB_G0 75 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_SB_G1 76 //LDR, STR, LDRB, STRB +#define R_ARM_LDR_SB_G2 77 //LDR, STR, LDRB, STRB +#define R_ARM_LDRS_SB_G0 78 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_SB_G1 79 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDRS_SB_G2 80 //LDRD, STRD, LDRH, STRH, LDRSH, LDRSB +#define R_ARM_LDC_SB_G0 81 //LDC, STC +#define R_ARM_LDC_SB_G1 82 //LDC, STC +#define R_ARM_LDC_SB_G2 83 //LDC, STC +#define R_ARM_MOVW_BREL_NC 84 //MOVW +#define R_ARM_MOVT_BREL 85 //MOVT +#define R_ARM_MOVW_BREL 86 //MOVW + +#define R_ARM_GOT_BREL12 97 //LDR +#define R_ARM_GOTOFF12 98 //LDR, STR + +#define R_ARM_TLS_LDO12 109 //LDR, STR +#define R_ARM_TLS_LE12 110 //LDR, STR +#define R_ARM_TLS_TE12GP 111 //LDR + + + +/*--------------------------------------------------------- + Dynamic Section elf_v1.2 + --------------------------------------------------------*/ +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + + +/* Additional symbol types for Thumb. */ +#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ +#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ + + + + + + + + + +/*--------------------------------------------------------- + ELFwb_ǂݏo + --------------------------------------------------------*/ +void *ELF_LoadELFHeader(const void *buf, Elf32_Ehdr *ehdr); + + + +#endif /* ELF_H_ */ + diff --git a/build/tools/makenorfirm/format_nlist.h b/build/tools/makenorfirm/format_nlist.h new file mode 100644 index 0000000..6e5ba82 --- /dev/null +++ b/build/tools/makenorfirm/format_nlist.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: format_nlist.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FORMAT_NLIST_H_ +#define FORMAT_NLIST_H_ + +#include +#include "misc.h" +#include "path.h" + +#define SPECFILE_MAGIC_ID "#NORSF" + +#define CRC16_INIT_VALUE 0xffff + +//--------------------------------------------------------------------------- +// Banner Spec File +//--------------------------------------------------------------------------- + +// Command List +typedef struct +{ + char *string; + BOOL (*funcp) (char *, int num); + +} +tCommandDesc; + + +// F Command +typedef struct +{ + u32 offsetStart; + u32 offsetEnd; + u32 padding; + char fullPathSrc[FILENAME_MAX]; + +} +tFileDesc; + + +#endif // FORMAT_NLIST_H_ diff --git a/build/tools/makenorfirm/format_rom.h b/build/tools/makenorfirm/format_rom.h new file mode 100644 index 0000000..3cb717f --- /dev/null +++ b/build/tools/makenorfirm/format_rom.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: format_rom.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FORMAT_ROM_H_ +#define FORMAT_ROM_H_ + +#include "misc.h" +#include + + +#define DEFAULT_ALIGN 16 +#define FIRM_ALIGN DEFAULT_ALIGN +#define FIRM_ALIGN_MASK (FIRM_ALIGN - 1) + +#define DEFAULT_HOSTROOT "." +#define DEFAULT_ROOT "/" + +#define DEFAULT_REJECT_1 "CVS" +#define DEFAULT_REJECT_2 "vssver.scc" + +#define FORMAT_VERSION "1.0" + +#define ENTRYNAME_MAX 127 + +#define DEFAULT_LISTFILE "default.nlf" + +#define DEFAULT_NORFIRM_SUFFIX ".nor" +#define DEFAULT_SPECFILE_SUFFIX ".norsf" + +/*===========================================================================* + * ROM FORMAT + *===========================================================================*/ + +//--------------------------------------------------------------------------- +// ROM HEADER +//--------------------------------------------------------------------------- + +#endif //FORMAT_ROM_H_ diff --git a/build/tools/makenorfirm/format_sign.h b/build/tools/makenorfirm/format_sign.h new file mode 100644 index 0000000..782a5d2 --- /dev/null +++ b/build/tools/makenorfirm/format_sign.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - SS + File: format_sign.h + + Copyright 2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_MAKENORFIRM_ACSIGN_FORMAT_H_ +#define FIRM_MAKENORFIRM_ACSIGN_FORMAT_H_ + +#include "format_rom.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_MAKENORFIRM_ACSIGN_FORMAT_H_ */ +#endif diff --git a/build/tools/makenorfirm/makenorfirm.c b/build/tools/makenorfirm/makenorfirm.c new file mode 100644 index 0000000..613efa7 --- /dev/null +++ b/build/tools/makenorfirm/makenorfirm.c @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: makenorfirm.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include +#include // strcasecmp() +#include // getopt() +#include "makenorfirm.h" +#include "format_rom.h" +#include "path.h" +#include "defval.h" +#include "version.h" + +static int makenorfirm(const char *specFile, const char *norFile); + +//--------------------------------------------------------------------------- +// Main +//--------------------------------------------------------------------------- + +int main(int argc, char *argv[]) +{ + int n; + int narg; + char *norfirmFile; + + InitAppName(argv[0]); + + while ((n = getopt(argc, argv, "D:hvpd")) != -1) + { + switch (n) + { + case 'h': + case 'v': + goto usage; + + case 'D': + AddDefVal(optarg); + break; + + case 'p': + PrintMode = TRUE; + break; + + case 'd': + DebugMode = TRUE; + break; + + default: + break; + } + } + + narg = argc - optind; + if (narg > 0) + { + // Make SpecFile->NorfirmFile + norfirmFile = + strdup(narg > + 1 ? argv[optind + 1] : ChangeSuffix(argv[optind], DEFAULT_NORFIRM_SUFFIX)); + return makenorfirm(argv[optind], norfirmFile); + } + + usage: + { + char *makenorfirm = GetAppName(); + + fprintf(stderr, + "NITRO-SDK Development Tool - %s - Make norfirm file \n" + "Build %lu\n\n" + "Usage: %s [-phv] [-DNAME=VALUE ...] SPECFILE [NORFIRMFILE]\n\n", + makenorfirm, SDK_DATE_OF_LATEST_FILE, makenorfirm); + } + return 1; +} + + +//--------------------------------------------------------------------------- +// makenorfirm +//--------------------------------------------------------------------------- + +static int makenorfirm(const char *specFile, const char *norFile) +{ + debug_printf("makenorfirm(): '%s' -> '%s'\n", specFile, norFile); + + // Check identical + if (specFile && norFile && !strcasecmp(specFile, norFile)) + { + error("norfirm spec file is identical '%s'", norFile); + return 1; + } + + return OutputNorfirmFile(specFile, norFile) ? 0 : 1; +} diff --git a/build/tools/makenorfirm/makenorfirm.h b/build/tools/makenorfirm/makenorfirm.h new file mode 100644 index 0000000..bb8eed6 --- /dev/null +++ b/build/tools/makenorfirm/makenorfirm.h @@ -0,0 +1,24 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: makenorfirm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef MAKENORFIRM_H_ +#define MAKENORFIRM_H_ + +#include "misc.h" + +BOOL OutputNorfirmFile(const char *specFile, const char *norFile); + +#endif //MAKENORFIRM_H_ diff --git a/build/tools/makenorfirm/misc.c b/build/tools/makenorfirm/misc.c new file mode 100644 index 0000000..7706d6b --- /dev/null +++ b/build/tools/makenorfirm/misc.c @@ -0,0 +1,628 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: misc.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include // calloc() +#include // free(), exit() +#include // setmode() +#include // stat() +#include // setmode() +#include // strlen() +#include // va_start(),va_end() +#include // localtime() + +#include +#include "misc.h" + +BOOL DebugMode = FALSE; +BOOL PrintMode = FALSE; +char *PubkeyFileName = NULL; + +/*---------------------------------------------------------------------------* + * File Output Utilities + * + * BOOL OpenFile( const char* filename ) + * void CloseFile( void ) + * BOOL CheckResult( void ) + * void PutBuffer( const void* ptr, int len ) + * void PutByte( u8 c ) + * void PutWord( u16 c ) + * void PutWord( u32 c ) + * void PutString( const char *str ) + *---------------------------------------------------------------------------*/ + +static FILE *OutFile = NULL; +static const char *FileName = NULL; +static BOOL Status = FALSE; + + +// +// File Open +// + +BOOL OpenFile(const char *filename) +{ + if (OutFile) + CloseFile(); + + if (filename) + { + if (NULL == (OutFile = fopen(filename, "wb+"))) + { + error("Can't write '%s'", filename); + Status = FALSE; + return FALSE; + } + } + else + { + setmode(1, O_BINARY); + OutFile = stdout; // out to console if filename == NULL + } + FileName = filename; + Status = TRUE; + + return TRUE; +} + + +// +// File Close +// + +BOOL CloseFile(void) +{ + if (OutFile) + { + if (FileName) + { + if (fclose(OutFile) == -1) + { + error("Can't close '%s'", FileName); + Status = FALSE; + } + } + else + { + setmode(1, O_TEXT); + } + } + OutFile = NULL; + + return Status; +} + + +// +// File Seek +// + +void SeekFile(long pos) +{ + if (OutFile && fseek(OutFile, pos, SEEK_SET)) + { + error("Can't seek '%s'", FileName ? FileName : ""); + CloseFile(); + Status = FALSE; + } +} + + +// +// Error Check +// + +BOOL CheckResult(void) +{ + return Status; +} + + +// +// Delete outfile +// + +void DeleteOutFile(void) +{ + // Delete outfile + if (FileName) + { + debug_printf("Delete '%s'\n", FileName); + (void)unlink(FileName); + FileName = NULL; + } + return; +} + + +// +// Buffer Output +// + +void PutBuffer(const void *ptr, int len) /* If error, close file */ +{ + if (OutFile && len != fwrite(ptr, 1, len, OutFile)) + { + error("Can't write buffer to '%s'", FileName ? FileName : ""); + CloseFile(); + Status = FALSE; + } +} + +// +// Buffer Input +// + +void GetBuffer(void *ptr, int len) /* If error, close file */ +{ + if (OutFile && len != fread(ptr, 1, len, OutFile)) + { + error("Can't read '%s'", FileName ? FileName : ""); + CloseFile(); + Status = FALSE; + } +} + +// +// Byte/Half/Word Output +// + +void PutByte(u8 c) +{ + PutBuffer(&c, 1); +} +void PutHalf(u16 c) +{ + PutBuffer(&c, 2); +} +void PutWord(u32 c) +{ + PutBuffer(&c, 4); +} +void PutString(const char *str) +{ + PutBuffer(str, strlen(str)); +} + + +// +// Printf +// + +void PrintString(const char *fmt, ...) +{ + char *buffer; + va_list va; + int nchars; + int bufsize = FILENAME_MAX; + + while (1) + { + buffer = Alloc(bufsize); + va_start(va, fmt); + nchars = vsnprintf(buffer, bufsize, fmt, va); + va_end(va); + + if (0 <= nchars && nchars < bufsize) + { + break; + } + + Free(&buffer); + bufsize *= 2; + } + + if (nchars > 0) + { + PutBuffer(buffer, nchars); + } + Free(&buffer); +} + + +/*---------------------------------------------------------------------------* + * File Read/Write Utilities + * + * int ReadFile( const char* filename, void** buffer ) + * + * Read a file to buffer allocated internally + * Return read size + * Add '\0' at tail of file for help to handle text file + * + * BOOL WriteFile( const char* filename, void** buffer, int size ) + *---------------------------------------------------------------------------*/ + +int ReadFile(const char *filename, void *filebuffer, int size) +{ + FILE *fp; + struct stat fileStat; + int fileSize, readSize; + void **buffer = (void **)filebuffer; + + /* Check file */ + if (stat(filename, &fileStat) || !S_ISREG(fileStat.st_mode)) + { + goto error; + } + fileSize = fileStat.st_size; + if (fileSize < 0) + { + goto error; + } + + /* Open file */ + fp = fopen(filename, "rb"); + if (!fp) + { + goto error; + } + + if (size && (size < fileSize)) + { + readSize = size; + } + else + { + readSize = fileSize; + } + + /* Read file */ + *buffer = Alloc(readSize + 1); /* error handle is done in Alloc() */ + /* size+1 for '\0' to handle text file */ + if (readSize != fread(*buffer, sizeof(char), readSize, fp)) + { + goto error_free_close; + } + + (*(char **)buffer)[readSize] = '\0'; /* Works as terminater if file is text file */ + + /* Close file */ + fclose(fp); + return readSize; + + error_free_close: + Free(buffer); + fclose(fp); + error: + error("Can't read '%s'", filename); + return -1; +} + + +int ReadFileWithPadding(const char *filename, void *filebuffer, int size, int boundary) +{ + FILE *fp; + struct stat fileStat; + int fileSize, readSize, padSize; + void **buffer = (void **)filebuffer; + + if (!boundary) + { + return ReadFile(filename, buffer, size); + } + + /* Check file */ + if (stat(filename, &fileStat) || !S_ISREG(fileStat.st_mode)) + { + goto error; + } + fileSize = fileStat.st_size; + if (fileSize < 0) + { + goto error; + } + + /* Open file */ + fp = fopen(filename, "rb"); + if (!fp) + { + goto error; + } + + if (size && (size < fileSize)) + { + readSize = size; + } + else + { + readSize = fileSize; + } + + padSize = (boundary - (readSize & (boundary-1))) & (boundary-1); + + /* Read file */ + *buffer = Alloc(readSize + padSize); /* error handle is done in Alloc() */ + /* size+1 for '\0' to handle text file */ + if (readSize != fread(*buffer, sizeof(char), readSize, fp)) + { + goto error_free_close; + } + + memset((char*)*buffer + readSize, 0, padSize); + + /* Close file */ + fclose(fp); + return readSize + padSize; + + error_free_close: + Free(buffer); + fclose(fp); + error: + error("Can't read '%s'", filename); + return -1; +} + + +BOOL WriteFile(const char *filename, void *buffer, int size) +{ + debug_printf("WriteFile %s\n", filename); + + (void)OpenFile(filename); + PutBuffer(buffer, size); + CloseFile(); + Free(&buffer); + return CheckResult(); +} + + +/*---------------------------------------------------------------------------* + * Time Format Utilities + * + * char* GetGMTime( const time_t time ) Show GMT + * char* GetTime( const time_t time ) Show local Time + *---------------------------------------------------------------------------*/ + +char *GetGMTime(const time_t time) +{ + static char timebuffer[32]; + strftime(timebuffer, sizeof(timebuffer), "%y/%m/%d-%H:%M:%S", gmtime(&time)); + return timebuffer; +} + + +char *GetTime(const time_t time) +{ + static char timebuffer[32]; + strftime(timebuffer, sizeof(timebuffer), "%y/%m/%d-%H:%M:%S", localtime(&time)); + return timebuffer; +} + + +/*---------------------------------------------------------------------------* + * Memory Allocation Utilities + * + * void* Alloc( size_t size ) + *---------------------------------------------------------------------------*/ + +void *Alloc(size_t size) +{ + void *t = calloc(1, size); + + if (t == NULL) + { + error("Can't allocate memory."); + exit(10); + } + return t; +} + + +void Free(void *p) +{ + void **ptr = (void **)p; + + if (*ptr) + { + free(*ptr); + (*ptr) = NULL; + } +} + + +/*---------------------------------------------------------------------------* + * VBuffer + * + * void PutVBuffer( VBuffer* vbuf, char c ) + *---------------------------------------------------------------------------*/ + +void PutVBuffer(VBuffer * vbuf, char c) +{ + int size; + char *tmp_buffer; + + if (vbuf->buffer == 0) + { + vbuf->size = VBUFFER_INITIAL_SIZE; + vbuf->buffer = Alloc(vbuf->size); // buffer is CALLOCed + } + size = strlen(vbuf->buffer); + + if (size >= vbuf->size - 1) + { + // Need buffer expansion + vbuf->size *= 2; + tmp_buffer = Alloc(vbuf->size); // buffer is CALLOCed + strcpy(tmp_buffer, vbuf->buffer); + Free(&vbuf->buffer); + vbuf->buffer = tmp_buffer; + } + vbuf->buffer[size] = c; + return; +} + +char *GetVBuffer(VBuffer * vbuf) +{ + return vbuf->buffer; +} + +void InitVBuffer(VBuffer * vbuf) +{ + vbuf->buffer = 0; + vbuf->size = 0; +} + +void FreeVBuffer(VBuffer * vbuf) +{ + Free(&vbuf->buffer); +} + + +/*---------------------------------------------------------------------------* + * File Path Utilities + * + * char* ChangeBackSlash( char* path ) + *---------------------------------------------------------------------------*/ + +char *ChangeBackSlash(char *path) +{ + char *p = path; + + while (*p) + { + if (*p == '\\') + { + *p = '/'; + } + p++; + } + return path; +} + + +/*---------------------------------------------------------------------------* + * Math + * + * u16 CalcCRC16( u16 start, u8 *data, int size ) + *---------------------------------------------------------------------------*/ + +static u16 crc16_table[16] = { + 0x0000, 0xCC01, 0xD801, 0x1400, + 0xF001, 0x3C00, 0x2800, 0xE401, + 0xA001, 0x6C00, 0x7800, 0xB401, + 0x5000, 0x9C01, 0x8801, 0x4400 +}; + +u16 CalcCRC16(u16 start, u8 *data, int size) +{ + u16 r1; + u16 total = start; + + while (size-- > 0) + { + // 4bit + r1 = crc16_table[total & 0xf]; + total = (total >> 4) & 0x0fff; + total = total ^ r1 ^ crc16_table[*data & 0xf]; + + // 4bit + r1 = crc16_table[total & 0xf]; + total = (total >> 4) & 0x0fff; + total = total ^ r1 ^ crc16_table[(*data >> 4) & 0xf]; + + data++; + } + return total; +} + + +/*---------------------------------------------------------------------------* + * for firm header + * + *---------------------------------------------------------------------------*/ + +static u8 ConvertAlign( u32 ofs ) +{ + u8 i; + + ofs /= 4; + for (i=0; i<7; i++) + { + if ( ofs & 1 ) + { + break; + } + ofs >>= 1; + } + + return i; +} + +tROMAddrConvType ConvertHeaderRamAddr( s32 p ) +{ + tROMAddrConvType retval; + + retval.align = ConvertAlign( p ); + retval.address = (u16)((p - HW_WRAM)/(4< + +typedef enum +{ + FALSE = 0, + TRUE = 1 +} +BOOL; + +typedef unsigned char u8; +typedef unsigned short int u16; +typedef unsigned long int u32; +typedef unsigned long long u64; +typedef signed char s8; +typedef signed short int s16; +typedef signed long int s32; +typedef signed long long s64; +typedef volatile u8 vu8; +typedef volatile u32 vu32; +typedef vu32 REGType32v; + + + + +#define error(...) do { fprintf(stderr, "Error: "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); } while(0) + +#define warning(...) do { fprintf(stderr, "Warning: "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); } while(0) + +BOOL OpenFile(const char *filename); +BOOL CloseFile(void); +void SeekFile(long pos); +BOOL CheckResult(void); +void DeleteOutFile(void); +void PutBuffer(const void *ptr, int len); +void GetBuffer(void *ptr, int len); +void PutByte(u8 c); +void PutHalf(u16 c); +void PutWord(u32 c); +void PutString(const char *str); +void PrintString(const char *fmt, ...); + +#define READ_ALL 0 +int ReadFile(const char *filename, void *filebuffer, int size); +int ReadFileWithPadding(const char *filename, void *filebuffer, int size, int boundary); +BOOL WriteFile(const char *filename, void *buffer, int size); + +char *GetGMTime(const time_t time); +char *GetTime(const time_t time); + +void *Alloc(size_t size); +void Free(void *p); + +typedef struct +{ + char *buffer; + int size; +} +VBuffer; + +#define VBUFFER_INITIAL_SIZE 1024 +void InitVBuffer(VBuffer * vbuf); +void FreeVBuffer(VBuffer * vbuf); +void PutVBuffer(VBuffer * vbuf, char c); +char *GetVBuffer(VBuffer * vbuf); + +char *ChangeBackSlash(char *path); + +u16 CalcCRC16(u16 start, u8 *data, int size); +const char *WrapNull(const char *str); + +typedef struct +{ + u16 address; + u8 align; +} +tROMAddrConvType; + +tROMAddrConvType ConvertHeaderRamAddr( s32 p ); +tROMAddrConvType ConvertHeaderRomOffset( s32 p ); +u16 ConvertHeaderRomOffsetAlign( s32 p, u32 align ); + +typedef union +{ + struct + { + u32 sign:1; + u32 header_hash:1; + u32 arm9_hash:1; + u32 arm7_hash:1; + u32 hash_table_hash:1; + u32 final_hash:1; + u32 header_footer:1; + u32 wl_check:1; + } + e; + u32 raw; +} +tErrorFlags; + +extern BOOL DebugMode; +extern BOOL PrintMode; +extern char *PubkeyFileName; +void debug_printf(const char *str, ...); +void debug_printf2(const char *str, ...); + +#endif //MISC_H_ diff --git a/build/tools/makenorfirm/out_norfirm.c b/build/tools/makenorfirm/out_norfirm.c new file mode 100644 index 0000000..d2416e0 --- /dev/null +++ b/build/tools/makenorfirm/out_norfirm.c @@ -0,0 +1,984 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: out_norfirm.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include // atoi() +#include // strcmp() +#include // isprint() +#include // chdir() +#include +#include // UCHAR_MAX +#include +#include // stat() +#include "elf.h" +#include "misc.h" +#include "defval.h" +#include "format_rom.h" +#include "format_nlist.h" +#include "makenorfirm.h" +#include "format_sign.h" +#include "acsign_nor.h" +#include "compress.h" + +#define SDK_ASM + +#include +#include "../acsign/aes2.h" + +#define NANDCMD "BOOT_NAND" +#define SBIN9CMD "ARM9_SBIN" +#define SBIN7CMD "ARM7_SBIN" +#define ELF9CMD "ARM9_ELF" +#define ELF7CMD "ARM7_ELF" +#define COMP9CMD "ARM9_COMP" +#define COMP7CMD "ARM7_COMP" +#define DECOMPCMD "DECOMP_PROC" +#define BAUDCMD "BAUDRATE" +#define ARM9X2CMD "ARM9_X2" +#define VERCMD "VERSION" +#define RSAKEYCMD "RSA_KEY" +#define OUTKEYCMD "OUT_KEY" +#define WREGCMD "WRAM_RBIN" +#define ENDKEYCMD "ENC_KEYINFO" +#define NCDCMD "NCD_ROMOFS" +#define ERRCMD "ERROR" + +static BOOL ConstructNorfirmFile(char * specFile); +static BOOL ReadSbinFile(const char *fileName, void* minfo, void* hash, BOOL comp); +static BOOL ReadKeyFile(const char *fileName); +static BOOL ReadWramRegFile(const char *fileName); +static s32 GetRamAddr(const char *fileName); + +static BOOL EncryptBuffer(char *buffer, int length); + +static BOOL BTNAND_Command(char * line, int num); +static BOOL Sbin9_Command(char * line, int num); +static BOOL Sbin7_Command(char * line, int num); +static BOOL Elf9_Command(char * line, int num); +static BOOL Elf7_Command(char * line, int num); +static BOOL Comp9_Command(char * line, int num); +static BOOL Comp7_Command(char * line, int num); +static BOOL Decomp_Command(char * line, int num); +static BOOL BAUDRATE_Command(char * line, int num); +static BOOL ARM9X2_Command(char * line, int num); +static BOOL VERSION_Command(char * line, int num); +static BOOL RSAKEY_Command(char * line, int num); +static BOOL OUTKEY_Command(char * line, int num); +static BOOL WramRegs_Command(char * line, int num); +static BOOL ENCKEY_Command(char * line, int num); +static BOOL NcdOffset_Command(char * line, int num); +static BOOL ERROR_Command(char * line, int num); + +static BOOL InitializeAesKey(void); +static BOOL InitializeNorfirmFile(void); +static BOOL FinalizeNorfirmFile(const char *norFile); + +static s32 Offset; // Current offset +static int LineNum; // Line number for error message +static const char *specFileName; // specFile name for error message + +NORHeader norHeader; // Norfirm Header Shadow +FIRMSignedContext signedContext; +u8 *keyFileBuf; +BOOL compArm9 = TRUE; +BOOL compArm7 = TRUE; +tErrorFlags errFlags; + +//--------------------------------------------------------------------------- +// Output - norfirm File +//--------------------------------------------------------------------------- + +BOOL OutputNorfirmFile(const char *specFile, const char *norFile) +{ + char *buffer; + BOOL state; + + if (ReadFile(specFile, &buffer, READ_ALL) <= 0) + { + return FALSE; + } + + if (!OpenFile(norFile)) + { + return FALSE; + } + + specFileName = specFile; + + state = InitializeNorfirmFile() && ConstructNorfirmFile(buffer) && + FinalizeNorfirmFile(norFile) && CloseFile(); + + if (!state) + { + DeleteOutFile(); + } + + return state; +} + + +//--------------------------------------------------------------------------- +// Output - Norfirm File +//--------------------------------------------------------------------------- + +static const tCommandDesc command[] = { + {SBIN9CMD, Sbin9_Command}, {SBIN7CMD, Sbin7_Command}, + {ELF9CMD, Elf9_Command},{ELF7CMD, Elf7_Command}, + {COMP9CMD, Comp9_Command},{COMP7CMD, Comp7_Command}, + {DECOMPCMD, Decomp_Command}, + {NANDCMD, BTNAND_Command}, + {VERCMD, VERSION_Command}, + {BAUDCMD, BAUDRATE_Command}, + {ARM9X2CMD, ARM9X2_Command}, + {RSAKEYCMD, RSAKEY_Command}, + {OUTKEYCMD, OUTKEY_Command}, + {WREGCMD, WramRegs_Command}, + {ENDKEYCMD, ENCKEY_Command}, + {NCDCMD, NcdOffset_Command}, + {ERRCMD, ERROR_Command}, +}; + +BOOL ConstructNorfirmFile(char * specFile) +{ + char *line; + char *line_top; + char *p; + int i; + + LineNum = 0; + Offset = 0x00000000; + + line = specFile++; + + while (*line != '\0') + { + LineNum++; + + // Get command line + line_top = line; + while (*line != '\0') + { + if (*line++ == '\n') + { + break; + } + } + + // Print for debug + debug_printf("NORSF Line%4d [", LineNum, line); + for (p = line_top; p != line; p++) + { + if (isprint(*p)) + { + debug_printf("%c", *p); + } + } + debug_printf("]\n"); + + if (*line_top == '#') + { + } + else + { + for (i = 0; i < (sizeof(command) / sizeof(command[0])); i++) + { + if (!strncmp(line_top, command[i].string, strlen(command[i].string))) + { + if (command[i].funcp != NULL) + { + char line_cmd[FILENAME_MAX]; + char line_scan[FILENAME_MAX]; + char* line_conv; + int num; + + num = sscanf( line_top, + "%1024[^ :] : %1024[^ \x0d:#\n]", + line_cmd, line_scan + ); + line_conv = ResolveDefVal(line_scan); + + debug_printf("line_cmd = %s, line_conv = %s\n", line_cmd, line_conv); + + if (!command[i].funcp(line_conv, num - 1)) + return FALSE; + } + } + } + } + + } + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - 'WramRegs' Command +//--------------------------------------------------------------------------- + +extern MIHeader_WramRegs wram_regs_init; +MIHeader_WramRegs* wram_regs; + +static BOOL WramRegs_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("wram regs file = %s\n", line); + + return ReadWramRegFile(line); +} + +static BOOL ReadWramRegFile(const char *fileName) +{ + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &wram_regs, READ_ALL)) < 0) + return FALSE; + + norHeader.h.w = *wram_regs; + + return CheckResult(); +} + +//--------------------------------------------------------------------------- +// Output - 'RSAKEY' Command +//--------------------------------------------------------------------------- + +static BOOL RSAKEY_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("rsa key = %s\n", line); + + return ReadKeyFile(line); +} + +static BOOL ReadKeyFile(const char *fileName) +{ + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &keyFileBuf, READ_ALL)) < 0) + return FALSE; + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'OUTKEY' Command +//--------------------------------------------------------------------------- + +static BOOL OUTKEY_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("out key = %s\n", line); + + PubkeyFileName = line; + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'VERSION' Command +//--------------------------------------------------------------------------- + +static u8 ConvToBCD8(int x) +{ + u8 bcd = 0; + + x %= 100; + bcd |= (x / 10)<<4; + bcd |= (x % 10); + + return bcd; +} + +static BOOL VERSION_Command(char * line, int num) +{ + char scan[FILENAME_MAX]; + u64 version = -1; + + // rescan + num = sscanf( line, + "0x%1024[^\x0d\n]", + scan + ); + + if (num == 1) + { + // convert version info + version = strtoull(scan, NULL, 16); + } + else if (num == 0) + { + // generate version info + u8* ver8 = (u8*)&version; + time_t timer; + struct tm *t_st; + + time(&timer); + t_st = localtime(&timer); + + ver8[0] = ConvToBCD8(t_st->tm_min); + ver8[1] = ConvToBCD8(t_st->tm_hour); + ver8[2] = ConvToBCD8(t_st->tm_mday); + ver8[3] = ConvToBCD8(t_st->tm_mon+1); + ver8[4] = ConvToBCD8(t_st->tm_year); + ver8[5] = 0xff; + ver8[6] = 0xff; + ver8[7] = 0xff; + } + + norHeader.d.card_key = version; + + debug_printf2("version = %08llx\n", version); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'BOOT_NAND' Command +//--------------------------------------------------------------------------- + +static BOOL BTNAND_Command(char * line, int num) +{ + char* dbg_str = "FALSE"; + + norHeader.l.boot_nandfirm = FALSE; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + if (!strcmp(line, "TRUE")) + { + norHeader.l.boot_nandfirm = TRUE; + dbg_str = "TRUE"; + } + + debug_printf2("boot nandfirm = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Decomp' Command +//--------------------------------------------------------------------------- + +static BOOL Decomp_Command(char * line, int num) +{ + char* dbg_str = "ARM7"; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + if (!strcmp(line, "ARM9")) + { + norHeader.l.arm9_decomp = TRUE; + dbg_str = "ARM9"; + } + + debug_printf2("decompress processor = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'ARM9_X2' Command +//--------------------------------------------------------------------------- + +static BOOL ARM9X2_Command(char * line, int num) +{ + char* dbg_str = "FALSE"; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + if (!strcmp(line, "TRUE")) + { + norHeader.l.arm9_x2 = TRUE; + dbg_str = "TRUE"; + } + + debug_printf2("arm9 x2 = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'BAUDRATE' Command +//--------------------------------------------------------------------------- + +static BOOL BAUDRATE_Command(char * line, int num) +{ + char* dbg_str = "4M"; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + if (!strcmp(line, "8M")) + { + norHeader.l.baudrate = TRUE; + dbg_str = "8M"; + } + + debug_printf2("spi speed = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Comp9' Command +//--------------------------------------------------------------------------- + +static BOOL Comp9_Command(char * line, int num) +{ + char* dbg_str = "FALSE"; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + compArm9 = FALSE; + + if (!strcmp(line, "TRUE")) + { + norHeader.l.comp_arm9_boot_area = TRUE; + compArm9 = TRUE; + dbg_str = "TRUE"; + } + + debug_printf2("arm9 compress = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Comp7' Command +//--------------------------------------------------------------------------- + +static BOOL Comp7_Command(char * line, int num) +{ + char* dbg_str = "FALSE"; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + compArm7 = FALSE; + + if (!strcmp(line, "TRUE")) + { + norHeader.l.comp_arm7_boot_area = TRUE; + compArm7 = TRUE; + dbg_str = "TRUE"; + } + + debug_printf2("arm7 compress = %s\n", dbg_str); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Elf9' Command +//--------------------------------------------------------------------------- + +static BOOL Elf9_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm9 elf = %s\n", line); + + { + s32 ramAddr = GetRamAddr(line); + norHeader.l.main_ram_address = (void*)ramAddr; + } + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'Elf7' Command +//--------------------------------------------------------------------------- + +static BOOL Elf7_Command(char * line, int num) +{ + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm7 elf = %s\n", line); + + { + s32 ramAddr = GetRamAddr(line); + norHeader.l.sub_ram_address = (void*)ramAddr; + } + + return CheckResult(); +} + + +static s32 GetRamAddr(const char *fileName) +{ + Elf32_Ehdr *ehdr; + s32 ramAddr; + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &ehdr, sizeof(Elf32_Ehdr))) < 0) + return FALSE; + + ramAddr = ehdr->e_entry; + + Free(&ehdr); + + debug_printf2("ramaddr = 0x%08x\n", ramAddr); + + return ramAddr; +} + + +//--------------------------------------------------------------------------- +// Output - 'Sbin9' Command +//--------------------------------------------------------------------------- + +static BOOL Sbin9_Command(char * line, int num) +{ + FIRMSignedContext* sc = &signedContext; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm9 sbin = %s\n", line); + + // Set ARM9 ROM Offset + if (!Offset) + { + Offset = (sizeof(NORHeader) + FIRM_ALIGN_MASK) & ~FIRM_ALIGN_MASK; + SeekFile(Offset); + } + debug_printf2("romoffset = %#x\n", Offset); + { + norHeader.l.main_rom_offset = Offset; + } + + return ReadSbinFile(line, &norHeader.l.main_rom_offset, &sc->hash[FIRM_SIGNED_HASH_IDX_ARM9], compArm9); +} + +//--------------------------------------------------------------------------- +// Output - 'Sbin7' Command +//--------------------------------------------------------------------------- + +static BOOL Sbin7_Command(char * line, int num) +{ + FIRMSignedContext* sc = &signedContext; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + debug_printf2("arm7 sbin = %s\n", line); + + // Set ARM7 ROM Offset + if (!Offset) + { + Offset = (sizeof(NORHeader) + FIRM_ALIGN_MASK) & ~FIRM_ALIGN_MASK; + SeekFile(Offset); + } + debug_printf2("romoffset = %#x\n", Offset); + { + norHeader.l.sub_rom_offset = Offset; + } + + return ReadSbinFile(line, &norHeader.l.sub_rom_offset, &sc->hash[FIRM_SIGNED_HASH_IDX_ARM7], compArm7); +} + + +static BOOL ReadSbinFile(const char *fileName, void* minfo, void* hash, BOOL comp) +{ + const NORHeader_ModuleInfo *m = minfo; + u32 *size = (void*)&m->size; + u32 *orig_size = (void*)&m->decomp_size; + char *buffer; + char *file; + int file_size; + struct stat st; + + if (FILESTATUS_FILE != GetFileStatus(&st, fileName)) + { + error("'%s' is not regular file.", fileName); + return FALSE; + } + + if ((file_size = ReadFile(fileName, &file, READ_ALL)) < 0) + return FALSE; + + *orig_size = file_size; + + // Digest file image + if (hash) + { + ACSign_DigestUnit(hash, file, file_size); + } + + // Compress file image with fitting region + buffer = Alloc(file_size * 2); + if ( comp ) + { + file_size = LZCompWrite(file, file_size, buffer, FIRM_ALIGN); + } + else + { + memcpy(&buffer[0], file, file_size); + { + u32 pad_size = (FIRM_ALIGN - (file_size % FIRM_ALIGN)) % FIRM_ALIGN; + if (pad_size) + memset(&buffer[file_size], 0, pad_size); + file_size += pad_size; + } + } + Free(&file); + file = buffer; + + if (size) + { + *size = file_size; + } + Offset += file_size; + + // Encrypt file image + EncryptBuffer(file, file_size); + + // Output file image with fitting region + PutBuffer(file, file_size); + + Free(&file); + + return CheckResult(); +} + +typedef struct +{ + unsigned long e[4]; +} u128; + +static BOOL EncryptBuffer(char *buffer, int length) +{ + const u128 id = {{ AES_IDS_ID2_A, AES_IDS_ID2_B, AES_IDS_ID2_C, AES_IDS_ID2_D }}; + u128 iv = {{ length, -length, ~length, 0 }}; + FIRMSignedContext* sc = &signedContext; + char *buffer2 = Alloc(length); + AES_KEY key; + if (!buffer2) + return FALSE; + AES_SetKey(&key, sc->aes_key, (unsigned char*)&id); + AES_Ctr(&key, buffer2, buffer, length, (unsigned char*)&iv); + memcpy(buffer, buffer2, length); + memset(buffer2, 0, length); + Free(buffer2); + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - 'ENC_KEYINFO' Command +//--------------------------------------------------------------------------- + +static BOOL ENCKEY_Command(char * line, int num) +{ + u32 key; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + key = strtoul(line, NULL, 0); + norHeader.d.ds_key = key; + + debug_printf2("keyinfo = %#x\n", key); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'NcdOffset' Command +//--------------------------------------------------------------------------- + +static BOOL NcdOffset_Command(char * line, int num) +{ + u32 ofs; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + ofs = strtoul(line, NULL, 0); + { + norHeader.d.ncd_romAdr = ConvertHeaderRomOffsetAlign(ofs, 8); + } + + debug_printf2("ncd romoffset = %#x\n", ofs); + + return CheckResult(); +} + + +//--------------------------------------------------------------------------- +// Output - 'ERROR' Command +//--------------------------------------------------------------------------- +static char* error_type[] = +{ + "SIGN", + "HEADER_HASH", + "ARM9_HASH", + "ARM7_HASH", + "HASH_TABLE_HASH", + "FINAL_HASH", + "HEADER_FOOTER", + "WL_CHECK", +}; + +static BOOL ERROR_Command(char * line, int num) +{ + char* dbg_str = "UNKNOWN"; + int i; + + if (num != 1) + { + error("Wrong format spec file '%s' line:%d", specFileName, LineNum); + return FALSE; + } + + for (i=0; ihash[FIRM_SIGNED_HASH_IDX_HEADER][0] ^= 1; + } + if ( errFlags.e.arm9_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_ARM9][0] ^= 1; + } + if ( errFlags.e.arm7_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_ARM7][0] ^= 1; + } + if ( errFlags.e.hash_table_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_HASH_TABLE][0] ^= 1; + } +} + +static void SetFinalHashError(FIRMSignedContext* sc) +{ + if ( errFlags.e.final_hash ) + { + sc->hash[FIRM_SIGNED_HASH_IDX_FINAL][0] ^= 1; + } +} + +static void SetSignError(NORHeader* nh) +{ + if ( errFlags.e.sign ) + { + nh->sign.raw[0] ^= 1; + } + +} + +static void SetFooterError(NORHeader* nh) +{ + if ( errFlags.e.header_footer ) + { + nh->h.reserved_footer[sizeof(nh->h.reserved_footer)-1] ^= 1; + } + +} + +static void SetWirelessCheck(NORHeader* nh) +{ + if ( errFlags.e.wl_check ) + { + nh->wl_params[0] ^= 0x80; + nh->wl_params[sizeof(nh->wl_params)-1] ^= 0x80; + } + +} + + +//--------------------------------------------------------------------------- +// Output - Initialize AES Key +//--------------------------------------------------------------------------- +static BOOL InitializeAesKey(void) +{ + FIRMSignedContext* sc = &signedContext; + struct stat specstat; + time_t spectime; + if (stat(specFileName, &specstat) != 0) + return FALSE; + time(&spectime); + memcpy(&sc->aes_key[0], &specstat.st_atime, 4); + memcpy(&sc->aes_key[4], &specstat.st_mtime, 4); + memcpy(&sc->aes_key[8], &specstat.st_ctime, 4); + memcpy(&sc->aes_key[12], &spectime, 4); + ACSign_GetKey(sc->aes_key, sizeof(sc->aes_key), sc->aes_key, sizeof(sc->aes_key)); + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - Initialize Norfirm File +//--------------------------------------------------------------------------- + +static BOOL InitializeNorfirmFile(void) +{ + memset(norHeader.wl_params, 0xff, sizeof(norHeader.wl_params)); + memset(&signedContext.hash[FIRM_SIGNED_HASH_IDX_HASH_TABLE], 0xff, sizeof(signedContext.hash[0])); + norHeader.l.boot_nandfirm = TRUE; + InitializeAesKey(); + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Output - Finalize Norfirm File +//--------------------------------------------------------------------------- + +static BOOL FinalizeNorfirmFile(const char *norFile) +{ + NORHeader* nh = &norHeader; + FIRMSignedContext* sc = &signedContext; + u8* key = keyFileBuf; + + ACSign_DigestHeader(&sc->hash[FIRM_SIGNED_HASH_IDX_HEADER], nh); + + SetUnitHashErrors(sc); + + ACSign_DigestUnit(&sc->hash[FIRM_SIGNED_HASH_IDX_FINAL], sc, FIRM_HEADER_2ND_HASH_AREA_LEN); + + SetFinalHashError(sc); + + if (key) + { + ACSign_Final(nh, sc, key); + } + + SetFooterError(nh); + + SetSignError(nh); + + SetWirelessCheck(nh); + + // Output file image + SeekFile(0L); + PutBuffer(&norHeader, sizeof(norHeader)); + + // Output public key (modulus) + if (PubkeyFileName) + { + WriteFile(PubkeyFileName, &keyFileBuf[ACS_RSA_PRVMOD_OFFSET], ACS_RSA_PRVMOD_LEN); + } + + return TRUE; +} diff --git a/build/tools/makenorfirm/path.c b/build/tools/makenorfirm/path.c new file mode 100644 index 0000000..eeeb989 --- /dev/null +++ b/build/tools/makenorfirm/path.c @@ -0,0 +1,931 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makebanner + File: path.c + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: path.c,v $ + Revision 1.3 2006/01/18 02:11:20 kitase_hirotake + do-indent + + Revision 1.2 2005/02/28 05:26:13 yosizaki + do-indent. + + Revision 1.1 2004/08/30 08:41:14 yasu + makebanner moves into CVS tree + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#include +#include // free() +#include // strcasecmp() +#include // stat() +#include // opendir()/readdir()/closedir() +#include // getcwd() +#ifdef __CYGWIN__ +#include // cygwin_conv_to_win32_path() +#endif +#include "path.h" + +//--------------------------------------------------------------------------- +// Get File Statue +//--------------------------------------------------------------------------- + +tFileStatus GetFileStatus(struct stat *s, const char *filename) +{ + // Get file status + if (stat(filename, s)) + { + error("Can't get status %s", filename); + return FILESTATUS_ERROR; + } + + if (S_ISREG(s->st_mode)) + { + return FILESTATUS_FILE; + } + else if (S_ISDIR(s->st_mode)) + { + return FILESTATUS_DIR; + } + + error("Unknown file type %s", filename); + return FILESTATUS_ERROR; +} + + +//--------------------------------------------------------------------------- +// File Globbing & Dir Listing +//--------------------------------------------------------------------------- + +typedef struct +{ + tCallBack callBack; + void *param; + tWildCard *accept; + tWildCard *reject; + +} +tForeachEntryParam; + + +static BOOL isAcceptEntryName(char *pathName, tWildCard * accept, tWildCard * reject) +{ + char *p = pathName; + + while (*p) + { + if (*p == '/') + pathName = p + 1; + p++; + } + + if (accept) + { + while (accept) + { + if (WildCardCmp(accept->name, pathName)) + { + goto accepted; + } + accept = accept->next; + } + return FALSE; + } + accepted: + + while (reject) + { + if (WildCardCmp(reject->name, pathName)) + { + return FALSE; + } + reject = reject->next; + } + return TRUE; +} + + +static BOOL ForeachEntry_CallBack(char *pathName, void *param) +{ + tForeachEntryParam *t = (tForeachEntryParam *) param; + struct stat fstat; + + if (!isAcceptEntryName(pathName, t->accept, t->reject)) + { + // Reject!!! ignored + return TRUE; + } + + switch (GetFileStatus(&fstat, pathName)) + { + case FILESTATUS_FILE: + return t->callBack(pathName, t->param); + + case FILESTATUS_DIR: + return ForeachDirList(pathName, ForeachEntry_CallBack, param); + + default: + break; + } + return FALSE; +} + + +BOOL ForeachEntry(const char *pathName, tWildCard * reject, tCallBack callBack, void *param) +{ + tForeachEntryParam t; + + t.callBack = callBack; + t.param = param; + t.accept = NULL; + t.reject = reject; + + return ForeachPathGlobbing(pathName, ForeachEntry_CallBack, &t); +} + + +typedef struct +{ + tCallBack callBack; + void *param; + char *baseName; + +} +tForeachFileParam; + + +static BOOL ForeachFile_CallBack(char *pathName, void *param) +{ + tForeachFileParam *t = (tForeachFileParam *) param; + + int len = strlen(t->baseName); + + debug_printf(" ForeachFile_CallBack path[%s] base[%s]\n", pathName, t->baseName); + + if (strncmp(pathName, t->baseName, len)) + { + error("Wildcard in Root is not supported"); + return FALSE; + } + + return t->callBack(pathName + len, t->param); +} + + +BOOL ForeachFile(const char *baseName, const char *fileName, tWildCard * reject, tCallBack callBack, + void *param) +{ + char *cBaseName; + char *cPathName; + BOOL state; + tForeachFileParam t; + + debug_printf("ForeachFile : baseName[%s] fileName[%s]\n", baseName, fileName); + + cBaseName = GetSrcPath(baseName, ""); + cPathName = GetSrcPath(baseName, fileName); + + debug_printf("ForeachFile : cBaseName[%s] cPathName[%s]\n", cBaseName, cPathName); + + t.callBack = callBack; + t.param = param; + t.baseName = cBaseName; + + state = ForeachEntry(cPathName, reject, ForeachFile_CallBack, &t); + + free(cBaseName); + free(cPathName); + + return state; +} + + +//--------------------------------------------------------------------------- +// FilePath Globbing +//--------------------------------------------------------------------------- + +typedef struct +{ + char *baseName; + char *pathName; + tCallBack callBack; + void *param; + +} +tGlobParam; + + +static int CountFile; +static BOOL ForeachPathGlobbing_Entry(tGlobParam * pg); +static BOOL ForeachPathGlobbing_WildCard(char *pathName, void *param); + +BOOL ForeachPathGlobbing(const char *pathName, tCallBack callBack, void *param) +{ + tGlobParam g; + BOOL ret; + + g.baseName = NULL; + g.pathName = PathNormalize(pathName, TRUE); + g.callBack = callBack; + g.param = param; + CountFile = 0; + + debug_printf("PathGlobbing : Name [%s]->[%s]\n", pathName, g.pathName); + + ret = ForeachPathGlobbing_Entry(&g); + + free(g.pathName); + + if (ret && CountFile == 0) + { + error("No file or directory matched %s", pathName); + return FALSE; + } + return ret; +} + + +static BOOL ForeachPathGlobbing_Entry(tGlobParam * pg) +{ + tGlobParam g; + char *entryName; + struct stat s; + BOOL state; + + if (pg->pathName) + { + entryName = PathDup(pg->pathName); + + g = *pg; + g.pathName = PathGetDirLevelDown(pg->pathName); + + if (pg->baseName) + { + g.baseName = Alloc(strlen(pg->baseName) + strlen(entryName) + 2); + sprintf(g.baseName, "%s/%s", pg->baseName, entryName); + } + else + { + g.baseName = strdup(entryName); + } + + // Check if wildcard ? + if (isPathWildCard(entryName)) + { + state = ForeachDirList(pg->baseName, ForeachPathGlobbing_WildCard, &g); + } + else + { + state = ForeachPathGlobbing_Entry(&g); + } + + Free(&entryName); + Free(&g.baseName); + } + else + { + // Check if file exists + if (!stat(pg->baseName, &s)) + { + debug_printf(" File Found [%s]\n", pg->baseName); + + // Globbing done, exec callback + + state = pg->callBack(pg->baseName, pg->param); + CountFile++; + } + else + { + debug_printf(" File Not Found [%s]\n", pg->baseName); + state = TRUE; // Ignored + } + } + return state; +} + + +static BOOL ForeachPathGlobbing_WildCard(char *pathName, void *param) +{ + tGlobParam g; + tGlobParam *pg = (tGlobParam *) param; + + debug_printf(" WildCardCmp: [%s] [%s]\n", pg->baseName, pathName); + + if (WildCardCmp(pg->baseName, pathName)) + { + g = *pg; + g.baseName = pathName; + return ForeachPathGlobbing_Entry(&g); + } + + return TRUE; // Ignored +} + + +//--------------------------------------------------------------------------- +// Directory Listing +// Listing directory & Exec CallBack +//--------------------------------------------------------------------------- + +BOOL ForeachDirList(const char *dirName, tCallBack callBack, void *param) +{ + DIR *dir; + struct dirent *entry; + char *pathName; + BOOL state = TRUE; + + if (!dirName) + { + dirName = "."; + } + + debug_printf("DirectoryList: Name [%s]\n", dirName); + + // Open directory + if (NULL == (dir = opendir(dirName))) + { + error("Can't read directory %s", dirName); + return FALSE; + } + + // Store new files + while (NULL != (entry = readdir(dir))) + { + pathName = entry->d_name; + + if (!strcmp(pathName, ".") || !strcmp(pathName, "..")) + { + continue; + } + + debug_printf(" :%s\n", pathName); + pathName = GetSrcPath(dirName, pathName); + state = callBack(pathName, param); + free(pathName); + + if (!state) + break; + } + + closedir(dir); + return state; +} + + +//--------------------------------------------------------------------------- +// +// PathName Utilities +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// StrCmp/StrCpy entry name terminated / or \0 +//--------------------------------------------------------------------------- + +int PathCmp(const char *path, const char *cmp) +{ + char c; + + do + { + c = *path; + if (c == '/') + c = '\0'; // end of string if '/' + if (c != *cmp) + return 1; + path++; + cmp++; + } + while (c); + + return 0; +} + + +char *PathCpy(char *dest, const char *src) +{ + while (*src != '\0' && *src != '/') + { + *dest++ = *src++; + } + return dest; // Don't set '\0' +} + + +int PathLen(const char *path) +{ + int n = 0; + + while (*path != '\0' && *path != '/') + { + n++; + path++; + } + return n; +} + + +char *PathDup(const char *src) +{ + int n = PathLen(src); + char *dest = Alloc(n + 2); + + PathCpy(dest, src); + dest[n] = '\0'; + + return dest; +} + + +BOOL WildCardCmp(const char *wildcard, const char *path) +{ + if (*wildcard == '*') + { + if (*path != '\0' && WildCardCmp(wildcard, path + 1)) + return TRUE; + if (WildCardCmp(wildcard + 1, path)) + return TRUE; + } + + else if (*wildcard == '?') + { + return *path != '\0' && WildCardCmp(wildcard + 1, path + 1); + } + + else if (*wildcard == *path) + { + return *path == '\0' || WildCardCmp(wildcard + 1, path + 1); + } + + return FALSE; +} + + +BOOL isPathWildCard(const char *path) +{ + while (*path != '\0' && *path != '/') + { + if (*path == '*' || *path == '?') + { + return TRUE; + } + path++; + } + return FALSE; +} + + +//--------------------------------------------------------------------------- +// Go up/down directory level +//--------------------------------------------------------------------------- + +char *PathGetDirLevelDown(const char *path) +{ + while (*path) + { + if (*path == '/') + return (char *)path + 1; + path++; + } + return NULL; +} + + +//--------------------------------------------------------------------------- +// Get Basename +//--------------------------------------------------------------------------- + +char *GetBaseName(const char *path) +{ + int i; + char *new_path; + + for (i = strlen(path) - 1; i >= 0; i--) + { + if (path[i] == '/') + { + new_path = strdup(path); + new_path[i] = '\0'; + return new_path; + } + if (path[i] == ':') + { + new_path = Alloc(i + 3); + strncpy(new_path, path, i); + strcpy(new_path + i, ":."); + return new_path; + } + } + + new_path = strdup("."); + return new_path; +} + + +//--------------------------------------------------------------------------- +// Get Filename +//--------------------------------------------------------------------------- + +char *GetFileName(const char *path) +{ + int i; + char *new_file; + + for (i = strlen(path) - 1; i >= 0; i--) + { + if (path[i] == '/' || path[i] == ':') + { + new_file = strdup(path + i + 1); + return new_file; + } + } + new_file = strdup(path); + return new_file; +} + + +//--------------------------------------------------------------------------- +// Reconstruct path name +// +// - Resolve '.' or '..' in path name +// - Work around . and / to translate regular form +// +// Regular form of path: +// Absolute Path [Drive:]/.[/Entry...] +// Relative Path [Drive:].[/Entry]... +// +// ex) +// abc/def -> ./abc/def +// /aaa -> /./aaa +// D:/aaa -> D:/./aaa +// / -> /. +// . -> . +// ../aa -> ./../aa +//--------------------------------------------------------------------------- + +char *PathNormalize(const char *pathName, BOOL isTreatDotDot) +{ + int i, level, level_root, n; + BOOL isAbsolute; + const char *entry[DIRLEVEL_MAX]; + + char *pathNormal = Alloc(strlen(pathName) + 4); + const char *p_org; + char *p_new; + + // + // Check if drive letter C: D: E: + // Check if absolute path + // + p_new = pathNormal; + p_org = SkipDriveName(pathName); + n = (int)p_org - (int)pathName; + + if (n > 0) + { + strncpy(p_new, pathName, n); + p_new += n; + } + isAbsolute = isAbsolutePath(p_org); + + // + // Resolve '.' and '..' + // + // Slice the path at point of / , put them into entry[] + // + + level = level_root = 0; + + for (; p_org; p_org = PathGetDirLevelDown(p_org)) + { + if (!PathCmp(p_org, "") || !PathCmp(p_org, ".")) + { + // skip it + continue; + } + else if (!PathCmp(p_org, "..") && isTreatDotDot) + { + if (level > level_root) + { + // Back to parent dir + level--; + continue; + } + + // if pathname starts with '/', no directory to go up + if (isAbsolute) + { + error("Can't go up directory, '..' Ignored. %s", pathName); + continue; + } + + // keep '..' + level_root = level + 1; + } + + // name entry + entry[level] = p_org; + level++; + } + + // Reconstruct pathname + if (isAbsolute) + { + *p_new++ = '/'; + } + *p_new++ = '.'; + + for (i = 0; i < level; i++) + { + *p_new++ = '/'; + p_new = PathCpy(p_new, entry[i]); + } + *p_new = '\0'; + +#if 0 + if (strcmp(pathNormal, pathName)) + { + debug_printf(" PathNormal: [%s] -> [%s]\n", pathName, pathNormal); + } +#endif + return pathNormal; +} + + +//--------------------------------------------------------------------------- +// Get Src Path +// Normalize BASENAME +// Normalize FILENAME +// Concat both +//--------------------------------------------------------------------------- + +char *GetSrcPath(const char *baseName, const char *fileName) +{ + char *base; + char *file; + char *t; + char *path; + + base = PathNormalize(baseName, TRUE); + file = PathNormalize(fileName, TRUE); + t = Alloc(strlen(base) + strlen(file) + 2); + + // Concat base + '/' + file + sprintf(t, "%s/%s", base, file); + path = PathNormalize(t, FALSE); + + free(base); + free(file); + free(t); + + debug_printf(" GetSrcPath: [%s]\n", path); + return path; +} + + +//--------------------------------------------------------------------------- +// Get Dest Path +// Concat BASENAME + FILENAME +// Normalize it +//--------------------------------------------------------------------------- + +char *GetDestPath(const char *baseName, const char *fileName) +{ + char *t; + char *path; + + t = Alloc(strlen(baseName) + strlen(fileName) + 2); + + // Concat base + '/' + file + sprintf(t, "%s/%s", baseName, fileName); + path = PathNormalize(t, TRUE); + + free(t); + + debug_printf(" GetDestPath: [%s]\n", path); + return path; +} + + +//--------------------------------------------------------------------------- +// Remake the path into familier shape +// Delete ./ +//--------------------------------------------------------------------------- + +char *PathDenormalize(char *path) +{ + char *p; + + p = (char *)SkipDriveName(path); + if (*p == '/') + { + p++; + } + + // Cut './' + if (*p == '.' && *(p + 1) == '/') + { + while ('\0' != (*p = *(p + 2))) + { + p++; + } + + if (p == path) + { + + } + } + + + + return path; +} + + +//--------------------------------------------------------------------------- +// Get PC Path +//--------------------------------------------------------------------------- + +char *GetWin32Path(char *cygpath) +{ + static char buffer[FILENAME_MAX]; + +#ifdef __CYGWIN__ + if (*cygpath == '/') + { + cygwin_conv_to_win32_path(cygpath, buffer); + } + else +#endif + { + strcpy(buffer, cygpath); + } + + return ChangeBackSlash(buffer); +} + +char *ChangeWin32Path(char *cygpath) +{ + char *win32path = strdup(GetWin32Path(cygpath)); + + free(cygpath); + return win32path; +} + +//--------------------------------------------------------------------------- +// Change suffix +//--------------------------------------------------------------------------- +char *ChangeSuffix(const char *file, const char *suffix) +{ + int i, n; + char *path; + + n = strlen(file); + + for (i = n; file[i] != '.'; i--) + { + if (file[i] == '/' || i == 0) + { + i = n; + break; + } + } + + path = Alloc(i + strlen(suffix) + 1); + strncpy(path, file, i); + strcpy(path + i, suffix); + + return path; +} + + +//--------------------------------------------------------------------------- +// Get Current Dir +//--------------------------------------------------------------------------- + +char *GetCurrentDirectory(void) +{ + static char buffer[FILENAME_MAX]; + char *cwd; + + cwd = getcwd(buffer, FILENAME_MAX); + if (!cwd) + { + error("Can't access current directory"); + exit(10); + } + return cwd; +} + + +//--------------------------------------------------------------------------- +// Check if absolute path +// +// Return True in case of ... +// +// /dirA/dirB/fileC +// D:/dirA/dirB/fileC +// +// Return False in case of ... +// +// dirX/dirY/fileZ +// D:dirX/dirY/fileZ +//--------------------------------------------------------------------------- + +BOOL isAbsolutePath(const char *path) +{ + const char *p = path; + + while (*p != '\0') + { + if (*p == '/' || *p == '\\') + { + if (p == path || p[-1] == ':') + { + return TRUE; + } + } + p++; + } + return FALSE; +} + +//--------------------------------------------------------------------------- +// Check if drive name +// +// Return next character of ':' if drive name +// Return head of path if no drive name +//--------------------------------------------------------------------------- + +const char *SkipDriveName(const char *path) +{ + const char *p = path; + + while (*p != '\0' && *p != '/' && *p != '\\') + { + if (*p == ':') + { + return p + 1; + } + p++; + } + return path; +} + + +//--------------------------------------------------------------------------- +// App Name Utilities +//--------------------------------------------------------------------------- +static char *appName; +static char *appBaseName; +static char *appFileName; + +void InitAppName(const char *path) +{ + char *slash_path = ChangeBackSlash(strdup(path)); + + appBaseName = GetBaseName(slash_path); + appFileName = GetFileName(slash_path); + appName = ChangeSuffix(appFileName, ""); + + free(slash_path); +} + +char *GetAppName(void) +{ + return appName; +} + +char *GetAppBaseName(void) +{ + return appBaseName; +} + +char *GetAppFileName(void) +{ + return appFileName; +} + + +#ifdef TEST +int main(int argc, char *argv[]) +{ + int i; + char *s; + + for (i = 1; i < argc; i++) + { + s = PathNormalize(argv[i], TRUE); + printf("[%s] -> [%s]\n", argv[i], s); + free(s); + } + return 0; +} +#endif diff --git a/build/tools/makenorfirm/path.h b/build/tools/makenorfirm/path.h new file mode 100644 index 0000000..e9956dc --- /dev/null +++ b/build/tools/makenorfirm/path.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------------* + Project: NitroSDK - tools - makebanner + File: path.h + + Copyright 2003-2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: path.h,v $ + Revision 1.3 2006/01/18 02:11:20 kitase_hirotake + do-indent + + Revision 1.2 2005/02/28 05:26:13 yosizaki + do-indent. + + Revision 1.1 2004/08/30 08:41:14 yasu + makebanner moves into CVS tree + + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef PATH_H_ +#define PATH_H_ + +#include // struct tat +#include "misc.h" + +#define DIRLEVEL_MAX 256 +#ifndef FILENAME_MAX +#define FILENAME_MAX 1024 +#endif + +typedef enum +{ + FILESTATUS_ERROR = -1, + FILESTATUS_FILE = 0, + FILESTATUS_DIR = 1 +} +tFileStatus; + + +// Item Reject Control + +typedef struct tWildCard +{ + struct tWildCard *next; + char *name; + +} +tWildCard; + + +// CallBacks + +typedef BOOL (*tCallBack) (char *, void *); + + +// Prototypes + +tFileStatus GetFileStatus(struct stat *s, const char *filename); +BOOL ForeachEntry(const char *pathName, tWildCard * reject, tCallBack callBack, void *param); +BOOL ForeachFile(const char *baseName, const char *fileName, tWildCard * reject, + tCallBack callBack, void *param); +BOOL ForeachPathGlobbing(const char *pathName, tCallBack callBack, void *param); +BOOL ForeachDirList(const char *dirName, tCallBack callBack, void *param); +int PathCmp(const char *path, const char *cmp); +char *PathCpy(char *dest, const char *src); +int PathLen(const char *path); +char *PathDup(const char *src); +char *PathGetDirLevelDown(const char *path); +char *GetBaseName(const char *path); +char *GetFileName(const char *path); +BOOL WildCardCmp(const char *wildcard, const char *path); +BOOL isPathWildCard(const char *path); +char *PathNormalize(const char *pathName, BOOL isTreatDotDot); +char *PathDenormalize(char *path); +char *GetSrcPath(const char *base, const char *file); +char *GetDestPath(const char *base, const char *file); +char *GetWin32Path(char *cygpath); +char *ChangeWin32Path(char *cygpath); +char *ChangeSuffix(const char *file, const char *suffix); +char *GetCurrentDirectory(void); +BOOL isAbsolutePath(const char *path); +const char *SkipDriveName(const char *path); +void InitAppName(const char *path); +char *GetAppName(void); +char *GetAppBaseName(void); +char *GetAppFileName(void); + +#endif //PATH_H_ diff --git a/build/tools/makenorfirm/test/Makefile b/build/tools/makenorfirm/test/Makefile new file mode 100644 index 0000000..992184a --- /dev/null +++ b/build/tools/makenorfirm/test/Makefile @@ -0,0 +1,58 @@ +#! make -f +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makenorfirm +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#--------------------------------------------------------------------------- + +SUBDIRS = wram_rbin \ + +include $(TWLSDK_ROOT)/build/buildtools/commondefs + +MAKENORFIRM = ../makenorfirm.exe + +MAKEFIRM_RSA_PRVKEY = ./rsa_private.der + +MAKEFIRM_ARM9 = ./twl_norfirm9_print.axf +MAKEFIRM_ARM7 = ./twl_norfirm7_print.axf +SDEPENDS_BIN += $(MAKEFIRM_ARM9) $(MAKEFIRM_ARM7) +MAKEFIRM_FLAGS += -d +MAKEFIRM_DEFS += -DFIRM_ROOT='$(FIRM_ROOT)' \ + -DMAKEFIRM_ARM9='$(basename $(MAKEFIRM_ARM9))' \ + -DMAKEFIRM_ARM7='$(basename $(MAKEFIRM_ARM7))' \ + -DMAKEFIRM_RSA_PRVKEY='$(MAKEFIRM_RSA_PRVKEY)' \ + +TARGET = test.srl + +%.srl: %.norsf $(MAKENORFIRM) $(MAKEFIRM_RSA_PRVKEY) + $(MAKENORFIRM) $(MAKEFIRM_FLAGS) $(MAKEFIRM_DEFS) $< $@ + +.PHONY: build install do-autotest clean clobber + +define ECHO_CURDIR + echo "==== $(CURDIR)"; +endef + +build: + @$(ECHO_CURDIR) + @$(MAKE) $(TARGET) + +install do-autotest: + @$(ECHO_CURDIR) + +clean clobber super-clobber: + @$(ECHO_CURDIR) + -rm -f $(TARGET) *~ + +test-utf16.bsf: icon.nbfc icon.nbfp diff --git a/build/tools/makenorfirm/test/rsa_private.der b/build/tools/makenorfirm/test/rsa_private.der new file mode 100644 index 0000000000000000000000000000000000000000..ccf67c186ba0783774a391fa190a1169155f281d GIT binary patch literal 608 zcmV-m0-yabf&yFu0RRGlfdI^ydqI7je1HOl+Yp(I)Tf4e@7hDDZ3|Vf5OZgl!rAb0 z*83f%7n*m8hv(?Xz=k%zT`bpHAL`&wX2*l5GxU>lo;sIsQeHis4((7+)?dUnagoFp zfy&R4POTg=aNJnsiHW0X2}6+c@s2=GxAACyF!yZ$ik#GkB}$mdW-kH*0RRC4fq+hQ zZdX^o3titC%RXCESiFGZC6%%IhdCg7s$)i{{KG5cEwT^QfEk#ZA%%I1dEh;uHZPjV z5t1~&-R{NuyD0C>s3WN#p=?Z z*(>6%jD;YYND`!^I52ZSVS9((vB6RD<0CRlzixl)1+a8Tu<UUPp7kh#$!@g$VcL08j(Mm6qlecx;X z-nFqs_-g#V-(^EJniWC02~+xnu{a#-yR)Yugs_$y8t~d@XK(+_sv%N?oT9CknwCzKqm_T literal 0 HcmV?d00001 diff --git a/build/tools/makenorfirm/test/test.norsf b/build/tools/makenorfirm/test/test.norsf new file mode 100644 index 0000000..7c3093a --- /dev/null +++ b/build/tools/makenorfirm/test/test.norsf @@ -0,0 +1,30 @@ +#NORSF --- Norfirm Spec File + +VERSION : 0x0 # GENERATE + +BOOT_NAND : TRUE # TRUE or FALSE + +RSA_KEY : rsa_private.der +OUT_KEY : rsa_public.sbin + +WRAM_RBIN: ./wram_rbin/wram_regs.rbin + +DECOMP_PROC : ARM9 # ARM9 or ARM7 + +ARM9_COMP : TRUE # TRUE or FALSE, should be before ARM9_SBIN +ARM9_SBIN : $(MAKEFIRM_ARM9).sbin +ARM9_ELF : $(MAKEFIRM_ARM9).axf + +ARM7_COMP : FALSE # TRUE or FALSE, should be before ARM7_SBIN +ARM7_SBIN : $(MAKEFIRM_ARM7).sbin +ARM7_ELF : $(MAKEFIRM_ARM7).axf + +BAUDRATE : 8M # 4M or 8M +ARM9_X2 : TRUE # TRUE or FALSE + +ENC_KEYINFO : 0x5043414d # 'MACP' +NCD_ROMOFS : 0x07fe00 + +ERROR : ARM7_HASH # SIGN, HEADER_HASH, ARM9_HASH, ARM7_HASH, HASH_TABLE_HASH or FINAL_HASH +ERROR : HEADER_FOOTER # for debug +ERROR : WL_CHECK # for debug diff --git a/build/tools/makenorfirm/test/twl_norfirm7_print.axf b/build/tools/makenorfirm/test/twl_norfirm7_print.axf new file mode 100644 index 0000000000000000000000000000000000000000..b255bd21a2a20901a9313cd8ff4c795d71cefd3b GIT binary patch literal 175676 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
U4<#z|> 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 V0e$D4tJkd|WOOI~ka7)h{{^{CZ=wJI literal 0 HcmV?d00001 diff --git a/build/tools/makenorfirm/test/twl_norfirm9_print.axf b/build/tools/makenorfirm/test/twl_norfirm9_print.axf new file mode 100644 index 0000000000000000000000000000000000000000..3d064b38a5509e8ea9e4ce4cc5302e3f0684d513 GIT binary patch literal 288636 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 literal 0 HcmV?d00001 diff --git a/build/tools/makenorfirm/test/wram_rbin/Makefile b/build/tools/makenorfirm/test/wram_rbin/Makefile new file mode 100644 index 0000000..f0ecbed --- /dev/null +++ b/build/tools/makenorfirm/test/wram_rbin/Makefile @@ -0,0 +1,48 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlFirm - tools - norfirm-print +# File: Makefile +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#---------------------------------------------------------------------------- + +SUBDIRS = + +LINCLUDES = ../include + +#---------------------------------------------------------------------------- + +TARGET_BIN = wram_regs.rbin + +SRCS = \ + wram_regs.c \ + +#SRCDIR = # using default +#LCFILE = # using default + + +include $(TWLIPL_ROOT)/build/buildtools/commondefs + +INSTALL_DIR = . +INSTALL_TARGETS = $(BINDIR)/$(TARGET_BIN) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + + +include $(TWLIPL_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/build/tools/makenorfirm/test/wram_rbin/wram_regs.c b/build/tools/makenorfirm/test/wram_rbin/wram_regs.c new file mode 100644 index 0000000..d2cdda9 --- /dev/null +++ b/build/tools/makenorfirm/test/wram_rbin/wram_regs.c @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: wram_regs.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include +#include + +MIHeader_WramRegs wram_regs = +{ + // ARM9 + { + REG_WRAM_A_BNK_PACK(0, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_0KB, TRUE), + REG_WRAM_A_BNK_PACK(1, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_64KB, TRUE), + REG_WRAM_A_BNK_PACK(2, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_128KB, TRUE), + REG_WRAM_A_BNK_PACK(3, MI_WRAM_A_ARM7, MI_WRAM_A_OFS_192KB, TRUE), + }, + { + REG_WRAM_B_BNK_PACK(0, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_0KB, TRUE), + REG_WRAM_B_BNK_PACK(1, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_32KB, TRUE), + REG_WRAM_B_BNK_PACK(2, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_64KB, TRUE), + REG_WRAM_B_BNK_PACK(3, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_96KB, TRUE), + REG_WRAM_B_BNK_PACK(4, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_128KB, TRUE), + REG_WRAM_B_BNK_PACK(5, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_160KB, TRUE), + REG_WRAM_B_BNK_PACK(6, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_192KB, TRUE), + REG_WRAM_B_BNK_PACK(7, MI_WRAM_B_ARM7, MI_WRAM_B_OFS_224KB, TRUE), + }, + { + REG_WRAM_C_BNK_PACK(0, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_0KB, TRUE), + REG_WRAM_C_BNK_PACK(1, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_32KB, TRUE), + REG_WRAM_C_BNK_PACK(2, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_64KB, TRUE), + REG_WRAM_C_BNK_PACK(3, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_96KB, TRUE), + REG_WRAM_C_BNK_PACK(4, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_128KB, TRUE), + REG_WRAM_C_BNK_PACK(5, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_160KB, TRUE), + REG_WRAM_C_BNK_PACK(6, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_192KB, TRUE), + REG_WRAM_C_BNK_PACK(7, MI_WRAM_C_ARM9, MI_WRAM_C_OFS_224KB, TRUE), + }, + REG_WRAM_A_MAP_PACK(MI_WRAM_MAP_NULL, + MI_WRAM_MAP_NULL, + MI_WRAM_A_IMG_128KB + ), + REG_WRAM_B_MAP_PACK(MI_WRAM_MAP_NULL, + MI_WRAM_MAP_NULL, + MI_WRAM_B_IMG_128KB + ), + REG_WRAM_C_MAP_PACK(HW_WRAM_AREA_HALF, + HW_WRAM_AREA_HALF + 0x00020000, + MI_WRAM_C_IMG_128KB + ), + + // ARM7 + REG_WRAM_A_MAP_PACK(HW_WRAM_AREA_HALF, + HW_WRAM_AREA_HALF + 0x00020000, + MI_WRAM_A_IMG_128KB + ), + REG_WRAM_B_MAP_PACK(HW_WRAM_AREA_HALF + 0x00020000, + HW_WRAM_AREA_HALF + 0x00040000, + MI_WRAM_B_IMG_128KB + ), + REG_WRAM_C_MAP_PACK(MI_WRAM_MAP_NULL, + MI_WRAM_MAP_NULL, + MI_WRAM_C_IMG_128KB + ), + // WRAM Lock + { + 0, + 0, + 0, + }, + + // WRAM-0/1 + MI_WRAM_ARM7_ALL, + + // VRAM-C + 7, + // VRAM-D + 7, +}; diff --git a/build/tools/makenorfirm/wram_regs.c b/build/tools/makenorfirm/wram_regs.c new file mode 100644 index 0000000..68ed468 --- /dev/null +++ b/build/tools/makenorfirm/wram_regs.c @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - tools - makenorfirm + File: wram_regs.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#include "format_rom.h" +//#define SDK_ASM +#define NITRO_TYPES_H_ +#include +#include +#include + + +MIHeader_WramRegs wram_regs_init = +{ + // ARM9 + { + REG_MI_MBK_A0_FIELD( 1, MI_WRAM_A_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_A1_FIELD( 1, MI_WRAM_A_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_A2_FIELD( 1, MI_WRAM_A_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_A3_FIELD( 1, MI_WRAM_A_OFFSET_192KB, MI_WRAM_ARM7 ), + }, + { + REG_MI_MBK_B0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM7 ), + REG_MI_MBK_B4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM7 ), + REG_MI_MBK_B7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM7 ), + }, + { + REG_MI_MBK_C0_FIELD( 1, MI_WRAM_BC_OFFSET_0KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C1_FIELD( 1, MI_WRAM_BC_OFFSET_32KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C2_FIELD( 1, MI_WRAM_BC_OFFSET_64KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C3_FIELD( 1, MI_WRAM_BC_OFFSET_96KB , MI_WRAM_ARM9 ), + REG_MI_MBK_C4_FIELD( 1, MI_WRAM_BC_OFFSET_128KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C5_FIELD( 1, MI_WRAM_BC_OFFSET_160KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C6_FIELD( 1, MI_WRAM_BC_OFFSET_192KB, MI_WRAM_ARM9 ), + REG_MI_MBK_C7_FIELD( 1, MI_WRAM_BC_OFFSET_224KB, MI_WRAM_ARM9 ), + }, + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, MI_WRAM_MAP_NULL ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, MI_WRAM_MAP_NULL ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, HW_WRAM_AREA_HALF + 0x00020000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, HW_WRAM_AREA_HALF ) + ), + + // ARM7 + REG_MI_MBK6_FIELD( REG_WRAM_MAP_CONV_ADDR( 6, A, EADDR, HW_WRAM_AREA_HALF + 0x00020000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 6, A, SADDR, HW_WRAM_AREA_HALF ) + ), + REG_MI_MBK7_FIELD( REG_WRAM_MAP_CONV_ADDR( 7, B, EADDR, HW_WRAM_AREA_HALF + 0x00040000 ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 7, B, SADDR, HW_WRAM_AREA_HALF + 0x00020000 ) + ), + REG_MI_MBK8_FIELD( REG_WRAM_MAP_CONV_ADDR( 8, C, EADDR, MI_WRAM_MAP_NULL ), + MI_WRAM_IMAGE_128KB, + REG_WRAM_MAP_CONV_ADDR( 8, C, SADDR, MI_WRAM_MAP_NULL ) + ), + + // WRAM Lock + { + 0, + 0, + 0, + }, + + // WRAM-0/1 + 3, + + // VRAM-C + 7, + // VRAM-D + 7, +}; + diff --git a/doc/NORフラッシュマップ.xls b/doc/NORフラッシュマップ.xls new file mode 100644 index 0000000000000000000000000000000000000000..4efbd6b41a1577ba1b314085768f356da59d345c GIT binary patch literal 19968 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 N3;q9p{-3)7{{t>SQEUJJ literal 0 HcmV?d00001 diff --git a/doc/TWL_SystemMenuメモリマップ.vsd b/doc/TWL_SystemMenuメモリマップ.vsd new file mode 100644 index 0000000000000000000000000000000000000000..db999465114b90e95560c4438217880893da1553 GIT binary patch literal 198144 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 literal 0 HcmV?d00001 diff --git a/doc/TWL_staticModule.xls b/doc/TWL_staticModule.xls new file mode 100644 index 0000000000000000000000000000000000000000..2921a9b578f1964fe0f55e24251a02f75b686213 GIT binary patch literal 54272 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 literal 0 HcmV?d00001 diff --git a/doc/TWLフォルダツリー&NUP.vsd b/doc/TWLフォルダツリー&NUP.vsd new file mode 100644 index 0000000000000000000000000000000000000000..b59bf8d2653c8996145d578eb57386a5f47a0323 GIT binary patch literal 844800 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 $KViJyrpYfR%t$ZmdE<~Iq;{N`kC@Y~~e#;;HU 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

;1igTv_2s!&26sH(GYrae)1|50oM~4^9!cLy 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%0A;m2$JQZRr7*FUj$(jat8MQguW_5uW_hp3KOHRSo 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%0AtC>ELg>WZ@X589!oW$M3rXFx(bRu5^cK{4MO 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�VxZHWSfY{8}6oZ4;=*?xTJIuek&&i1T%9-}*K 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 z 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≨Kd?qg5$Fi!CdyH?8Yy&yGHO&VYqLfr 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 literal 0 HcmV?d00001 diff --git a/include/firm.h b/include/firm.h new file mode 100644 index 0000000..37ccbca --- /dev/null +++ b/include/firm.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm + File: firm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_H_ +#define FIRM_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +/* +#include +#include +*/ + +/* FIRM_H_ */ +#endif diff --git a/include/firm/.DS_Store b/include/firm/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..40cfa8d7c6b700c60ca675ae03bf7b038c8cfc65 GIT binary patch literal 8196 zcmeHLyH4Ct5S_bT5Gc(eq=*W+q-2#JFleDo!4L3QUea1#g`lKCa-SwW5;aKqg?vJ! z^r_SE1(ckbJ7|5^9vXy%#9Zm#W6k59@ma6!F%gCB%khwCjfj>o83!M*bPV?MY>l2; zHh=;7G~7F?%4sXk4X%JI;0m|`u7E4>b`-!fo5zyz+>c&gT>)3%T`Iu$ha8i!P^=@$ ztpkg+0Kh)XGH^WL17NOLDAp0-!3Z%G7*m6`7$K&^o@-p8SVxTM6twvW${e&q3Br#3 za|x$VMD*1aa0S{5aPOYc0UguDs2~J3VXe zx`{Mepc62D#X85idX;(&-bQ{|b#gZ%QvRIz7r|W77b>}m^sKLc&ijoTl0A$nl9;rP zzg$N~r*uT)w1QusW*&oE^9)w?cJTG+jJ~C8AAf*N>;{+mI#m{5$|JvT56YgWJj2hz z1G~v1K7$9ol&8RUsJoiKf;Rs>*-akg7|O|hDbIf7nNpda&){BoU^jWhXPggwDNoKk z8BOW?ymIRgGmpWgdB$0(H|3MxX_+p-c#LcCgwAQwx(8%`Zou6UWz^9b*{MKBWKv(h z*4GET2NbA*-xunL{`?mmd~pR{sz4SuSmXYG$Nv8RQX0>91zdqQtU&0G_D0(%P@k=> zQn}a8G50Zfa9kZxQm}9c+oc@`YCA5rTz!RN9Z^z|BdNgH$@_-@R>y}c@VW{-0%`UX ABme*a literal 0 HcmV?d00001 diff --git a/include/firm/acsign.h b/include/firm/acsign.h new file mode 100644 index 0000000..f275754 --- /dev/null +++ b/include/firm/acsign.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - ACSIGN + File: acsign.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_ACSIGN_H_ +#define FIRM_ACSIGN_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_ACSIGN_H_ */ +#endif diff --git a/include/firm/aes.h b/include/firm/aes.h new file mode 100644 index 0000000..0f479d2 --- /dev/null +++ b/include/firm/aes.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - include - AES + File: aes.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_AES_H_ +#define FIRM_AES_H_ + +#ifdef SDK_ARM7 +#include +#include +#include +#include +#endif // SDK_ARM7 + +/* FIRM_AES_H_ */ +#endif diff --git a/include/firm/aes/ARM7/aes_ids.h b/include/firm/aes/ARM7/aes_ids.h new file mode 100644 index 0000000..3969442 --- /dev/null +++ b/include/firm/aes/ARM7/aes_ids.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirmSDK - AES - include + File: aes_ids.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef TWL_AES_AES_IDS_H_ +#define TWL_AES_AES_IDS_H_ + +#define AES_IDS_ID0_A (('N' << 0) | ('i' << 8) | ('n' << 16) | ('t' << 24)) +#define AES_IDS_ID0_B (('e' << 0) | ('n' << 8) | ('d' << 16) | ('o' << 24)) +#define AES_IDS_ID0_C(c) (((unsigned long)c[0] << 0) | ((unsigned long)c[1] << 8) | ((unsigned long)c[2] << 16) | ((unsigned long)c[3] << 24)) +#define AES_IDS_ID0_D(c) (((unsigned long)c[3] << 0) | ((unsigned long)c[2] << 8) | ((unsigned long)c[1] << 16) | ((unsigned long)c[0] << 24)) + +#define AES_IDS_ID1_A(c) (((unsigned long)c[3] << 0) | ((unsigned long)c[1] << 8) | ((unsigned long)c[2] << 16) | ((unsigned long)c[0] << 24)) +#define AES_IDS_ID1_B(c) (((unsigned long)c[0] << 0) | ((unsigned long)c[2] << 8) | ((unsigned long)c[1] << 16) | ((unsigned long)c[3] << 24)) +#define AES_IDS_ID1_C (*(unsigned long*)0x04004d04) +#define AES_IDS_ID1_D (*(unsigned long*)0x04004d00) + +#define AES_IDS_ID2_A (('N' << 0) | ('i' << 8) | ('n' << 16) | ('t' << 24)) +#define AES_IDS_ID2_B (('e' << 0) | ('n' << 8) | ('d' << 16) | ('o' << 24)) +#define AES_IDS_ID2_C ((' ' << 0) | ('D' << 8) | ('S' << 16) | ('\0' << 24)) +#define AES_IDS_ID2_D ((0x01 << 0) | (0x23 << 8) | (0x21 << 16) | (0x00 << 24)) + +#define AES_IDS_ID3_A (*(unsigned long*)0x04004d00) +#define AES_IDS_ID3_B (('N' << 0) | ('I' << 8) | ('N' << 16) | ('T' << 24)) +#define AES_IDS_ID3_C (('E' << 0) | ('N' << 8) | ('D' << 16) | ('O' << 24)) +#define AES_IDS_ID3_D (*(unsigned long*)0x04004d04) + +/* TWL_AES_AES_IDS_H_ */ +#endif diff --git a/include/firm/aes/ARM7/aes_init.h b/include/firm/aes/ARM7/aes_init.h new file mode 100644 index 0000000..00150c7 --- /dev/null +++ b/include/firm/aes/ARM7/aes_init.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - AES - include + File: aes_init.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef TWL_AES_AES_INIT_H_ +#define TWL_AES_AES_INIT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------* + ֐` + *---------------------------------------------------------------------------*/ +void AESi_InitGameKeys( u8 game_code[4] ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* TWL_AES_AES_INIT_H_ */ +#endif diff --git a/include/firm/aes/ARM7/aes_util.h b/include/firm/aes/ARM7/aes_util.h new file mode 100644 index 0000000..3f36a08 --- /dev/null +++ b/include/firm/aes/ARM7/aes_util.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - AES - include + File: aes_util.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef TWL_AES_AES_UTIL_H_ +#define TWL_AES_AES_UTIL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------* + ֐` + *---------------------------------------------------------------------------*/ +void AESi_AddCounter(AESCounter* pCounter, u32 nums); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* TWL_AES_AES_UTIL_H_ */ +#endif diff --git a/include/firm/fatfs.h b/include/firm/fatfs.h new file mode 100644 index 0000000..2d6cc20 --- /dev/null +++ b/include/firm/fatfs.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - include - fatfs + File: fatfs.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_FATFS_H_ +#define FIRM_FATFS_H_ + +#ifdef SDK_ARM7 +#include +#include +#endif // SDK_ARM7 + + +/* FIRM_FATFS_H_ */ +#endif diff --git a/include/firm/fatfs/ARM7/fatfs_firm.h b/include/firm/fatfs/ARM7/fatfs_firm.h new file mode 100644 index 0000000..23badb9 --- /dev/null +++ b/include/firm/fatfs/ARM7/fatfs_firm.h @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - include - fatfs + File: fatfs.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_FATFS_FATFS_FIRM_H_ +#define FIRM_FATFS_FATFS_FIRM_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------* + Name: FATFS_EnableAES + + Description: enable AES data path + + Arguments: counter initial counter value + + Returns: None + *---------------------------------------------------------------------------*/ +void FATFS_EnableAES( const AESCounter* pCounter ); + +/*---------------------------------------------------------------------------* + Name: FATFS_DisableAES + + Description: bypass AES + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void FATFS_DisableAES( void ); + +/*---------------------------------------------------------------------------* + Name: FATFS_InitFIRM + + Description: init file system + + Arguments: nandContext : nand context to omit initialization (if any) + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL FATFS_InitFIRM( void* nandContext ); + +/*---------------------------------------------------------------------------* + Name: FATFS_MountDriveFIRM + + Description: mount nand partition + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL FATFS_MountDriveFIRM( int driveno, FATFSMediaType media, int partition_no ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +/* FIRM_FATFS_FATFS_FIRM_H_ */ +#endif diff --git a/include/firm/fatfs/ARM7/fatfs_loader.h b/include/firm/fatfs/ARM7/fatfs_loader.h new file mode 100644 index 0000000..74b80d8 --- /dev/null +++ b/include/firm/fatfs/ARM7/fatfs_loader.h @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - include - fatfs + File: fatfs_loader.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_FATFS_FATFS_LOADER_H_ +#define FIRM_FATFS_FATFS_LOADER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------* + Name: FATFS_OpenRecentMenu + + Description: open recent menu file + + Arguments: driveno drive number ('A' is 0) + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL FATFS_OpenRecentMenu( int driveno ); + +/*---------------------------------------------------------------------------* + Name: FATFS_OpenSpecifiedSrl + + Description: open specified menu file + + Arguments: menufile target filename + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL FATFS_OpenSpecifiedSrl( const char* menufile ); + +/*---------------------------------------------------------------------------* + Name: FATFS_LoadHeader + + Description: load menu header + + Arguments: None + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +BOOL FATFS_LoadHeader( void ); + +/*---------------------------------------------------------------------------* + Name: FATFS_LoadStatic + + Description: load static binary + + Arguments: None + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +BOOL FATFS_LoadStatic( void ); + +/*---------------------------------------------------------------------------* + Name: FATFS_Boot + + Description: boot + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void FATFS_Boot( void ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +/* FIRM_FATFS_FATFS_LOADER_H_ */ +#endif diff --git a/include/firm/format/firm_common.h b/include/firm/format/firm_common.h new file mode 100644 index 0000000..404ec28 --- /dev/null +++ b/include/firm/format/firm_common.h @@ -0,0 +1,67 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - format - firm + File: firm_common.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_FORMAT_FIRM_COMMON_H_ +#define FIRM_FORMAT_FIRM_COMMON_H_ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +// 풓W[ +typedef struct +{ + u32 rom_offset; /* ] ROM ItZbg */ + u32 decomp_size; /* WJTCY */ + void *ram_address; /* ] RAM ItZbg */ + u32 size; /* ]TCY */ +} +FIRMHeader_ModuleInfo; + +// DS-IPL2wb_ +typedef struct +{ + u16 reserved_0h[4]; + u32 ds_key; + u16 ds_arm9_romAdr; + u16 ds_arm9_ramAdr; + u16 ds_arm7_romAdr; + u16 ds_arm7_ramAdr; + u16 ds_arm9_romOffsetUnit:3; + u16 ds_arm9_ramOffsetUnit:3; + u16 ds_arm7_romOffsetUnit:3; + u16 ds_arm7_ramOffsetUnit:3; + u16 :2; + u16 ds_header_ver:2; + u16 ds_data_romAdr; + u64 card_key; + u16 ncd_romAdr; + u16 reserved_24h[2]; + u16 ds_data_crc16; +} +NORHeaderDS; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // FIRM_FORMAT_FIRM_COMMON_H_ diff --git a/include/firm/format/format_rom.h b/include/firm/format/format_rom.h new file mode 100644 index 0000000..33309be --- /dev/null +++ b/include/firm/format/format_rom.h @@ -0,0 +1,532 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - tools - makerom.TWL + File: format_rom.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FORMAT_ROM_H_ +#define FORMAT_ROM_H_ + +//#include "misc.h" +//#include "format_rom_certificate.h" +//#include "acsign/include/acsign.h" +//#include "aes/include/aes2.h" +#include +#include + + +//#define ENABLE_OVERLAY_DIGEST_ANNEX // ̒`LȂAOverlaỹ_CWFXgcompstaticMBp̂̂Ƃ͕ʓr‚悤ɂȂB + +#define ROM_KEYTABLE2_SIZE 0x3000 // TWL-ROMTWLp̈擪ɂL[e[uQTCYBTWLp̈̃ZLÄ́Ǎ납JnB +#define ROM_TWL_LTD_ALIGN 0x80000 // TWL-ROMTWLp̈̐ݒPʁ@dl512KB +#define ROM_TWL_LTD_ALIGN_SHIFT 19 // L̒PʂrbgVtgɊZ +#define ROM_TWL_ALL_NORMAL_AREA_FLAG 0x8000 + +#define DS_DLPLAY_SIGNATURE_PADDING_SIZE 512 // DS_E[hvCi[GATCY + +#define DIGEST_SIZE_SHA1 20 + +#define DEFAULT_ALIGN 512 +#define DEFAULT_HOSTROOT "." +#define DEFAULT_ROOT "/" +#define DEFAULT_ROMHEADER_TEMPLATE "rom_header.template.sbin" +#define DEFAULT_ROMHEADER_SURFFIX "_header.sbin" +#define DEFAULT_FILENAME_SURFFIX "_files.sbin" + +#define DEFAULT_REJECT { "CVS", "vssver.scc", ".?*", 0/*Terminater*/ } +#define DEFAULT_REJECT_CONSERVATIVE { "CVS", "vssver.scc", 0/*Terminater*/ } + +#define FORMAT_VERSION "1.1" + +#define ENTRYNAME_MAX 127 + +#define FILE_ID_START 0x0000 +#define FILE_ID_END 0xefff +#define DIR_ID_START 0xf000 +#define DIR_ID_END 0xffff + +#define DEFAULT_LISTFILE "default.nlf" + +#define DEFAULT_ROMFILE_SUFFIX ".srl" +#define DEFAULT_LISTFILE_SUFFIX ".nlf" +#define DEFAULT_LISTFILE_SUFFIX_TWL ".tlf" + +#define ROM_SIZE_MIN 0x20000 + +#define CRC16_INIT_VALUE 0xffff +#define CALC_CRC16_SIZE 0x15e + +#define SECURE_AREA_START 0x00004000 +#define SECURE_AREA_END 0x00008000 +#define SECURE_AREA_SIZE (SECURE_AREA_END - SECURE_AREA_START) + +#define CARD_LATENCY_MASK 0x083f1fff +#define CARD_MROM_GAME_LATENCY 0x00010017 +#define CARD_MROM_SECURE_HW_LATENCY 0x001808f8 +#define CARD_MROM_SECURE_SW_LATENCY 0x051e +#define CARD_1TROM_GAME_LATENCY 0x00010657 +#define CARD_1TROM_SECURE_HW_LATENCY 0x081808f8 +#define CARD_1TROM_SECURE_SW_LATENCY 0x0d7e + +// for out_romheader.c size check +#define BOOTABLE_SIZE_ARM9 0x00280000 // 2.5M +#define BOOTABLE_SIZE_ARM7 0x00040000 // 256K + +/*===========================================================================* + * ROM FORMAT + *===========================================================================*/ + +//--------------------------------------------------------------------------- +// Section A ROM HEADER +//--------------------------------------------------------------------------- + +#define ROMHEADER_CORP_ID "NINTENDO " +#define TITLE_NAME_MAX 12 +#define GAME_CODE_MAX 4 +#define MAKER_CODE_MAX 2 + +typedef struct ROM_Header_Short +{ + //========================================================== + // + // NTR/TWL common + // + //========================================================== + + // + // 0x000 System Reserved + // + char title_name[TITLE_NAME_MAX]; // Soft title name + char game_code[GAME_CODE_MAX]; // Game code + char maker_code[MAKER_CODE_MAX]; // Maker code + char platform_code; // Platform code bit0: not support NTR, bit1: support TWL ( NTR_only=0x00, NTR/TWL=0x03, TWL_only=0x02 ) + u8 rom_type; // Rom type + u8 rom_size; // Rom size (2rom_size Mbit: ex. 128Mbit̂Ƃrom_size = 7) + + u8 reserved_A[7]; // System Reserved A ( Set ALL 0 ) + + u8 enable_signature:1; // enable ROM Header signature + u8 enable_aes:1; // enable AES encryption + u8 developer_encrypt:1; // JpZLeBĂꍇ"1"Biłł"0" + u8: 5; + + u8: 6; + u8 for_korea:1; // For Korea + u8 for_china:1; // For China + + u8 rom_version; // Rom version + + u8 comp_arm9_boot_area:1; // Compress arm9 boot area + u8 comp_arm7_boot_area:1; // Compress arm7 boot area + u8 inspect_card:1; // Show inspect card + u8 disable_clear_memory_pad:1; // for Debugger + u8 enable_twl_rom_cache_read:1; // Enable TWL ROM cacheRead command + u8: 1; + u8 warning_no_spec_rom_speed:1;// Warning not to specify rom speed + u8 disable_detect_pull_out:1; // + + // + // 0x020 for Static modules (Section:B) + // + // ARM9 + u32 main_rom_offset; // ROM offset + void *main_entry_address; // Entry point + void *main_ram_address; // RAM address + u32 main_size; // Module size + + // ARM7 + u32 sub_rom_offset; // ROM offset + void *sub_entry_address; // Entry point + void *sub_ram_address; // RAM address + u32 sub_size; // Module size + + // + // 0x040 for File Name Table[FNT] (Section:C) + // + struct ROM_FNT *fnt_offset; // ROM offset + u32 fnt_size; // Table size + + // + // 0x048 for File Allocation Table[FAT] (Section:E) + // + struct ROM_FAT *fat_offset; // ROM offset + u32 fat_size; // Table size + + // + // 0x050 for Overlay Tables[OVT] (Section:D) + // + // ARM9 + struct ROM_OVT *main_ovt_offset; // ROM offset + u32 main_ovt_size; // Table size + + // ARM7 + struct ROM_OVT *sub_ovt_offset; // ROM offset + u32 sub_ovt_size; // Table size + + // 0x060 for ROM control parameter (Section:F) + u32 game_cmd_param; // Game command parameter + u32 secure_cmd_param; // Secure command parameter + + u32 banner_offset; // Banner ROM offset + + u16 secure_area_crc16; // Secure area CRC-16 + u16 secure_cmd_latency; // Secure command latency ((param+2)*256 system cycles) + + // since NITRO-SDK 2.0PR4 + void *main_autoload_done; // ARM9 autoload done callback address (debug purpose) + void *sub_autoload_done; // ARM7 autoload done callback address (debug purpose) + + u8 ctrl_reserved_B[8]; // Ctrl Reserved B (Set 0) + + // since NITRO-SDK 2.0PR6 + u32 rom_valid_size; // ROM Original Size + u32 rom_header_size; // ROM Header size + u32 main_module_param_offset; // Offset for table of ARM9 module parameters + u32 sub_module_param_offset; // Offset for table of ARM7 module parameters + + // 0x090 - 0x0C0 System Reserved + u16 twl_card_normal_area_rom_offset; // undeveloped + u16 twl_card_keytable_area_rom_offset; // undeveloped + u16 nand_card_dl_area_rom_offset; // undeveloped + u16 nand_card_bk_area_rom_offset; // undeveloped + u8 nand_card_flag; // undeveloped + u8 reserved_B[39]; + + // 0x0C0 for NINTENDO logo data + u8 nintendo_logo[0x9c]; // NINTENDO logo data + u16 nintendo_logo_crc16; // CRC-16 + + // 0x15E ROM header CRC-16 + u16 header_crc16; // ROM header CRC-16 + + // 0x160 - 0x180 Debugger Reserved + u8 reserved_C[32]; // Debugger Reserved (Set ALL 0) + + //========================================================== + // + // TWL only + // + //========================================================== + + // 0x180 - 0x190 TWL-WRAM A/B/C ARM9 configuration data + u32 main_wram_config_data[8]; // developing... + + // 0x1A0 - 0x1B0 TWL-WRAM A/B/C ARM7 configuration data + u32 sub_wram_config_data[4]; // developing... + + // 0x1B0 - reserved. + u8 reserved_ltd_A[ 15 ]; + + // 0x1BF - TWL expansion flags + u8 codec_mode:1; // 0:NTR mode, 1:TWL mode // undeveloped + u8: 3; + u8 enable_boot_nand:1; // undeveloped + u8 enable_boot_sd_card:1; // undeveloped + u8 enable_boot_game_card:1; // undeveloped + u8 enable_boot_download_play:1; // undeveloped + + // 0x1C0 for EX Static modules + // + // ARM9 + u32 main_ltd_rom_offset; // ROM offset // undeveloped + u8 reserved_ltd_B[ 4 ]; + void *main_ltd_ram_address; // RAM address // undeveloped + u32 main_ltd_size; // Module size // undeveloped + + // ARM7 + u32 sub_ltd_rom_offset; // ROM offset // undeveloped + u8 reserved_ltd_C[ 4 ]; + void *sub_ltd_ram_address; // RAM address // undeveloped + u32 sub_ltd_size; // Module size // undeveloped + + // 0x01E0 - 0x01E8 for NITRO digest area offset & size + u32 nitro_digest_area_rom_offset; + u32 nitro_digest_area_size; + + // 0x01E8 - 0x01F0 for TWL digest area offset & size + u32 twl_digest_area_rom_offset; + u32 twl_digest_area_size; + + // 0x01F0 - 0x01F8 for FS digest table1 offset & size + u32 digest1_table_offset; + u32 digest1_table_size; + + // 0x01F8 - 0x0200 for FS digest table1 offset + u32 digest2_table_offset; + u32 digest2_table_size; + + // 0x0200 - 0x0208 for FS digest config parameters + u32 digest1_block_size; + u32 digest2_covered_digest1_num; + + // 0x0208 - 0x0210 for Banner for TWL + u32 banner_twl_offset; + u32 banner_twl_size; + + // 0x0210 - 0x0218 for TWL rom valid size + u32 twl_rom_valid_size; // ROM Original Size + u8 reserved_ltd_D[ 4 ]; + + // 0x0218 - 0x0220 for TWL ltd module param offset + u32 main_ltd_module_param_offset; // Offset for table of ARM9 ltd module parameters + u32 sub_ltd_module_param_offset; // Offset for table of ARM7 ltd module parameters + + // 0x0220 - 0x0230 for AES target offset & size + u32 aes_target_rom_offset; + u32 aes_target_size; + u8 reserved_ltd_E[ 8 ]; + + // 0x230 - 0x300 reserved. + u8 reserved_ltd_F[ 0x300 - 0x230 ]; + + // 0x300 - 0x378 Rom Segment Digest + u8 main_static_digest[ DIGEST_SIZE_SHA1 ]; + u8 sub_static_digest[ DIGEST_SIZE_SHA1 ]; + u8 digest2_table_digest[ DIGEST_SIZE_SHA1 ]; + u8 banner_twl_digest[ DIGEST_SIZE_SHA1 ]; + u8 main_ltd_static_digest[ DIGEST_SIZE_SHA1 ]; + u8 sub_ltd_static_digest[ DIGEST_SIZE_SHA1 ]; + + +#ifdef ENABLE_OVERLAY_DIGEST_ANNEX + // ͖B + // overlaỹ_CWFXǵAcompstaticstaticW[ɕtA + // DS_E[hvCp̃I[o[C_CWFXggp̂ŁAȂB + // ܂Aoverlay_ex́AoverlayƋʉ\Ȃ̂ŁAOVT_CWFXge[uȂB + u32 main_overlay_digest_table_offset; + u32 sub_overlay_digest_table_offset; + u8 main_overlay_digesttable_digest[ DIGEST_SIZE_SHA1 ]; + u8 sub_overlay_digesttable_digest[ DIGEST_SIZE_SHA1 ]; + +#endif // ENABLE_OVERLAY_DIGEST_ANNEX +} +ROM_Header_Short; + +typedef struct +{ + struct ROM_Header_Short s; + + //// + //// EXTRA SYSTEM REGION + //// + + // + // 0x02f0 - 0x0e00 System Reserved + // + u8 reserved_D[4 * 1024 - sizeof(ROM_Header_Short) - sizeof(RomCertificate) - RSA_KEY_LENGTH ]; // Reserved D + + // + // 0x0e00 - 0x0f80 ROM Certificate + // + RomCertificate certificate; + + // + // 0x0f80 - 0x1000 ROM Header Signature + // + u8 signature[ RSA_KEY_LENGTH ]; // PKCS#1_v1.5̌`ŃtH[}bgꂽSignatureDataARSAÍꂽ + + // + // 0x01000 - 0x04000 System Reserved + // + u8 reserved_E[12 * 1024]; // Reserved E + +} +ROM_Header; // 16KB + + + +// (ROM_Header.signature)̃f[^ +typedef struct SignatureData +{ + u8 aes_key_seed[ AES_BLOCK_SIZE ]; + u8 digest[ DIGEST_SIZE_SHA1 ]; +}SignatureData; + + + +//--------------------------------------------------------------------------- +// Section C FNT: FILE NAME TABLE +// - DIRECTORY TABLE +// - ENTRY TABLE +//--------------------------------------------------------------------------- + +typedef struct ROM_FNTDir +{ + u32 entry_start; // offset for entry + u16 entry_file_id; // file id for 1st file + u16 parent_id; // parent directory id + +} +ROM_FNTDir; + + +/* P-SEUDO CODE for YOUR INFO. +typedef struct ROM_FNTStrFile +{ + u8 entry_type :1; // 0 if file entry + u8 entry_name_length:7; // length of filename (0-127) + char entry_name[length]; // file name (surpress '\0') + +} ROM_FNTStrFile; + + +typedef struct ROM_FNTStrDir +{ + u8 entry_type :1; // 1 if directory entry + u8 entry_name_length:7; // length of directory name (0-127) + char entry_name[length]; // directory name (surpress '\0') + u8 dir_id_L; // low byte of directory id + u8 dir_id_H; // high byte of directory id +} ROM_FNTStrDir; +*/ + +//--------------------------------------------------------------------------- +// Section D OVT: OVERLAY TABLE +//--------------------------------------------------------------------------- + +typedef struct ROM_OVT +{ + void *id; // Overlay ID + void *ram_address; // ram address + u32 ram_size; // ram size + u32 bss_size; // bss size + void *sinit_init; // static initializer start + void *sinit_init_end; // static initializer end + u32 file_id; // file id in FAT + u32 compressed:24; // I[o[Ck̃TCY + u32 flag:8; // I[o[CtO + +} +ROM_OVT; + + +//--------------------------------------------------------------------------- +// Section E FAT: FILE ALLOCATION TABLE +//--------------------------------------------------------------------------- + +typedef struct ROM_FilePtr +{ + u32 offset; // offset + +} +ROM_FilePtr; + + +typedef struct ROM_FAT +{ + ROM_FilePtr top; // file region start + ROM_FilePtr bottom; // end + +} +ROM_FAT; + + +//--------------------------------------------------------------------------- +// Section F LT: ROM LATENCY +//--------------------------------------------------------------------------- + +typedef enum +{ + ONETROM = 0, + MROM +} +tRomSpeedType; + +typedef struct ROM_LT +{ + u32 game_latency; + u32 secure_hw_latency; + u16 secure_sw_latency; + +} +ROM_LT; + + +//--------------------------------------------------------------------------- +// Section X ONT: OVERLAY NAME TABLE (not include in ROM) generated by LD +// - OverlayDefs +//--------------------------------------------------------------------------- + +typedef struct ROM_ONTHeader +{ + void *static_ram_address; // static module ram_address + void *static_entry_address; // entry address + u32 static_size; // size + void *static_autoload_done; // autoload done callback address + +} +ROM_ONTHeader; + +typedef struct ROM_ONT +{ + ROM_ONTHeader header; + char file_list[1]; + +} +ROM_ONT; + +#define SIZE_OF_SIGN 136 +#define NITROCODE_LE 0x2106c0de +#define NITROCODE_BE 0xdec00621 +#define TWLCODE_LE 0x6314c0de +#define TWLCODE_BE 0xdec01463 + +//--------------------------------------------------------------------------- +// Section Y MDP: Module params +//--------------------------------------------------------------------------- +typedef struct tModuleParam +{ + void *autoload_list; + void *autoload_list_end; + void *autoload_start; + void *static_bss_start; + void *static_bss_end; + void *compressed_static_end; // tCompFooter 1vfw + u32 version; + u32 nitro_magic_be; + u32 nitro_magic_le; + +} +tModuleParam; + +typedef struct tLtdModuleParam +{ + void *autoload_list; + void *autoload_list_end; + void *autoload_start; + void *compressed_static_end; // tCompFooter 1vfw + u32 twl_magic_be; + u32 twl_magic_le; +} +tLtdModuleParam; + + +typedef struct +{ + u32 bufferTop:24; + u32 compressBottom:8; + u32 originalBottom; +} +tCompFooter; + +typedef struct // compstatic/component.h蔲 +{ + u32 magicNumber; // Fq ==MAGICNUMBER_FOOTER + int staticParamsOffset; // StaticParams ւ̃ItZbg + int digestParamsOffset; // SDK_DIGEST_TABLE ւ̃ItZbg + int ltdStaticParamsOffset; // LtdStaticParams ւ̃ItZbg +} +StaticFooter; + +#endif //FORMAT_ROM_H_ diff --git a/include/firm/format/format_rom_certificate.h b/include/firm/format/format_rom_certificate.h new file mode 100644 index 0000000..859d40a --- /dev/null +++ b/include/firm/format/format_rom_certificate.h @@ -0,0 +1,50 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - tools - makerom.TWL + File: format_rom_certificate.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FORMAT_ROM_CERTIFICATE_H_ +#define FORMAT_ROM_CERTIFICATE_H_ + +//#include "misc.h" + +/*===========================================================================* + * ROM CERTIFICATE FORMAT + *===========================================================================*/ + +#define TWL_ROM_CERT_MAGIC_NUMBER 0x54524543 // "CERT"̕ + +#define RSA_KEY_LENGTH ( 1024 / 8 ) +#define ROM_CERT_SIGN_OFFSET 256 + +#define ROM_HEADER_SIGN_TARGET_SIZE 0xe00 + +// ROMؖwb_ +typedef struct RomCertificateHeader { + u32 magicNumber; + u32 version; + u32 serialNo; + u32 gameCode; +}RomCertificateHeader; + +// ROMؖ +typedef struct RomCertificate { + RomCertificateHeader header; + u8 reserved[ ROM_CERT_SIGN_OFFSET - sizeof(RomCertificateHeader) - RSA_KEY_LENGTH ]; + u8 pubKeyMod[ RSA_KEY_LENGTH ]; + u8 sign[ RSA_KEY_LENGTH ]; +}RomCertificate; + +#endif //FORMAT_ROM_CERTIFICATE_H_ diff --git a/include/firm/format/from_brom.h b/include/firm/format/from_brom.h new file mode 100644 index 0000000..cad8390 --- /dev/null +++ b/include/firm/format/from_brom.h @@ -0,0 +1,100 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - format - from_brom + File: from_brom.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_FORMAT_FROM_BROM_H_ +#define FIRM_FORMAT_FROM_BROM_H_ + +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SDK_ARM9 +#define RSA_PUBKEY_NUM_FROM_BROM 8 +#define AESKEY_NUM_FROM_BROM 8 +#else // SDK_ARM7 +#define RSA_PUBKEY_NUM_FROM_BROM 4 +#define AESKEY_NUM_FROM_BROM 4 +#endif // SDK_ARM7 + + +// sizeof(SDPortContext) +typedef struct SDportContextData +{ + u32 data[17]; +} +SDPortContextData; + + +typedef struct +{ + union + { + NANDHeader nand; + NORHeader nor; + GCDHeader gcd; + u8 max[0x400]; + } + header; // 1KB + + u8 rsa_pubkey[RSA_PUBKEY_NUM_FROM_BROM][ACS_PUBKEY_LEN]; // 1KB + u8 aes_key[AESKEY_NUM_FROM_BROM][ACS_AES_LEN]; // 128B + u8 hash_table_hash[ACS_HASH_LEN]; // 20B + + BLOWFISH_CTX ds_blowfish; // 4KB + + BLOWFISH_CTX twl_blowfish; // 4KB + +} +OSFromBrom9Buf; + +typedef struct +{ + union + { + NANDHeader nand; + NORHeader nor; + GCDHeader gcd; + u8 max[0x400]; + } + header; // 1KB + + u8 rsa_pubkey[RSA_PUBKEY_NUM_FROM_BROM][ACS_PUBKEY_LEN]; // 512B + u8 aes_key[AESKEY_NUM_FROM_BROM][ACS_AES_LEN]; // 64B + u8 hash_table_hash[ACS_HASH_LEN]; // 20B + + BLOWFISH_CTX twl_blowfish[2]; // (4KB + ) * 2 + + SDPortContextData SDNandContext; +} +OSFromBrom7Buf; + +#ifdef SDK_ARM9 +typedef OSFromBrom9Buf OSFromBromBuf; +#else // SDK_ARM7 +typedef OSFromBrom7Buf OSFromBromBuf; +#endif // SDK_ARM7 + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // FIRM_FORMAT_FROM_BROM_H_ diff --git a/include/firm/format/gcdfirm.h b/include/firm/format/gcdfirm.h new file mode 100644 index 0000000..3e489a1 --- /dev/null +++ b/include/firm/format/gcdfirm.h @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - format - gcdfirm + File: gcdfirm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_FORMAT_GCDFIRM_H_ +#define FIRM_FORMAT_GCDFIRM_H_ + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*===========================================================================* + * NOR FORMAT + *===========================================================================*/ + +//--------------------------------------------------------------------------- +// Section A NOR HEADER +//--------------------------------------------------------------------------- + +// 풓W[ +typedef FIRMHeader_ModuleInfo GCDHeader_ModuleInfo; + +// TWL-GCDt@[wb_ +typedef struct +{ + /* 0x000-0x020 [VXe\̈] */ + u8 reserved_0h[0x14]; + u8 rom_size; // Rom size (2rom_size Mbit: ex. 128Mbit̂Ƃrom_size = 7) + u8 reserved_16h[0xb]; + + /* 0x020-0x040 [풓W[pp[^] */ + u32 main_rom_offset; /* ARM9 ] ROM ItZbg */ + u32 main_decomp_size; /* ARM9 WJTCY */ + void *main_ram_address; /* ARM9 ] RAM ItZbg */ + u32 main_size; /* ARM9 ]TCY */ + u32 sub_rom_offset; /* ARM7 ] ROM ItZbg */ + u32 sub_decomp_size; /* ARM9 WJTCY */ + void *sub_ram_address; /* ARM7 ] RAM ItZbg */ + u32 sub_size; /* ARM7 ]TCY */ + + /* 0x040-0x080 [VXe\̈] */ + u8 reserved_40h[0x40]; + + /* 0x080-0x090 [t@[oCi] */ + u32 nandfirm_offset; // address of rom_valid_size + u32 nandfirm_size; // address of rom_header_size + u32 norfirm_offset; // address of main_module_param + u32 norfirm_size; // address of sub_module_param + + /* 0x090-0x094 [TWL-ROMRg[] */ + u16 normal_area_offset; + u16 twl_area_offset; + + /* 0x094-0x0c0 [VXe\̈] */ + u8 reserved_98h[0x2c]; + + /* 0x0c0-0x100 [DSJ[hNINTENDOSd̈] */ + u8 reserved_C0h[0x3f]; + + u8 comp_arm9_boot_area:1; // Compress arm9 boot area + u8 comp_arm7_boot_area:1; // Compress arm7 boot area + u8 arm9_x2:1; + u8 :0; +} +GCDHeaderLow; + +typedef struct +{ + /* 0x180-0x1b0 [WRAMWX^p[^] */ + MIHeader_WramRegs w; + + /* 0x1b0-0x200 [VXe\̈] */ + u8 reserved_footer[0x50]; +} +GCDHeaderHigh; + +// GCDwb_ +typedef struct +{ + /* 0x000-0x100 */ + GCDHeaderLow l; + + /* 0x100-0x180 */ + FIRMPaddedSign sign; + + /* 0x180-0x200 */ + GCDHeaderHigh h; +} +GCDHeader; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //FIRM_FORMAT_GCDFIRM_H_ diff --git a/include/firm/format/nandfirm.h b/include/firm/format/nandfirm.h new file mode 100644 index 0000000..68b9ad6 --- /dev/null +++ b/include/firm/format/nandfirm.h @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - format - nandfirm + File: nandfirm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_FORMAT_NAND_H_ +#define FIRM_FORMAT_NAND_H_ + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*===========================================================================* + * NAND FORMAT + *===========================================================================*/ + +//--------------------------------------------------------------------------- +// Section A NAND HEADER +//--------------------------------------------------------------------------- + +// 풓W[ +typedef FIRMHeader_ModuleInfo NANDHeader_ModuleInfo; + +// TWL-NANDt@[wb_ +typedef struct +{ + /* 0x000-0x020 [VXe\̈] */ + u8 reserved_0h[0x20]; /* VXe\ A */ + + /* 0x020-0x040 [풓W[pp[^] */ + u32 main_rom_offset; /* ARM9 ] ROM ItZbg */ + u32 main_decomp_size; /* ARM9 WJTCY */ + void *main_ram_address; /* ARM9 ] RAM ItZbg */ + u32 main_size; /* ARM9 ]TCY */ + u32 sub_rom_offset; /* ARM7 ] ROM ItZbg */ + u32 sub_decomp_size; /* ARM9 WJTCY */ + void *sub_ram_address; /* ARM7 ] RAM ItZbg */ + u32 sub_size; /* ARM7 ]TCY */ + + /* 0x040-0x0c0 [VXe\̈] */ + u8 reserved_40h[0x80]; + + /* 0x0c0-0x100 [DSJ[hNINTENDOSd̈] */ + u8 reserved_C0h[0x3f]; + + u8 comp_arm9_boot_area:1; // Compress arm9 boot area + u8 comp_arm7_boot_area:1; // Compress arm7 boot area + u8 arm9_x2:1; + u8 arm9_decomp:1; + u8 :0; +} +NANDHeaderLow; + +typedef struct +{ + /* 0x180-0x1b0 [WRAMWX^p[^] */ + MIHeader_WramRegs w; + + /* 0x1b0-0x200 [VXe\̈] */ + u8 reserved_footer[0x50]; +} +NANDHeaderHigh; + +// NANDwb_ +typedef struct +{ + /* 0x000-0x028 [DS-NORwb_] */ + NORHeaderDS d; + + /* 0x028-0x200 [VXe\̈(O)] */ + u8 reserved_mbr[512 - sizeof(NORHeaderDS)]; + + /* 0x200-0x300 */ + NANDHeaderLow l; + + /* 0x300-0x380 */ + FIRMPaddedSign sign; + + /* 0x380-0x400 */ + NANDHeaderHigh h; +} +NANDHeader; + +// 璷wb_ (璷) +typedef struct +{ + /* 0x400-0x500 *//* 0x600-0x700 */ + NANDHeaderLow l; + + /* 0x500-0x580 *//* 0x700-0x780 */ + FIRMPaddedSign sign; + + /* 0x580-0x600 *//* 0x780-0x800 */ + NANDHeaderHigh h; +} +NANDHeaderCore; + +// 璷wb_ (S) +typedef struct +{ + /* 0x000-0x400 [ۂɎgpwb_] */ + NANDHeader g; + /* 0x400-0x600 [ftHgʒuC[Wɑ΂wb_] */ + NANDHeaderCore o; + /* 0x600-0x800 [ꎞҔʒuC[Wɑ΂wb_] */ + NANDHeaderCore m; +} +NANDHeaderEx; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //FIRM_FORMAT_NAND_H_ diff --git a/include/firm/format/norfirm.h b/include/firm/format/norfirm.h new file mode 100644 index 0000000..27587fa --- /dev/null +++ b/include/firm/format/norfirm.h @@ -0,0 +1,108 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - format - norfirm + File: norfirm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_FORMAT_NOR_H_ +#define FIRM_FORMAT_NOR_H_ + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*===========================================================================* + * NOR FORMAT + *===========================================================================*/ + +//--------------------------------------------------------------------------- +// Section A NOR HEADER +//--------------------------------------------------------------------------- + +// 풓W[ +typedef FIRMHeader_ModuleInfo NORHeader_ModuleInfo; + +// TWL-NORt@[wb_ +typedef struct +{ + /* 0x000-0x020 [VXe\̈] */ + u8 reserved_0h[0x20]; /* VXe\ A */ + + /* 0x020-0x040 [풓W[pp[^] */ + u32 main_rom_offset; /* ARM9 ] ROM ItZbg */ + u32 main_decomp_size; /* ARM9 WJTCY */ + void *main_ram_address; /* ARM9 ] RAM ItZbg */ + u32 main_size; /* ARM9 ]TCY */ + u32 sub_rom_offset; /* ARM7 ] ROM ItZbg */ + u32 sub_decomp_size; /* ARM9 WJTCY */ + void *sub_ram_address; /* ARM7 ] RAM ItZbg */ + u32 sub_size; /* ARM7 ]TCY */ + + /* 0x040-0x0c0 [VXe\̈] */ + u8 reserved_40h[0x80]; + + /* 0x0c0-0x100 [DSJ[hNINTENDOSd̈] */ + u8 reserved_C0h[0x3f]; + + u8 comp_arm9_boot_area:1; // Compress arm9 boot area + u8 comp_arm7_boot_area:1; // Compress arm7 boot area + u8 arm9_x2:1; + u8 arm9_decomp:1; + u8 :2; + u8 baudrate:1; + u8 boot_nandfirm:1; +} +NORHeaderLow; + +typedef struct +{ + /* 0x180-0x1b0 [WRAMWX^p[^] */ + MIHeader_WramRegs w; + + /* 0x1b0-0x200 [VXe\̈] */ + u8 reserved_footer[0x50]; +} +NORHeaderHigh; + +// NORwb_ +typedef struct +{ + /* 0x000-0x028 */ + NORHeaderDS d; + + /* 0x028-0x200 */ + u8 wl_params[472]; + + /* 0x200-0x300 */ + NORHeaderLow l; + + /* 0x300-0x380 */ + FIRMPaddedSign sign; + + /* 0x380-0x400 */ + NORHeaderHigh h; +} +NORHeader; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //FIRM_FORMAT_NOR_H_ diff --git a/include/firm/format/sign.h b/include/firm/format/sign.h new file mode 100644 index 0000000..25887d7 --- /dev/null +++ b/include/firm/format/sign.h @@ -0,0 +1,95 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - format - sign + File: sign.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FORMAT_SIGN_H_ +#define FORMAT_SIGN_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +// signed hash index +typedef enum +{ + FIRM_SIGNED_HASH_IDX_HEADER = 0, + FIRM_SIGNED_HASH_IDX_ARM9 = 1, + FIRM_SIGNED_HASH_IDX_ARM7 = 2, + FIRM_SIGNED_HASH_IDX_HASH_TABLE = 3, + FIRM_SIGNED_HASH_IDX_FINAL = 4, + + FIRM_SIGNED_HASH_NUM = 5 +} +FIRMSignedHashIndex; + + +#define ACS_BASE_BLOCK_SIZE 4096 // should be the multiple of 16 +#define ACS_META_BLOCK_SIZE 5120 // should be the multiple of 16 and the multiple of 20 + // would be the multiple of 512, then the mutilple of 2560 + +#define ACS_PUBKEY_LEN 128 +#define ACS_HASH_LEN 20 +#define ACS_AES_LEN 16 + +#define ACS_ENCRYPTED_HASH_LEN ACS_PUBKEY_LEN +#define ACS_DECRYPTED_HASH_LEN ACS_HASH_LEN + +#define ACS_RSA_EXP 0x00010001 +#define ACS_RSA_EXP_LEN 3 + +// DER format of RSA keys + +#define ACS_RSA_PRVMOD_OFFSET 0x0B +#define ACS_RSA_PRVEXP_OFFSET 0x93 +#define ACS_RSA_PRVMOD_LEN 128 +#define ACS_RSA_PRVEXP_LEN 128 + +#define ACS_RSA_PUBMOD_OFFSET 0x1D +#define ACS_RSA_PUBEXP_OFFSET 0x93 +#define ACS_RSA_PUBMOD_LEN 128 +#define ACS_RSA_PUBEXP_LEN ACS_RSA_EXP_LEN + +#define FIRM_HEADER_2ND_HASH_AREA_LEN (sizeof(FIRMSignedContext) - ACS_HASH_LEN) + + +// ReLXg +typedef struct +{ + unsigned char aes_key[ACS_AES_LEN]; + unsigned char hash[FIRM_SIGNED_HASH_NUM][ACS_HASH_LEN]; +} +FIRMSignedContext; + +// +typedef union +{ + struct + { + unsigned char prePad[(ACS_ENCRYPTED_HASH_LEN - sizeof(FIRMSignedContext))-1]; + FIRMSignedContext c; + unsigned char postPad[1]; + } + e; + unsigned int raw[ACS_ENCRYPTED_HASH_LEN/4]; +} +FIRMPaddedSign; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //FORMAT_SIGN_H_ diff --git a/include/firm/format/wram_regs.h b/include/firm/format/wram_regs.h new file mode 100644 index 0000000..08c8d19 --- /dev/null +++ b/include/firm/format/wram_regs.h @@ -0,0 +1,85 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - MI - include + File: wram_regs.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_FORMAT_WRAM_REGS_H_ +#define FIRM_FORMAT_WRAM_REGS_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef enum +{ + MI_WRAM_A_OFFSET_0KB = 0, + MI_WRAM_A_OFFSET_64KB = 1, + MI_WRAM_A_OFFSET_128KB = 2, + MI_WRAM_A_OFFSET_192KB = 3 +} MIWramAOffset; + +typedef enum +{ + MI_WRAM_BC_OFFSET_0KB = 0, + MI_WRAM_BC_OFFSET_32KB = 1, + MI_WRAM_BC_OFFSET_64KB = 2, + MI_WRAM_BC_OFFSET_96KB = 3, + MI_WRAM_BC_OFFSET_128KB = 4, + MI_WRAM_BC_OFFSET_160KB = 5, + MI_WRAM_BC_OFFSET_192KB = 6, + MI_WRAM_BC_OFFSET_224KB = 7 +} MIWramBCOffset; + + +#define MI_WRAM_MAP_NULL HW_WRAM_AREA + +#define REG_WRAM_MAP_CONV_ADDR( regno, abc, border, addr ) \ +( \ + ((((addr) - HW_WRAM_AREA) / MI_WRAM_##abc##_SLOT_SIZE) & \ + (REG_MI_MBK##regno##_W##abc##_##border##_MASK >> \ + REG_MI_MBK##regno##_W##abc##_##border##_SHIFT)) \ +) + + +// WRAM}bsOWX^ +typedef struct +{ + u8 main_wrambnk_a[4]; // ARM9 SCFG_MBK1 + u8 main_wrambnk_b[8]; // ARM9 SCFG_MBK2-3 + u8 main_wrambnk_c[8]; // ARM9 SCFG_MBK4-5 + + u32 main_wrammap_a; // ARM9 SCFG_MBK6 + u32 main_wrammap_b; // ARM9 SCFG_MBK7 + u32 main_wrammap_c; // ARM9 SCFG_MBK8 + + u32 sub_wrammap_a; // ARM7 SCFG_MBK6 + u32 sub_wrammap_b; // ARM7 SCFG_MBK7 + u32 sub_wrammap_c; // ARM7 SCFG_MBK8 + + u8 sub_wramlock[3]; // ARM7 SCFG_MBK9 + + u8 main_wrambnk_01:2; // ARM9 RBKCNT1_H + u8 main_vrambnk_c:3; // ARM9 RBKCNT0_H + u8 main_vrambnk_d:3; // ARM9 RBKCNT0_H +} +MIHeader_WramRegs; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_FORMAT_WRAM_REGS_H_ */ +#endif diff --git a/include/firm/gcd.h b/include/firm/gcd.h new file mode 100644 index 0000000..26593c55 --- /dev/null +++ b/include/firm/gcd.h @@ -0,0 +1,26 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - GCD + File: gcd.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_GCD_H_ +#define FIRM_GCD_H_ + +//#include +#include +#include + +/* FIRM_GCD_H_ */ +#endif diff --git a/include/firm/gcd/blowfish.h b/include/firm/gcd/blowfish.h new file mode 100644 index 0000000..bba522a --- /dev/null +++ b/include/firm/gcd/blowfish.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - GCD - include + File: blowfish.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_GCD_BLOWFISH_H +#define FIRM_GCD_BLOWFISH_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + u32 P[16 + 2]; + u32 S[4][256]; +} BLOWFISH_CTX; + + +void InitBlowfish(BLOWFISH_CTX *ctx, const unsigned char *key, int keyLen); +void EncryptByBlowfish(const BLOWFISH_CTX *ctx, u32 *xl, u32 *xr); +void DecryptByBlowfish(const BLOWFISH_CTX *ctx, u32 *xl, u32 *xr); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // FIRM_GCD_BLOWFISH_H diff --git a/include/firm/gcd/gcd.h b/include/firm/gcd/gcd.h new file mode 100644 index 0000000..c910675 --- /dev/null +++ b/include/firm/gcd/gcd.h @@ -0,0 +1,779 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - GCD - include + File: gcd.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_GCD_GCD_H_ +#define FIRM_GCD_GCD_H_ + +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + GCD_PRIMARY_SLOT = 0, + GCD_SECONDARY_SLOT = 1, + + GCD_NO_SLOT = -1 +} +GCDSlot; + + +/*****************/ + +/* ROMwb_Eu[gp[^\ */ +typedef struct { + u8 *romAddr; // ROMAhX + u8 *entryAddr; // GgAhX + u8 *ramAddr; // RAMAhX + s32 romSize; // ROMTCY +} GCDBootUsrParam; + +// J[hANZXERg[WX^\ +typedef struct { + u16 latency1:13; // CeVP̃TCN + u16 dataScramble_on:1; // f[^XNu nm + u16 scrambleUnit_on:1; // XNuH nm + u16 initScramblePN:1; // XNuomf[^ + u16 latency2:6; // CeVQ̃TCN + u16 cmdScramble_on:1; // R}hXNu nm + u16 dataReady:1; // f[^ fB + u16 pages:3; // y[W + u16 clockType:1; // NbN^CviPTO^QSOj + u16 clockInLatency:1; // CeVԂɃNbN + u16 reset:1; // ZbgM + u16 accessMode:1; // ANZX[h + u16 start:1; // X^[g +} GCDCardCnt; + +// J[hRg[Ep[^\ +typedef struct { + // u32 dmaNo; // DMAԍ + u32 cardCnt; // J[hRg[ + u32 op[2]; // R}h +} GCDCardCtrlParam; + + +/* ROMwb_\ */ +typedef struct { + s8 titleName[12]; // \tg^Cg + u32 initialCode; // CjVR[h + + u16 makerCode; // [J[R[h + u8 machineCode; // {̃R[h + u8 deviceType; // foCX^Cv + + u8 nonVerReserved[4]; // \i4oCgj + u8 verDepReserved[4]; // \io[WˑA4oCgj + u16 wirelessSerialNo; + u16 softVersion:8; // \tgo[W + u16 compArm9BootArea:1; // ARM9u[gGAktO + u16 compArm7BootArea:1; // ARM7u[gGAktO + u16 :0; + + GCDBootUsrParam arm9; // ARM9u[g̈p[^ + GCDBootUsrParam arm7; // ARM7u[g̈p[^ + + u32 fileSysReserved[8]; // t@CVXe\i32oCgj + + GCDCardCnt romCtrl4Game; // ROMRg[iNORMAL & GAME[hj + GCDCardCnt romCtrl4Secure; // iSECURE[hj + u8 romCtrlReserved_l[4]; // \ + u16 secureCRC16; // ZLÄCRC16bit + u16 romTimerLatency; // ^C}[CeVi(TCN/256) - 2A3Dpj + u8 romReserved_h[8]; // \ + u32 romNormalModeKey[2]; // NORMAL[hL[ + + u8 reserved_80h[0x10]; // \̈i16oCgj + + u16 normalAreaOffset; // NORMAL̈ + u16 twlAreaOffset; // TWLp̈ + + u8 reserved_94h[0x2c]; // \̈i44oCgj + + u16 nintendoLogo[0x9c/2]; // NINTENDOSi156oCgj + u16 ninLogoCRC16; // NINTENDOSCRC16 + u16 headerCRC16; // wb_CRC16 + + u8 *dbgRomAddr; // fobKj^ROMAhX + s32 dbgRomSize; // fobKj^ROMTCY + u8 *dbgArm9RamAddr; // fobKj^ARM9-RAMAhX + u8 *dbgArm7RamAddr; // fobKj^ARM7-RAMAhX + + u8 reserved_170h[0x10]; // \̈i16oCgj +} +GCDRomHeaderDS; + +typedef struct { + // DS݊ + GCDRomHeaderDS l; + + // TWLg + MIHeader_WramRegs w; + + u8 reserved_1b0h[0x10]; // \̈i16oCgj + + GCDBootUsrParam arm9ex; // ARM9gu[g̈p[^ + GCDBootUsrParam arm7ex; // ARM7gu[g̈p[^ + + u8 reserved_1e0h[0x1000 - 0x1e0 - 0x200]; // \̈ + + u8 acsign_contents[0x180]; // Recؖ + + u8 acsign_header[0x80]; // ROMwb_dq +} +GCDRomHeader; + + +/* ZLA[N\ */ +typedef struct { + u8 recvRtcBuf[8]; // RTCf[^Mobt@iv4oCgEj +#if 0 + u16 flashCrc16; // tbVCRC16 + u16 flashCount; // tbV 8oCgJEg + u32 flashBuf[2]; // tbVMobt@iv4oCgEj + u32 flashKeyBuf[3]; // tbVL[Ee|obt@ +#endif + u32 unScrambleKey[2]; // XNuL[i8oCgAMakeBlowfishTable() ŎZoj + s16 isGenUnScrambleKey; // XNuL[iMakeBlowfishTable() Őݒj + + u32 va; // 24biti24bitMj + u32 vb; // 20biti+`4bitAVBI: 32bitMj + u32 vc_dummy; // 16biti16bitMj + u32 vd; // 24biti24bitMj + + GCDCardCnt cardCntBak4Secure; // SECURER}hp[^EobNAbv + s16 enableReadSecure; // SECURË惊[hECl[uiLoadSecure4Card() Őݒj + u32 cardNormalModeKey[2]; // NORMAL[hL[iMakeBlowfishTable() ŎZoj + u32 cardKeyBuf[3]; // J[hL[Ee|obt@ + s32 secureSize; // SECURËTCY + s16 sequenceNo4Secure; // V[PXԍiSECUREpj + s16 segmentTblShift; // ZOgԍe[uVtgliSECUREpj + u8 *segmentTblp; // ZOge[u|C^iSECUREpj + s16 numSecureSegment; // SECUREZOgiSECUREpj + s16 segmentOffset; // ZOgItZbgiSECUREpj + s16 blockOffset; // ubNItZbgiSECUREpj + + // CardCtrlParam paramBak; // J[hp[^ ÍOobNAbviSECUREpj + + BLOWFISH_CTX blowfishCardTable; // J[hpBlowfishe[u + BLOWFISH_CTX blowfishFlashTable; + + u8 bufEnd[4]; // ZLA[NŏIf[^ +} GCDSecureWork; + + +/* L[N\ */ +typedef struct { + u32 nCardID; // NORMALJ[hIDiLoadCardHeader() Ŏ擾j + u32 sCardID; // SECUREJ[hIDiCardTimerIntr4Secure() Ŏ擾j + u16 cardHeaderCrc16; // J[hwb_CRC16iLoadCardHeader() ŎZoj + u16 cardSecureCrc16; // J[hSECURËCRC16iLoadSecure4Card() ŎZoj + s16 cardHeaderError; // J[hwb_G[iCheckCardHeader() Őݒj + s16 disableEncryptedCardData;// J[hSECURËÍf[^iDecryptObjectFile() Őݒj + s16 cardSequenceNo; // J[hǂݍ݃V[PXԍ + s16 enableCardNormalOnly; // J[hNORMAL[ĥݗLiLoadFlashDemo() Őݒj + + // s16 isOnDebugger; // fobKœ쒆 + // s16 rtcError; // RTCG[ + + u32 recvRtc[2]; // RTCXe[^X1^C}[f[^iv4oCgEj + +} GCDSharedWork; + + +typedef union +{ + u64 dw; + u8 b[8]; +} +GCDCmd64; + +typedef struct +{ + u32 ctrl; + s32 cmdcount; + u32 latency; + u32 scramble; + u8 master; + u8 spi; + GCDSlot slot; +} +GCDCtrlRegs; + +typedef struct +{ + GCDCmd64 gcdOp; + u32 dmaNo; + u32 lastDmaNo; + BOOL ltckReq; + GCDCtrlRegs *gcdRegs; + GCDCtrlRegs nLoadTableRegs; + GCDCtrlRegs nSendOnlyOpRegs; + GCDCtrlRegs sSendOnlyOpRegs; + GCDCtrlRegs nIDRegs; + GCDCtrlRegs sIDRegs; + GCDCtrlRegs gIDRegs; + GCDCtrlRegs nReadShortHeaderRegs; + GCDCtrlRegs nReadRomRegs; + GCDCtrlRegs sReadRomRegs; + GCDCtrlRegs gReadRomRegs; + GCDCtrlRegs gWriteRomRegs; +} +GCDRomCtrls; + +typedef void (* GCDRomFuncp)( u32 romp, void *ramp, s32 size ); +typedef void (* GCDAsyncCoreFuncp)( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDRomCtrls *ctrls ); + + +typedef struct +{ + u32 romp; // ROM offset + u8 *ramp; // RAM address + s32 restSize; // rest size + s32 oneShotSize; // one shot size + vs8 intrDone; + s8 isAsync; + volatile BOOL isPxiDone; + GCDRomCtrls ctrls; + GCDAsyncCoreFuncp funcp; +} +GCDWork; + + +#define GCD_DEFAULT_DMA_A_NO 7 +#define GCD_DEFAULT_DMA_B_NO 6 + +#define GCD_CHATTERING_CYCLES 0x200U + +#define GCD_ROM_PAGE_SIZE 0x200 // 512B +#define GCD_SECURE_SEGMENT_SIZE 0x1000 // 4KB +#define GCD_LOAD_TABLE_SIZE 0x2000 // 8KB + +#define GCD_NML_AREA_ALIGN 0x80000 // 512KB +#define GCD_TWL_AREA_ALIGN 0x80000 // 512KB +#define GCD_SECURE2_AREA_SIZE 0x4000 // 16KB +#define GCD_SECURE2_AREA_OFFSET 0x3000 // 12KB +#define GCD_GAME2_AREA_OFFSET 0x7000 // 28KB + + +// ROM area + +#define GCD_LOAD_TABLE_SIZE 0x2000 // 8KB +#define GCD_DS_ROM_HEADER_SIZE 0x200 // 512B +#define GCD_ROM_HEADER_SIZE 0x1000 // 4KB +#define GCD_SECURE_AREA_SIZE 0x4000 // 16KB + +#define GCD_SECURE_AREA_OFFSET 0x4000 +#define GCD_GAME_AREA_OFFSET 0x8000 + + +// ROM command + +#define GCDOP_BIT_NUM 64 + +// NORMAL mode + +#define GCDOP_N_OP_MASK 0xff00000000000000ULL +#define GCDOP_N_OP_SIZE 8 + +#define GCDOP_N_OP_RD_ROM_ID 0x9000000000000000ULL +#define GCDOP_N_OP_RD_PAGE 0x0000000000000000ULL +#define GCDOP_N_OP_WR_PAGE 0x8000000000000000ULL +#define GCDOP_N_OP_LD_TABLE 0x9f00000000000000ULL +#define GCDOP_N_OP_CHG_MODE 0x3c00000000000000ULL +#define GCDOP_N_OP_CHG2_MODE 0x3d00000000000000ULL + +#define GCDOP_N_RD_ROM_ID_PAD 0x00ffffffffffffffULL +#define GCDOP_N_RD_PAGE_PAD 0x00fffffeff00ffffULL +#define GCDOP_N_CHG_MODE_PAD 0x00000000f00000ffULL +#define GCDOP_N_CHG2_MODE_PAD GCDOP_N_CHG_MODE_PAD + +#define GCDOP_N_RD_PAGE_ADDR_SHIFT 33 +#define GCDOP_N_RD_PAGE_ADDR_SIZE 23 +#define GCDOP_N_RD_PAGE_ADDR_MASK 0x00fffffe00000000ULL + +#define GCDOP_N_VAE_SHIFT 32 +#define GCDOP_N_VAE_SIZE 24 +#define GCDOP_N_VAE_MASK 0x00ffffff00000000ULL + +#define GCDOP_N_VBI_SHIFT 8 +#define GCDOP_N_VBI_SIZE 20 +#define GCDOP_N_VBI_MASK 0x000000000fffff00ULL + + +// SECURE mode + +#define GCDOP_S_OP_MASK 0xf000000000000000ULL +#define GCDOP_S_OP_SIZE 4 + +#define GCDOP_S_OP_RD_ROM_ID 0x1000000000000000ULL +#define GCDOP_S_OP_RD_SEGMENT 0x2000000000000000ULL +#define GCDOP_S_OP_PNG_ON 0x4000000000000000ULL +#define GCDOP_S_OP_PNG_OFF 0x6000000000000000ULL +#define GCDOP_S_OP_CHG_MODE 0xa000000000000000ULL + +#define GCDOP_S_VA_SHIFT GCDOP_S_VB_SIZE +#define GCDOP_S_VA_SIZE 24 +#define GCDOP_S_VA_MASK 0x00000ffffff00000ULL + +#define GCDOP_S_VB_SHIFT 0 +#define GCDOP_S_VB_SIZE 20 +#define GCDOP_S_VB_MASK 0x00000000000fffffULL + +#define GCDOP_S_VC_SHIFT (GCDOP_S_VA_SIZE + GCDOP_S_VB_SIZE) +#define GCDOP_S_VC_SIZE 16 +#define GCDOP_S_VC_MASK 0x0ffff00000000000ULL + +#define GCDOP_S_VD_SHIFT GCDOP_S_VA_SHIFT +#define GCDOP_S_VD_SIZE GCDOP_S_VA_SIZE +#define GCDOP_S_VD_MASK GCDOP_S_VA_MASK + + +// GAME mode + +#define GCDOP_G_OP_MASK 0xff00000000000000ULL +#define GCDOP_G_OP_SIZE 8 + +#define GCDOP_G_OP_RD_ROM_ID 0xb800000000000000ULL +#define GCDOP_G_OP_RD_ROM_UID 0xb900000000000000ULL +#define GCDOP_G_OP_RD_PAGE 0xb700000000000000ULL +#define GCDOP_G_OP_RD_CACHE_START 0x5800000000000000ULL +#define GCDOP_G_OP_RD_CACHE 0x6000000000000000ULL +#define GCDOP_G_OP_RD_CACHE_LAST 0x6800000000000000ULL +#define GCDOP_G_OP_WR_PAGE 0x8000000000000000ULL + +#define GCDOP_G_RD_ROM_ID_PAD 0x00ffffffffffffffULL +#define GCDOP_G_RD_ROM_UID_PAD 0x00ffffffffffffffULL +#define GCDOP_G_RD_PAGE_PAD 0x00f0000000ffffffULL + +#define GCDOP_G_RD_PAGE_ADDR_SHIFT 33 +#define GCDOP_G_RD_PAGE_ADDR_SIZE 23 +#define GCDOP_G_RD_PAGE_ADDR_MASK 0x000ffffe00000000ULL + + +// ROM ID + +#define GCD_ROMID_1TROM_MASK 0x80000000UL +#define GCD_ROMID_TWLROM_MASK 0x40000000UL +#define GCD_ROMID_BADBLK_MASK 0x20000000UL +#define GCD_ROMID_SIZE_MASK 0x0000ff00UL + + + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadRomID + + Description: read rom ID + sync version + + Arguments: None + + Returns: rom ID + *---------------------------------------------------------------------------*/ +u32 GCDi_ReadRomID( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadRom + + Description: read rom data + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_ReadRom( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadRomAsync + + Description: read rom data + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_ReadRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadNormalModeRom + + Description: read rom data on normal mode + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_ReadNormalModeRom( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCD_ReadNormalModeRomAsync + + Description: read rom data on normal mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadNormalModeRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadGameModeRom + + Description: read rom data on game mode + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_ReadGameModeRom( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCDi_ReadGameModeRomAsync + + Description: read rom data on game mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_ReadGameModeRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCDi_WriteGameModeRom + + Description: write rom data on game mode + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WriteGameModeRom( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCDi_WriteGameModeRomAsync + + Description: write rom data on game mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WriteGameModeRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCDi_Enable + + Description: Enable game card master control + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_Enable( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_Disable + + Description: disable game card master control + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_Disable( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCD_SetPrimarySlot + + Description: set primary game card slot + + Arguments: primary slot + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_SetPrimarySlot( u8 slot ); + +/*---------------------------------------------------------------------------* + Name: GCD_GetPrimarySlot + + Description: get primary game card slot + + Arguments: None + + Returns: primary slot + *---------------------------------------------------------------------------*/ +u8 GCD_GetPrimarySlot(void ); + +/*---------------------------------------------------------------------------* + Name: GCD_Reset + + Description: reset game card + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_Reset( GCDSlot slot, u32 chat_cycles ); + +/*---------------------------------------------------------------------------* + Name: GCD_Reset + + Description: reset game card + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ResetAll( u32 chat_cycles ); + +/*---------------------------------------------------------------------------* + Name: GCDi_SelectRom + + Description: select game card spi + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_SelectRom( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_SelectSpi + + Description: select game card spi + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_SelectSpi( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_SetDmaNo + + Description: set card dma number + + Arguments: dmaNo : dma channel number + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_SetDmaNo( GCDSlot slot, u32 dmaNo ); + +/*---------------------------------------------------------------------------* + Name: GCDi_GetDmaNo + + Description: get card dma number + + Arguments: None + + Returns: dmaNo : dma channel number + *---------------------------------------------------------------------------*/ +u32 GCDi_GetDmaNo( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_InterruptHandler + + Description: interrupt handler + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_InterruptHandlerPRIME( void ); +void GCDi_InterruptHandlerSECOND( void ); +void GCDi_InterruptHandlerCommon( GCDSlot slot ); + +//================================================================================ +// WAIT/STOP +//================================================================================ +/*---------------------------------------------------------------------------* + Name: GCDi_IsBusy + + Description: check whether game card is busy or not + + Arguments: None + + Returns: TRUE if game card is busy, FALSE if not + *---------------------------------------------------------------------------*/ +BOOL GCDi_IsBusy( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_IsDataReady + + Description: check whether data is ready or not + + Arguments: None + + Returns: TRUE if game card is busy, FALSE if not + *---------------------------------------------------------------------------*/ +BOOL GCDi_IsDataReady( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_Stop + + Description: stop game card access + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_Stop( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_WaitCtrl + + Description: wait while game card is busy + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WaitCtrl( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_WaitData + + Description: wait until data is ready + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WaitData( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_WaitDma + + Description: wait for stopping game card DMA + + Arguments: dmaNo : DMA channel No. + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WaitDma( GCDSlot slot, u32 dmaNo ); + +/*---------------------------------------------------------------------------* + Name: GCDi_WaitInterrupt + + Description: wait for game card interrupt + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_WaitInterrupt( GCDSlot slot ); + + +// internal + +BOOL GCDi_IsSecureInitialized( GCDSlot slot ); +BOOL GCDi_IsCtrApp( GCDSlot slot ); +BOOL GCDi_IsDsApp( GCDSlot slot ); + +u32 GCDi_ReadNormalModeID( GCDSlot slot ); +u32 GCDi_ReadSecureModeID( GCDSlot slot ); +u32 GCDi_ReadGameModeID( GCDSlot slot ); + +u32 GCDi_ReadRomIDCore( GCDSlot slot, GCDRomCtrls *ctrls ); +void GCDi_ReadRomCore( GCDSlot slot, void *ramp, s32 size, GCDRomCtrls *ctrls ); +BOOL GCDi_ReadRomCommonPreCore( GCDSlot slot, u32 romp, void *ram, s32 size ); +void GCDi_WriteRomCore( GCDSlot slot, void *ramp, s32 size, GCDRomCtrls *ctrls ); + +void GCDi_ReadNormalModeRomCore( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDRomCtrls *ctrls ); + +void GCDi_InitSecureParam( GCDSlot slot, BOOL twl_ex ); +void GCDi_InitPngIntf( GCDSlot slot ); +void GCDi_SetInitCardOpBlowfish( void (*p)( void ) ); +void GCDi_SetDecryptObjectFilep( void (*p)( void ) ); +void GCDi_SetSetPngIntf( void (*p)( u32 pnA_l, u8 pnA_h, u32 pnB_l, u8 pnB_h ) ); +void GCDi_SetReadSecureModeIDCorep( u32 (p)( GCDRomCtrls *ctrls ) ); +void GCDi_SetReadSecureModeRomCorep( void (p)( u32 romp, void *ramp, s32 size, GCDRomCtrls *ctrls ) ); +void GCDi_SetGetOneShotSizeFromCtrlp( s32 (p)( u32 ctrl ) ); + +void GCDi_SetSendOnlyCardOpCorep( void (*p)( GCDRomCtrls *ctrls ) ); +void GCDi_ChangeIntoSecureMode( GCDSlot slot ); +void GCDi_ChangeIntoSecure2Mode( GCDSlot slot ); +void GCDi_SendPngON( GCDSlot slot ); +void GCDi_SendPngOFF( GCDSlot slot ); +void GCDi_ChangeIntoGameMode( GCDSlot slot ); +void GCDi_ReadCardSegmentAsync4Secure( GCDSlot slot, BOOL twl_ex ); + +void GCDi_InitCardOpBlowfish( GCDSlot slot ); +void GCDi_InitCardOpBlowfishDS( GCDSlot slot ); +void GCDi_DecryptObjectFile( GCDSlot slot ); +void GCDi_DecryptObjectFileDS( GCDSlot slot ); + +void GCD_SetInterrupt( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDWork *wp ); + +void* GCDi_GetRomHeaderAddr( GCDSlot slot ); + + +extern u32 GCDi_HeaderBuf[2][ GCD_ROM_HEADER_SIZE/sizeof(u32) ]; +extern u32 GCDi_SecureAreaBuf[2][ GCD_SECURE_AREA_SIZE/sizeof(u32) ]; +extern u32 GCDi_Secure2AreaBuf[2][ GCD_SECURE_AREA_SIZE/sizeof(u32) ]; + +extern GCDSharedWork GCDi_SharedWork[2]; +extern GCDWork GCDi_Work[2]; + +// e[u +extern const BLOWFISH_CTX GCDi_BlowfishInitTableDS; +extern const BLOWFISH_CTX GCDi_BlowfishInitTableGCDFIRM; + + +// SecondarySlot̃J[hbNpӂĂȂ̂ŁAƂ肠PrimarySlotƋpŁB +s32 OS_LockExCard( u16 lockID ); +s32 OS_UnlockExCard( u16 lockID ); + +#ifdef __cplusplus +} /* extern "C" */ + +#endif + +/* FIRM_GCD_GCD_H_ */ +#endif diff --git a/include/firm/gcd/gcd_misc.h b/include/firm/gcd/gcd_misc.h new file mode 100644 index 0000000..4b3da84 --- /dev/null +++ b/include/firm/gcd/gcd_misc.h @@ -0,0 +1,516 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - GCD - include + File: ngcd.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_GCD_GCD_MISC_H_ +#define FIRM_GCD_GCD_MISC_H_ + +#include +#include "./gcd.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define PXI_FIFO_TAG_GCD PXI_FIFO_TAG_USER_1 + +#define reg_MI_MC_DET (*(REGType8v *) REG_MC_OFFSET) +#define reg_MI_MC_SWP (*(REGType8v *) ( REG_MC_OFFSET + 1 ) ) + +#define REG_MCCHAT_OFFSET 0x4012 +#define REG_MCCHAT_ADDR (HW_REG_BASE + REG_MCCHAT_OFFSET) +#define reg_MI_MCCHAT (*( REGType16v *) REG_MCCHAT_ADDR) + +/* MCSCRA_L */ + +#define REG_MCSCRA_L_OFFSET 0x1b0 +#define REG_MCSCRA_L_ADDR (HW_REG_BASE + REG_MCSCRA_L_OFFSET) +#define reg_MI_MCSCRA_L (*( REGType32v *) REG_MCSCRA_L_ADDR) + +/* MCSCRB_L */ + +#define REG_MCSCRB_L_OFFSET 0x1b4 +#define REG_MCSCRB_L_ADDR (HW_REG_BASE + REG_MCSCRB_L_OFFSET) +#define reg_MI_MCSCRB_L (*( REGType32v *) REG_MCSCRB_L_ADDR) + +/* MCSCRA_H */ + +#define REG_MCSCRA_H_OFFSET 0x1b8 +#define REG_MCSCRA_H_ADDR (HW_REG_BASE + REG_MCSCRA_H_OFFSET) +#define reg_MI_MCSCRA_H (*( REGType8v *) REG_MCSCRA_H_ADDR) + +/* MCSCRB_H */ + +#define REG_MCSCRB_H_OFFSET 0x1ba +#define REG_MCSCRB_H_ADDR (HW_REG_BASE + REG_MCSCRB_H_OFFSET) +#define reg_MI_MCSCRB_H (*( REGType8v *) REG_MCSCRB_H_ADDR) + + +#define REG_MI_MCCNT1_A_CSC_SHIFT 22 +#define REG_MI_MCCNT1_A_CSC_SIZE 1 +#define REG_MI_MCCNT1_A_CSC_MASK 0x00400000 + +#define REG_MI_MC_SWP_E_SHIFT 7 +#define REG_MI_MC_SWP_E_SIZE 1 +#define REG_MI_MC_SWP_E_MASK 0x80 + + + +typedef enum +{ + GCD_PAGE_0 = 0x0UL << REG_MI_MCCNT1_A_PC_SHIFT, + GCD_PAGE_1 = 0x1UL << REG_MI_MCCNT1_A_PC_SHIFT, + GCD_PAGE_2 = 0x2UL << REG_MI_MCCNT1_A_PC_SHIFT, + GCD_PAGE_4 = 0x3UL << REG_MI_MCCNT1_A_PC_SHIFT, + GCD_PAGE_8 = 0x4UL << REG_MI_MCCNT1_A_PC_SHIFT, + GCD_PAGE_16 = 0x5UL << REG_MI_MCCNT1_A_PC_SHIFT, + GCD_PAGE_32 = 0x6UL << REG_MI_MCCNT1_A_PC_SHIFT, + GCD_PAGE_STAT = 0x7UL << REG_MI_MCCNT1_A_PC_SHIFT +} +GCDPageCount; + +typedef enum +{ + GCD_CKT_150NS = 0x0UL << REG_MI_MCCNT1_A_CT_SHIFT, + GCD_CKT_240NS = 0x1UL << REG_MI_MCCNT1_A_CT_SHIFT +} +GCDClockType; + +typedef enum +{ + GCD_RW_READ = 0x0UL << REG_MI_MCCNT1_WR_SHIFT, + GCD_RW_WRITE = 0x1UL << REG_MI_MCCNT1_WR_SHIFT +} +GCDRw; + +typedef enum +{ + GCD_RESET_LO = 0x0UL << REG_MI_MCCNT1_A_RESB_SHIFT, + GCD_RESET_HI = 0x1UL << REG_MI_MCCNT1_A_RESB_SHIFT +} +GCDReset; + +typedef enum +{ +#ifdef SDK_ARM9 + GCD_LTCK_DISABLE = 0x0UL << REG_MI_MCCNT1_A_TRM_SHIFT, + GCD_LTCK_ENABLE = 0x1UL << REG_MI_MCCNT1_A_TRM_SHIFT +#else + GCD_LTCK_DISABLE = 0x0UL << REG_MI_MCCNT1_A_RTM_SHIFT, + GCD_LTCK_ENABLE = 0x1UL << REG_MI_MCCNT1_A_RTM_SHIFT +#endif +} +GCDLtClkEnable; + +typedef struct +{ + u32 ctrl; + u8 master; + u8 spi; +} +NGCDCtrlRegs; + +// PXIł̒ʐMvgR֘A` +#define GCD_PXI_COMMAND_MASK 0x0000003f // Jn[h̃R}h +#define GCD_PXI_COMMAND_SHIFT 0 +#define GCD_PXI_COMMAND_SIZE 6 +#define GCD_PXI_COMMAND_PARAM_MASK 0x03ffffc0 // Jn[h̃p[^ +#define GCD_PXI_COMMAND_PARAM_SHIFT 6 +#define GCD_PXI_COMMAND_PARAM_SIZE 20 + +typedef union +{ + struct + { + u32 cmd:GCD_PXI_COMMAND_SIZE; + u32 param:GCD_PXI_COMMAND_PARAM_SIZE-1; + u32 slot:1; + } + e; + u32 raw; +} +GCDPxiCmd; + +// PXIoRŔs閽 +#define GCD_PXI_COMMAND_RESET 0x01 +#define GCD_PXI_COMMAND_LOADED 0x02 + + +/*---------------------------------------------------------------------------* + Name: GCD_Init + + Description: initialize for game card access + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_Init( void ); + +/*---------------------------------------------------------------------------* + Name: GCDi_Init + + Description: initialize for game card access + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_Init( BOOL reset ); + +/*---------------------------------------------------------------------------* + Name: GCD_ReadRomID + + Description: read rom ID + sync version + + Arguments: None + + Returns: rom ID + *---------------------------------------------------------------------------*/ +u32 GCD_ReadRomID( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCD_ReadRom + + Description: read rom data + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadRom( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCD_ReadRomAsync + + Description: read rom data + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCD_ReadNormalModeRom + + Description: read rom data on normal mode + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadNormalModeRom( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCD_ReadGameModeRom + + Description: read rom data on game mode + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadGameModeRom( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCD_ReadRomPreCore + + Description: read rom data + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL GCD_ReadRomPreCore( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCD_ReadGameModeRomAsync + + Description: read rom data on game mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_ReadGameModeRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCD_WriteGameModeRom + + Description: write rom data on game mode + sync version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_WriteGameModeRom( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCD_WriteGameModeRomAsync + + Description: write rom data on game mode + async version + + Arguments: romp : rom offset + ramp : ram destination address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_WriteGameModeRomAsync( GCDSlot slot, u32 romp, void *ramp, s32 size ); + +/*---------------------------------------------------------------------------* + Name: GCDi_Enable + + Description: Enable game card master control + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_Enable( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_Disable + + Description: disable game card master control + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCDi_Disable( GCDSlot slot ); + +//================================================================================ +// WAIT/STOP +//================================================================================ +/*---------------------------------------------------------------------------* + Name: GCD_IsExisting + + Description: get whether cartridge exists + + Arguments: None + + Returns: TRUE if game card is busy, FALSE if not + *---------------------------------------------------------------------------*/ +static inline BOOL GCD_IsExisting( GCDSlot slot ) +{ + s32 ofs = (GCD_GetPrimarySlot() ^ slot) * 4; + s32 r = ~reg_MI_MC_DET & (REG_MI_MC_SL1_CDET_MASK << ofs); + return r >> (REG_MI_MC_SL1_CDET_SHIFT + ofs); +} + +/*---------------------------------------------------------------------------* + Name: GCD_SetDetectMode + + Description: + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static inline void GCD_SetDetectMode( GCDSlot slot, u32 mode ) +{ + s32 ofs = (GCD_GetPrimarySlot() ^ slot) * 4; + s32 others = reg_MI_MC_DET & ~(REG_MI_MC_SL1_MODE_MASK << ofs); + reg_MI_MC_DET = (u8)((mode << (REG_MI_MC_SL1_MODE_SHIFT + ofs)) | others); +} + +/*---------------------------------------------------------------------------* + Name: GCD_GetDetectMode + + Description: + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static inline u8 GCD_GetDetectMode( GCDSlot slot ) +{ + s32 ofs = (GCD_GetPrimarySlot() ^ slot) * 4; + return (u8)((reg_MI_MC_DET & (REG_MI_MC_SL1_MODE_MASK << ofs)) + >> (REG_MI_MC_SL1_MODE_SHIFT + ofs)); +} + +/*---------------------------------------------------------------------------* + Name: GCD_SetChatCounter + + Description: + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static inline void GCD_SetChatCounter( u16 value ) +{ + reg_MI_MCCHAT = value; +} + +/*---------------------------------------------------------------------------* + Name: GCD_IsBusy + + Description: check whether game card is busy or not + + Arguments: None + + Returns: TRUE if game card is busy, FALSE if not + *---------------------------------------------------------------------------*/ +BOOL GCD_IsBusy( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCD_IsDataReady + + Description: check whether data is ready or not + + Arguments: None + + Returns: TRUE if game card is busy, FALSE if not + *---------------------------------------------------------------------------*/ +BOOL GCD_IsDataReady( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCD_Stop + + Description: stop game card access + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_Stop( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCD_WaitRomAsync + + Description: wait for game card async access + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void GCD_WaitRomAsync( GCDSlot slot ); + +/*---------------------------------------------------------------------------* + Name: GCDi_SelectRegAddr + + Description: + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static inline void* GCDi_SelectRegAddr( GCDSlot slot, u32 base ) +{ + u32 addr = base; + + if ( slot == GCD_SECONDARY_SLOT ) + { + addr += REG_MCCNT0_B_ADDR - REG_MCCNT0_ADDR; + } + + return (void*)addr; +} + +/*---------------------------------------------------------------------------* + Name: GCDi_SelectIrqMask + + Description: + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static inline u32 GCDi_SelectIrqMask( GCDSlot slot, u32 base_mask ) +{ + u32 mask = base_mask; + + if ( slot == GCD_SECONDARY_SLOT ) + { + switch ( mask ) + { + case OS_IE_CARD_DATA: + mask = OS_IE_CARD_B_DATA; + break; + case OS_IE_CARD_IREQ: + mask = OS_IE_CARD_B_IREQ; + break; + case OS_IE_CARD_A_DET: + mask = OS_IE_CARD_B_DET; + break; + } + } + + return mask; +} + + +// internal + +u32 GCD_ReadNormalModeID( GCDSlot slot ); +u32 GCD_ReadSecureModeID( GCDSlot slot ); +u32 GCD_ReadGameModeID( GCDSlot slot ); + +void GCDi_SetOp( GCDSlot slot, GCDCmd64* op ); +void GCDi_SetCtrl( GCDSlot slot, GCDCtrlRegs* regs ); +void GCDi_GenCtrl( GCDCtrlRegs* regs, + GCDRw rw, + GCDPageCount pcount, + GCDClockType ckt, u32 lt1, u32 lt2, + BOOL cpn, BOOL dpn, BOOL csc, BOOL dsc ); +s32 GCDi_GetOneShotSizeFromCtrl( u32 ctrl ); +void GCD_SendOnlyCardOpCore( GCDSlot slot, GCDRomCtrls *ctrls ); +u32 GCDi_ReadRomIDCore( GCDSlot slot, GCDRomCtrls *ctrls ); +void GCD_ReadRomCore( GCDSlot slot, u32 romp, void *ramp, s32 size, GCDRomCtrls *ctrls ); +void GCD_WaitRomAsyncCore( GCDSlot slot ); + +void GCDi_WaitCtrl( GCDSlot slot ); +void GCDi_WaitData( GCDSlot slot ); +void GCDi_WaitDma( GCDSlot slot, u32 dmaNo ); +void GCDi_WaitInterrupt( GCDSlot slot ); + +void GCDi_SendtoPxi(u32 data); + +#ifdef __cplusplus +} /* extern "C" */ + +#endif + +/* FIRM_GCD_GCD_MISC_H_ */ +#endif diff --git a/include/firm/hw/ARM7/mmap_firm.h b/include/firm/hw/ARM7/mmap_firm.h new file mode 100644 index 0000000..d93fe22 --- /dev/null +++ b/include/firm/hw/ARM7/mmap_firm.h @@ -0,0 +1,55 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - HW - include + File: mmap_firm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_HW_MMAP_FIRM_H_ +#define FIRM_HW_MMAP_FIRM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------- FIRM +#define HW_FIRM HW_WRAM +#define HW_FIRM_END (HW_FIRM + HW_FIRM_SIZE) +#define HW_FIRM_SIZE (HW_WRAM_0_SIZE + HW_WRAM_1_SIZE + HW_WRAM_A_SIZE_MAX + HW_WRAM_B_SIZE_MAX) + +//------------------------------------- FIRM_WRAM_ABC +#define HW_FIRM_WRAM_A_MAP_END (HW_WRAM_AREA_END - HW_PRV_WRAM_SIZE) +#define HW_FIRM_WRAM_B_MAP_END HW_FIRM_WRAM_A_MAP_END +#define HW_FIRM_WRAM_C_MAP_END HW_FIRM_WRAM_A_MAP_END + +//------------------------------------- HW_FIRM_FROM_BROM_BUF +#define HW_FIRM_FROM_BROM_BUF (HW_FIRM_FROM_BROM_BUF_END - HW_FIRM_FROM_BROM_BUF_SIZE) +#define HW_FIRM_FROM_BROM_BUF_END (HW_WRAM_AREA_END - 0x1000) // END - 4KB +#define HW_FIRM_FROM_BROM_BUF_SIZE 0x3000 // 12KB + +//------------------------------------- HW_FIRM_APP_BUF +#define HW_FIRM_APP_BUF (HW_MAIN_MEM_HI_EX_END - HW_FIRM_APP_BUF_SIZE) +#define HW_FIRM_APP_BUF_END (HW_FIRM_APP_BUF + HW_FIRM_APP_BUF_SIZE) +#define HW_FIRM_APP_BUF_SIZE 0x00800000 // 8MB + +//------------------------------------- HW_FIRM_BOOT_CORE +#define HW_FIRM_BOOT_CORE HW_EXT_WRAM +#define HW_FIRM_BOOT_CORE_END (HW_FIRM_BOOT_CORE + HW_FIRM_BOOT_CORE_SIZE) +#define HW_FIRM_BOOT_CORE_SIZE 0x200 // 512B + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_HW_MMAP_FIRM_H_ */ +#endif diff --git a/include/firm/hw/ARM9/mmap_firm.h b/include/firm/hw/ARM9/mmap_firm.h new file mode 100644 index 0000000..6a96de0 --- /dev/null +++ b/include/firm/hw/ARM9/mmap_firm.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - HW - include + File: mmap_firm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_HW_MMAP_FIRM_H_ +#define FIRM_HW_MMAP_FIRM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------- FIRM +#define HW_FIRM HW_WRAM_EX +#define HW_FIRM_END (HW_FIRM + HW_FIRM_SIZE) +#define HW_FIRM_SIZE HW_WRAM_C_SIZE_MAX + +//------------------------------------- FIRM_WRAM_ABC +#define HW_FIRM_WRAM_A_MAP_END HW_WRAM_AREA_END +#define HW_FIRM_WRAM_B_MAP_END HW_FIRM_WRAM_A_MAP_END +#define HW_FIRM_WRAM_C_MAP_END HW_FIRM_WRAM_A_MAP_END + +//------------------------------------- HW_FIRM_FROM_BROM_BUF +#define HW_FIRM_FROM_BROM_BUF (HW_FIRM_FROM_BROM_BUF_END - HW_FIRM_FROM_BROM_BUF_SIZE) +#define HW_FIRM_FROM_BROM_BUF_END (HW_ITCM_END - 0x1000) // END - 4KB +#define HW_FIRM_FROM_BROM_BUF_SIZE 0x3000 // 12KB + +//------------------------------------- HW_FIRM_APP_BUF +#define HW_FIRM_APP_BUF (HW_MAIN_MEM_HI_EX_END - HW_FIRM_APP_BUF_SIZE) +#define HW_FIRM_APP_BUF_END (HW_FIRM_APP_BUF + HW_FIRM_APP_BUF_SIZE) +#define HW_FIRM_APP_BUF_SIZE 0x00800000 // 8MB + +//------------------------------------- HW_FIRM_BOOT_CORE +#define HW_FIRM_BOOT_CORE HW_FIRM_FROM_BROM_BUF_END +#define HW_FIRM_BOOT_CORE_END (HW_FIRM_BOOT_CORE + HW_FIRM_BOOT_CORE_SIZE) +#define HW_FIRM_BOOT_CORE_SIZE 0x200 // 512B + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_HW_MMAP_FIRM_H_ */ +#endif diff --git a/include/firm/hw/common/mmap_firm.h b/include/firm/hw/common/mmap_firm.h new file mode 100644 index 0000000..6b86cd3 --- /dev/null +++ b/include/firm/hw/common/mmap_firm.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - HW - include + File: mmap_firm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_HW_COMMON_MMAP_FIRM_H_ +#define FIRM_HW_COMMON_MMAP_FIRM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------- *_LoadBuffer +#define HW_FIRM_LOAD_BUFFER_BASE MI_GetWramMapStart_B() +#define HW_FIRM_LOAD_BUFFER_UNIT_SIZE 0x8000 +#define HW_FIRM_LOAD_BUFFER_UNIT_NUMS 8 +#define HW_FIRM_LOAD_BUFFER_SIZE (HW_FIRM_LOAD_BUFFER_UNIT_SIZE * HW_FIRM_LOAD_BUFFER_UNIT_NUMS) +#define HW_FIRM_LOAD_BUFFER_END (HW_FIRM_LOAD_BUFFER_BASE + HW_FIRM_LOAD_BUFFER_SIZE) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_HW_COMMON_MMAP_FIRM_H_ */ +#endif diff --git a/include/firm/memorymap.h b/include/firm/memorymap.h new file mode 100644 index 0000000..fa95b48 --- /dev/null +++ b/include/firm/memorymap.h @@ -0,0 +1,30 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - include - HW + File: memorymap.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_MEMORYMAP_H_ +#define FIRM_MEMORYMAP_H_ + +#include +#include + +#ifdef SDK_ARM9 +#include +#else //SDK_ARM7 +#include +#endif + +/* FIRM_MEMORYMAP_H_ */ +#endif diff --git a/include/firm/mi.h b/include/firm/mi.h new file mode 100644 index 0000000..475c4c1 --- /dev/null +++ b/include/firm/mi.h @@ -0,0 +1,30 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - include - MI + File: mi.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_MI_H_ +#define FIRM_MI_H_ + +#include + +#include +#include +#ifdef SDK_ARM9 +#include +#endif + +/* FIRM_MI_H_ */ +#endif diff --git a/include/firm/mi/ARM9/mi_loader.h b/include/firm/mi/ARM9/mi_loader.h new file mode 100644 index 0000000..0fa3274 --- /dev/null +++ b/include/firm/mi/ARM9/mi_loader.h @@ -0,0 +1,67 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - include - mi + File: mi_loader.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_MI_LOADER_H_ +#define FIRM_MI_LOADER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------* + Name: MI_LoadHeader + + Description: load header + + Arguments: pool pointer to the pool info for SVCSignHeapContext + rsa_key key address + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +BOOL MI_LoadHeader( SVCSignHeapContext* pool, const void* rsa_key ); + +/*---------------------------------------------------------------------------* + Name: MI_LoadStatic + + Description: load static binary + + Arguments: None + + Returns: TRUE if success + *---------------------------------------------------------------------------*/ +BOOL MI_LoadStatic( void ); + +/*---------------------------------------------------------------------------* + Name: MI_Boot + + Description: boot + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void MI_Boot( void ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +/* FIRM_MI_LOADER_H_ */ +#endif diff --git a/include/firm/mi/exDma.h b/include/firm/mi/exDma.h new file mode 100644 index 0000000..38d8ec1 --- /dev/null +++ b/include/firm/mi/exDma.h @@ -0,0 +1,203 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - libraries - mi + File: exDma.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef TWL_MI_EXDMA_H_ +#define TWL_MI_EXDMA_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//---------------------------------------------------------------------- + +//---- registers +typedef struct +{ + const void * src; + void * dest; + u32 totalCount; + u32 wordCount; + u32 blockInterval; + u32 fillData; + u32 ctrl; +} +t_MIExDmaChanRegs; + +typedef volatile t_MIExDmaChanRegs MIExDmaChanRegs; + + +//================================================================================ +// DMA control definition +//================================================================================ +//---- DMA channel No. +#define MI_EXDMA_CH_MIN 4 +#define MI_EXDMA_CH_MAX 7 + +#define MI_EXDMA_CH_NUM 4 + + +//================================================================================ +// DMA WAIT +//================================================================================ +/*---------------------------------------------------------------------------* + Name: MIi_IsExDmaBusy + + Description: check whether extended DMA is busy or not + + Arguments: dmaNo : DMA channel No. + + Returns: TRUE if extended DMA is busy, FALSE if not + *---------------------------------------------------------------------------*/ +BOOL MIi_IsExDmaBusy( u32 dmaNo ); + +/*---------------------------------------------------------------------------* + Name: MIi_WaitExDma + + Description: wait while extended DMA is busy + + Arguments: dmaNo : DMA channel No. + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_WaitExDma( u32 dmaNo ); + +/*---------------------------------------------------------------------------* + Name: MIi_StopExDma + + Description: stop extended DMA + + Arguments: dmaNo : DMA channel No. + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_StopExDma( u32 dmaNo ); + +/*---------------------------------------------------------------------------* + Name: MIi_StopDmaAsync + + Description: stop extended DMA + async version + + Arguments: dmaNo : DMA channel No. + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_StopExDmaAsync( u32 dmaNo ); + +//================================================================================ +// memory operation using DMA +//================================================================================ +/*---------------------------------------------------------------------------* + Name: MIi_ExDmaSendAsync + + Description: send data with DMA + sync version + + Arguments: dmaNo : DMA channel No. + dest : destination address + src : source address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_ExDmaSendAsync( u32 dmaNo, const void *src, void *dest, u32 size ); + +/*---------------------------------------------------------------------------* + Name: MIi_ExDmaRecvAsync + + Description: receive data with DMA + sync version + + Arguments: dmaNo : DMA channel No. + dest : destination address + src : source address + size : size (byte) + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_ExDmaRecvAsync( u32 dmaNo, const void *src, void *dest, u32 size ); + +//----------------- internel functions ------------------- +/*---------------------------------------------------------------------------* + Name: MIi_ExDmaSendAsyncCore + + Description: send data with DMA + async version + + Arguments: dmaNo : DMA channel No. + dest : destination address + src : source address + size : size (byte) + blockSize : block size + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_ExDmaSendAsyncCore( u32 dmaNo, const void *src, void *dest, u32 size, u32 oneShotSize, + u32 blockSize, u32 interval, u32 prescale, + u32 continuous, u32 srcRld, u32 destRld, + u32 timing ); + +/*---------------------------------------------------------------------------* + Name: MIi_ExDmaRecvAsyncCore + + Description: receive data with DMA + async version + + Arguments: dmaNo : DMA channel No. + dest : destination address + src : source address + size : size (byte) + blockSize : block size + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_ExDmaRecvAsyncCore( u32 dmaNo, const void *src, void *dest, u32 size, u32 oneShotSize, + u32 blockSize, u32 interval, u32 prescale, + u32 continuous, u32 srcRld, u32 destRld, + u32 timing ); + +/*---------------------------------------------------------------------------* + Name: MIi_SetExDmaParams + + Description: set DMA + + Arguments: dmaNo : DMA channel No. + dest : destination address + src : source address + size : size (byte) + blockSize : block size + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_SetExDmaParams( u32 dmaNo, const void *src, void *dest, u32 size, u32 oneShotSize, + u32 blockSize, u32 interval, u32 prescale, + u32 continuous, u32 srcRld, u32 destRld, + u32 timing, + u32 fillData, u32 srcDir, u32 destDir); + + +#ifdef __cplusplus +} /* extern "C" */ + +#endif + +/* TWL_MI_EXDMA_H_ */ +#endif diff --git a/include/firm/mi/mainMemory.h b/include/firm/mi/mainMemory.h new file mode 100644 index 0000000..424a2bf --- /dev/null +++ b/include/firm/mi/mainMemory.h @@ -0,0 +1,111 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - include - MI + File: mainMemory.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_MI_MAINMEMORY_H_ +#define FIRM_MI_MAINMEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + u16 cr0; + u16 cr1; + u16 cr2; +} +MIMmemCR; + +//---------------------------------------------------------------------- +// C CRR}h +//---------------------------------------------------------------------- + +// for DS-PSRAM + +// CR0 +#define MMEM_DCR0_PARTIAL_REFRESH_NONE 0x0003 // p[VtbV +#define MMEM_DCR0_BURST_CONTINUOUS 0x001c // Ao[XgiQQSoCgj +#define MMEM_DCR0_BURST_MODE 0x0000 // o[Xg[h +#define MMEM_DCR0_PAGE_MODE 0x0020 // y[W[h +#define MMEM_DCR0_SB1 0xffc0 // PŒ + +// CR1 +#define MMEM_DCR1_1ST_R4_W3 0x0002 // Pq^v S^R +#define MMEM_DCR1_BURST_WRITE 0x0000 // o[XgCg +#define MMEM_DCR1_CLOCK_TRIGGER_UP 0x0100 // NbN +#define MMEM_DCR1_BURST_LINER 0x0200 // o[XgjAEV[PX +#define MMEM_DCR1_SB1 0xe430 // PŒ + +// CR2 +#define MMEM_DCR2_SB1 0x004003fe // PŒ +#define MMEM_DCR2_CLOCK_TRIGGER_UP 0x00000400 // NbN +#define MMEM_DCR2_BURST_WRITE 0x00000000 // o[XgCg +#define MMEM_DCR2_BURST_LINER 0x00001000 // o[XgjAEV[PX +#define MMEM_DCR2_1ST_R4_W3 0x00004000 // Pq^v S^R +#define MMEM_DCR2_BURST_MODE 0x00000000 // o[Xg[h +#define MMEM_DCR2_PAGE_MODE 0x00010000 // y[W[h +#define MMEM_DCR2_BURST_CONTINUOUS 0x000e0000 // Ao[XgiQQSoCgj +#define MMEM_DCR2_PARTIAL_REFRESH_NONE 0x00300000 // p[VtbV + +// for TWL-PSRAM + +#define MMEM_TCR0 0xFFFF +#define MMEM_TCR1 0xFFDF +#define MMEM_TCR2 0xFFEA + + +/*---------------------------------------------------------------------------* + Name: MIi_InitMainMemCR + + Description: change main memory into the burst mode + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_InitMainMemCR( BOOL setCR ); + +void MIi_GetMainMemCR( MIMmemCR* dest ); + +/*---------------------------------------------------------------------------* + Name: MIi_IsMainMemoryInitialized + + Description: + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL MIi_IsMainMemoryInitialized( void ); + +/*---------------------------------------------------------------------------* + Name: MIi_WaitMainMemoryInitialize + + Description: + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void MIi_WaitMainMemoryInitialize( void ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_MI_MAINMEMORY_H_ */ +#endif diff --git a/include/firm/misc.h b/include/firm/misc.h new file mode 100644 index 0000000..36d3cfc --- /dev/null +++ b/include/firm/misc.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - include - + File: misc.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_MISC_H_ +#define FIRM_MISC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define offsetof(t, memb) ((size_t)(&(((t *)0)->memb))) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_MISC_H_ */ +#endif diff --git a/include/firm/nvram.h b/include/firm/nvram.h new file mode 100644 index 0000000..ea9e4c8 --- /dev/null +++ b/include/firm/nvram.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - NVRAM + File: nvram.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_NVRAM_H_ +#define FIRM_NVRAM_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SDK_ARM9 +#else // SDK_ARM7 + +/*---------------------------------------------------------------------------* + ֐` + *---------------------------------------------------------------------------*/ +void NVRAMi_Read(u32 address, void *buf, u32 size); +void NVRAMi_Write(u32 address, void *buf, u32 size); + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_NVRAM_H_ */ +#endif diff --git a/include/firm/os.h b/include/firm/os.h new file mode 100644 index 0000000..f91cfcf --- /dev/null +++ b/include/firm/os.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - OS + File: os.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_OS_H_ +#define FIRM_OS_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_OS_H_ */ +#endif diff --git a/include/firm/os/ARM9/os_cache_tag.h b/include/firm/os/ARM9/os_cache_tag.h new file mode 100644 index 0000000..7116eaf --- /dev/null +++ b/include/firm/os/ARM9/os_cache_tag.h @@ -0,0 +1,151 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - OS - include + File: os_cache_tag.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef TWL_OS_CACHE_TAG_H_ +#define TWL_OS_CACHE_TAG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +//=========================================================================== +// DATA CACHE (for specified range) +//=========================================================================== +/*---------------------------------------------------------------------------* + Name: DC_ClearTagAll + + Description: clear tag in data cache + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +void DC_ClearTagAll( void ); + +/*---------------------------------------------------------------------------* + Name: DC_ClearDataAll + + Description: clear data in data cache + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +void DC_ClearDataAll( void ); + +/*---------------------------------------------------------------------------* + Name: DC_FillTagAll + + Description: clear tag in data cache + + Arguments: data : fill data + + Returns: None. + *---------------------------------------------------------------------------*/ +void DC_FillTagAll( u32 data ); + +/*---------------------------------------------------------------------------* + Name: DC_FillDataAll + + Description: fill data in data cache + + Arguments: data : fill data + + Returns: None. + *---------------------------------------------------------------------------*/ +void DC_FillDataAll( u32 data ); + +/*---------------------------------------------------------------------------* + Name: DC_GetTagAndDataAll + + Description: get tag and data in data cache + + Arguments: tag tag address + data data address + + Returns: None. + *---------------------------------------------------------------------------*/ +void DC_GetTagAndDataAll( void* tag, void* data ); + +//=========================================================================== +// INSTRUCTION CACHE +//=========================================================================== +/*---------------------------------------------------------------------------* + Name: IC_ClearTagAll + + Description: clear tag in instruction cache + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +void IC_ClearTagAll( void ); + +/*---------------------------------------------------------------------------* + Name: IC_ClearInstructionAll + + Description: clear instruction in instruction cache + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +void IC_ClearInstructionAll( void ); + +/*---------------------------------------------------------------------------* + Name: IC_FillTagAll + + Description: fill tag in instruction cache + + Arguments: None + + Returns: None. + *---------------------------------------------------------------------------*/ +void IC_FillTagAll( u32 data ); + +/*---------------------------------------------------------------------------* + Name: IC_FillInstructionAll + + Description: fill instruction in instruction cache + + Arguments: data : fill data + + Returns: None. + *---------------------------------------------------------------------------*/ +void IC_FillInstructionAll( u32 data ); + +/*---------------------------------------------------------------------------* + Name: IC_GetTagAndInstructionAll + + Description: get tag and instruction in instruction cache + + Arguments: tag tag address + inst instruction address + + Returns: None. + *---------------------------------------------------------------------------*/ +void IC_GetTagAndInstructionAll( void* tag, void* inst ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* TWL_OS_CACHE_TAG_H_ */ +#endif diff --git a/include/firm/os/common/boot.h b/include/firm/os/common/boot.h new file mode 100644 index 0000000..2c78f4a --- /dev/null +++ b/include/firm/os/common/boot.h @@ -0,0 +1,86 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - OS - include + File: boot.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_OS_BOOT_H_ +#define FIRM_OS_BOOT_H_ + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//---- entry point type +typedef void (*OSEntryPoint) (void); + +/*---------------------------------------------------------------------------* + Name: OSi_Boot + + Description: boot firm + + Arguments: entry : entry point + w : wram settings + + Returns: None + *---------------------------------------------------------------------------*/ +void OSi_Boot( void* entry, MIHeader_WramRegs* w ); + +/*---------------------------------------------------------------------------* + Name: OSi_Finalize + + Description: finalize + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void OSi_Finalize(void); + +/*---------------------------------------------------------------------------* + Name: OSi_ClearWorkArea + + Description: clear work area + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void OSi_ClearWorkArea( void ); + +/*---------------------------------------------------------------------------* + Name: OSi_GetFromBromAddr + + Description: data address from bootrom to firm + + Arguments: None + + Returns: address + *---------------------------------------------------------------------------*/ +static inline OSFromBromBuf* OSi_GetFromBromAddr( void ) +{ + return (OSFromBromBuf*)HW_FIRM_FROM_BROM_BUF; +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_OS_BOOT_H_ */ +#endif diff --git a/include/firm/os/common/init.h b/include/firm/os/common/init.h new file mode 100644 index 0000000..45e596c --- /dev/null +++ b/include/firm/os/common/init.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - OS - include + File: init.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_OS_INIT_H_ +#define FIRM_OS_INIT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------* + Name: OS_InitFIRM + + Description: initialize sdk os for firm + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void OS_InitFIRM(void); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_OS_INIT_H_ */ +#endif diff --git a/include/firm/os/common/system.h b/include/firm/os/common/system.h new file mode 100644 index 0000000..2cdd5f8 --- /dev/null +++ b/include/firm/os/common/system.h @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------------* + Project: TwlSDK - OS - include + File: system.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ +#ifndef TWL_FIRM_OS_SYSTEM_H_ +#define TWL_FIRM_OS_SYSTEM_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//---------------------------------------------------------------------------- + +typedef u32 OSCpuCycle; + +#define OS_CPU_CLOCK HW_CPU_CLOCK + +//---- sec to cpu cycle +// 150nsec - 30sec +#define OS_SEC_TO_CPUCYC( sec ) ((OSCpuCycle)( ( OS_CPU_CLOCK * (u32)(sec)) )) +#define OS_MSEC_TO_CPUCYC( msec ) ((OSCpuCycle)( ((OS_CPU_CLOCK/1000) * (u32)(msec)) )) +#define OS_USEC_TO_CPUCYC( usec ) ((OSCpuCycle)( ((OS_CPU_CLOCK/1000) * (u32)(usec)) / 1000 )) +#define OS_NSEC_TO_CPUCYC( nsec ) ((OSCpuCycle)( ((OS_CPU_CLOCK/1000) * (u32)(nsec)) / (1000 * 1000) )) + +//---- cpu cycle to sec +// 150nsec - 30sec +#define OS_CPUCYC_TO_SEC( cyc ) ( ((u32)(cyc) ) / OS_CPU_CLOCK ) +#define OS_CPUCYC_TO_MSEC( cyc ) ( ((u32)(cyc) ) / (OS_CPU_CLOCK/1000) ) +#define OS_CPUCYC_TO_USEC( cyc ) ( ((u32)(cyc) * 1000) / (OS_CPU_CLOCK/1000) ) +#define OS_CPUCYC_TO_NSEC( cyc ) ( ((u32)(cyc) * 1000 * 1000) / (OS_CPU_CLOCK/1000) ) + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* TWL_FIRM_OS_SYSTEM_H_ */ +#endif diff --git a/include/firm/os/common/tick_brom.h b/include/firm/os/common/tick_brom.h new file mode 100644 index 0000000..c0471bf --- /dev/null +++ b/include/firm/os/common/tick_brom.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------* + Project: TwlBromSDK - OS - include + File: tick_addin.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FRIM_OS_TICK_BROM_H_ +#define FRIM_OS_TICK_BROM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//---- sec to tick +#define OS_MicroSecondsToTicksBROM( usec ) ((OSTick)( ((OS_SYSTEM_CLOCK/1000) * (u64)(usec)) / 1024 / 1000 )) +#define OS_MicroSecondsToTicksBROM32( usec ) ((OSTick)( ((OS_SYSTEM_CLOCK/1000) * (u32)(usec)) / 1024 / 1000 )) + +#define OS_MilliSecondsToTicksBROM( msec ) ((OSTick)( ((OS_SYSTEM_CLOCK/1000) * (u64)(msec)) / 1024 )) +#define OS_MilliSecondsToTicksBROM32( msec ) ((OSTick)( ((OS_SYSTEM_CLOCK/1000) * (u32)(msec)) / 1024 )) + +#define OS_SecondsToTicksBROM( sec ) ((OSTick)( (OS_SYSTEM_CLOCK * (u64)(sec)) / 1024 )) +#define OS_SecondsToTicksBROM32( sec ) ((OSTick)( (OS_SYSTEM_CLOCK * (u32)(sec)) / 1024 )) + +//---- tick to sec +#define OS_TicksToMicroSecondsBROM( tick ) ( ((u64)(tick) * 1024 * 1000) / (OS_SYSTEM_CLOCK/1000) ) +#define OS_TicksToMicroSecondsBROM32( tick ) ( ((u32)(tick) * 1024 * 1000) / (OS_SYSTEM_CLOCK/1000) ) + +#define OS_TicksToMilliSecondsBROM( tick ) ( ((u64)(tick) * 1024) / (OS_SYSTEM_CLOCK/1000) ) +#define OS_TicksToMilliSecondsBROM32( tick ) ( ((u32)(tick) * 1024) / (OS_SYSTEM_CLOCK/1000) ) + +#define OS_TicksToSecondsBROM( tick ) ( ((u64)(tick) * 1024) / OS_SYSTEM_CLOCK ) +#define OS_TicksToSecondsBROM32( tick ) ( ((u32)(tick) * 1024) / OS_SYSTEM_CLOCK ) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FRIM_OS_TICK_BROM_H_ */ +#endif diff --git a/include/firm/pm.h b/include/firm/pm.h new file mode 100644 index 0000000..dfb8919 --- /dev/null +++ b/include/firm/pm.h @@ -0,0 +1,27 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - include - pm + File: pm.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_PM_H_ +#define FIRM_PM_H_ + +#ifdef SDK_ARM7 +#include +#include +#endif // SDK_ARM7 + +/* FIRM_PM_H_ */ +#endif diff --git a/include/firm/pm/ARM7/pm_init.h b/include/firm/pm/ARM7/pm_init.h new file mode 100644 index 0000000..055c8d9 --- /dev/null +++ b/include/firm/pm/ARM7/pm_init.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - include - pm + File: pm_init.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_PM_ARM7_PM_INIT_H_ +#define FIRM_PM_ARM7_PM_INIT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------* + Name: PM_InitFIRM + + Description: power B/L on + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void PM_InitFIRM( void ); + +/*---------------------------------------------------------------------------* + Name: PM_CheckINIFlag + + Description: Check INI in GX_DISPSTAT (able to call before PM_InitFIRM) + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void PM_CheckINIFlag(void); + +/*---------------------------------------------------------------------------* + Name: PM_BackLightOn + + Description: power B/L on if not set yet + + Arguments: force TRUE: wait until valid condition + FALSE not set unless valid condition + + Returns: None + *---------------------------------------------------------------------------*/ +void PM_BackLightOn( BOOL force ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_PM_ARM7_PM_INIT_H_ */ +#endif diff --git a/include/firm/pm/ARM7/pm_pmic_ex.h b/include/firm/pm/ARM7/pm_pmic_ex.h new file mode 100644 index 0000000..3651590 --- /dev/null +++ b/include/firm/pm/ARM7/pm_pmic_ex.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - include - pm + File: pm_pmic_ex.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef FIRM_PM_PMIC_EX_H_ +#define FIRM_PM_PMIC_EX_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//================================================================================ +// PMIC ACCESS +//================================================================================ +/*---------------------------------------------------------------------------* + Name: PMi_SetParams + + Description: set control bit to device register + + Arguments: reg : device register + setBits : bits to set + maskBits : bits to mask + + Returns: None + *---------------------------------------------------------------------------*/ +void PMi_SetParams( u8 reg, u8 setBits, u8 maskBits ); + +/*---------------------------------------------------------------------------* + Name: PMi_SetFlags + + Description: set control bit to device register + + Arguments: reg : device register + setBits : bits to set + + Returns: None + *---------------------------------------------------------------------------*/ +void PMi_SetFlags( u8 reg, u8 setBits ); + +/*---------------------------------------------------------------------------* + Name: PMi_ResetFlags + + Description: clear control bit to device register + + Arguments: reg : device register + clrBits : bits to set + + Returns: None + *---------------------------------------------------------------------------*/ +void PMi_ResetFlags( u8 reg, u8 clrBits ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* FIRM_PM_PMIC_EX_H_ */ +#endif diff --git a/include/firm/pxi.h b/include/firm/pxi.h new file mode 100644 index 0000000..b257e65 --- /dev/null +++ b/include/firm/pxi.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - include - PXI + File: pxi.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_PXI_H_ +#define FIRM_PXI_H_ + +#include + +#include +#include + + +/* FIRM_PXI_H_ */ +#endif diff --git a/include/firm/pxi/common/misc.h b/include/firm/pxi/common/misc.h new file mode 100644 index 0000000..36c740b --- /dev/null +++ b/include/firm/pxi/common/misc.h @@ -0,0 +1,217 @@ +/*---------------------------------------------------------------------------* + Project: TwlFirm - -include - PXI + File: misc.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_PXI_COMMON_MISC_H_ +#define FIRM_PXI_COMMON_MISC_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// PXI sync ID for bootrom +typedef enum +{ + // from ARM7 + FIRM_PXI_ID_COLDBOOT = 1, + FIRM_PXI_ID_WARMBOOT = 2, + + FIRM_PXI_ID_INIT_ARM7 = 7, + FIRM_PXI_ID_LOAD_HEADER = 6, + FIRM_PXI_ID_LOAD_STATIC = 5, + + // *_Loaderp (ARM7ARM9) + FIRM_PXI_ID_LOAD_PIRIOD = 1, + + // from ARM9 + FIRM_PXI_ID_INIT_ARM9 = 9, + FIRM_PXI_ID_AUTH_HEADER = 10, + FIRM_PXI_ID_AUTH_STATIC = 11, + + // from both of ARM9 and ARM7 + FIRM_PXI_ID_NULL = 0, + FIRM_PXI_ID_ERR = 0xF +} +FIRMPxiID; + + +/*---------------------------------------------------------------------------* + Name: PXI_InitFifoFIRM + + Description: initialize FIFO system for bootrom + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ +void PXI_InitFifoFIRM(void); + +/*---------------------------------------------------------------------------* + Name: PXI_NotifyID + + Description: send 4bit id to other processor + + Arguments: id notifying id + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_NotifyID( u32 id ); + +/*---------------------------------------------------------------------------* + Name: PXI_WaitID + + Description: Wait 4bit id from the other processor + + Arguments: id waiting id + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_WaitID( u32 id ); + +/*---------------------------------------------------------------------------* + Name: PXI_RecvID + + Description: Receive 4bit id from the other processor + + Arguments: None + + Returns: id + *---------------------------------------------------------------------------*/ +u8 PXI_RecvID( void ); + +/*---------------------------------------------------------------------------* + Name: PXI_SendIDByIntf + + Description: send 4bit id to other processor + + Arguments: id notifying id + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_SendIDByIntf( u32 id ); + +/*---------------------------------------------------------------------------* + Name: PXI_RecvIDByIntf + + Description: receive 4bit id from the other processor + + Arguments: None + + Returns: received id + *---------------------------------------------------------------------------*/ +u32 PXI_RecvIDByIntf( void ); + +/*---------------------------------------------------------------------------* + Name: PXI_WaitIDByIntf + + Description: Wait 4bit id from the other processor + + Arguments: id waiting id + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_WaitIDByIntf( u32 id ); + +/*---------------------------------------------------------------------------* + Name: PXI_SendIDByFifo + + Description: Send 32bit-word to another CPU via FIFO + + Arguments: + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_SendIDByFifo(PXIFifoTag tag, u32 id); + +/*---------------------------------------------------------------------------* + Name: PXI_RecvIDByFifo + + Description: Recv 32bit-word from another CPU via FIFO + + Arguments: + + Returns: if error occured, returns minus value + *---------------------------------------------------------------------------*/ +PXIFifoStatus PXI_RecvIDByFifo(PXIFifoTag tag, void* buf); + +/*---------------------------------------------------------------------------* + Name: PXI_WaitIDByFifo + + Description: Wait 32bit-word from another CPU via FIFO + + Arguments: id waiting id + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_WaitIDByFifo(PXIFifoTag tag, u32 id); + +/*---------------------------------------------------------------------------* + Name: PXI_SendDataByFifo + + Description: Send 32bit-word to another CPU via FIFO + + Arguments: + + Returns: None + *---------------------------------------------------------------------------*/ +void PXI_SendDataByFifo(PXIFifoTag tag, void* buf, int size); + +/*---------------------------------------------------------------------------* + Name: PXI_RecvDataByFifo + + Description: Recv 32bit-word to another CPU via FIFO + + Arguments: + + Returns: if error occured, returns minus value + *---------------------------------------------------------------------------*/ +PXIFifoStatus PXI_RecvDataByFifo(PXIFifoTag tag, void* buf, int max_size); + +/*---------------------------------------------------------------------------* + Name: PXI_IsSendFifoFull + + Description: Check if send fifo is full? + + Arguments: None. + + Returns: if send fifo is full + *---------------------------------------------------------------------------*/ +static inline BOOL PXI_IsSendFifoFull(void) +{ + return (reg_PXI_FIFO_CNT & REG_PXI_FIFO_CNT_SEND_FULL_MASK) >> REG_PXI_FIFO_CNT_SEND_FULL_SHIFT; +} + +/*---------------------------------------------------------------------------* + Name: PXI_IsRecvFifoEmpty + + Description: Check if receive fifo is empty? + + Arguments: None. + + Returns: if receive fifo is empty + *---------------------------------------------------------------------------*/ +static inline BOOL PXI_IsRecvFifoEmpty(void) +{ + return (reg_PXI_FIFO_CNT & REG_PXI_FIFO_CNT_RECV_EMP_MASK) >> REG_PXI_FIFO_CNT_RECV_EMP_SHIFT; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* FIRM_PXI_COMMON_MISC_H_ */ diff --git a/include/firm/pxi/common/regname_ex.h b/include/firm/pxi/common/regname_ex.h new file mode 100644 index 0000000..5883d6c --- /dev/null +++ b/include/firm/pxi/common/regname_ex.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - include - PXI + File: regname.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Log: $ + $NoKeywords: $ + *---------------------------------------------------------------------------*/ + +#ifndef FIRM_PXI_COMMON_REGNAME_EX_H_ +#define FIRM_PXI_COMMON_REGNAME_EX_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SDK_ARM9 + +#define REG_PXI_FIFO_CNT_SEND_FULL_SHIFT REG_PXI_SUBP_FIFO_CNT_SEND_FULL_SHIFT +#define REG_PXI_FIFO_CNT_RECV_EMP_SHIFT REG_PXI_SUBP_FIFO_CNT_RECV_EMP_SHIFT + +#else // SDK_ARM7 + +#define REG_PXI_FIFO_CNT_SEND_FULL_SHIFT REG_PXI_MAINP_FIFO_CNT_SEND_FULL_SHIFT +#define REG_PXI_FIFO_CNT_RECV_EMP_SHIFT REG_PXI_MAINP_FIFO_CNT_RECV_EMP_SHIFT + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif +/* FIRM_PXI_COMMON_REGNAME_EX_H_ */ +#endif diff --git a/include/firm/specfiles/ARM7-BB-FIRM.lcf.template b/include/firm/specfiles/ARM7-BB-FIRM.lcf.template new file mode 100644 index 0000000..a0176d4 --- /dev/null +++ b/include/firm/specfiles/ARM7-BB-FIRM.lcf.template @@ -0,0 +1,507 @@ +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makelcf +# File: ARM7-BB-FIRM.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 # > + + (RWX) : ORIGIN = , LENGTH = 0x0 > + +# binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 > + + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + arena.MAIN (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + check.WORKRAM (RWX) : ORIGIN = , LENGTH = 0x48000 > workram.check +} + +KEEP_SECTION +{ + .ctor +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); . = ALIGN(4); # Fit to cache line + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + OBJECT(_start,*) + crt0_firm.o (.text) + + + + + + + . = ALIGN(4); + * (.exception) + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + EXCEPTION + SDK_STATIC_ETABLE_END =.; + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(4); + SDK_STATIC_TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(4); + SDK_STATIC_DATA_END =.; + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + __exception_table_start__ = SDK_STATIC_ETABLE_START; # for exception table + __exception_table_end__ = SDK_STATIC_ETABLE_END; # for exception table + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(4); + SDK_STATIC_BSS_END = .; + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.MAIN.START = 0x02380000; + SDK_AUTOLOAD.MAIN.END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.BSS_END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.SIZE = 0; + SDK_AUTOLOAD.MAIN.BSS_SIZE = 0; + SDK_AUTOLOAD.WRAM.START = 0x037f8000; + SDK_AUTOLOAD.WRAM.END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.BSS_END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.SIZE = 0; + SDK_AUTOLOAD.WRAM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + SDK_AUTOLOAD..DATA_END =.; + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(4); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_MAIN_START = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD_MAIN_END = SDK_AUTOLOAD.MAIN.END; + SDK_AUTOLOAD_MAIN_BSS_END = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_AUTOLOAD_MAIN_SIZE = SDK_AUTOLOAD.MAIN.SIZE; + SDK_AUTOLOAD_MAIN_BSS_SIZE = SDK_AUTOLOAD.MAIN.BSS_SIZE; + SDK_AUTOLOAD_WRAM_START = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD_WRAM_END = SDK_AUTOLOAD.WRAM.END; + SDK_AUTOLOAD_WRAM_BSS_END = SDK_AUTOLOAD.WRAM.BSS_END; + SDK_AUTOLOAD_WRAM_SIZE = SDK_AUTOLOAD.WRAM.SIZE; + SDK_AUTOLOAD_WRAM_BSS_SIZE = SDK_AUTOLOAD.WRAM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + SDK_AUTOLOAD_LIST = .; + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + SDK_AUTOLOAD_LIST_END = .; + } >> # > binary.AUTOLOAD_INFO + +# SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; +# SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(4); + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(4); + SDK_OVERLAY..DATA_END =.; + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(4); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + + ############################ ARENA ################################## + .arena.MAIN: + { + . = ALIGN(4); + SDK_SECTION_ARENA_START =.; + } > arena.MAIN + + + ############################ OVERLAYDEFS ############################ + .: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > + + + ############################ OVERLAYTABLE ########################### + .: + { + + # Overlay + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + + } > + + + ############################ OTHERS ################################# + SDK_SUBPRIV_ARENA_LO = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_WRAM_ARENA_LO = SDK_SECTION_ARENA_START; + SDK_IRQ_STACKSIZE = ; # allocated in WRAM + SDK_SYS_STACKSIZE = ; # allocated in WRAM + + # work ram size checker + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + .check.WORKRAM: + { + . = . + SDK_SECTION_ARENA_START - + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + } > check.WORKRAM +} diff --git a/include/firm/specfiles/ARM7-BB-FIRM.lsf b/include/firm/specfiles/ARM7-BB-FIRM.lsf new file mode 100644 index 0000000..4217650 --- /dev/null +++ b/include/firm/specfiles/ARM7-BB-FIRM.lsf @@ -0,0 +1,28 @@ +#---------------------------------------------------------------------------- +# Project: TwlFirm - include +# File: ARM7-BB-NORFIRM.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TwlFirm LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x037f8000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) + Object * (.wram) + StackSize 1024 512 +} diff --git a/include/firm/specfiles/ARM7-BB-GCDFIRM.lcf.template b/include/firm/specfiles/ARM7-BB-GCDFIRM.lcf.template new file mode 100644 index 0000000..ebabab9 --- /dev/null +++ b/include/firm/specfiles/ARM7-BB-GCDFIRM.lcf.template @@ -0,0 +1,507 @@ +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makelcf +# File: ARM7-BB-NORFIRM.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 # > + + (RWX) : ORIGIN = , LENGTH = 0x0 > + +# binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 > + + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + arena.MAIN (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + check.WORKRAM (RWX) : ORIGIN = , LENGTH = 0x48000 > workram.check +} + +KEEP_SECTION +{ + .ctor +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); . = ALIGN(4); # Fit to cache line + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + OBJECT(_start,*) + crt0.o (.text) + + + + + + + . = ALIGN(4); + * (.exception) + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + EXCEPTION + SDK_STATIC_ETABLE_END =.; + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(4); + SDK_STATIC_TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(4); + SDK_STATIC_DATA_END =.; + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + __exception_table_start__ = SDK_STATIC_ETABLE_START; # for exception table + __exception_table_end__ = SDK_STATIC_ETABLE_END; # for exception table + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(4); + SDK_STATIC_BSS_END = .; + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.MAIN.START = 0x02380000; + SDK_AUTOLOAD.MAIN.END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.BSS_END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.SIZE = 0; + SDK_AUTOLOAD.MAIN.BSS_SIZE = 0; + SDK_AUTOLOAD.WRAM.START = 0x037f8000; + SDK_AUTOLOAD.WRAM.END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.BSS_END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.SIZE = 0; + SDK_AUTOLOAD.WRAM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + SDK_AUTOLOAD..DATA_END =.; + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(4); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_MAIN_START = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD_MAIN_END = SDK_AUTOLOAD.MAIN.END; + SDK_AUTOLOAD_MAIN_BSS_END = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_AUTOLOAD_MAIN_SIZE = SDK_AUTOLOAD.MAIN.SIZE; + SDK_AUTOLOAD_MAIN_BSS_SIZE = SDK_AUTOLOAD.MAIN.BSS_SIZE; + SDK_AUTOLOAD_WRAM_START = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD_WRAM_END = SDK_AUTOLOAD.WRAM.END; + SDK_AUTOLOAD_WRAM_BSS_END = SDK_AUTOLOAD.WRAM.BSS_END; + SDK_AUTOLOAD_WRAM_SIZE = SDK_AUTOLOAD.WRAM.SIZE; + SDK_AUTOLOAD_WRAM_BSS_SIZE = SDK_AUTOLOAD.WRAM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + SDK_AUTOLOAD_LIST = .; + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + SDK_AUTOLOAD_LIST_END = .; + } >> # > binary.AUTOLOAD_INFO + +# SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; +# SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(4); + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(4); + SDK_OVERLAY..DATA_END =.; + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(4); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + + ############################ ARENA ################################## + .arena.MAIN: + { + . = ALIGN(4); + SDK_SECTION_ARENA_START =.; + } > arena.MAIN + + + ############################ OVERLAYDEFS ############################ + .: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > + + + ############################ OVERLAYTABLE ########################### + .: + { + + # Overlay + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + + } > + + + ############################ OTHERS ################################# + SDK_SUBPRIV_ARENA_LO = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_WRAM_ARENA_LO = SDK_SECTION_ARENA_START; + SDK_IRQ_STACKSIZE = ; # allocated in WRAM + SDK_SYS_STACKSIZE = ; # allocated in WRAM + + # work ram size checker + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + .check.WORKRAM: + { + . = . + SDK_SECTION_ARENA_START - + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + } > check.WORKRAM +} diff --git a/include/firm/specfiles/ARM7-BB-GCDFIRM.lsf b/include/firm/specfiles/ARM7-BB-GCDFIRM.lsf new file mode 100644 index 0000000..4217650 --- /dev/null +++ b/include/firm/specfiles/ARM7-BB-GCDFIRM.lsf @@ -0,0 +1,28 @@ +#---------------------------------------------------------------------------- +# Project: TwlFirm - include +# File: ARM7-BB-NORFIRM.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TwlFirm LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x037f8000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) + Object * (.wram) + StackSize 1024 512 +} diff --git a/include/firm/specfiles/ARM7-TS-FIRM.lcf.template b/include/firm/specfiles/ARM7-TS-FIRM.lcf.template new file mode 100644 index 0000000..8f7597a --- /dev/null +++ b/include/firm/specfiles/ARM7-TS-FIRM.lcf.template @@ -0,0 +1,929 @@ +#--------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ARM7-BB.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 > + + + (RWX) : ORIGIN = , LENGTH = 0x0 >> + + binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + binary.STATIC_FOOTER (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + F (RW) : ORIGIN = 0, LENGTH = 0x0 > + F (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + + arena.MAIN (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + check.WORKRAM (RWX) : ORIGIN = 0x037f8000, LENGTH = 0x18000 > workram.check + check.MAINMEM (RWX) : ORIGIN = 0x02fe0000, LENGTH = 0x1c000 > mainmem.check + + binary.LTDAUTOLOAD_TOP (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWX) : ORIGIN = , LENGTH = 0x0 >> + + binary.LTDAUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + L (RW) : ORIGIN = 0, LENGTH = 0x0 > + L (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + + check.LTDWRAM (RWX) : ORIGIN = 0x03000000, LENGTH = 0x40000 > ltdwram.check + check.LTDMAIN (RWX) : ORIGIN = 0x02f88000, LENGTH = 0x58000 > ltdmain.check +} + +KEEP_SECTION +{ + .sinit +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + OBJECT(_start,*) + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + #:::::::::: text/rodata + SDK_STATIC_TEXT_END =.; + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + __exception_table_start__ =.; + EXCEPTION + __exception_table_end__ =.; + SDK_STATIC_ETABLE_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(4); + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_STATIC_DATA_END =.; + . = ALIGN(4); + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_STATIC_BSS_END = .; + + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.MAIN.START = 0x02fe0000; + SDK_AUTOLOAD.MAIN.END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.BSS_END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.SIZE = 0; + SDK_AUTOLOAD.MAIN.BSS_SIZE = 0; + SDK_AUTOLOAD.WRAM.START = 0x037f8000; + SDK_AUTOLOAD.WRAM.END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.BSS_END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.SIZE = 0; + SDK_AUTOLOAD.WRAM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + . = ALIGN(4); + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_AUTOLOAD..DATA_END =.; + . = ALIGN(4); + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_MAIN_START = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD_MAIN_END = SDK_AUTOLOAD.MAIN.END; + SDK_AUTOLOAD_MAIN_BSS_END = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_AUTOLOAD_MAIN_SIZE = SDK_AUTOLOAD.MAIN.SIZE; + SDK_AUTOLOAD_MAIN_BSS_SIZE = SDK_AUTOLOAD.MAIN.BSS_SIZE; + SDK_AUTOLOAD_WRAM_START = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD_WRAM_END = SDK_AUTOLOAD.WRAM.END; + SDK_AUTOLOAD_WRAM_BSS_END = SDK_AUTOLOAD.WRAM.BSS_END; + SDK_AUTOLOAD_WRAM_SIZE = SDK_AUTOLOAD.WRAM.SIZE; + SDK_AUTOLOAD_WRAM_BSS_SIZE = SDK_AUTOLOAD.WRAM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + } > binary.AUTOLOAD_INFO + + SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; + SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + + ############################ STATIC_FOOTER ########################## + .binary.STATIC_FOOTER: + { + WRITEW 0xdec00621; # LE(0x2106C0DE) = NITRO CODE + WRITEW _start_ModuleParams - ADDR(.); + WRITEW 0; # NO DIGEST + WRITEW _start_LtdModuleParams - ADDR(.); + } > binary.STATIC_FOOTER + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + #:::::::::: text/rodata + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(4); + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_OVERLAY..DATA_END =.; + . = ALIGN(4); + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + ############################ ARENA ################################## + .arena.MAIN: + { + . = ALIGN(4); + SDK_SECTION_ARENA_START =.; + + } > arena.MAIN + + ############################ OVERLAYDEFS ############################ + .F: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > F + + ############################ OVERLAYTABLE ########################### + .F: + { + + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + } > F + + ############################ OTHERS ################################# + SDK_WRAM_ARENA_LO = SDK_AUTOLOAD.WRAM.BSS_END; + SDK_SUBPRIV_ARENA_LO = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_IRQ_STACKSIZE = ; # allocated in WRAM + SDK_SYS_STACKSIZE = ; # allocated in WRAM + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + + .check.WORKRAM: + { + . = . + SDK_AUTOLOAD.WRAM.BSS_END - SDK_AUTOLOAD.WRAM.START + 0x080 + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + + } > check.WORKRAM + + .check.MAINMEM: + { + . = SDK_SUBPRIV_ARENA_LO; + + } > check.MAINMEM + + ########################### LTDAUTOLOADS ############################ + SDK_LTDAUTOLOAD.LTDMAIN.START = SDK_STATIC_BSS_END; + SDK_LTDAUTOLOAD.LTDMAIN.END = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD.LTDMAIN.BSS_END = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD.LTDMAIN.SIZE = 0; + SDK_LTDAUTOLOAD.LTDMAIN.BSS_SIZE = 0; + SDK_LTDAUTOLOAD.LTDWRAM.START = 0x03000000; + SDK_LTDAUTOLOAD.LTDWRAM.END = SDK_LTDAUTOLOAD.LTDWRAM.START; + SDK_LTDAUTOLOAD.LTDWRAM.BSS_END = SDK_LTDAUTOLOAD.LTDWRAM.START; + SDK_LTDAUTOLOAD.LTDWRAM.SIZE = 0; + SDK_LTDAUTOLOAD.LTDWRAM.BSS_SIZE = 0; + SDK_LTDAUTOLOAD_TOP_START = 0x02e80000; + SDK_LTDAUTOLOAD_TOP_SIZE = 4; # STATIC ̈悪 4 bytes ̃_~[oCit@C̐擪ɓ # + SDK_LTDAUTOLOAD_START = SDK_LTDAUTOLOAD_TOP_START + SDK_LTDAUTOLOAD_TOP_SIZE; + SDK_LTDAUTOLOAD_SIZE = 0; + SDK_LTDAUTOLOAD_NUMBER = ; + + .binary.LTDAUTOLOAD_TOP: + { + WRITEW 0xdeadbeef; + + } > binary.LTDAUTOLOAD_TOP + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + SDK_LTDAUTOLOAD__ID =; + SDK_LTDAUTOLOAD..ID =; + SDK_LTDAUTOLOAD..START =.; + # + # TEXT BLOCK: READ ONLY + # + SDK_LTDAUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + #:::::::::: text/rodata + SDK_LTDAUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + . = ALIGN(4); + SDK_LTDAUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_LTDAUTOLOAD..DATA_END =.; + . = ALIGN(4); + SDK_LTDAUTOLOAD..END =.; + + SDK_LTDAUTOLOAD..TEXT_SIZE = SDK_LTDAUTOLOAD..TEXT_END - SDK_LTDAUTOLOAD..TEXT_START; + SDK_LTDAUTOLOAD..DATA_SIZE = SDK_LTDAUTOLOAD..DATA_END - SDK_LTDAUTOLOAD..DATA_START; + SDK_LTDAUTOLOAD..SIZE = SDK_LTDAUTOLOAD..END - SDK_LTDAUTOLOAD..START; + SDK_LTDAUTOLOAD_SIZE = SDK_LTDAUTOLOAD_SIZE + SDK_LTDAUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_LTDAUTOLOAD..BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_LTDAUTOLOAD..BSS_END =.; + + SDK_LTDAUTOLOAD..BSS_SIZE = SDK_LTDAUTOLOAD..BSS_END - SDK_LTDAUTOLOAD..BSS_START; + + } >> + + + + SDK_LTDAUTOLOAD_LTDMAIN_START = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD_LTDMAIN_END = SDK_LTDAUTOLOAD.LTDMAIN.END; + SDK_LTDAUTOLOAD_LTDMAIN_BSS_END = SDK_LTDAUTOLOAD.LTDMAIN.BSS_END; + SDK_LTDAUTOLOAD_LTDMAIN_SIZE = SDK_LTDAUTOLOAD.LTDMAIN.SIZE; + SDK_LTDAUTOLOAD_LTDMAIN_BSS_SIZE = SDK_LTDAUTOLOAD.LTDMAIN.BSS_SIZE; + SDK_LTDAUTOLOAD_LTDWRAM_START = SDK_LTDAUTOLOAD.LTDWRAM.START; + SDK_LTDAUTOLOAD_LTDWRAM_END = SDK_LTDAUTOLOAD.LTDWRAM.END; + SDK_LTDAUTOLOAD_LTDWRAM_BSS_END = SDK_LTDAUTOLOAD.LTDWRAM.BSS_END; + SDK_LTDAUTOLOAD_LTDWRAM_SIZE = SDK_LTDAUTOLOAD.LTDWRAM.SIZE; + SDK_LTDAUTOLOAD_LTDWRAM_BSS_SIZE = SDK_LTDAUTOLOAD.LTDWRAM.BSS_SIZE; + + ######################### LTDAUTOLOAD_INFO ########################## + .binary.LTDAUTOLOAD_INFO: + { + + WRITEW ADDR(.); + WRITEW SDK_LTDAUTOLOAD..SIZE; + WRITEW SDK_LTDAUTOLOAD..BSS_SIZE; + + } > binary.LTDAUTOLOAD_INFO + + SDK_LTDAUTOLOAD_LIST = SDK_LTDAUTOLOAD_START + SDK_LTDAUTOLOAD_SIZE; + SDK_LTDAUTOLOAD_LIST_END = SDK_LTDAUTOLOAD_LIST + SIZEOF(.binary.LTDAUTOLOAD_INFO); + SDK_LTDAUTOLOAD_SIZE = SDK_LTDAUTOLOAD_SIZE + SIZEOF(.binary.LTDAUTOLOAD_INFO); + + ########################### LTDOVERLAYS ############################# + SDK_LTDOVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + SDK_LTDOVERLAY__ID =; + SDK_LTDOVERLAY..ID =; + SDK_LTDOVERLAY..START =.; + # + # TEXT BLOCK: READ ONLY + # + SDK_LTDOVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_LTDOVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_LTDOVERLAY..SINIT_END =.; + #:::::::::: text/rodata + SDK_LTDOVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(4); + SDK_LTDOVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_LTDOVERLAY..DATA_END =.; + . = ALIGN(4); + SDK_LTDOVERLAY..END =.; + + SDK_LTDOVERLAY..TEXT_SIZE = SDK_LTDOVERLAY..TEXT_END - SDK_LTDOVERLAY..TEXT_START; + SDK_LTDOVERLAY..DATA_SIZE = SDK_LTDOVERLAY..DATA_END - SDK_LTDOVERLAY..DATA_START; + SDK_LTDOVERLAY..SIZE = SDK_LTDOVERLAY..END - SDK_LTDOVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_LTDOVERLAY..BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_LTDOVERLAY..BSS_END =.; + + SDK_LTDOVERLAY..BSS_SIZE = SDK_LTDOVERLAY..BSS_END - SDK_LTDOVERLAY..BSS_START; + + } >> + + + + ########################## LTDOVERLAYDEFS ########################### + .L: + { + ### TWL limited extended static module information + WRITEW SDK_LTDAUTOLOAD_TOP_START; # load address + WRITEW 0; # padding + WRITEW SDK_LTDAUTOLOAD_SIZE + SDK_LTDAUTOLOAD_TOP_SIZE; # size of module + WRITEW 0; # padding + + ### TWL limited overlay filename + + WRITES (""); + + + } > L + + ######################### LTDOVERLAYTABLE ########################### + .L: + { + + WRITES # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_LTDOVERLAY..SIZE; # size of module + WRITEW SDK_LTDOVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_LTDOVERLAY..SINIT_START; # start address of static init + WRITEW SDK_LTDOVERLAY..SINIT_END; # end address of static init + WRITEW # ROM file ID + WRITEW 0; # Reserved + + + } > L + + ############################ OTHERS ################################# + .check.LTDWRAM: + { + . = SDK_LTDAUTOLOAD.LTDWRAM.BSS_END; + + } > check.LTDWRAM + + .check.LTDMAIN: + { +# . = SDK_LTDAUTOLOAD.LTDMAIN.BSS_END; + + } > check.LTDMAIN + +} diff --git a/include/firm/specfiles/ARM7-TS-FIRM.lsf b/include/firm/specfiles/ARM7-TS-FIRM.lsf new file mode 100644 index 0000000..10fc59e --- /dev/null +++ b/include/firm/specfiles/ARM7-TS-FIRM.lsf @@ -0,0 +1,31 @@ +#---------------------------------------------------------------------------- +# Project: TwlFirm - include +# File: ARM7-TS-NORFIRM.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TwlFirm LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x037f8000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) + Object * (.etable) + Object * (.wram) + Object * (.ltdwram) + Object * (.ltdmain) + StackSize 1024 1024 +} diff --git a/include/firm/specfiles/ARM7-TS-GCDFIRM.lcf.template b/include/firm/specfiles/ARM7-TS-GCDFIRM.lcf.template new file mode 100644 index 0000000..c3244f8 --- /dev/null +++ b/include/firm/specfiles/ARM7-TS-GCDFIRM.lcf.template @@ -0,0 +1,507 @@ +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makelcf +# File: ARM7-TS-NORFIRM.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 # > + + (RWX) : ORIGIN = , LENGTH = 0x0 > + +# binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 > + + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + arena.MAIN (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + check.WORKRAM (RWX) : ORIGIN = , LENGTH = 0x48000 > workram.check +} + +KEEP_SECTION +{ + .ctor +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); . = ALIGN(4); # Fit to cache line + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + OBJECT(_start,*) + crt0.o (.text) + + + + + + + . = ALIGN(4); + * (.exception) + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + EXCEPTION + SDK_STATIC_ETABLE_END =.; + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(4); + SDK_STATIC_TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(4); + SDK_STATIC_DATA_END =.; + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + __exception_table_start__ = SDK_STATIC_ETABLE_START; # for exception table + __exception_table_end__ = SDK_STATIC_ETABLE_END; # for exception table + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(4); + SDK_STATIC_BSS_END = .; + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.MAIN.START = 0x02380000; + SDK_AUTOLOAD.MAIN.END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.BSS_END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.SIZE = 0; + SDK_AUTOLOAD.MAIN.BSS_SIZE = 0; + SDK_AUTOLOAD.WRAM.START = 0x037f8000; + SDK_AUTOLOAD.WRAM.END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.BSS_END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.SIZE = 0; + SDK_AUTOLOAD.WRAM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + SDK_AUTOLOAD..DATA_END =.; + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(4); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_MAIN_START = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD_MAIN_END = SDK_AUTOLOAD.MAIN.END; + SDK_AUTOLOAD_MAIN_BSS_END = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_AUTOLOAD_MAIN_SIZE = SDK_AUTOLOAD.MAIN.SIZE; + SDK_AUTOLOAD_MAIN_BSS_SIZE = SDK_AUTOLOAD.MAIN.BSS_SIZE; + SDK_AUTOLOAD_WRAM_START = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD_WRAM_END = SDK_AUTOLOAD.WRAM.END; + SDK_AUTOLOAD_WRAM_BSS_END = SDK_AUTOLOAD.WRAM.BSS_END; + SDK_AUTOLOAD_WRAM_SIZE = SDK_AUTOLOAD.WRAM.SIZE; + SDK_AUTOLOAD_WRAM_BSS_SIZE = SDK_AUTOLOAD.WRAM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + SDK_AUTOLOAD_LIST = .; + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + SDK_AUTOLOAD_LIST_END = .; + } >> # > binary.AUTOLOAD_INFO + +# SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; +# SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(4); + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(4); + SDK_OVERLAY..DATA_END =.; + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(4); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(4); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + + ############################ ARENA ################################## + .arena.MAIN: + { + . = ALIGN(4); + SDK_SECTION_ARENA_START =.; + } > arena.MAIN + + + ############################ OVERLAYDEFS ############################ + .: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > + + + ############################ OVERLAYTABLE ########################### + .: + { + + # Overlay + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + + } > + + + ############################ OTHERS ################################# + SDK_SUBPRIV_ARENA_LO = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_WRAM_ARENA_LO = SDK_SECTION_ARENA_START; + SDK_IRQ_STACKSIZE = ; # allocated in WRAM + SDK_SYS_STACKSIZE = ; # allocated in WRAM + + # work ram size checker + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + .check.WORKRAM: + { + . = . + SDK_SECTION_ARENA_START - + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + } > check.WORKRAM +} diff --git a/include/firm/specfiles/ARM7-TS-GCDFIRM.lsf b/include/firm/specfiles/ARM7-TS-GCDFIRM.lsf new file mode 100644 index 0000000..d4f5d88 --- /dev/null +++ b/include/firm/specfiles/ARM7-TS-GCDFIRM.lsf @@ -0,0 +1,28 @@ +#---------------------------------------------------------------------------- +# Project: TwlFirm - include +# File: ARM7-TS-NORFIRM.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TwlFirm LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x037f8000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) + Object * (.wram) + StackSize 1024 512 +} diff --git a/include/firm/specfiles/ARM7-TS-PARTNER.lcf.template b/include/firm/specfiles/ARM7-TS-PARTNER.lcf.template new file mode 100644 index 0000000..5e9c415 --- /dev/null +++ b/include/firm/specfiles/ARM7-TS-PARTNER.lcf.template @@ -0,0 +1,899 @@ +#--------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ARM7-BB.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 #> + + + (RWX) : ORIGIN = , LENGTH = 0x0 #>> + +# binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + F (RW) : ORIGIN = 0, LENGTH = 0x0 > + F (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + + arena.MAIN (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + check.WORKRAM (RWX) : ORIGIN = 0x037f8000, LENGTH = 0x18000 > workram.check + check.MAINMEM (RWX) : ORIGIN = 0x02fe0000, LENGTH = 0x1c000 > mainmem.check + +# binary.LTDAUTOLOAD_TOP (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWX) : ORIGIN = , LENGTH = 0x0 #>> + +# binary.LTDAUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + L (RW) : ORIGIN = 0, LENGTH = 0x0 > + L (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + + check.LTDWRAM (RWX) : ORIGIN = 0x03000000, LENGTH = 0x40000 > ltdwram.check + check.LTDMAIN (RWX) : ORIGIN = 0x02f88000, LENGTH = 0x58000 > ltdmain.check +} + +KEEP_SECTION +{ + .sinit +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + OBJECT(_start,*) + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + #:::::::::: text/rodata + SDK_STATIC_TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(4); + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_STATIC_DATA_END =.; + . = ALIGN(4); + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_STATIC_BSS_END = .; + + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.MAIN.START = 0x02fe0000; + SDK_AUTOLOAD.MAIN.END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.BSS_END = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD.MAIN.SIZE = 0; + SDK_AUTOLOAD.MAIN.BSS_SIZE = 0; + SDK_AUTOLOAD.WRAM.START = 0x037f8000; + SDK_AUTOLOAD.WRAM.END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.BSS_END = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD.WRAM.SIZE = 0; + SDK_AUTOLOAD.WRAM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + __exception_table_start__ =.; + EXCEPTION + __exception_table_end__ =.; + SDK_STATIC_ETABLE_END =.; + + + + + + + + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + . = ALIGN(4); + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_AUTOLOAD..DATA_END =.; + . = ALIGN(4); + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_MAIN_START = SDK_AUTOLOAD.MAIN.START; + SDK_AUTOLOAD_MAIN_END = SDK_AUTOLOAD.MAIN.END; + SDK_AUTOLOAD_MAIN_BSS_END = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_AUTOLOAD_MAIN_SIZE = SDK_AUTOLOAD.MAIN.SIZE; + SDK_AUTOLOAD_MAIN_BSS_SIZE = SDK_AUTOLOAD.MAIN.BSS_SIZE; + SDK_AUTOLOAD_WRAM_START = SDK_AUTOLOAD.WRAM.START; + SDK_AUTOLOAD_WRAM_END = SDK_AUTOLOAD.WRAM.END; + SDK_AUTOLOAD_WRAM_BSS_END = SDK_AUTOLOAD.WRAM.BSS_END; + SDK_AUTOLOAD_WRAM_SIZE = SDK_AUTOLOAD.WRAM.SIZE; + SDK_AUTOLOAD_WRAM_BSS_SIZE = SDK_AUTOLOAD.WRAM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + SDK_AUTOLOAD_LIST = .; + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + SDK_AUTOLOAD_LIST_END = .; + } >> #> binary.AUTOLOAD_INFO + +# SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; +# SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + #:::::::::: text/rodata + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(4); + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_OVERLAY..DATA_END =.; + . = ALIGN(4); + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + ############################ ARENA ################################## + .arena.MAIN: + { + . = ALIGN(4); + SDK_SECTION_ARENA_START =.; + + } > arena.MAIN + + ############################ OVERLAYDEFS ############################ + .F: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > F + + ############################ OVERLAYTABLE ########################### + .F: + { + + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + } > F + + ############################ OTHERS ################################# + SDK_WRAM_ARENA_LO = SDK_AUTOLOAD.WRAM.BSS_END; + SDK_SUBPRIV_ARENA_LO = SDK_AUTOLOAD.MAIN.BSS_END; + SDK_IRQ_STACKSIZE = ; # allocated in WRAM + SDK_SYS_STACKSIZE = ; # allocated in WRAM + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + + .check.WORKRAM: + { + . = . + SDK_AUTOLOAD.WRAM.BSS_END - SDK_AUTOLOAD.WRAM.START + 0x080 + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + + } > check.WORKRAM + + .check.MAINMEM: + { + . = SDK_SUBPRIV_ARENA_LO; + + } > check.MAINMEM + + ########################### LTDAUTOLOADS ############################ + SDK_LTDAUTOLOAD.LTDMAIN.START = SDK_STATIC_BSS_END; + SDK_LTDAUTOLOAD.LTDMAIN.END = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD.LTDMAIN.BSS_END = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD.LTDMAIN.SIZE = 0; + SDK_LTDAUTOLOAD.LTDMAIN.BSS_SIZE = 0; + SDK_LTDAUTOLOAD.LTDWRAM.START = 0x03000000; + SDK_LTDAUTOLOAD.LTDWRAM.END = SDK_LTDAUTOLOAD.LTDWRAM.START; + SDK_LTDAUTOLOAD.LTDWRAM.BSS_END = SDK_LTDAUTOLOAD.LTDWRAM.START; + SDK_LTDAUTOLOAD.LTDWRAM.SIZE = 0; + SDK_LTDAUTOLOAD.LTDWRAM.BSS_SIZE = 0; + SDK_LTDAUTOLOAD_TOP_START = 0x02e80000; + SDK_LTDAUTOLOAD_TOP_SIZE = 4; # STATIC ̈悪 4 bytes ̃_~[oCit@C̐擪ɓ # + SDK_LTDAUTOLOAD_START = SDK_LTDAUTOLOAD_TOP_START + SDK_LTDAUTOLOAD_TOP_SIZE; + SDK_LTDAUTOLOAD_SIZE = 0; + SDK_LTDAUTOLOAD_NUMBER = ; + + .binary.LTDAUTOLOAD_TOP: + { + WRITEW 0xdeadbeef; + + } >> #> binary.LTDAUTOLOAD_TOP + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + SDK_LTDAUTOLOAD__ID =; + SDK_LTDAUTOLOAD..ID =; + SDK_LTDAUTOLOAD..START =.; + # + # TEXT BLOCK: READ ONLY + # + SDK_LTDAUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + #:::::::::: text/rodata + SDK_LTDAUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + . = ALIGN(4); + SDK_LTDAUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_LTDAUTOLOAD..DATA_END =.; + . = ALIGN(4); + SDK_LTDAUTOLOAD..END =.; + + SDK_LTDAUTOLOAD..TEXT_SIZE = SDK_LTDAUTOLOAD..TEXT_END - SDK_LTDAUTOLOAD..TEXT_START; + SDK_LTDAUTOLOAD..DATA_SIZE = SDK_LTDAUTOLOAD..DATA_END - SDK_LTDAUTOLOAD..DATA_START; + SDK_LTDAUTOLOAD..SIZE = SDK_LTDAUTOLOAD..END - SDK_LTDAUTOLOAD..START; + SDK_LTDAUTOLOAD_SIZE = SDK_LTDAUTOLOAD_SIZE + SDK_LTDAUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_LTDAUTOLOAD..BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_LTDAUTOLOAD..BSS_END =.; + + SDK_LTDAUTOLOAD..BSS_SIZE = SDK_LTDAUTOLOAD..BSS_END - SDK_LTDAUTOLOAD..BSS_START; + + } >> + + + + SDK_LTDAUTOLOAD_LTDMAIN_START = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD_LTDMAIN_END = SDK_LTDAUTOLOAD.LTDMAIN.END; + SDK_LTDAUTOLOAD_LTDMAIN_BSS_END = SDK_LTDAUTOLOAD.LTDMAIN.BSS_END; + SDK_LTDAUTOLOAD_LTDMAIN_SIZE = SDK_LTDAUTOLOAD.LTDMAIN.SIZE; + SDK_LTDAUTOLOAD_LTDMAIN_BSS_SIZE = SDK_LTDAUTOLOAD.LTDMAIN.BSS_SIZE; + SDK_LTDAUTOLOAD_LTDWRAM_START = SDK_LTDAUTOLOAD.LTDWRAM.START; + SDK_LTDAUTOLOAD_LTDWRAM_END = SDK_LTDAUTOLOAD.LTDWRAM.END; + SDK_LTDAUTOLOAD_LTDWRAM_BSS_END = SDK_LTDAUTOLOAD.LTDWRAM.BSS_END; + SDK_LTDAUTOLOAD_LTDWRAM_SIZE = SDK_LTDAUTOLOAD.LTDWRAM.SIZE; + SDK_LTDAUTOLOAD_LTDWRAM_BSS_SIZE = SDK_LTDAUTOLOAD.LTDWRAM.BSS_SIZE; + + ######################### LTDAUTOLOAD_INFO ########################## + .binary.LTDAUTOLOAD_INFO: + { + SDK_LTDAUTOLOAD_LIST = .; + + WRITEW ADDR(.); + WRITEW SDK_LTDAUTOLOAD..SIZE; + WRITEW SDK_LTDAUTOLOAD..BSS_SIZE; + + SDK_LTDAUTOLOAD_LIST_END = .; + } >> #> binary.LTDAUTOLOAD_INFO + +# SDK_LTDAUTOLOAD_LIST = SDK_LTDAUTOLOAD_START + SDK_LTDAUTOLOAD_SIZE; +# SDK_LTDAUTOLOAD_LIST_END = SDK_LTDAUTOLOAD_LIST + SIZEOF(.binary.LTDAUTOLOAD_INFO); + SDK_LTDAUTOLOAD_SIZE = SDK_LTDAUTOLOAD_SIZE + SIZEOF(.binary.LTDAUTOLOAD_INFO); + + ########################### LTDOVERLAYS ############################# + SDK_LTDOVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + SDK_LTDOVERLAY__ID =; + SDK_LTDOVERLAY..ID =; + SDK_LTDOVERLAY..START =.; + # + # TEXT BLOCK: READ ONLY + # + SDK_LTDOVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_LTDOVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_LTDOVERLAY..SINIT_END =.; + #:::::::::: text/rodata + SDK_LTDOVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(4); + SDK_LTDOVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_LTDOVERLAY..DATA_END =.; + . = ALIGN(4); + SDK_LTDOVERLAY..END =.; + + SDK_LTDOVERLAY..TEXT_SIZE = SDK_LTDOVERLAY..TEXT_END - SDK_LTDOVERLAY..TEXT_START; + SDK_LTDOVERLAY..DATA_SIZE = SDK_LTDOVERLAY..DATA_END - SDK_LTDOVERLAY..DATA_START; + SDK_LTDOVERLAY..SIZE = SDK_LTDOVERLAY..END - SDK_LTDOVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(4); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_LTDOVERLAY..BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(4); + SDK_LTDOVERLAY..BSS_END =.; + + SDK_LTDOVERLAY..BSS_SIZE = SDK_LTDOVERLAY..BSS_END - SDK_LTDOVERLAY..BSS_START; + + } >> + + + + ########################## LTDOVERLAYDEFS ########################### + .L: + { + ### TWL limited extended static module information + WRITEW SDK_LTDAUTOLOAD_TOP_START; # load address + WRITEW 0; # padding + WRITEW SDK_LTDAUTOLOAD_SIZE + SDK_LTDAUTOLOAD_TOP_SIZE; # size of module + WRITEW 0; # padding + + ### TWL limited overlay filename + + WRITES (""); + + + } > L + + ######################### LTDOVERLAYTABLE ########################### + .L: + { + + WRITES # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_LTDOVERLAY..SIZE; # size of module + WRITEW SDK_LTDOVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_LTDOVERLAY..SINIT_START; # start address of static init + WRITEW SDK_LTDOVERLAY..SINIT_END; # end address of static init + WRITEW # ROM file ID + WRITEW 0; # Reserved + + + } > L + + ############################ OTHERS ################################# + .check.LTDWRAM: + { + . = SDK_LTDAUTOLOAD.LTDWRAM.BSS_END; + + } > check.LTDWRAM + + .check.LTDMAIN: + { +# . = SDK_LTDAUTOLOAD.LTDMAIN.BSS_END; + + } > check.LTDMAIN + +} diff --git a/include/firm/specfiles/ARM9-BB-FIRM.lcf.template b/include/firm/specfiles/ARM9-BB-FIRM.lcf.template new file mode 100644 index 0000000..da10b75 --- /dev/null +++ b/include/firm/specfiles/ARM9-BB-FIRM.lcf.template @@ -0,0 +1,602 @@ +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makelcf +# File: ARM9-BB-FIRM.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 # > + + (RWX) : ORIGIN = , LENGTH = 0x0 # > + +# binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 > +# binary.STATIC_FOOTER (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + dummy.MAIN_EX (RW) : ORIGIN = 0x023e0000, LENGTH = 0x0 + arena.MAIN (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + arena.MAIN_EX (RW) : ORIGIN = AFTER(dummy.MAIN_EX,), LENGTH = 0x0 + arena.ITCM (RW) : ORIGIN = AFTER(ITCM,), LENGTH = 0x0 + arena.DTCM (RW) : ORIGIN = AFTER(DTCM,), LENGTH = 0x0 + binary.MODULE_FILES (RW) : ORIGIN = 0x0, LENGTH = 0x0 > component.files + check.ITCM (RWX) : ORIGIN = 0x0, LENGTH = 0x08000 > itcm.check + check.DTCM (RW) : ORIGIN = 0x0, LENGTH = 0x04000 > dtcm.check +} + +FORCE_ACTIVE +{ + SVC_SoftReset +} + +KEEP_SECTION +{ + .sinit +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); . = ALIGN(32); # Fit to cache line + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + crt0_firm.o (.text) + libsyscall.a (.text) + crt0_firm.o (.rodata) + # + # .version ZNVljĂ܂B + # ̃ZNVɊ܂܂̓bg`FbN̍ۂ + # KvƂȂ܂̂ŁAK̈ʒuɎc悤ɂĉB + # + * (.version) + OBJECT(TwlMain,*) + + + + + + + . = ALIGN(4); + * (.exception) + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + EXCEPTION + SDK_STATIC_ETABLE_END =.; + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(32); + SDK_STATIC_TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + SDK_OVERLAY_DIGEST =.; + # NO DIGEST + SDK_OVERLAY_DIGEST_END =.; + #:::::::::: data + . = ALIGN(32); + SDK_STATIC_DATA_END =.; + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + __exception_table_start__ = SDK_STATIC_ETABLE_START; # for exception table + __exception_table_end__ = SDK_STATIC_ETABLE_END; # for exception table + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(32); + SDK_STATIC_BSS_END = .; + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.ITCM.START = 0x01ff8000; + SDK_AUTOLOAD.ITCM.END = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD.ITCM.BSS_END = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD.ITCM.SIZE = 0; + SDK_AUTOLOAD.ITCM.BSS_SIZE = 0; + SDK_AUTOLOAD.DTCM.START = 0x027e0000; + SDK_AUTOLOAD.DTCM.END = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD.DTCM.BSS_END = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD.DTCM.SIZE = 0; + SDK_AUTOLOAD.DTCM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(32); + SDK_AUTOLOAD..DATA_END =.; + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(32); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_ITCM_START = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD_ITCM_END = SDK_AUTOLOAD.ITCM.END; + SDK_AUTOLOAD_ITCM_BSS_END = SDK_AUTOLOAD.ITCM.BSS_END; + SDK_AUTOLOAD_ITCM_SIZE = SDK_AUTOLOAD.ITCM.SIZE; + SDK_AUTOLOAD_ITCM_BSS_SIZE = SDK_AUTOLOAD.ITCM.BSS_SIZE; + SDK_AUTOLOAD_DTCM_START = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD_DTCM_END = SDK_AUTOLOAD.DTCM.END; + SDK_AUTOLOAD_DTCM_BSS_END = SDK_AUTOLOAD.DTCM.BSS_END; + SDK_AUTOLOAD_DTCM_SIZE = SDK_AUTOLOAD.DTCM.SIZE; + SDK_AUTOLOAD_DTCM_BSS_SIZE = SDK_AUTOLOAD.DTCM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + SDK_AUTOLOAD_LIST = .; + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + SDK_AUTOLOAD_LIST_END = .; + } >> # > binary.AUTOLOAD_INFO + +# SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; +# SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + + ############################ STATIC_FOOTER ########################## + .binary.STATIC_FOOTER: + { + WRITEW 0xdec00621; # LE(0x2106C0DE) = NITRO CODE + WRITEW _start_ModuleParams - ADDR(.); + WRITEW 0; # NO DIGEST + } >> # > binary.STATIC_FOOTER + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(32); + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(32); + SDK_OVERLAY..DATA_END =.; + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(32); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + ############################ MAIN EX ################################## + # MAIN EX Area + .dummy.MAIN_EX: + { + . = ALIGN(32); + } > dummy.MAIN_EX + + ############################ ARENA ################################## + .arena.MAIN: + { + . = ALIGN(32); + SDK_SECTION_ARENA_START =.; + } > arena.MAIN + + .arena.MAIN_EX: + { + . = ALIGN(32); + SDK_SECTION_ARENA_EX_START =.; + } > arena.MAIN_EX + + .arena.ITCM: + { + . = ALIGN(32); + SDK_SECTION_ARENA_ITCM_START =.; + } > arena.ITCM + + .arena.DTCM: + { + . = ALIGN(32); + SDK_SECTION_ARENA_DTCM_START =.; + } > arena.DTCM + + ############################ OVERLAYDEFS ############################ + .: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > + + + ############################ OVERLAYTABLE ########################### + .: + { + + # Overlay + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + + } > + + + ############################ OTHERS ################################# + SDK_MAIN_ARENA_LO = SDK_SECTION_ARENA_START; + SDK_IRQ_STACKSIZE = ; # allocated in DTCM + SDK_SYS_STACKSIZE = ; # when 0 means all remains of DTCM + + # Module filelist + .binary.MODULE_FILES: + { + WRITES (""); + WRITES (""); + WRITES (""); + } > binary.MODULE_FILES + + # ITCM/DTCM size checker => check AUTOLOAD_ITCM/DTCM + .check.ITCM: + { + . = . + SDK_AUTOLOAD_ITCM_SIZE + SDK_AUTOLOAD_ITCM_BSS_SIZE; + } > check.ITCM + + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + .check.DTCM: + { + . = . + SDK_AUTOLOAD_DTCM_SIZE + SDK_AUTOLOAD_DTCM_BSS_SIZE; + . = . + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + } > check.DTCM + +} diff --git a/include/firm/specfiles/ARM9-BB-FIRM.lsf b/include/firm/specfiles/ARM9-BB-FIRM.lsf new file mode 100644 index 0000000..c7676d2 --- /dev/null +++ b/include/firm/specfiles/ARM9-BB-FIRM.lsf @@ -0,0 +1,42 @@ +#---------------------------------------------------------------------------- +# Project: TwlFirm - include +# File: ARM9-BB-NORFIRM.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TwlFirm LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x03800000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) +} + +Autoload ITCM +{ + Address 0x01ff8000 + Object * (.itcm) + Object $(OBJS_AUTOLOAD) (.text) +} + +Autoload DTCM +{ + Address 0x027e0000 + Object * (.dtcm) + Object $(OBJS_AUTOLOAD) (.data) + Object $(OBJS_AUTOLOAD) (.bss) +} + diff --git a/include/firm/specfiles/ARM9-BB-GCDFIRM.lcf.template b/include/firm/specfiles/ARM9-BB-GCDFIRM.lcf.template new file mode 100644 index 0000000..4cace18 --- /dev/null +++ b/include/firm/specfiles/ARM9-BB-GCDFIRM.lcf.template @@ -0,0 +1,602 @@ +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makelcf +# File: ARM9-BB-NORFIRM.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 # > + + (RWX) : ORIGIN = , LENGTH = 0x0 # > + +# binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 > +# binary.STATIC_FOOTER (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + dummy.MAIN_EX (RW) : ORIGIN = 0x023e0000, LENGTH = 0x0 + arena.MAIN (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + arena.MAIN_EX (RW) : ORIGIN = AFTER(dummy.MAIN_EX,), LENGTH = 0x0 + arena.ITCM (RW) : ORIGIN = AFTER(ITCM,), LENGTH = 0x0 + arena.DTCM (RW) : ORIGIN = AFTER(DTCM,), LENGTH = 0x0 + binary.MODULE_FILES (RW) : ORIGIN = 0x0, LENGTH = 0x0 > component.files + check.ITCM (RWX) : ORIGIN = 0x0, LENGTH = 0x08000 > itcm.check + check.DTCM (RW) : ORIGIN = 0x0, LENGTH = 0x04000 > dtcm.check +} + +FORCE_ACTIVE +{ + SVC_SoftReset +} + +KEEP_SECTION +{ + .sinit +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); . = ALIGN(32); # Fit to cache line + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + crt0.o (.text) + libsyscall.a (.text) + crt0.o (.rodata) + # + # .version ZNVljĂ܂B + # ̃ZNVɊ܂܂̓bg`FbN̍ۂ + # KvƂȂ܂̂ŁAK̈ʒuɎc悤ɂĉB + # + * (.version) + OBJECT(TwlMain,*) + + + + + + + . = ALIGN(4); + * (.exception) + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + EXCEPTION + SDK_STATIC_ETABLE_END =.; + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(32); + SDK_STATIC_TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + SDK_OVERLAY_DIGEST =.; + # NO DIGEST + SDK_OVERLAY_DIGEST_END =.; + #:::::::::: data + . = ALIGN(32); + SDK_STATIC_DATA_END =.; + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + __exception_table_start__ = SDK_STATIC_ETABLE_START; # for exception table + __exception_table_end__ = SDK_STATIC_ETABLE_END; # for exception table + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(32); + SDK_STATIC_BSS_END = .; + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.ITCM.START = 0x01ff8000; + SDK_AUTOLOAD.ITCM.END = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD.ITCM.BSS_END = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD.ITCM.SIZE = 0; + SDK_AUTOLOAD.ITCM.BSS_SIZE = 0; + SDK_AUTOLOAD.DTCM.START = 0x027e0000; + SDK_AUTOLOAD.DTCM.END = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD.DTCM.BSS_END = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD.DTCM.SIZE = 0; + SDK_AUTOLOAD.DTCM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(32); + SDK_AUTOLOAD..DATA_END =.; + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(32); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_ITCM_START = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD_ITCM_END = SDK_AUTOLOAD.ITCM.END; + SDK_AUTOLOAD_ITCM_BSS_END = SDK_AUTOLOAD.ITCM.BSS_END; + SDK_AUTOLOAD_ITCM_SIZE = SDK_AUTOLOAD.ITCM.SIZE; + SDK_AUTOLOAD_ITCM_BSS_SIZE = SDK_AUTOLOAD.ITCM.BSS_SIZE; + SDK_AUTOLOAD_DTCM_START = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD_DTCM_END = SDK_AUTOLOAD.DTCM.END; + SDK_AUTOLOAD_DTCM_BSS_END = SDK_AUTOLOAD.DTCM.BSS_END; + SDK_AUTOLOAD_DTCM_SIZE = SDK_AUTOLOAD.DTCM.SIZE; + SDK_AUTOLOAD_DTCM_BSS_SIZE = SDK_AUTOLOAD.DTCM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + SDK_AUTOLOAD_LIST = .; + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + SDK_AUTOLOAD_LIST_END = .; + } >> # > binary.AUTOLOAD_INFO + +# SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; +# SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + + ############################ STATIC_FOOTER ########################## + .binary.STATIC_FOOTER: + { + WRITEW 0xdec00621; # LE(0x2106C0DE) = NITRO CODE + WRITEW _start_ModuleParams - ADDR(.); + WRITEW 0; # NO DIGEST + } >> # > binary.STATIC_FOOTER + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(32); + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(32); + SDK_OVERLAY..DATA_END =.; + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(32); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + ############################ MAIN EX ################################## + # MAIN EX Area + .dummy.MAIN_EX: + { + . = ALIGN(32); + } > dummy.MAIN_EX + + ############################ ARENA ################################## + .arena.MAIN: + { + . = ALIGN(32); + SDK_SECTION_ARENA_START =.; + } > arena.MAIN + + .arena.MAIN_EX: + { + . = ALIGN(32); + SDK_SECTION_ARENA_EX_START =.; + } > arena.MAIN_EX + + .arena.ITCM: + { + . = ALIGN(32); + SDK_SECTION_ARENA_ITCM_START =.; + } > arena.ITCM + + .arena.DTCM: + { + . = ALIGN(32); + SDK_SECTION_ARENA_DTCM_START =.; + } > arena.DTCM + + ############################ OVERLAYDEFS ############################ + .: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > + + + ############################ OVERLAYTABLE ########################### + .: + { + + # Overlay + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + + } > + + + ############################ OTHERS ################################# + SDK_MAIN_ARENA_LO = SDK_SECTION_ARENA_START; + SDK_IRQ_STACKSIZE = ; # allocated in DTCM + SDK_SYS_STACKSIZE = ; # when 0 means all remains of DTCM + + # Module filelist + .binary.MODULE_FILES: + { + WRITES (""); + WRITES (""); + WRITES (""); + } > binary.MODULE_FILES + + # ITCM/DTCM size checker => check AUTOLOAD_ITCM/DTCM + .check.ITCM: + { + . = . + SDK_AUTOLOAD_ITCM_SIZE + SDK_AUTOLOAD_ITCM_BSS_SIZE; + } > check.ITCM + + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + .check.DTCM: + { + . = . + SDK_AUTOLOAD_DTCM_SIZE + SDK_AUTOLOAD_DTCM_BSS_SIZE; + . = . + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + } > check.DTCM + +} diff --git a/include/firm/specfiles/ARM9-BB-GCDFIRM.lsf b/include/firm/specfiles/ARM9-BB-GCDFIRM.lsf new file mode 100644 index 0000000..c7676d2 --- /dev/null +++ b/include/firm/specfiles/ARM9-BB-GCDFIRM.lsf @@ -0,0 +1,42 @@ +#---------------------------------------------------------------------------- +# Project: TwlFirm - include +# File: ARM9-BB-NORFIRM.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TwlFirm LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x03800000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) +} + +Autoload ITCM +{ + Address 0x01ff8000 + Object * (.itcm) + Object $(OBJS_AUTOLOAD) (.text) +} + +Autoload DTCM +{ + Address 0x027e0000 + Object * (.dtcm) + Object $(OBJS_AUTOLOAD) (.data) + Object $(OBJS_AUTOLOAD) (.bss) +} + diff --git a/include/firm/specfiles/ARM9-TS-FIRM.lcf.template b/include/firm/specfiles/ARM9-TS-FIRM.lcf.template new file mode 100644 index 0000000..fd41209 --- /dev/null +++ b/include/firm/specfiles/ARM9-TS-FIRM.lcf.template @@ -0,0 +1,1033 @@ +#--------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ARM9-BB.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 > + + + (RWX) : ORIGIN = , LENGTH = 0x0 >> + + binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + binary.STATIC_FOOTER (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + F (RW) : ORIGIN = 0, LENGTH = 0x0 > + F (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + + dummy.MAIN_EX.NITRO (RW) : ORIGIN = 0x023e0000, LENGTH = 0x0 + arena.MAIN.NITRO (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + arena.MAIN_EX.NITRO (RW) : ORIGIN = AFTER(dummy.MAIN_EX.NITRO,), LENGTH = 0x0 + arena.ITCM (RW) : ORIGIN = AFTER(ITCM,), LENGTH = 0x0 + arena.DTCM (RW) : ORIGIN = AFTER(DTCM,), LENGTH = 0x0 + + check.ITCM (RW) : ORIGIN = 0x0, LENGTH = 0x08000 > itcm.check + check.DTCM (RW) : ORIGIN = 0x0, LENGTH = 0x04000 > dtcm.check + + binary.LTDAUTOLOAD_TOP (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWX) : ORIGIN = , LENGTH = 0x0 >> + + binary.LTDAUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + L (RW) : ORIGIN = 0, LENGTH = 0x0 > + L (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + + dummy.MAIN_EX.TWL (RW) : ORIGIN = 0x0d000000, LENGTH = 0x0 + arena.MAIN.TWL (RW) : ORIGIN = AFTER(,,LTDMAIN,), LENGTH = 0x0 + arena.MAIN_EX.TWL (RW) : ORIGIN = AFTER(dummy.MAIN_EX.TWL,,,LTDMAIN,), LENGTH = 0x0 + + binary.MODULE_FILES (RW) : ORIGIN = 0, LENGTH = 0x0 > component.files +} + +FORCE_ACTIVE +{ + SVC_SoftReset +} + +KEEP_SECTION +{ + .sinit +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); + . = ALIGN(32); # Fit to cache line + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + OBJECT(_start,*) + crt0_firm.o (.text) + crt0_firm.o (.rodata) + libsyscall.a (.text) + # + # .version ZNVljĂ܂B + # ̃ZNVɊ܂܂̓bg`FbN̍ۂ + # KvƂȂ܂̂ŁAK̈ʒuɎc悤ɂĉB + # + * (.version) + OBJECT(TwlMain,*) + + + + + + + * (.exception) + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + __exception_table_start__ =.; + EXCEPTION + __exception_table_end__ =.; + SDK_STATIC_ETABLE_END =.; + + + + + + + + + + + + + . = ALIGN(4); + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + #:::::::::: text/rodata + SDK_STATIC_TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(32); # Fit to cache line + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + . = ALIGN(4); + SDK_OVERLAY_DIGEST =.; + # NO DIGEST + SDK_OVERLAY_DIGEST_END =.; + #:::::::::: data + SDK_STATIC_DATA_END =.; + . = ALIGN(32); + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(32); # Fit to cache line + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(32); + SDK_STATIC_BSS_END = .; + + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.ITCM.START = 0x01ff8000; + SDK_AUTOLOAD.ITCM.END = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD.ITCM.BSS_END = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD.ITCM.SIZE = 0; + SDK_AUTOLOAD.ITCM.BSS_SIZE = 0; + SDK_AUTOLOAD.DTCM.START = 0x02fe0000; + SDK_AUTOLOAD.DTCM.END = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD.DTCM.BSS_END = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD.DTCM.SIZE = 0; + SDK_AUTOLOAD.DTCM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_AUTOLOAD..SINIT_START = .; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_AUTOLOAD..SINIT_END = .; + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + . = ALIGN(32); + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_AUTOLOAD..DATA_END =.; + . = ALIGN(32); + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(32); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_ITCM_START = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD_ITCM_END = SDK_AUTOLOAD.ITCM.END; + SDK_AUTOLOAD_ITCM_BSS_END = SDK_AUTOLOAD.ITCM.BSS_END; + SDK_AUTOLOAD_ITCM_SIZE = SDK_AUTOLOAD.ITCM.SIZE; + SDK_AUTOLOAD_ITCM_BSS_SIZE = SDK_AUTOLOAD.ITCM.BSS_SIZE; + SDK_AUTOLOAD_DTCM_START = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD_DTCM_END = SDK_AUTOLOAD.DTCM.END; + SDK_AUTOLOAD_DTCM_BSS_END = SDK_AUTOLOAD.DTCM.BSS_END; + SDK_AUTOLOAD_DTCM_SIZE = SDK_AUTOLOAD.DTCM.SIZE; + SDK_AUTOLOAD_DTCM_BSS_SIZE = SDK_AUTOLOAD.DTCM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..SINIT_START; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + } > binary.AUTOLOAD_INFO + + SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; + SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + + ############################ STATIC_FOOTER ########################## + .binary.STATIC_FOOTER: + { + WRITEW 0xdec00621; # LE(0x2106C0DE) = NITRO CODE + WRITEW _start_ModuleParams - ADDR(.); + WRITEW 0; # NO DIGEST + WRITEW _start_LtdModuleParams - ADDR(.); + } > binary.STATIC_FOOTER + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(32); # Fit to cache line + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + #:::::::::: text/rodata + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(32); + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_OVERLAY..DATA_END =.; + . = ALIGN(32); + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(32); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + ############################ OVERLAYDEFS ############################ + .F: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > F + + ############################ OVERLAYTABLE ########################### + .F: + { + + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + } > F + + ############################ ARENA ################################## + .dummy.MAIN_EX.NITRO: + { + . = ALIGN(32); + + } > dummy.MAIN_EX.NITRO + + .arena.MAIN.NITRO: + { + . = ALIGN(32); + SDK_SECTION_ARENA_START =.; + + } > arena.MAIN.NITRO + + .arena.MAIN_EX.NITRO: + { + . = ALIGN(32); + SDK_SECTION_ARENA_EX_START =.; + + } > arena.MAIN_EX.NITRO + + .arena.ITCM: + { + . = ALIGN(32); + SDK_SECTION_ARENA_ITCM_START =.; + + } > arena.ITCM + + .arena.DTCM: + { + . = ALIGN(32); + SDK_SECTION_ARENA_DTCM_START =.; + + } > arena.DTCM + + ############################ OTHERS ################################# + SDK_MAIN_ARENA_LO = SDK_SECTION_ARENA_START; + SDK_IRQ_STACKSIZE = ; # allocated in DTCM + SDK_SYS_STACKSIZE = ; # when 0 means all remains of DTCM + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + + .check.ITCM: + { + . = . + SDK_AUTOLOAD_ITCM_SIZE + SDK_AUTOLOAD_ITCM_BSS_SIZE; + + . = . + SDK_OVERLAY..SIZE + SDK_OVERLAY..BSS_SIZE; + + + } > check.ITCM + + .check.DTCM: + { + . = . + SDK_AUTOLOAD_DTCM_SIZE + SDK_AUTOLOAD_DTCM_BSS_SIZE; + + . = . + SDK_OVERLAY..SIZE + SDK_OVERLAY..BSS_SIZE; + + . = . + 0x080 + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + } > check.DTCM + + ########################### LTDAUTOLOADS ############################ + SDK_LTDAUTOLOAD.LTDMAIN.START = SDK_STATIC_BSS_END; + SDK_LTDAUTOLOAD.LTDMAIN.END = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD.LTDMAIN.BSS_EDN = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD.LTDMAIN.SIZE = 0; + SDK_LTDAUTOLOAD.LTDMAIN.BSS_SIZE = 0; + SDK_LTDAUTOLOAD_TOP_START = 0x02400000; + SDK_LTDAUTOLOAD_TOP_SIZE = 4; # STATIC ̈悪 4 bytes ̃_~[oCit@C̐擪ɓ # + SDK_LTDAUTOLOAD_START = SDK_LTDAUTOLOAD_TOP_START + SDK_LTDAUTOLOAD_TOP_SIZE; + SDK_LTDAUTOLOAD_SIZE = 0; + SDK_LTDAUTOLOAD_NUMBER = ; + + .binary.LTDAUTOLOAD_TOP: + { + WRITEW 0; + + } > binary.LTDAUTOLOAD_TOP + + + .: + { + ALIGNALL(4); + . = ALIGN(32); # Fit to cache line + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + SDK_LTDAUTOLOAD__ID =; + SDK_LTDAUTOLOAD..ID =; + SDK_LTDAUTOLOAD..START =.; + # + # TEXT BLOCK: READ ONLY + # + SDK_LTDAUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_LTDAUTOLOAD..SINIT_START = .; + #:::::::::: ctor + + + + + + + + + + + + + #:::::::::: ctor + SDK_LTDAUTOLOAD..SINIT_END = .; + #:::::::::: text/rodata + SDK_LTDAUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(32); + SDK_LTDAUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_LTDAUTOLOAD..DATA_END =.; + . = ALIGN(32); + SDK_LTDAUTOLOAD..END =.; + + SDK_LTDAUTOLOAD..TEXT_SIZE = SDK_LTDAUTOLOAD..TEXT_END - SDK_LTDAUTOLOAD..TEXT_START; + SDK_LTDAUTOLOAD..DATA_SIZE = SDK_LTDAUTOLOAD..DATA_END - SDK_LTDAUTOLOAD..DATA_START; + SDK_LTDAUTOLOAD..SIZE = SDK_LTDAUTOLOAD..END - SDK_LTDAUTOLOAD..START; + SDK_LTDAUTOLOAD_SIZE = SDK_LTDAUTOLOAD_SIZE + SDK_LTDAUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_LTDAUTOLOAD..BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(32); + SDK_LTDAUTOLOAD..BSS_END =.; + + SDK_LTDAUTOLOAD..BSS_SIZE = SDK_LTDAUTOLOAD..BSS_END - SDK_LTDAUTOLOAD..BSS_START; + + } >> + + + + SDK_LTDAUTOLOAD_LTDMAIN_START = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD_LTDMAIN_END = SDK_LTDAUTOLOAD.LTDMAIN.END; + SDK_LTDAUTOLOAD_LTDMAIN_BSS_END = SDK_LTDAUTOLOAD.LTDMAIN.BSS_END; + SDK_LTDAUTOLOAD_LTDMAIN_SIZE = SDK_LTDAUTOLOAD.LTDMAIN.SIZE; + SDK_LTDAUTOLOAD_LTDMAIN_BSS_SIZE = SDK_LTDAUTOLOAD.LTDMAIN.BSS_SIZE; + + ######################### LTDAUTOLOAD_INFO ########################## + .binary.LTDAUTOLOAD_INFO: + { + + WRITEW ADDR(.); + WRITEW SDK_LTDAUTOLOAD..SIZE; + WRITEW SDK_LTDAUTOLOAD..BSS_SIZE; + + } > binary.LTDAUTOLOAD_INFO + + SDK_LTDAUTOLOAD_LIST = SDK_LTDAUTOLOAD_START + SDK_LTDAUTOLOAD_SIZE; + SDK_LTDAUTOLOAD_LIST_END = SDK_LTDAUTOLOAD_LIST + SIZEOF(.binary.LTDAUTOLOAD_INFO); + SDK_LTDAUTOLOAD_SIZE = SDK_LTDAUTOLOAD_SIZE + SIZEOF(.binary.LTDAUTOLOAD_INFO); + + ########################### LTDOVERLAYS ############################# + SDK_LTDOVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + SDK_LTDOVERLAY__ID =; + SDK_LTDOVERLAY..ID =; + SDK_LTDOVERLAY..START =.; + # + # TEXT BLOCK: READ ONLY + # + SDK_LTDOVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_LTDOVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_LTDOVERLAY..SINIT_END =.; + #:::::::::: text/rodata + SDK_LTDOVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(32); + SDK_LTDOVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_LTDOVERLAY..DATA_END =.; + . = ALIGN(32); + SDK_LTDOVERLAY..END =.; + + SDK_LTDOVERLAY..TEXT_SIZE = SDK_LTDOVERLAY..TEXT_END - SDK_LTDOVERLAY..TEXT_START; + SDK_LTDOVERLAY..DATA_SIZE = SDK_LTDOVERLAY..DATA_END - SDK_LTDOVERLAY..DATA_START; + SDK_LTDOVERLAY..SIZE = SDK_LTDOVERLAY..END - SDK_LTDOVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_LTDOVERLAY..BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(32); + SDK_LTDOVERLAY..BSS_END =.; + + SDK_LTDOVERLAY..BSS_SIZE = SDK_LTDOVERLAY..BSS_END - SDK_LTDOVERLAY..BSS_START; + + } >> + + + + ########################## LTDOVERLAYDEFS ########################### + .L: + { + ### TWL limited extended static module information + WRITEW SDK_LTDAUTOLOAD_TOP_START; # load address + WRITEW 0; # padding + WRITEW SDK_LTDAUTOLOAD_SIZE + SDK_LTDAUTOLOAD_TOP_SIZE; # size of module + WRITEW 0; # padding + + ### TWL limited overlay filename + + WRITES (""); + + + } > L + + ######################### LTDOVERLAYTABLE ########################### + .L: + { + + WRITES # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_LTDOVERLAY..SIZE; # size of module + WRITEW SDK_LTDOVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_LTDOVERLAY..SINIT_START; # start address of static init + WRITEW SDK_LTDOVERLAY..SINIT_END; # end address of static init + WRITEW # ROM file ID + WRITEW 0; # Reserved + + + } > L + + ############################ ARENA ################################## + .dummy.MAIN_EX.TWL: + { + . = ALIGN(32); + + } > dummy.MAIN_EX.TWL + + .arena.MAIN.TWL: + { + . = ALIGN(32); + SDK_LTDMAIN_ARENA_LO =.; + + } > arena.MAIN.TWL + + .arena.MAIN_EX.TWL: + { + . = ALIGN(32); + SDK_LTDMAIN_EX_ARENA_LO =.; + + } > arena.MAIN_EX.TWL + + ############################ OTHERS ################################# + # Module filelist + .binary.MODULE_FILES: + { + WRITES (""); + WRITES (""); + WRITES (""); + WRITES (""); + WRITES (""); + WRITES (""); + + } > binary.MODULE_FILES + +} diff --git a/include/firm/specfiles/ARM9-TS-FIRM.lsf b/include/firm/specfiles/ARM9-TS-FIRM.lsf new file mode 100644 index 0000000..272005c --- /dev/null +++ b/include/firm/specfiles/ARM9-TS-FIRM.lsf @@ -0,0 +1,56 @@ +#---------------------------------------------------------------------------- +# Project: TwlFirm - include +# File: ARM9-TS-NORFIRM.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TwlFirm LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x03800000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) + Object * (.itcm) + Object $(OBJS_AUTOLOAD) (.text) + Object $(OBJS_AUTOLOAD) (.rodata) + Object $(OBJS_AUTOLOAD) (.init) + Object $(OBJS_AUTOLOAD) (.ctor) + Object $(OBJS_AUTOLOAD) (.sinit) + Object * (.ltdmain) + Object $(OBJS_LTDAUTOLOAD) + Library $(LLIBS_EX) $(GLIBS_EX) + Object * (.dtcm) + Object $(OBJS_AUTOLOAD) (.data) + Object $(OBJS_AUTOLOAD) (.sdata) + Object $(OBJS_AUTOLOAD) (.bss) + Object $(OBJS_AUTOLOAD) (.sbss) +} + +Autoload ITCM +{ + Address 0x01ff8000 +} + +Autoload DTCM +{ + Address $(ADDRESS_DTCM) +} + +Ltdautoload LTDMAIN +{ + # NITRO/TWL L̃I[o[C݂ꍇ́Aɂ̌ɔzuKv܂B + After $(TARGET_NAME) +} diff --git a/include/firm/specfiles/ARM9-TS-GCDFIRM.lcf.template b/include/firm/specfiles/ARM9-TS-GCDFIRM.lcf.template new file mode 100644 index 0000000..a5236b6 --- /dev/null +++ b/include/firm/specfiles/ARM9-TS-GCDFIRM.lcf.template @@ -0,0 +1,602 @@ +#--------------------------------------------------------------------------- +# Project: TwlFirm - tools - makelcf +# File: ARM9-TS-NORFIRM.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev:$ +# $Author:$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 # > + + (RWX) : ORIGIN = , LENGTH = 0x0 # > + +# binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 > +# binary.STATIC_FOOTER (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + (RW) : ORIGIN = AFTER(), LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + dummy.MAIN_EX (RW) : ORIGIN = 0x023e0000, LENGTH = 0x0 + arena.MAIN (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + arena.MAIN_EX (RW) : ORIGIN = AFTER(dummy.MAIN_EX,), LENGTH = 0x0 + arena.ITCM (RW) : ORIGIN = AFTER(ITCM,), LENGTH = 0x0 + arena.DTCM (RW) : ORIGIN = AFTER(DTCM,), LENGTH = 0x0 + binary.MODULE_FILES (RW) : ORIGIN = 0x0, LENGTH = 0x0 > component.files + check.ITCM (RWX) : ORIGIN = 0x0, LENGTH = 0x08000 > itcm.check + check.DTCM (RW) : ORIGIN = 0x0, LENGTH = 0x04000 > dtcm.check +} + +FORCE_ACTIVE +{ + SVC_SoftReset +} + +KEEP_SECTION +{ + .sinit +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); . = ALIGN(32); # Fit to cache line + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + crt0.o (.text) + libsyscall.a (.text) + crt0.o (.rodata) + # + # .version ZNVljĂ܂B + # ̃ZNVɊ܂܂̓bg`FbN̍ۂ + # KvƂȂ܂̂ŁAK̈ʒuɎc悤ɂĉB + # + * (.version) + OBJECT(TwlMain,*) + + + + + + + . = ALIGN(4); + * (.exception) + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + EXCEPTION + SDK_STATIC_ETABLE_END =.; + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(32); + SDK_STATIC_TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + SDK_OVERLAY_DIGEST =.; + # NO DIGEST + SDK_OVERLAY_DIGEST_END =.; + #:::::::::: data + . = ALIGN(32); + SDK_STATIC_DATA_END =.; + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + __exception_table_start__ = SDK_STATIC_ETABLE_START; # for exception table + __exception_table_end__ = SDK_STATIC_ETABLE_END; # for exception table + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(32); + SDK_STATIC_BSS_END = .; + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.ITCM.START = 0x01ff8000; + SDK_AUTOLOAD.ITCM.END = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD.ITCM.BSS_END = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD.ITCM.SIZE = 0; + SDK_AUTOLOAD.ITCM.BSS_SIZE = 0; + SDK_AUTOLOAD.DTCM.START = 0x027e0000; + SDK_AUTOLOAD.DTCM.END = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD.DTCM.BSS_END = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD.DTCM.SIZE = 0; + SDK_AUTOLOAD.DTCM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(32); + SDK_AUTOLOAD..DATA_END =.; + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(32); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_ITCM_START = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD_ITCM_END = SDK_AUTOLOAD.ITCM.END; + SDK_AUTOLOAD_ITCM_BSS_END = SDK_AUTOLOAD.ITCM.BSS_END; + SDK_AUTOLOAD_ITCM_SIZE = SDK_AUTOLOAD.ITCM.SIZE; + SDK_AUTOLOAD_ITCM_BSS_SIZE = SDK_AUTOLOAD.ITCM.BSS_SIZE; + SDK_AUTOLOAD_DTCM_START = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD_DTCM_END = SDK_AUTOLOAD.DTCM.END; + SDK_AUTOLOAD_DTCM_BSS_END = SDK_AUTOLOAD.DTCM.BSS_END; + SDK_AUTOLOAD_DTCM_SIZE = SDK_AUTOLOAD.DTCM.SIZE; + SDK_AUTOLOAD_DTCM_BSS_SIZE = SDK_AUTOLOAD.DTCM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + SDK_AUTOLOAD_LIST = .; + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + SDK_AUTOLOAD_LIST_END = .; + } >> # > binary.AUTOLOAD_INFO + +# SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; +# SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + + ############################ STATIC_FOOTER ########################## + .binary.STATIC_FOOTER: + { + WRITEW 0xdec00621; # LE(0x2106C0DE) = NITRO CODE + WRITEW _start_ModuleParams - ADDR(.); + WRITEW 0; # NO DIGEST + } >> # > binary.STATIC_FOOTER + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + + #:::::::::: text/rodata + . = ALIGN(32); + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: data + . = ALIGN(32); + SDK_OVERLAY..DATA_END =.; + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); . = ALIGN(32); + + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + . = ALIGN(4); + + + + + + + . = ALIGN(4); + #:::::::::: bss + . = ALIGN(32); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + ############################ MAIN EX ################################## + # MAIN EX Area + .dummy.MAIN_EX: + { + . = ALIGN(32); + } > dummy.MAIN_EX + + ############################ ARENA ################################## + .arena.MAIN: + { + . = ALIGN(32); + SDK_SECTION_ARENA_START =.; + } > arena.MAIN + + .arena.MAIN_EX: + { + . = ALIGN(32); + SDK_SECTION_ARENA_EX_START =.; + } > arena.MAIN_EX + + .arena.ITCM: + { + . = ALIGN(32); + SDK_SECTION_ARENA_ITCM_START =.; + } > arena.ITCM + + .arena.DTCM: + { + . = ALIGN(32); + SDK_SECTION_ARENA_DTCM_START =.; + } > arena.DTCM + + ############################ OVERLAYDEFS ############################ + .: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > + + + ############################ OVERLAYTABLE ########################### + .: + { + + # Overlay + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + + } > + + + ############################ OTHERS ################################# + SDK_MAIN_ARENA_LO = SDK_SECTION_ARENA_START; + SDK_IRQ_STACKSIZE = ; # allocated in DTCM + SDK_SYS_STACKSIZE = ; # when 0 means all remains of DTCM + + # Module filelist + .binary.MODULE_FILES: + { + WRITES (""); + WRITES (""); + WRITES (""); + } > binary.MODULE_FILES + + # ITCM/DTCM size checker => check AUTOLOAD_ITCM/DTCM + .check.ITCM: + { + . = . + SDK_AUTOLOAD_ITCM_SIZE + SDK_AUTOLOAD_ITCM_BSS_SIZE; + } > check.ITCM + + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + .check.DTCM: + { + . = . + SDK_AUTOLOAD_DTCM_SIZE + SDK_AUTOLOAD_DTCM_BSS_SIZE; + . = . + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + } > check.DTCM + +} diff --git a/include/firm/specfiles/ARM9-TS-GCDFIRM.lsf b/include/firm/specfiles/ARM9-TS-GCDFIRM.lsf new file mode 100644 index 0000000..2678095 --- /dev/null +++ b/include/firm/specfiles/ARM9-TS-GCDFIRM.lsf @@ -0,0 +1,42 @@ +#---------------------------------------------------------------------------- +# Project: TwlFirm - include +# File: ARM9-TS-NORFIRM.lsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: 2007-09-06$ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TwlFirm LCF SPEC FILE +# + +Static $(TARGET_NAME) +{ + Address 0x03800000 + Object $(OBJS_STATIC) + Library $(LLIBS) $(GLIBS) $(CW_LIBS) +} + +Autoload ITCM +{ + Address 0x01ff8000 + Object * (.itcm) + Object $(OBJS_AUTOLOAD) (.text) +} + +Autoload DTCM +{ + Address 0x027e0000 + Object * (.dtcm) + Object $(OBJS_AUTOLOAD) (.data) + Object $(OBJS_AUTOLOAD) (.bss) +} + diff --git a/include/firm/specfiles/ARM9-TS-PARTNER.lcf.template b/include/firm/specfiles/ARM9-TS-PARTNER.lcf.template new file mode 100644 index 0000000..d4582b7 --- /dev/null +++ b/include/firm/specfiles/ARM9-TS-PARTNER.lcf.template @@ -0,0 +1,983 @@ +#--------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ARM9-BB.lcf.template +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#--------------------------------------------------------------------------- +MEMORY +{ + (RWX) : ORIGIN = , LENGTH = 0x0 #> + + + (RWX) : ORIGIN = , LENGTH = 0x0 #>> + +# binary.AUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> +# binary.STATIC_FOOTER (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + F (RW) : ORIGIN = 0, LENGTH = 0x0 > + F (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + + dummy.MAIN_EX.NITRO (RW) : ORIGIN = 0x023e0000, LENGTH = 0x0 + arena.MAIN.NITRO (RW) : ORIGIN = AFTER(,), LENGTH = 0x0 + arena.MAIN_EX.NITRO (RW) : ORIGIN = AFTER(dummy.MAIN_EX.NITRO,), LENGTH = 0x0 + arena.ITCM (RW) : ORIGIN = AFTER(ITCM,), LENGTH = 0x0 + arena.DTCM (RW) : ORIGIN = AFTER(DTCM,), LENGTH = 0x0 + + check.ITCM (RW) : ORIGIN = 0x0, LENGTH = 0x08000 > itcm.check + check.DTCM (RW) : ORIGIN = 0x0, LENGTH = 0x04000 > dtcm.check + +# binary.LTDAUTOLOAD_TOP (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWX) : ORIGIN = , LENGTH = 0x0 #>> + +# binary.LTDAUTOLOAD_INFO (RWX) : ORIGIN = 0, LENGTH = 0x0 >> + + L (RW) : ORIGIN = 0, LENGTH = 0x0 > + L (RW) : ORIGIN = 0, LENGTH = 0x0 > + + (RWXO): ORIGIN = , LENGTH = 0x0 > + + + dummy.MAIN_EX.TWL (RW) : ORIGIN = 0x0d000000, LENGTH = 0x0 + arena.MAIN.TWL (RW) : ORIGIN = AFTER(,,LTDMAIN,), LENGTH = 0x0 + arena.MAIN_EX.TWL (RW) : ORIGIN = AFTER(dummy.MAIN_EX.TWL,,,LTDMAIN,), LENGTH = 0x0 + + binary.MODULE_FILES (RW) : ORIGIN = 0, LENGTH = 0x0 > component.files +} + +FORCE_ACTIVE +{ + SVC_SoftReset +} + +KEEP_SECTION +{ + .sinit +} + +SECTIONS +{ + ############################ STATIC ################################# + .: + { + ALIGNALL(4); + . = ALIGN(32); # Fit to cache line + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_STATIC_START =.; + SDK_STATIC_TEXT_START =.; + #:::::::::: text/rodata + libsyscall.a (.text) + OBJECT(_start,*) + crt0_firm.o (.text) + crt0_firm.o (.rodata) + # + # .version ZNVljĂ܂B + # ̃ZNVɊ܂܂̓bg`FbN̍ۂ + # KvƂȂ܂̂ŁAK̈ʒuɎc悤ɂĉB + # + * (.version) + OBJECT(TwlMain,*) + + + + + + + * (.exception) + . = ALIGN(4); + SDK_STATIC_ETABLE_START =.; + __exception_table_start__ =.; + EXCEPTION + __exception_table_end__ =.; + SDK_STATIC_ETABLE_END =.; + + + + + + + + + + + + + . = ALIGN(4); + SDK_STATIC_SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_STATIC_SINIT_END =.; + #:::::::::: text/rodata + SDK_STATIC_TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(32); # Fit to cache line + SDK_STATIC_DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + . = ALIGN(4); + SDK_OVERLAY_DIGEST =.; + # NO DIGEST + SDK_OVERLAY_DIGEST_END =.; + #:::::::::: data + SDK_STATIC_DATA_END =.; + . = ALIGN(32); + SDK_STATIC_END =.; + + SDK_STATIC_TEXT_SIZE = SDK_STATIC_TEXT_END - SDK_STATIC_TEXT_START; + SDK_STATIC_DATA_SIZE = SDK_STATIC_DATA_END - SDK_STATIC_DATA_START; + SDK_STATIC_SIZE = SDK_STATIC_END - SDK_STATIC_START; + __sinit__ = SDK_STATIC_SINIT_START; # for static initializer + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(32); # Fit to cache line + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_STATIC_BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(32); + SDK_STATIC_BSS_END = .; + + SDK_STATIC_BSS_SIZE = SDK_STATIC_BSS_END - SDK_STATIC_BSS_START; + + } >> + + + ############################ AUTOLOADS ############################## + SDK_AUTOLOAD.ITCM.START = 0x01ff8000; + SDK_AUTOLOAD.ITCM.END = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD.ITCM.BSS_END = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD.ITCM.SIZE = 0; + SDK_AUTOLOAD.ITCM.BSS_SIZE = 0; + SDK_AUTOLOAD.DTCM.START = 0x02fe0000; + SDK_AUTOLOAD.DTCM.END = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD.DTCM.BSS_END = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD.DTCM.SIZE = 0; + SDK_AUTOLOAD.DTCM.BSS_SIZE = 0; + SDK_AUTOLOAD_START = SDK_STATIC_END; + SDK_AUTOLOAD_SIZE = 0; + SDK_AUTOLOAD_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_AUTOLOAD__ID =; + SDK_AUTOLOAD..ID =; + SDK_AUTOLOAD..START =.; + SDK_AUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + #:::::::::: text/rodata + SDK_AUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE BLOCK + # + . = ALIGN(32); + SDK_AUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_AUTOLOAD..DATA_END =.; + . = ALIGN(32); + SDK_AUTOLOAD..END =.; + + SDK_AUTOLOAD..TEXT_SIZE = SDK_AUTOLOAD..TEXT_END - SDK_AUTOLOAD..TEXT_START; + SDK_AUTOLOAD..DATA_SIZE = SDK_AUTOLOAD..DATA_END - SDK_AUTOLOAD..DATA_START; + SDK_AUTOLOAD..SIZE = SDK_AUTOLOAD..END - SDK_AUTOLOAD..START; + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SDK_AUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL + + + # + # BSS BLOCK + # + SDK_AUTOLOAD..BSS_START = .; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(32); + SDK_AUTOLOAD..BSS_END = .; + + SDK_AUTOLOAD..BSS_SIZE = SDK_AUTOLOAD..BSS_END - SDK_AUTOLOAD..BSS_START; + + } >> + + + + SDK_AUTOLOAD_ITCM_START = SDK_AUTOLOAD.ITCM.START; + SDK_AUTOLOAD_ITCM_END = SDK_AUTOLOAD.ITCM.END; + SDK_AUTOLOAD_ITCM_BSS_END = SDK_AUTOLOAD.ITCM.BSS_END; + SDK_AUTOLOAD_ITCM_SIZE = SDK_AUTOLOAD.ITCM.SIZE; + SDK_AUTOLOAD_ITCM_BSS_SIZE = SDK_AUTOLOAD.ITCM.BSS_SIZE; + SDK_AUTOLOAD_DTCM_START = SDK_AUTOLOAD.DTCM.START; + SDK_AUTOLOAD_DTCM_END = SDK_AUTOLOAD.DTCM.END; + SDK_AUTOLOAD_DTCM_BSS_END = SDK_AUTOLOAD.DTCM.BSS_END; + SDK_AUTOLOAD_DTCM_SIZE = SDK_AUTOLOAD.DTCM.SIZE; + SDK_AUTOLOAD_DTCM_BSS_SIZE = SDK_AUTOLOAD.DTCM.BSS_SIZE; + + ############################ AUTOLOAD_INFO ########################## + .binary.AUTOLOAD_INFO: + { + SDK_AUTOLOAD_LIST = .; + + WRITEW ADDR(.); + WRITEW SDK_AUTOLOAD..SIZE; + WRITEW SDK_AUTOLOAD..BSS_SIZE; + + SDK_AUTOLOAD_LIST_END = .; + } >> #> binary.AUTOLOAD_INFO + +# SDK_AUTOLOAD_LIST = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE; +# SDK_AUTOLOAD_LIST_END = SDK_AUTOLOAD_START + SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + SDK_AUTOLOAD_SIZE = SDK_AUTOLOAD_SIZE + SIZEOF(.binary.AUTOLOAD_INFO); + +# ############################ STATIC_FOOTER ########################## +# .binary.STATIC_FOOTER: +# { +# WRITEW 0xdec00621; # LE(0x2106C0DE) = NITRO CODE +# WRITEW _start_ModuleParams - ADDR(.); +# WRITEW 0; # NO DIGEST +# } > binary.STATIC_FOOTER + + ############################ OVERLAYS ############################### + SDK_OVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(32); # Fit to cache line + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # TEXT BLOCK: READ ONLY + # + SDK_OVERLAY__ID =; ### SEGMENT OVERLAY ID + SDK_OVERLAY..ID =; + SDK_OVERLAY..START =.; + SDK_OVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_OVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_OVERLAY..SINIT_END =.; + #:::::::::: text/rodata + SDK_OVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(32); + SDK_OVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_OVERLAY..DATA_END =.; + . = ALIGN(32); + SDK_OVERLAY..END =.; + + SDK_OVERLAY..TEXT_SIZE = SDK_OVERLAY..TEXT_END - SDK_OVERLAY..TEXT_START; + SDK_OVERLAY..DATA_SIZE = SDK_OVERLAY..DATA_END - SDK_OVERLAY..DATA_START; + SDK_OVERLAY..SIZE = SDK_OVERLAY..END - SDK_OVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_OVERLAY..BSS_START = .; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(32); + SDK_OVERLAY..BSS_END = .; + + SDK_OVERLAY..BSS_SIZE = SDK_OVERLAY..BSS_END - SDK_OVERLAY..BSS_START; + + } >> + + + + ############################ OVERLAYDEFS ############################ + .F: + { + ### module information + WRITEW ADDR(.); # load address + WRITEW _start; # entry address + WRITEW SDK_STATIC_SIZE + SDK_AUTOLOAD_SIZE; # size of module + WRITEW _start_AutoloadDoneCallback; # callback autoload done + + ### overlay filename + + WRITES (""); # Overlay + + + } > F + + ############################ OVERLAYTABLE ########################### + .F: + { + + WRITEW ; # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_OVERLAY..SIZE; # size of module + WRITEW SDK_OVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_OVERLAY..SINIT_START; # start address of static init + WRITEW SDK_OVERLAY..SINIT_END; # end address of static init + WRITEW ; # ROM file ID + WRITEW 0; # Reserved + + + } > F + + ############################ ARENA ################################## + .dummy.MAIN_EX.NITRO: + { + . = ALIGN(32); + + } > dummy.MAIN_EX.NITRO + + .arena.MAIN.NITRO: + { + . = ALIGN(32); + SDK_SECTION_ARENA_START =.; + + } > arena.MAIN.NITRO + + .arena.MAIN_EX.NITRO: + { + . = ALIGN(32); + SDK_SECTION_ARENA_EX_START =.; + + } > arena.MAIN_EX.NITRO + + .arena.ITCM: + { + . = ALIGN(32); + SDK_SECTION_ARENA_ITCM_START =.; + + } > arena.ITCM + + .arena.DTCM: + { + . = ALIGN(32); + SDK_SECTION_ARENA_DTCM_START =.; + + } > arena.DTCM + + ############################ OTHERS ################################# + SDK_MAIN_ARENA_LO = SDK_SECTION_ARENA_START; + SDK_IRQ_STACKSIZE = ; # allocated in DTCM + SDK_SYS_STACKSIZE = ; # when 0 means all remains of DTCM + SDK_SYS_STACKSIZE_SIGN = (SDK_SYS_STACKSIZE < 0x80000000) * 2 - 1; + + .check.ITCM: + { + . = . + SDK_AUTOLOAD_ITCM_SIZE + SDK_AUTOLOAD_ITCM_BSS_SIZE; + + . = . + SDK_OVERLAY..SIZE + SDK_OVERLAY..BSS_SIZE; + + + } > check.ITCM + + .check.DTCM: + { + . = . + SDK_AUTOLOAD_DTCM_SIZE + SDK_AUTOLOAD_DTCM_BSS_SIZE; + + . = . + SDK_OVERLAY..SIZE + SDK_OVERLAY..BSS_SIZE; + + . = . + 0x080 + SDK_IRQ_STACKSIZE + SDK_SYS_STACKSIZE * SDK_SYS_STACKSIZE_SIGN; + } > check.DTCM + + ########################### LTDAUTOLOADS ############################ + SDK_LTDAUTOLOAD.LTDMAIN.START = SDK_STATIC_BSS_END; + SDK_LTDAUTOLOAD.LTDMAIN.END = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD.LTDMAIN.BSS_EDN = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD.LTDMAIN.SIZE = 0; + SDK_LTDAUTOLOAD.LTDMAIN.BSS_SIZE = 0; + SDK_LTDAUTOLOAD_TOP_START = 0x02400000; + SDK_LTDAUTOLOAD_TOP_SIZE = 4; # STATIC ̈悪 4 bytes ̃_~[oCit@C̐擪ɓ # + SDK_LTDAUTOLOAD_START = SDK_LTDAUTOLOAD_TOP_START + SDK_LTDAUTOLOAD_TOP_SIZE; + SDK_LTDAUTOLOAD_SIZE = 0; + SDK_LTDAUTOLOAD_NUMBER = ; + + .binary.LTDAUTOLOAD_TOP: + { + WRITEW 0; + + } >> #> binary.LTDAUTOLOAD_TOP + + + .: + { + ALIGNALL(4); + . = ALIGN(32); # Fit to cache line + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + SDK_LTDAUTOLOAD__ID =; + SDK_LTDAUTOLOAD..ID =; + SDK_LTDAUTOLOAD..START =.; + # + # TEXT BLOCK: READ ONLY + # + SDK_LTDAUTOLOAD..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + #:::::::::: text/rodata + SDK_LTDAUTOLOAD..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(32); + SDK_LTDAUTOLOAD..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + + + + + + + #:::::::::: data + SDK_LTDAUTOLOAD..DATA_END =.; + . = ALIGN(32); + SDK_LTDAUTOLOAD..END =.; + + SDK_LTDAUTOLOAD..TEXT_SIZE = SDK_LTDAUTOLOAD..TEXT_END - SDK_LTDAUTOLOAD..TEXT_START; + SDK_LTDAUTOLOAD..DATA_SIZE = SDK_LTDAUTOLOAD..DATA_END - SDK_LTDAUTOLOAD..DATA_START; + SDK_LTDAUTOLOAD..SIZE = SDK_LTDAUTOLOAD..END - SDK_LTDAUTOLOAD..START; + SDK_LTDAUTOLOAD_SIZE = SDK_LTDAUTOLOAD_SIZE + SDK_LTDAUTOLOAD..SIZE; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_LTDAUTOLOAD..BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(32); + SDK_LTDAUTOLOAD..BSS_END =.; + + SDK_LTDAUTOLOAD..BSS_SIZE = SDK_LTDAUTOLOAD..BSS_END - SDK_LTDAUTOLOAD..BSS_START; + + } >> + + + + SDK_LTDAUTOLOAD_LTDMAIN_START = SDK_LTDAUTOLOAD.LTDMAIN.START; + SDK_LTDAUTOLOAD_LTDMAIN_END = SDK_LTDAUTOLOAD.LTDMAIN.END; + SDK_LTDAUTOLOAD_LTDMAIN_BSS_END = SDK_LTDAUTOLOAD.LTDMAIN.BSS_END; + SDK_LTDAUTOLOAD_LTDMAIN_SIZE = SDK_LTDAUTOLOAD.LTDMAIN.SIZE; + SDK_LTDAUTOLOAD_LTDMAIN_BSS_SIZE = SDK_LTDAUTOLOAD.LTDMAIN.BSS_SIZE; + + ######################### LTDAUTOLOAD_INFO ########################## + .binary.LTDAUTOLOAD_INFO: + { + SDK_LTDAUTOLOAD_LIST = .; + + WRITEW ADDR(.); + WRITEW SDK_LTDAUTOLOAD..SIZE; + WRITEW SDK_LTDAUTOLOAD..BSS_SIZE; + + SDK_LTDAUTOLOAD_LIST_END = .; + } >> #> binary.LTDAUTOLOAD_INFO + +# SDK_LTDAUTOLOAD_LIST = SDK_LTDAUTOLOAD_START + SDK_LTDAUTOLOAD_SIZE; +# SDK_LTDAUTOLOAD_LIST_END = SDK_LTDAUTOLOAD_LIST + SIZEOF(.binary.LTDAUTOLOAD_INFO); + SDK_LTDAUTOLOAD_SIZE = SDK_LTDAUTOLOAD_SIZE + SIZEOF(.binary.LTDAUTOLOAD_INFO); + + ########################### LTDOVERLAYS ############################# + SDK_LTDOVERLAY_NUMBER = ; + + + .: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + SDK_LTDOVERLAY__ID =; + SDK_LTDOVERLAY..ID =; + SDK_LTDOVERLAY..START =.; + # + # TEXT BLOCK: READ ONLY + # + SDK_LTDOVERLAY..TEXT_START =.; + #:::::::::: text/rodata + + + + + + + + + + + + + + + + + + + . = ALIGN(4); + SDK_LTDOVERLAY..SINIT_START =.; + #:::::::::: ctor + + + + + + + + + + + + + WRITEW 0; + #:::::::::: ctor + SDK_LTDOVERLAY..SINIT_END =.; + #:::::::::: text/rodata + SDK_LTDOVERLAY..TEXT_END =.; + + # + # DATA BLOCK: READ WRITE + # + . = ALIGN(32); + SDK_LTDOVERLAY..DATA_START =.; + #:::::::::: data + + + + + + + + + + + + + #:::::::::: data + SDK_LTDOVERLAY..DATA_END =.; + . = ALIGN(32); + SDK_LTDOVERLAY..END =.; + + SDK_LTDOVERLAY..TEXT_SIZE = SDK_LTDOVERLAY..TEXT_END - SDK_LTDOVERLAY..TEXT_START; + SDK_LTDOVERLAY..DATA_SIZE = SDK_LTDOVERLAY..DATA_END - SDK_LTDOVERLAY..DATA_START; + SDK_LTDOVERLAY..SIZE = SDK_LTDOVERLAY..END - SDK_LTDOVERLAY..START; + + } > + + ..bss: + { + ALIGNALL(4); + . = ALIGN(32); + + # + # Definition to refer overlay segment, when same name symbols exist in multiple overlays. + # + + SEARCH_SYMBOL ; + + + # + # BSS BLOCK + # + SDK_LTDOVERLAY..BSS_START =.; + #:::::::::: bss + + + + + + + + + + + + + #:::::::::: bss + . = ALIGN(32); + SDK_LTDOVERLAY..BSS_END =.; + + SDK_LTDOVERLAY..BSS_SIZE = SDK_LTDOVERLAY..BSS_END - SDK_LTDOVERLAY..BSS_START; + + } >> + + + + ########################## LTDOVERLAYDEFS ########################### + .L: + { + ### TWL limited extended static module information + WRITEW SDK_LTDAUTOLOAD_TOP_START; # load address + WRITEW 0; # padding + WRITEW SDK_LTDAUTOLOAD_SIZE + SDK_LTDAUTOLOAD_TOP_SIZE; # size of module + WRITEW 0; # padding + + ### TWL limited overlay filename + + WRITES (""); + + + } > L + + ######################### LTDOVERLAYTABLE ########################### + .L: + { + + WRITES # overlay ID + WRITEW ADDR(.); # load address + WRITEW SDK_LTDOVERLAY..SIZE; # size of module + WRITEW SDK_LTDOVERLAY..BSS_SIZE; # size of bss + WRITEW SDK_LTDOVERLAY..SINIT_START; # start address of static init + WRITEW SDK_LTDOVERLAY..SINIT_END; # end address of static init + WRITEW # ROM file ID + WRITEW 0; # Reserved + + + } > L + + ############################ ARENA ################################## + .dummy.MAIN_EX.TWL: + { + . = ALIGN(32); + + } > dummy.MAIN_EX.TWL + + .arena.MAIN.TWL: + { + . = ALIGN(32); + SDK_LTDMAIN_ARENA_LO =.; + + } > arena.MAIN.TWL + + .arena.MAIN_EX.TWL: + { + . = ALIGN(32); + SDK_LTDMAIN_EX_ARENA_LO =.; + + } > arena.MAIN_EX.TWL + + ############################ OTHERS ################################# + # Module filelist + .binary.MODULE_FILES: + { +# WRITES (""); + WRITES (""); + WRITES (""); + WRITES (""); + WRITES (""); + WRITES (""); + WRITES (""); + + } > binary.MODULE_FILES + +} diff --git a/include/firm/specfiles/ROM-TS.rsf b/include/firm/specfiles/ROM-TS.rsf new file mode 100644 index 0000000..6d3681c --- /dev/null +++ b/include/firm/specfiles/ROM-TS.rsf @@ -0,0 +1,148 @@ +#---------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ROM-BB.rsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TWL ROM SPEC FILE +# + +Arm9 +{ + Static "$(MAKEROM_ARM9:r).FLX.TWL.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.FLX.TWL.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.FLX.TWL.sbin$(COMPSUFFIX9)" + Elf "$(MAKEROM_ARM9:r).tef" +} + +Arm7 +{ + Static "$(MAKEROM_ARM7_BASE:r).FLX.TWL.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.FLX.TWL.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.FLX.TWL.sbin$(COMPSUFFIX7)" + Elf "$(MAKEROM_ARM7_BASE:r).tef" +} + +Arm9.Ltd +{ + Static "$(MAKEROM_ARM9:r).LTD.TWL.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.LTD.TWL.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.LTD.TWL.sbin$(COMPSUFFIX9)" +} + +Arm7.Ltd +{ + Static "$(MAKEROM_ARM7_BASE:r).LTD.TWL.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.LTD.TWL.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.LTD.TWL.sbin$(COMPSUFFIX7)" +} + +Property +{ + ### + ### Settings for FinalROM + ### + #### BEGIN + # + # TITLE NAME: Your product name within 12bytes + # + TitleName "FIRM" + + # + # MAKER CODE: Your company ID# in 2 ascii words + # issued by NINTENDO + # + MakerCode "01" + + # + # REMASTER VERSION: Mastering version + # + #RomVersion 0 + + # + # ROM SPEED TYPE: [MROM/1TROM/UNDEFINED] + # + RomSpeedType $(MAKEROM_ROMSPEED) + + # + # ROM SIZE: in bit [64M/128M/256M/512M/1G/2G] + # + #RomSize 128M + #RomSize 256M + + # + # ROM PADDING: TRUE if finalrom + # + #RomFootPadding TRUE + + # + # ROM HEADER TEMPLATE: Provided to every product by NINTENDO + # + #RomHeaderTemplate ./etc/rom_header.template.sbin + + # + # BANNER FILE: generated from Banner Spec File + # + #BannerFile ./etc/myGameBanner.bnr + BannerFile $(TWLSDK_ROOT)/include/twl/specfiles/default.bnr + + ### + ### Setting for TWL + ### + # + # BANNER FILE: + # + BannerTWLFile $(TWLSDK_ROOT)/include/twl/specfiles/default.bnr + + # + # Boot allowed Media: [GameCard/NAND/SDCard/DownloadPlay] + # possible to choose one or more. + # + BootMedia GameCard NAND SDCard DownloadPlay + + # + # Certification FILE: + # + Certificate $(TWLSDK_ROOT)/include/twl/specfiles/default_sgn.sbin + + # + # Digest parameters: + # + DigestParam 1024 32 + + # + # WRAM mapping: [MAP_BB_HYB/MAP_BB_LTD/MAP_TS_HYB/MAP_TS_LTD] + # don't have to edit + # + #WramMapping $(MAKEROM_WRAM_MAPPING) + WramMappingDirect wram_regs/wram_regs.rbin + + # + # Codec mode: + # don't have to edit + # + CodecMode $(MAKEROM_CODEC_MODE) + + ### + #### END +} + +RomSpec +{ + Offset 0x00000000 + Segment ALL + HostRoot $(MAKEROM_ROMROOT) + Root / + File $(MAKEROM_ROMFILES) +} diff --git a/include/sysmenu.h b/include/sysmenu.h new file mode 100644 index 0000000..80dbc8f --- /dev/null +++ b/include/sysmenu.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: sysmenu.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef SYSMENU_H_ +#define SYSMENU_H_ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* SYSMENU_H_ */ +#endif diff --git a/include/sysmenu/.DS_Store b/include/sysmenu/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..cf1554cb7ad111edb1fbe4c5aca1c90b1424dbda GIT binary patch literal 6148 zcmeHKK~BRk5FA5=C_T^<;^;5*$SqXi1$_XJ7PXa{rlRz~Ee9S0PvF3fuka6MZ3|%% zlM6x!?N;kaHoNxjMDf-D%y>5&0YdeRo!?VSX12!8Wx7NW=XmmsXClwUyop>B-f_NGvQYV12H3Mj z4hJ4}R0fm*W#EGW*&i%bFbi0FbXx}pcLX5zXm-MD*IS5I48$y8?U5FW@u5T?YQho2 z_;A{7@XG?$9(_2BTbc8Ol}$LI7`Hm@*15xE9(7a(l!2ImeSbTY{(q4^|Hnakrwk|q z|B3@K7gpHiLhnUxD-7O?h63q}73I2v?N I27Z-+cdbC6P5=M^ literal 0 HcmV?d00001 diff --git a/include/sysmenu/acsign.h b/include/sysmenu/acsign.h new file mode 100644 index 0000000..f334333 --- /dev/null +++ b/include/sysmenu/acsign.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - ACSIGN + File: acsign.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef SYSM_ACSIGN_H_ +#define SYSM_ACSIGN_H_ + +#ifdef SDK_ARM9 +#include +#include +#endif // SDK_ARM9 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* SYSM_ACSIGN_H_ */ +#endif diff --git a/include/sysmenu/acsign/ARM9/acsign.h b/include/sysmenu/acsign/ARM9/acsign.h new file mode 100644 index 0000000..eff3b53 --- /dev/null +++ b/include/sysmenu/acsign/ARM9/acsign.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: acsign.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef _ACSIGN_H_ +#define _ACSIGN_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined( RSA_ENC_DEC ) +#define ACSIGN_BUFFER ((160/8)*4) // o̓obt@ +#else +#define ACSIGN_BUFFER ((160/8)*1) // o̓obt@ +#endif + +// +int ACSign_Decrypto( + void* buffer, // o͗̈ + void* sgn_ptr, // f[^ւ̃|C^ + void* key_ptr // L[ւ̃|C^ + ); + +// +int ACSign_Digest( + void* buffer, // o͗̈ + void* romh_ptr, // f[^ւ̃|C^ + void* mbin_ptr, // f[^ւ̃|C^ + int mbin_len, // f[^̒ + void* sbin_ptr, // f[^ւ̃|C^ + int sbin_len, // f[^̒ + u32 serial_num // VAio[ + ); + +// +int ACSign_Compare( + void* dercypto, // ACSign_Decryptȍo + void* digest // ACSign_Digest̏o + ); + +#ifdef __cplusplus +} +#endif + +#endif //_ACSIGN_H_ diff --git a/include/sysmenu/acsign/ARM9/acsign_util.h b/include/sysmenu/acsign/ARM9/acsign_util.h new file mode 100644 index 0000000..dd09d6b --- /dev/null +++ b/include/sysmenu/acsign/ARM9/acsign_util.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: acsign_util.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef _ACSIGN_UTIL_H_ +#define _ACSIGN_UTIL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define AUTH_BUFFER_LEN 20 + +extern int ACSignDecrpto(void *output_buffer, MBDownloadFileInfo *download_file_info_buf); +extern int ACSignDigest(void *input_buffer, MBDownloadFileInfo *download_file_info_buf); + + +#ifdef __cplusplus +} +#endif + +#endif //_ACSIGN_UTIL_H_ diff --git a/include/sysmenu/banner.h b/include/sysmenu/banner.h new file mode 100644 index 0000000..3479150 --- /dev/null +++ b/include/sysmenu/banner.h @@ -0,0 +1,111 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: banner.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef BANNER_H_ +#define BANNER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef BANNER_ROM_OFFSET +#define BANNER_ROM_OFFSET (HW_ROM_HEADER_BUF + 0x68) +#endif + +#define BNR_VER_MIN 1 +#define BNR_VER_MAX 3 +#define BNR_HEADER_RSV_SIZE 24 + +#define BNR_CHINESE_SUPPORT_VER 2 +#define BNR_HANGUL_SUPPORT_VER 3 + +typedef enum +{ + BNR_JAPANESE = 0, + BNR_ENGLISH = 1, + BNR_FRENCH = 2, + BNR_GERMAN = 3, + BNR_ITALIAN = 4, + BNR_SPANISH = 5, + BNR_CHINESE = 6, + BNR_HANGUL = 7, + BNR_LANG_NUM +} BannerFileLangIdx; + +#define BNR_LANG_NUM_V1 6 +#define BNR_LANG_NUM_V2 1 +#define BNR_LANG_NUM_V3 1 + + +#define BNR_HEADER_SIZE 32 +#define BNR_VER_OFFSET 0 +#define BNR_V1_CRC16_OFFSET 2 +#define BNR_IMAGE_OFFSET BNR_HEADER_SIZE +#define BNR_IMAGE_SIZE (32 * 32 / (8/4)) +#define BNR_PLTT_OFFSET (BNR_IMAGE_OFFSET + BANNER_IMAGE_SIZE) +#define BNR_PLTT_NUM 16 +#define BNR_PLTT_SIZE (BNR_PLTT_NUM * 2) +#define BNR_LANG_OFFSET (BNR_PLTT_OFFSET + BANNER_PLTT_SIZE) +#define BNR_LANG_LENGTH 128 +#define BNR_LANG_SIZE (BNR_LANG_LENGTH * 2) + +typedef struct +{ + u8 version; + u8 reserved_A; + u16 crc16_v1; + u16 crc16_v2; + u16 crc16_v3; + u8 reserved_B[BNR_HEADER_RSV_SIZE]; +} BannerHeader; + +typedef struct +{ + u8 image[BNR_IMAGE_SIZE]; + GXRgba pltt[BNR_PLTT_NUM]; + + u16 gameName[BNR_LANG_NUM_V1][BNR_LANG_LENGTH]; +} BannerFileV1; + +typedef struct +{ + u16 gameName[BNR_LANG_NUM_V2][BNR_LANG_LENGTH]; +} BannerFileV2; + +typedef struct +{ + u16 gameName[BNR_LANG_NUM_V3][BNR_LANG_LENGTH]; +} BannerFileV3; + +typedef struct +{ + BannerHeader h; + BannerFileV1 v1; + BannerFileV2 v2; + BannerFileV3 v3; +} BannerFile; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* BANNER_H_ */ +#endif diff --git a/include/sysmenu/machineSettings.h b/include/sysmenu/machineSettings.h new file mode 100644 index 0000000..be955cd --- /dev/null +++ b/include/sysmenu/machineSettings.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: machineSettings.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef SYSM_MACHINE_SETTINGS_H_ +#define SYSM_MACHINE_SETTINGS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* SYSM_MACHINE_SETTINGs_H_ */ +#endif diff --git a/include/sysmenu/machineSettings/common/nitroSettings.h b/include/sysmenu/machineSettings/common/nitroSettings.h new file mode 100644 index 0000000..9dca4b7 --- /dev/null +++ b/include/sysmenu/machineSettings/common/nitroSettings.h @@ -0,0 +1,483 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: NitroSettings.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + + +#ifndef NITRO_SETTINGS_H_ +#define NITRO_SETTINGS_H_ +#if defined(SDK_CW) // NitroConfigDataɃrbgtB[hgĂ̂ŁARpCˑŕs”\B + // āACWȊÕRpC̏ꍇ́Ãwb_𖳌ɂăG[o悤ɂčĊmFB + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +// define data ------------------------------------ +#define NITRO_CONFIG_DATA_VERSION 5 // NITROݒf[^tH[}bgo[W +#define NITRO_CONFIG_DATA_EX_VERSION 1 // gNITROݒf[^tH[}bgo[W +#define NCD_NICKNAME_LENGTH 10 // jbNl[ +#define NCD_COMMENT_LENGTH 26 // Rg +#define NCD_FAVORITE_COLOR_MAX_NUM 16 // DȐF̍ő吔 + +// ݒR[h +typedef enum NvLangCode{ + LANG_JAPANESE =0, // { + LANG_ENGLISH =1, // p + LANG_FRENCH =2, // tX + LANG_GERMAN =3, // hCc + LANG_ITALIAN =4, // C^A + LANG_SPANISH =5, // XyC + LANG_CHINESE =6, // + LANG_HANGUL =7, // ؍ + LANG_CODE_MAX +}NvLangCode; + +#define LANG_CODE_MAX_WW ( LANG_SPANISH + 1 ) +#define LANG_BITMAP_WW ( ( 0x0001 << LANG_JAPANESE ) \ + | ( 0x0001 << LANG_ENGLISH ) \ + | ( 0x0001 << LANG_FRENCH ) \ + | ( 0x0001 << LANG_GERMAN ) \ + | ( 0x0001 << LANG_ITALIAN ) \ + | ( 0x0001 << LANG_SPANISH ) ) // ʏłł̑Ήrbg}bv + +#define VALID_LANG_BITMAP LANG_BITMAP_WW // {IPL2̑Ήrbg}bv + + +// tf[^ +typedef struct NvDate{ + u8 month; // :01`12 + u8 day; // :01`31 +}NvDate; // 2byte + +// jbNl[ +typedef struct NvNickname{ + u16 str[NCD_NICKNAME_LENGTH]; // jbNl[iUnicode(UTF16)ōő10AI[R[hȂj + u8 length; // + u8 rsv; +}NvNickname; // 22byte + +// Rg +typedef struct NvComment{ + u16 str[NCD_COMMENT_LENGTH]; //RgiUnicode(UTF16)ōő26AI[R[hȂj + u8 length; // + u8 rsv; +}NvComment; // 54byte + +// I[i[ +typedef struct NvOwnerInfo{ + u8 favoriteColor : 4; // DȐF + u8 rsv : 4; // \B + NvDate birthday; // N + u8 pad; + NvNickname nickname; // jbNl[ + NvComment comment; // Rg +}NvOwnerInfo; // 80byte + +// IPLpڊo܂vf[^ +typedef struct NvAlarm{ + u8 hour; // A[:00`23 + u8 minute; // A[:00`59 + u8 rsv1; // \ + u8 pad; + u16 alarmOn : 1; // A[ON,OFFi0:OFF, 1:ONj + u16 rsv2 : 15; // \ +}NvAlarm; // 6byte + +// ^b`plLu[Vf[^ +typedef struct NvTpCalibData{ + u16 raw_x1; // PLu[V_TP擾lX + u16 raw_y1; // @@@@V@@@@@@@@TP擾lY + u8 dx1; // @@@@V@@@@@@@@LCDW X + u8 dy1; // @@@@V@@@@@@@@LCDW Y + u16 raw_x2; // QLu[V_TP擾lX + u16 raw_y2; // @@@@V@@@@@@@@TP擾lY + u8 dx2; // @@@@V@@@@@@@@LCDW X + u8 dy2; // @@@@V@@@@@@@@LCDW Y +}NvTpCalibData; // 12byte + +// IvV +typedef struct NvOption{ + u16 language : 3; // R[hiLANG_SPANISH܂ł̕WR[hj + u16 agbLcd : 1; // AGB[hŋN鎞ɂǂLCDŋN邩Hi0:TOP,1:BOTTOMj + u16 backLightBrightness : 2; // obNCgPxf[^ + u16 autoBootFlag : 1; // NV[PXŁAj[~ȂŎN邩ǂH(0:OFF, 1:ON) + u16 backLightOffFlag : 1; // obNCgON,OFFtOi0:ON, 1:OFFj + u16 rsv2 : 1; // \ + u16 destroyFlashFlag : 1; // tbVV[PXtO + u16 input_birthday : 1; // a͂ꂽH + u16 input_favoriteColor : 1; // DȐF͂ꂽH + u16 input_tp : 1; // ^b`plLu[VꂽHi V ) + u16 input_language : 1; // ͂ꂽH@ (0:ݒ, 1:ݒς) + u16 input_rtc : 1; // RTCݒ肪ꂽH ( V@@@@@ ) + u16 input_nickname : 1; // jbNl[͂ꂽH ( V@@@@@ ) + u8 rtcLastSetYear; // RTC̑OݒN + u8 rtcClockAdjust; // RTCNbNl + s64 rtcOffset; // RTCݒ莞̃ItZbgli[U[RTCݒύXxɂ̒lɉđ܂Bj +}NvOption; // 12byte + +// NITROeݒf[^ +typedef struct NitroConfigData{ + u8 version; // tbVi[f[^tH[}bg̃o[W + u8 pad; + NvOwnerInfo owner; // I[i[ + NvAlarm alarm; // IPLpڊo܂vf[^ + NvTpCalibData tp; // ^b`plLu[Vf[^ + NvOption option; // IvV +}NitroConfigData; // 112byte + +// NITROeݒf[^NVRAMۑtH[}bg +typedef struct NCDStore{ + NitroConfigData ncd; // NITROeݒf[^ + u16 saveCount; // 0x00-0x7f[văJEgAJEglVf[^LB + u16 crc16; // NITROeݒf[^16bitCRC + u8 pad[ 128 - sizeof(NitroConfigData) - 4]; +}NCDStore; // 128byte // {ȂAsaveCountcrc16256byte̍ŌɕtāAԂɃpfBO𖄂߂B + + +//---------------------------------------------- +// IPL2E؍łł̊gtH[}bg +//---------------------------------------------- +// gNITROݒf[^ +typedef struct NitroConfigDataEx{ + u8 version; // o[W + u8 language; // R[hiLANG_CHINESEȍ~ɊgꂽlBj + u16 valid_language_bitmap; // {IPL2ŗLȌR[hrbg}bv + u8 pad[ 256 - sizeof(NitroConfigData) - 4 - 4 - 2 ]; // 4:saveCount+crc16, 2:NCDEx.version+NCDEx.language, 2:crc16_ex +}NitroConfigDataEx; // 138bytes + +// NITROeݒf[^NVRAMۑtH[}bg +typedef struct NCDStoreEx{ + NitroConfigData ncd; // NITROeݒf[^ + u16 saveCount; // 0x00-0x7f[văJEgAJEglVf[^LB + u16 crc16; // NITROeݒf[^16bitCRC + NitroConfigDataEx ncd_ex; + u16 crc16_ex; +}NCDStoreEx; // 256byte // {ȂAsaveCountcrc16256byte̍ŌɕtāAԂɃpfBO𖄂߂B + + +//========================================================= +// NVRAMւ̃[hCg֐ +//========================================================= +#ifdef SDK_ARM9 +extern int NVRAMm_ReadNitroConfigData (NitroConfigData *dstp); +extern void NVRAMm_WriteNitroConfigData(NitroConfigData *dstp); +#endif + + +//========================================================= +// NITROݒf[^ւ̃ANZX֐ +//========================================================= +extern NitroConfigDataEx ncdEx; + +#define GetNCDWork() ( (NitroConfigData *)( HW_NVRAM_USER_INFO ) ) +#define GetNCDExWork() ( &ncdEx ) + // NITROݒf[^̈̃AhXl + +extern void NCD_ClearOwnerInfo( void ); // jbNl[EaEDȐF̃NA +extern u8 NCD_GetIPL2Type( void ); +extern u8 *NCD_GetIPL2Version( void ); +extern u32 NCD_GetNCDRomAddr( void ); + +//========================================================= +// f[^擾 +//========================================================= + +//----------------------------------- +// I[i[Ŝ̎擾B +static inline NvOwnerInfo *NCD_GetOwnerInfo(void) +{ + return &GetNCDWork()->owner; +} + +// DȐF̎擾B +static inline u8 NCD_GetFavoriteColor(void) +{ + return (u8)GetNCDWork()->owner.favoriteColor; +} + +// a̎擾B +static inline NvDate *NCD_GetBirthday(void) +{ + return &GetNCDWork()->owner.birthday; +} + +// jbNl[̎擾B +static inline NvNickname *NCD_GetNickname(void) +{ + return &GetNCDWork()->owner.nickname; +} + +// Rg̎擾B +static inline NvComment *NCD_GetComment(void) +{ + return &GetNCDWork()->owner.comment; +} + + +//----------------------------------- +// A[̎擾B +static inline NvAlarm *NCD_GetAlarmData(void) +{ + return &GetNCDWork()->alarm; +} + + +//----------------------------------- +// ^b`plLu[Vf[^̎擾B +static inline NvTpCalibData *NCD_GetTPCalibration(void) +{ + return &GetNCDWork()->tp; +} + + +//----------------------------------- +// IvV̎擾B + +// R[h̎擾 +static inline NvLangCode NCD_GetLanguage(void) +{ + return (NvLangCode)GetNCDExWork()->language; +} + +static inline NvLangCode NCD_GetLanguageOrg(void) +{ + return (NvLangCode)GetNCDWork()->option.language; +} + +// RTCItZbgl̎擾 +static inline s64 NCD_GetRtcOffset(void) +{ + return GetNCDWork()->option.rtcOffset; +} + +// RTCNbNl̎擾 +static inline u8 NCD_GetRtcClockAdjust(void) +{ + return GetNCDWork()->option.rtcClockAdjust; +} + +// RTC̑OZbgN̎擾 +static inline u8 NCD_GetRtcLastSetYear(void) +{ + return GetNCDWork()->option.rtcLastSetYear; +} + +// NV[PX̎NONHi0:OFF, 1:ONj +static inline int NCD_GetAutoBootFlag(void) +{ + return (int)GetNCDWork()->option.autoBootFlag; +} + +// obNCgPx擾i0-3j +static inline int NCD_GetBackLightBrightness(void) +{ + return (int)GetNCDWork()->option.backLightBrightness; +} + +// tbVV[PXǂH +static inline int NCD_GetDestroyFlash(void) +{ + return (int)GetNCDWork()->option.destroyFlashFlag; +} + +// af[^ZbgĂ邩H +static inline int NCD_GetInputBirthday(void) +{ + return (int)GetNCDWork()->option.input_birthday; +} + +// DȐFf[^ZbgĂ邩H +static inline int NCD_GetInputFavoriteColor(void) +{ + return (int)GetNCDWork()->option.input_favoriteColor; +} + +// TPLu[Vf[^ZbgĂ邩H +static inline int NCD_GetInputTP(void) +{ + return (int)GetNCDWork()->option.input_tp; +} + +// R[hZbgĂ邩H +static inline int NCD_GetInputLanguage(void) +{ + return (int)GetNCDWork()->option.input_language; +} + +// RTCf[^ZbgĂ邩H +static inline int NCD_GetInputRTC(void) +{ + return (int)GetNCDWork()->option.input_rtc; +} + +// I[i[̃jbNl[ZbgĂ邩H +static inline int NCD_GetInputNickname(void) +{ + return (int)GetNCDWork()->option.input_nickname; +} + +//========================================================= +// f[^Zbg +//========================================================= +//----------------------------------- +// I[i[Ŝ̃ZbgB +static inline void NCD_SetOwnerInfo(NvOwnerInfo *owinfop) +{ + SVC_CpuCopy( owinfop, &GetNCDWork()->owner, sizeof(NvOwnerInfo), 16); +} + +// DȐF̃ZbgB +static inline void NCD_SetFavoriteColor(u8 favoriteColor) +{ + GetNCDWork()->owner.favoriteColor = favoriteColor; +} + +// ãZbgB +static inline void NCD_SetBirthday(NvDate *birthp) +{ + GetNCDWork()->owner.birthday.month = birthp->month; + GetNCDWork()->owner.birthday.day = birthp->day; +} + +// jbNl[̃ZbgB +static inline void NCD_SetNickname(NvNickname *namep) +{ + SVC_CpuCopy( namep, &GetNCDWork()->owner.nickname, sizeof(NvNickname), 16); +} + +// Rg̃ZbgB +static inline void NCD_SetComment(NvComment *commentp) +{ + SVC_CpuCopy( commentp, &GetNCDWork()->owner.comment, sizeof(NvComment), 16); +} + + +//----------------------------------- +// A[̃ZbgB +static inline void NCD_SetAlarmData(NvAlarm *alarmp) +{ + SVC_CpuCopy( alarmp, &GetNCDWork()->alarm, sizeof(NvAlarm), 16); +} + + +//----------------------------------- +// ^b`plLu[Vf[^̃ZbgB +static inline void NCD_SetTPCalibration(NvTpCalibData *tp_calibp) +{ + SVC_CpuCopy( tp_calibp, &GetNCDWork()->tp, sizeof(NvTpCalibData), 16); +} + + +//----------------------------------- +// IvṼZbgB + +// R[h̃Zbg +static inline void NCD_SetLanguage(NvLangCode language) +{ + GetNCDExWork()->language = language; + + if( language >= LANG_CODE_MAX_WW ) { + GetNCDWork()->option.language = LANG_ENGLISH; + }else { + GetNCDWork()->option.language = language; + } +} + +// RTCItZbgl̃Zbg +static inline void NCD_SetRtcOffset(s64 rtcOffset) +{ + GetNCDWork()->option.rtcOffset = rtcOffset; +} + +// RTCNbNl̃Zbg +static inline void NCD_SetRtcClockAdjust(u8 rtcClockAdjust) +{ + GetNCDWork()->option.rtcClockAdjust = rtcClockAdjust; +} + + +// RTCLastSetYearւ̃Zbg +static inline void NCD_SetRtcLastSetYear(u8 rtcLastSetYear) +{ + GetNCDWork()->option.rtcLastSetYear = rtcLastSetYear; +} + + +// NV[PX̎NON,OFFtOZbgB +static inline void NCD_SetAutoBootFlag(BOOL autoBootFlag) +{ + GetNCDWork()->option.autoBootFlag = (u16)autoBootFlag; +} + +// obNCgPxZbgB +static inline void NCD_SetBackLightBrightness(BOOL backLightBrightness ) +{ + GetNCDWork()->option.backLightBrightness = (u16)backLightBrightness; +} + +// tbVV[PXǂ̃tOZbgB +static inline void NCD_SetDestroyFlash(BOOL destroy) +{ + GetNCDWork()->option.destroyFlashFlag = (u16)destroy; +} + +// af[^͍̓ς݃tOZbgB +static inline void NCD_SetInputBirthday(BOOL input) +{ + GetNCDWork()->option.input_birthday = (u16)input; +} + +// DȐFf[^͍̓ς݃tOZbgB +static inline void NCD_SetInputFavoriteColor(BOOL input) +{ + GetNCDWork()->option.input_favoriteColor = (u16)input; +} + +// TPLu[Vf[^͍̓ς݃tOZbgB +static inline void NCD_SetInputTP(BOOL input) +{ + GetNCDWork()->option.input_tp = (u16)input; +} + +// R[h͍̓ς݃tOZbgB +static inline void NCD_SetInputLanguage(BOOL input) +{ + GetNCDWork()->option.input_language = (u16)input; +} + +// RTCf[^͍̓ς݃tOZbgB +static inline void NCD_SetInputRTC(BOOL input) +{ + GetNCDWork()->option.input_rtc = (u16)input; +} + +// I[i[̃jbNl[͍̓ς݃tOZbgB +static inline void NCD_SetInputNickname(BOOL input) +{ + GetNCDWork()->option.input_nickname = (u16)input; +} + + + +#ifdef __cplusplus +} +#endif + +#endif // SDK_CW +#endif // NITRO_SETTINGS_H_ diff --git a/include/sysmenu/mb_loader.h b/include/sysmenu/mb_loader.h new file mode 100644 index 0000000..d5a1933 --- /dev/null +++ b/include/sysmenu/mb_loader.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - MB_LOADER + File: mb_loader.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef SYSM_MB_LOADER_H_ +#define SYSM_MB_LOADER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* SYSM_MB_LOADER_H_ */ +#endif diff --git a/include/sysmenu/mb_loader/common/mb_loader.h b/include/sysmenu/mb_loader/common/mb_loader.h new file mode 100644 index 0000000..9b853e6 --- /dev/null +++ b/include/sysmenu/mb_loader/common/mb_loader.h @@ -0,0 +1,86 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: mb_loader.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#if !defined(_LOADER_H_) +#define _LOADER_H_ + +#include +#include // twl/mb.hȂB + +#ifdef __cplusplus +extern "C" { +#endif + +#define PXI_FIFO_TAG_MB PXI_FIFO_TAG_USER_0 +/* + ̍ہAFIFO_TAGƂȂTAGԍɎw肵ĂB +*/ + +/*---------------------------------------------------------------------------* + Type definition + *---------------------------------------------------------------------------*/ + +typedef void (*MB_LoaderCallback)(void); + +/*---------------------------------------------------------------------------* + functions + *---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------* + Name: LOADER_Init + + Description: [_[̏ + + Arguments: callback - u[g̏oƂɕԂR[obN + + Returns: None. + *---------------------------------------------------------------------------*/ + +void LOADER_Init(MB_LoaderCallback callback); + + +/*---------------------------------------------------------------------------* + Name: LOADER_Start + + Description: [_[̃X^[g + + Arguments: None. + + Returns: None. + *---------------------------------------------------------------------------*/ + +void LOADER_Start( void ); + + +/*---------------------------------------------------------------------------* + Name: MIm_CpuCopy32 + + Description: [_[pCpuCopy32֐ + + Arguments: + + Returns: TRUE - success FALSE - failed + *---------------------------------------------------------------------------*/ + +void MIm_CpuCopy32( register const void *srcp, register void *destp, register u32 size ); + + +#ifdef __cplusplus +} +#endif + +#endif /* _LOADER_H_ */ diff --git a/include/sysmenu/memorymap.h b/include/sysmenu/memorymap.h new file mode 100644 index 0000000..cfa4bf0 --- /dev/null +++ b/include/sysmenu/memorymap.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - memorymap + File: memorymap.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef SYSM_MEMORYMAP_H_ +#define SYSM_MEMORYMAP_H_ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* SYSM_MEMORYMAP_H_ */ +#endif diff --git a/include/sysmenu/mmap.h b/include/sysmenu/mmap.h new file mode 100644 index 0000000..9aab156 --- /dev/null +++ b/include/sysmenu/mmap.h @@ -0,0 +1,57 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: mmap.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef __MMAP_H__ +#define __MMAP_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// define data ------------------------------------ + +#define RETURN_FROM_MAIN_ARM9_FUNCP 0x023fee00 // NITROQ[u[gARM9ŏI̓AhX +#define RETURN_FROM_MAIN_ARM7_FUNCP 0x0380f600 // NITROQ[u[gARM7ŏI̓AhX + +#define SYSM_ADDR_TOP 0x02300000 // SYSMzu擪AhX +#define SYSM_ADDR_BOTTOM 0x023fe000 // SYSMzuŏIAhX + +#define SYSM_ARM9_MMEM_ENTRY_ADDR_LIMIT ( SYSM_ADDR_TOP - 0x80000 ) // 0x02800000 + +#define SYSM_ARM9_LOAD_MMEM_LAST_ADDR ( SYSM_ADDR_TOP - 0x80000 ) // SYSM[h”\NITROJ[hu[gR[h̃CŏIAhX +#define SYSM_ARM7_LOAD_MMEM_LAST_ADDR ( SYSM_ADDR_BOTTOM ) // SYSM[h”\NITROJ[hu[gR[h̃CŏIAhX +#define SYSM_ARM7_LOAD_WRAM_LAST_ADDR ( RETURN_FROM_MAIN_ARM7_FUNCP & ~0x0fff ) // SYSM[h”\NITROJ[hu[gR[h̃CŏIAhX +#define SYSM_ARM7_LOAD_BUF_ADDR ( SYSM_ADDR_TOP - 0x40000 ) // SYSMNITROJ[hARM7u[gR[h̃[hsۂ̃[hobt@AhX +#define SYSM_ARM7_LOAD_BUF_SIZE ( SYSM_ADDR_TOP - SYSM_ARM7_LOAD_BUF_ADDR ) // SYSMNITROJ[hARM7R[h[hobt@TCY + +#define UNCOMP_TEMP_BUF ( SYSM_ARM7_LOAD_BUF_ADDR ) // kWJpf[^ꎞi[obt@AhX +#define UNCOMP_TEMP_BUF_SIZE ( SYSM_ARM7_LOAD_BUF_SIZE ) // kWJpf[^ꎞi[obt@TCY + +#define NITRO_CARD_SECURE_SIZE 0x4000 // NITROJ[h̃ZLÄTCY(16Kbytes) + +#define SYSROM9_NINLOGO_ADR 0xffff0020 // ARM9VXeROM̔CVSi[AhX +#define AGB_CARTRIDGE_NIN_LOGO_DATA (HW_CTRDG_ROM + 4) // AGBJ[gbWNintendoSf[^i[AhX + + +#ifdef __cplusplus +} +#endif + +#endif // __MMAP_H__ + diff --git a/include/sysmenu/rom_header.h b/include/sysmenu/rom_header.h new file mode 100644 index 0000000..b09e1f2 --- /dev/null +++ b/include/sysmenu/rom_header.h @@ -0,0 +1,175 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: rom_header.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef _ROM_HEADER_H_ +#define _ROM_HEADER_H_ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#define NINTENDO_LOGO_LENGTH 0x9c // NintendoSf[^TCY + +//---------------------------------------------------------------------- +// t@Cl[e[u +//---------------------------------------------------------------------- + +typedef struct ROM_FNT{ + char entry_name[FS_FILE_NAME_MAX]; // t@C (I[ \0 ͏Ȃ) +} ROM_FNT; + +//---------------------------------------------------------------------- +// t@CAP[Ve[u +//---------------------------------------------------------------------- +typedef struct { + void *top; // t@C̐擪 ROM AhX + void *bottom; // t@C̍ŏI ROM AhX +} ROM_FAT; + +//---------------------------------------------------------------------- +// I[o[Ce[u +//---------------------------------------------------------------------- +typedef struct { + u32 id; // I[o[C ID + void *ram_address; // [h擪ʒu + u32 ram_size; // [hTCY + u32 bss_size; // bss ̈TCY + void *sinit_init; // static initializer 擪AhX + void *sinit_init_end; // static initializer ŏIAhX + u32 file_id; // I[o[Ct@CID + u32 rsv; // \B +} ROM_OVT; + +//---------------------------------------------------------------------- +// ROMwb_ +//---------------------------------------------------------------------- +typedef struct { + // + // 0x000 System Reserved + // + char title_name[12]; // Soft title name + u32 game_code; // Game code + + u16 maker_code; // Maker code + u8 machine_code; // Machine code + u8 rom_type; // Rom type + u8 rom_size; // Rom size + + u8 agbRomCycle1st; // 1ZOAGBRomANZXTCN1st. + u8 agbRomCycle2nd; // 1ZOAGBRomANZXTCN2nd. + u8 reserved_A[7]; // System Reserved A ( Set ALL 0 ) + + u8 soft_version; // Soft version + u8 comp_arm9_boot_area:1; // Compress arm9 boot area + u8 comp_arm7_boot_area:1; // Compress arm7 boot area + u8 inspectCard:1; // J[htO + u8 disableClearMemoryPad:1; // IPL2pbhNAEfBZ[utO + u8 enableAgbRomCycle:1; + u8 :2; + u8 disableDetectPullOut:1; // J[hofBZ[utO + + // + // 0x020 for Static modules (Section:B) + // + // ARM9 + u32 main_rom_offset; // ROM offset + void* main_entry_address; // Entry point + void* main_ram_address; // RAM address + u32 main_size; // Module size + + // ARM7 + u32 sub_rom_offset; // ROM offset + void* sub_entry_address; // Entry point + void* sub_ram_address; // RAM address + u32 sub_size; // Module size + + // + // 0x040 for File Name Table[FNT] (Section:C) + // + ROM_FNT* fnt_offset; // ROM offset + u32 fnt_size; // Table size + + // + // 0x048 for File Allocation Table[FAT] (Section:E) + // + ROM_FAT* fat_offset; // ROM offset + u32 fat_size; // Table size + + // + // 0x050 for Overlay Tables[OVT] (Section:D) + // + // ARM9 + ROM_OVT* main_ovt_offset; // ROM offset + u32 main_ovt_size; // Table size + + // ARM7 + ROM_OVT* sub_ovt_offset; // ROM offset + u32 sub_ovt_size; // Table size + + // 0x060 for ROM control parameter + u32 game_cmd_param; // Game command parameter + u32 secure_cmd_param; // Secure command parameter + + u32 banner_offset; // Banner ROM offset + + u16 secure_area_crc16; // Secure area CRC-16 + u16 secure_cmd_latency; // Secure command latency ((param+2)*256 system cycles) + u8 ctrl_reserved_B[16]; // Ctrl Reserved B (Set 0) + + // 0x080 - 0x0C0 System Reserved + u32 total_rom_size; + u8 reserved_B[60]; // System Reserved B (Set 0) + + // 0x0C0 for NINTENDO logo data + u8 nintendo_logo[ NINTENDO_LOGO_LENGTH ]; // NINTENDO logo data + u16 nintendo_logo_crc16; // CRC-16 + + // 0x15E ROM header CRC-16 + u16 header_crc16; // ROM header CRC-16 + + // + // 0x0160 - 0x0180 System Reserved + // + u32 dbgRomAddr; // fobKj^ROMAhX + s32 dbgRomSize; // fobKj^ROMTCY + u32 dbgArm9RamAddr; // fobKj^ARM9-RAMAhX + u32 dbgArm7RamAddr; // fobKj^ARM7-RAMAhX + u8 reserved_C[16]; // Debugger Reserved (Set ALL 0) + +} RomHeader; + + +//---------------------------------------------------------------------- +// ROMwb_AhXl +//---------------------------------------------------------------------- + +#define GetRomHeaderAddr() ((RomHeader *)HW_ROM_HEADER_BUF) + +//EROMwb_AhXl܂B + + +#ifdef __cplusplus + +#endif + +#endif // _ROM_HEADER_H_ + + + diff --git a/include/sysmenu/sysmenu_lib.h b/include/sysmenu/sysmenu_lib.h new file mode 100644 index 0000000..d0565c0 --- /dev/null +++ b/include/sysmenu/sysmenu_lib.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - SYSMENU_LIB + File: sysmenu_lib.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef SYSM_SYSMENU_LIB_H_ +#define SYSM_SYSMENU_LIB_H_ + +#ifdef SDK_ARM9 +#include +#include +#endif // SDK_ARM9 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* SYSM_SYSMENU_LIB_H_ */ +#endif diff --git a/include/sysmenu/sysmenu_lib/ARM9/cmn.h b/include/sysmenu/sysmenu_lib/ARM9/cmn.h new file mode 100644 index 0000000..9640c41 --- /dev/null +++ b/include/sysmenu/sysmenu_lib/ARM9/cmn.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: mainFunc.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef CMN_H_ +#define CMN_H_ + + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +// define data--------------------------------------------- +#define ARY_SIZEOF(ary) ( sizeof(ary) / sizeof( (ary)[0] ) ) +#define ROUNDUP_DIV(a, b) (( (a) + ((b) - 1) ) / (b)) + + +// function------------------------------------------------ +void CMN_InitAllocator( NNSFndAllocator* pAllocator ); +void CMN_InitFileSystem( NNSFndAllocator* pAllocator ); +void CMN_ClearVram( void ); +u32 CMN_LoadFile(void** ppFile, const char* fpath, NNSFndAllocator* pAlloc); +void CMN_UnloadFile(void* pFile, NNSFndAllocator* pAlloc); +NNSFndArchive* CMN_LoadArchive(const char* name, const char* path, NNSFndAllocator* pAllocator); +void CMN_RemoveArchive(NNSFndArchive* archive, NNSFndAllocator* pAllocator); + + +#ifdef __cplusplus +}/* extern "C" */ +#endif + +#endif // CMN_H_ + diff --git a/include/sysmenu/sysmenu_lib/ARM9/sysmenu_api.h b/include/sysmenu/sysmenu_lib/ARM9/sysmenu_api.h new file mode 100644 index 0000000..db5e09b --- /dev/null +++ b/include/sysmenu/sysmenu_lib/ARM9/sysmenu_api.h @@ -0,0 +1,117 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: SYSM_lib.h + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef __SYSM_LIB_H__ +#define __SYSM_LIB_H__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// define data---------------------------------------------------------- + +// ^Cg +typedef struct TitleProperty { // ̏́A`[ɂ͔FؒʂĂȂǁANɂ͔Fؒʂ̂őv낤B + u64 titleID; // ^CgID + void *pBanner; // oi[ւ̃|C^iŒ蒷tH[}bgȂUĂv낤B) + u32 rsv; +}TitleProperty; + + +// Zbgp[^ +typedef struct ResetParam { + u64 bootTitleID; // N^Cg邩HȂ炻̃^CgID + u32 rsv; + BOOL isLogoSkip; // SfXLbv邩H +}ResetParam; + + +// AvF، +typedef enum AuthResult { + AUTH_PROCESSING = 0, + AUTH_RESULT_SUCCEEDED = 1, + AUTH_RESULT_TITLE_POINTER_ERROR = 2, + AUTH_RESULT_AUTHENTICATE_FAILED = 3, + AUTH_RESULT_ENTRY_ADDRESS_ERROR = 4 +}AuthResult; + + +// global variable------------------------------------------------------ + +// function------------------------------------------------------------- +extern void SYSM_Init( void ); +extern BOOL SYSM_IsLogoDemoSkip( void ); +extern void SYSM_CaribrateTP( void ); +extern int SYSM_GetCardTitleList( TitleProperty *pTitleList_Card ); +extern int SYSM_GetNandTitleList( TitleProperty *pTitleList_Nand ); +extern AuthResult SYSM_LoadAndAuthenticateTitle( TitleProperty *pBootTitle ); +extern void SYSM_Finalize( void ); + +extern void SYSM_PermitToBootSelectedTarget( void ); +extern void SYSM_LoadSYSMData( void ); +extern BOOL SYSM_BootNITRO( void ); +extern void SYSM_BootPictChat( void ); +extern void SYSM_BootDSDownloadPlay( void ); +extern void SYSM_BootMachineSetting( void ); + +extern BOOL SYSM_ReadBannerFile( BannerFile *banner ); +extern BOOL SYSM_IsTPReadable( void ); + +extern BOOL SYSM_CheckNinLogo( u16 *logo_cardp ); +extern void SYSM_LoadNintendoLogo2D( u16 *ninLogoDatap, u16 *dstp, u16 color, u32 *tempBuffp ); // tempBuffpɂ0x700byteKvłB +extern void SYSM_LoadNintendoLogo1D( u16 *ninLogoDatap, u16 *dstp, u16 color, u32 *tempBuffp ); // B + +extern void SYSM_SetBootFlag( u32 value ); +extern void SYSM_ClearBootFlag( u32 value ); + + +extern void SYSM_GoSleepMode( void ); +extern void PMm_SetBackLightBrightness( void ); + + +extern void NCD_ClearOwnerInfo( void ); // jbNl[EaEDȐF̃NA +extern BOOL SYSM_CheckRTCDate( RTCDate *datep ); +extern BOOL SYSM_CheckRTCTime( RTCTime *timep ); +extern s64 SYSM_CalcRtcOffsetAndSetDateTime( RTCDate *newDate, RTCTime *newTime ); +extern u32 SYSM_GetDayNum( u32 year, u32 month ); +extern BOOL SYSM_IsLeapYear100( u32 year ); + +// ȉ̊֐́ASYSM_MainR[ꂽɐl擾ł悤ɂȂ܂B + +// NITROJ[hĂ邩H +static inline BOOL SYSM_IsNITROCard( void ) +{ + return (SYSM_GetBootFlag() & BFLG_EXIST_NITRO_CARD) ? TRUE : FALSE; +} + +// pNITROJ[hĂ邩H +static inline BOOL SYSM_IsInspectNITROCard( void ) +{ + return ( (SYSM_IsNITROCard()) && (GetRomHeaderAddr()->inspectCard) ); +} + + +#ifdef __cplusplus +} +#endif + +#endif // __SYSM_LIB_H__ diff --git a/include/sysmenu/sysmenu_work.h b/include/sysmenu/sysmenu_work.h new file mode 100644 index 0000000..593f66a --- /dev/null +++ b/include/sysmenu/sysmenu_work.h @@ -0,0 +1,202 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL + File: sysmenu_work.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#ifndef __SYSMENU_WORK_H__ +#define __SYSMENU_WORK_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// compile switch --------------------------------- +#ifndef SDK_FINALROM + +//#define __SYSM_DEBUG + +#endif // SDK_FINALROM + +//#define __DEBUG_SECURITY_CODE // PassMẽZLeBR[hmFpXCb` + + +// define data ------------------------------------ +#define SYSMENU_VER 0x071029 // SystemMenuo[W + +#define PXI_FIFO_TAG_SYSM PXI_FIFO_TAG_USER_1 // SystemMenupFIFO^O + +#define PAD_PRODUCTION_NITRO_SHORTCUT ( PAD_BUTTON_A | PAD_BUTTON_B \ + | PAD_BUTTON_X | PAD_BUTTON_Y | PAD_BUTTON_R ) +#define PAD_PRODUCTION_AGB_SHORTCUT ( PAD_BUTTON_A | PAD_BUTTON_B \ + | PAD_BUTTON_X | PAD_BUTTON_Y | PAD_BUTTON_L ) + // ʎYHŎgpNITRONݒLZV[gJbgL[ + + + // bootFlag̒l +#define BFLG_EXIST_AGB_CARTRIDGE 0x00000001 +#define BFLG_EXIST_NITRO_CARD 0x00000002 +#define BFLG_ILLEGAL_NITRO_CARD 0x00000004 +#define BFLG_ILLEGAL_BMENU 0x00000008 +#define BFLG_BOOT_AGB 0x00000010 +#define BFLG_BOOT_NITRO 0x00000020 +#define BFLG_BOOT_BMENU 0x00000040 +#define BFLG_BOOT_PICT_CHAT 0x00000080 +#define BFLG_BOOT_WIRELESS_BOOT 0x00000100 +#define BFLG_LOAD_CARD_COMPLETED 0x00000200 +#define BFLG_LOAD_BMENU_COMPLETED 0x00000400 +#define BFLG_LOAD_SYSM_DATA_COMPLETED 0x00000800 +#define BFLG_REQ_UNCOMP_BMENU 0x00001000 +#define BFLG_REQ_UNCOMP_SYSM_DATA 0x00002000 +#define BFLG_ARM7_INIT_COMPLETED 0x00004000 +#define BFLG_READ_NCD_COMPLETED 0x00008000 +#define BFLG_SHORTCUT_CHECK_COMPLETED 0x00010000 +#define BFLG_HOT_START 0x00020000 +#define BFLG_BOOT_1SEG 0x00040000 +#define BFLG_PERMIT_TO_BOOT 0x08000000 +#define BFLG_SYSM_DATA_ENABLE 0x10000000 +#define BFLG_CARD_CHECKED 0x20000000 +#define BFLG_WM_INITIALIZED 0x40000000 +#define BFLG_BOOT_DECIDED 0x80000000 + +#define CLONE_BOOT_MODE 1 +#define OTHER_BOOT_MODE 2 + + // mainp_state̒l +typedef enum MainpState { + MAINP_STATE_INIT = 1, + MAINP_STATE_START, + MAINP_STATE_WAIT_BOOT_DECISION, + MAINP_STATE_WAIT_NITRO_GAME_LOAD, + MAINP_STATE_WAIT_READY_CHANGE_AGB, + MAINP_STATE_WAIT_BMENU_LOAD, + MAINP_STATE_WAIT_BOOT_REQ, + MAINP_STATE_WAIT_START_NITRO_GAME_REQ, + MAINP_STATE_BOOT_SELECTED_TARGET, + MAINP_STATE_BOOT_AGB_REQ +}MainpState; + + + // subp_state̒l +typedef enum SubpState { + SUBP_STATE_INIT = 1, + SUBP_STATE_STAY, + SUBP_STATE_CLEAR_MAIN_MEMORY, + SUBP_STATE_BOOT_NITRO_GAME_INIT, + SUBP_STATE_LOAD_NITRO_GAME, + SUBP_STATE_LOAD_BMENU, + SUBP_STATE_BOOT_NITRO_GAME, + SUBP_STATE_WAIT_START_BMENU_REQ, + SUBP_STATE_START_BMENU, + SUBP_STATE_BOOT_AGB, + SUBP_STATE_BOOT_AGB_ACK, + SUBP_STATE_BOOT_FAILED, + SUBP_STATE_MB_BOOT, + SUBP_STATE_TERMINATE_WM +}SubpState; + + + // SYSMi_SendMessageToARM7(int msg)ARM9ARM7ɒʒm郁bZ[W + // ARM7̃bZ[W܂ +typedef enum SYSMMsg { + MSG_INVALID = 0, // f[^B + + MSG_UNCOMP_SYSM_DATA, // ARM9SYSM_datakWJ悤vB + MSG_UNCOMP_BMENU, // ARM9bmenukWJ悤vB + + MSG_BOOT_TYPE_NITRO, // ARM7ɁuNITROQ[NvʒmB + MSG_BOOT_TYPE_AGB, // ARM7ɁuAGBNvʒmB +#ifndef __DS_CHAT_OFF + MSG_BOOT_TYPE_PICT_CHAT, // ARM7ɁuG`bgNvʒmB +#endif + MSG_BOOT_TYPE_WIRELESS_BOOT, // ARM7Ɂu}`u[gNvʒmB + MSG_BOOT_TYPE_BMENU, // ARM7Ɂuu[gj[NvʒmB + MSG_START_BMENU, // ARM7Ɂuu[gj[JnvʒmB + MSG_TERMINATE_WM // ARM7ɁuWMIvʒmB +}SYSMMsg; + + +//---------------------------------------------------------------------- +//@f[^^` +//---------------------------------------------------------------------- + +// bN +typedef struct LockVariable{ + OSLockWord lock; + vu32 value; +}LockVariable; + +// RTCt\ +typedef struct RtcDateTime { + RTCDate Date; + RTCTime Time; +}RtcDateTime; + +// SYSML[N\ +typedef struct SYSM_work{ + u32 card_arm7_ram_adr; // NITROJ[hARM7u[gR[hRAM[hAhX + int ncd_invalid; // NITROݒf[^tO + u32 ncd_rom_adr; // NITROݒf[^ROMAhX + u32 bm_arm7_ram_adr; // u[gj[ARM9RAMAhX + u32 bm_arm7_comp_adr; // u[gj[ARM7̈koCiRAMAhX + u16 sysm_data_crc16; + u16 bm_crc16; + u8 sysm_type; + u8 pmic_type; // fobK݂̂ŎgpB + u8 clone_boot_mode; + + + u8 rtcStatus; + u16 cardHeaderCrc16; + u16 rsv; + BOOL isOnDebugger; + BOOL enableCardNormalOnly; + u32 nCardID; // NORMALJ[hIDiLoadCardHeader() Ŏ擾j + + volatile MainpState mainp_state; // ARM9vOXe[g + volatile SubpState subp_state; // ARM7vOXe[g + LockVariable boot_flag; // u[gԃtOiSYSM_GetBootFlag(),SetBootFlag()ŃANZXs܂Bj + RtcDateTime rtc[2]; // RTCԃf[^([0]:N̒lA[1]:Q[u[gO̒lj +// u32 mb_flag; +// u32 mb_ggid; +}SYSM_work; + + +//---------------------------------------------------------------------- +//@SYSML[N̈̃AhXl +//---------------------------------------------------------------------- + +#define SYSM_GetResetParam() ( (ResetParam *)HW_RED_RESERVED ) + +#define GetSYSMWork() ( (SYSM_work *)( HW_RED_RESERVED + sizeof(ResetParam) ) ) + +//ESYSML[N̈̃AhXl܂B + +//---------------------------------------------------------------------- +//@bootFlag̃[h +//---------------------------------------------------------------------- +#define SYSM_GetBootFlag() ( *(vu32 *)&GetSYSMWork()->boot_flag.value ) + +//EbootFlagll܂B + + +#ifdef __cplusplus +} +#endif + +#endif // __SYSMENU_WORK_H__ + diff --git a/keys/dummy/rsa/private_gcd.der b/keys/dummy/rsa/private_gcd.der new file mode 100644 index 0000000000000000000000000000000000000000..91e7fe42ef394828046f918f0b20fdce4ccb3ca9 GIT binary patch literal 609 zcmV-n0-pUaf&yIv0RRGlfdKE=pK%j@IE3J3;#*^C@}4Q~9R>}bc`n`PS1VhFsoVrL zKQG}CGRP1!6yCrPfQAd^>$+7Mm5&sX6ZP_4>+$%1J$USr*XjpF2Ig1u-4)c4EFL(2 z`VuzeHF{ewHGij$6eCnU_HFb_!EGkua-FGFlNyRT8>d;YF!yD1>eT`R0RRC4fq-Vx zw}=9hS|^@9U zj5CVf6)>B3C~p5wXq{3c!cq>GY+AD%;6f`>)RmndJ{hj@XSP44CQIrdtc&)bS*aXU zznd}?t?Z0d&9i9$e|2cXtro}mzySh50RF-;eq;8UE+W&~!)Bvcc2E>py!Xjb4_*9C z(0^lGX%kNs=g($nq_~^Qgf)&YwuQ~JCs&EM?6VOZ$7?!+l>$Kk@dMMDGE0=V61OrK zD9ShT%`k6EIXm;W%Vd4P(_fzEoR&fjwwA3hif&}uewfGEG8TdQ-4nbD!WWk(RCW46 z0zm-K6q`zEsjW*3rBI}kJI(NH{sD0BPM(L?vr%_{&ozwfGRVf}sg#_3KCWe6xj$EttktnQ7@^TE#c=)hvFM zaGCqWv~w+^ykLYU4Bts{3wOQ$6uR8afYk&2>A?a(6OqYjlX3Ktfkm!`#yqN}sx??J vir`~Fi7|C3#Uy{)P?fl~V0S)6k{N|&pgBm?{EQ*_6ov?zM|F2W0`!6%71$z1 literal 0 HcmV?d00001 diff --git a/keys/dummy/rsa/private_nand.der b/keys/dummy/rsa/private_nand.der new file mode 100644 index 0000000000000000000000000000000000000000..771e3bf3e8d052e43601e6a02c5b33e6dfbf6fca GIT binary patch literal 607 zcmV-l0-*gcf&yCt0RRGlfdHj5&VEJ0`=e!bLnznEpLp$;4CC8jH%vOQwf|rygF|=g z6e}-U^O263q;|$@kiGq=F3DqrW&ylK!uYQ>u2SF!o$3lk(0zrd>m0)M)a!`)TcUjk zn3mts8{Pgyy(Z^L-;dE`3eIP-NHEUiOHfE>g6{oU$@|m2KcAd|5A6a20RRC4fq*(O ztF_aCLH}n64W?g>qU(rOLslrea4k$Hxx&Hj4ks*w;}T{cu!=<6G={9GgYy7!>Ob~0$h0i$gl0Uk*YDyZEF}3i7=l-< z8BvAy_+2S#Avx@c_?NjuDEJV;z)1o@0M%c=1(HgL_vm%P5B~(Oij(IY!cPBPvi}T$ zEmHa;2)-R3T;%P;PPRu0Zjq}@C+Vxuy>`i2@yNe&`&tV1M*=|r#x#CbZHeZ7Z(`Hk zpT}Dyx44J3orEl@*R8GyF?~PVOC!VmUi|nFN{oNRIFC<5QI_icmS%!LE>EH;Le6R#tg+pqd&RBF>()cENo%!`pY?! z8|Eu8GVn@iPl0*@;hci#22c_Znlk`ZD? literal 0 HcmV?d00001 diff --git a/keys/dummy/rsa/private_nor.der b/keys/dummy/rsa/private_nor.der new file mode 100644 index 0000000000000000000000000000000000000000..2f3aba7b3df8b583aadad4448c13864a922abf44 GIT binary patch literal 607 zcmV-l0-*gcf&yCt0RRGlfdII%=wwufXTYE3bn@{ziGxbymyLnC?Ms&=zIJRGY+`9Bkp zS42VT$@V`rMhdb$!mGvewFmVRj#$W{F6dh&Cf{x4QW54BH>E-JRP_P_0RRC4fq;57 z9kb<1gBUHe!XZur=skOUt=jMqBb#)x*JHdpm3gqwWN`DF*{%19#Kge%;`qvXK~m00 z18MsIw3hMq4gr;g4@ zpEEY1RV{zgr0hv~xP?~2$c~^ECouv+0OX#_o^rLh06Dq1K@j4oM^XcSLqxF4Ir`{E zx364S&m7Yw7tU{WenvMX?xRd#G4WsD@27LD@>>@bjwDmbMTwwyG9RkRoC9XB z0zf!!o)TGnQ_~}Cop-7vSf^?(B+kV6;^9a3=jGLKB1`S7acp@?1^m}7i;6-$4#?9! z44J%No?XPWpdZK@`g;OEF%Ii+Z@Utv0;ca=w85H|6TK*ei8Ql0XHG`WJ}33a|Fo#r zV8MG9smQeb-*=E8LfMBdg<3*DL>ZFr#2jL60zi3x%2p;4=T?d%Th)}YHgi4fjs0DO tESjqeeDFQcg@8TkNSca&yyDUQ7))uU9{w;BF+c-c#ZgY3^qhq7M3sUxD|7$= literal 0 HcmV?d00001 diff --git a/keys/dummy/rsa/pubkey_gcd.der b/keys/dummy/rsa/pubkey_gcd.der new file mode 100644 index 0000000000000000000000000000000000000000..b9cc07d19d108fb0ff105e7a125419a72ed8f80c GIT binary patch literal 162 zcmV;T0A2qufuAr91_>&LNQU^h?2QCgO6Psa2C2iaHyo QS+FqoWpnD)0s{d60Ul*VjsO4v literal 0 HcmV?d00001 diff --git a/keys/dummy/rsa/pubkey_nand.der b/keys/dummy/rsa/pubkey_nand.der new file mode 100644 index 0000000000000000000000000000000000000000..cbd2740d1d66cd79144b8c430856aa5697d6b512 GIT binary patch literal 162 zcmV;T0A2qufuAr91_>&LNQU(PRqFXR$~y&g4r_NN0lX{aMNT Q)4e~RoPiJR0s{d60WPpkQUCw| literal 0 HcmV?d00001 diff --git a/keys/dummy/rsa/pubkey_nor.der b/keys/dummy/rsa/pubkey_nor.der new file mode 100644 index 0000000000000000000000000000000000000000..3c3999eb6d2c7743ca16454fc75e1ba3417ed80f GIT binary patch literal 162 zcmV;T0A2qufuAr91_>&LNQU{KT`QW6OmU$LF&o&KQ%@QvOU79#q+fX^%IU*$e}LiTO}snZRJuC Q<`y@lLG)Dh0s{d60fXpBtN;K2 literal 0 HcmV?d00001 diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..79bb150 --- /dev/null +++ b/readme.txt @@ -0,0 +1,13 @@ +1.rhɕKvȂ +@NORt@[ANANDt@[ + ENitroSDK4.0ȍ~ + ETwlSDK +@VXej[ +@@ETwlSDK +@@ENitroSystem 070314({c[add-insTwlSDKΉpb`𓖂Ắj + + +2.‹ϐ̐ݒ +@TWLIPL_ROOT + ex.) TWLIPL_ROOT=c:/TwlIPL + diff --git a/setup b/setup new file mode 100644 index 0000000..55e7ae2 --- /dev/null +++ b/setup @@ -0,0 +1,8 @@ +#!/usr/bin/bash + +#---------------------------------------------------------------- +# This script is not for execute directly. +# Please use 'source ./setup'. +#---------------------------------------------------------------- + +export TWLIPL_ROOT=`cygpath -m $PWD` diff --git a/tools/.DS_Store b/tools/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ddddbdafa22f4f12425e0b89bc9463ea4accc090 GIT binary patch literal 6148 zcmeHKOK!qI47DLrsk&j=?HmjFT5Bj){nuubTzYoQP&n!O1O_5fQ)WKqh7pC(9X&)l*$H$vPcGyWux7AkS_} z1?^~GZoAL#xc&B2b)FYxUBDvo$Ip+qhpu;X#oN4ePkl!k-B3*pJ=2~J_?5l7*?J`6 zLjALIs(SP~&Z2tPqt&FMi!ELs*dwR3MY<= zzB&WWK%W7d(dW|tA1}}U{UrbA3^)USiUH2@RldY6S#KTOob=iNT|-4Au2npxV3S%g eVx<+|LzBQBWCM(bts*QC{}4zt_~H!wC<9-X21TF% literal 0 HcmV?d00001 diff --git a/tools/bin/TXLib.dll b/tools/bin/TXLib.dll new file mode 100644 index 0000000000000000000000000000000000000000..7e1dc0bd904049625e8943420df26ca4ce5625ab GIT binary patch literal 90112 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�OA{~@e0i0LA5eRmnU$Q7^(l%B(o2t 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

T;QxXoK8V@!j7 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 C)wc=& literal 0 HcmV?d00001 diff --git a/tools/openssl/openssl.exe b/tools/openssl/openssl.exe new file mode 100644 index 0000000000000000000000000000000000000000..8967c31685635cce6f45ecac0dae00f79faff51c GIT binary patch literal 286720 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 z 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 literal 0 HcmV?d00001

PXG`h-HiOQa)UTY}ubk4aG=;ILZ`G#vD`)mAXZ0(u z&YnW)S2FsQ%zmZqwSJ{tztX;6>Cmrq^yybRb*a@-4EmLG;YIWMl~(;qmwx5Ke&v-! zN+CsuqS>mZ)vwf<(XX7)uhi>T>h~)<5f77orCGl+()KRJ5?(f~UkT4s`<2cWwi*3O z8hyc_1-oC_NO4=TQ_W+O+9G&E`Vu&CX}@w=zfz-Lxwv0RS>CSJ+0G2=vYiqDcoS9vE|?M!$DSD! z$DR^!1dd18Fwg^M^uQUP;rQ7W29Cos$Ki}m@E)J=dl=DY1{u+(1f;+dDflJd;M8yM z5*{3R_$9yL!EYGIfHN}i8QJh48{T6z99QFkud10rUsY2A!r@F^9=z!c`plpi@TQ%} z%%DyL&d`EWwcsVXaD?ceDFGMZ!9^G#!;y>!4B&wQ3`~UML_AOl4=Q0G65ce@5#IDJ z1%BC-DFONLL_R*F76$IZKpQeMs11RELU^VSUa|p>8}Jz=@Sp?+XmF(AfkJpmA-tp< z2Fme(1w62TGxU&|L3;T2V>%2>hXETn+Tb%B;DG}S%z@(^Jg@*BEPw$P99ek49Ui#D zz+yNq#skaX!7>=|hNCwgsDcMoFi;D}T09U84}xJJ431%VfJTQ;NS_k$347ijY9da+67RRP2Vt_IR9AQ7D#OjcD>yUeFDaYWn<2vNewv-b(_! z4*7@<`4hZbst!3#hipWrY=+ae=#Zh?j^q!s&`9M#N!B4B)gh1A6;f=<*}rWmB6wDZ zoDJ`tsYA}vA+Kgr(&0rJI^-F2N{$XW_l6Exi%q%zhxuT>d80#q3op%QQ-dL$+X3UctwCtwUzADR*?p z%y$UW0X}s*!t6kpbJ&!w+X%B8VJ?8iLJ0Gd4Z>W;rt~4qeuP;Cr`<)E zQiK`IrZlbk!)y+5r+h}3Ul3*%jZP7?Gb7uX&*0-!AbJ068wkx*MLosjtkcI1Y6e9c41&0*Z`BA?dBkQfPThu zE^jq19X@iLmCb%dQ!8dZXI_>trBJ!w%xx`g+l**txH>a>Ep0o=QH?t#i#{P70e)>w z?Y6XaAd9ZFW!QGX{~n;W4yjggwD7&WkKx*??eTWXiM%@)PWgpI;0^|^I`@t?PLqia z0>HhUBe1v;Gm&?n`<|C(dE^}TKG$mKtYJVG+pUR?jRKNkaTCL(JXEoe^2@^ClTW(` zFw}GTsIEo-TlA#+hb)fW5R+Ns} zCWhvlkNkqIf-_m>f0=d^HKwn&N_oV&m8G1Martxr1)1i6Sk#8Tq9KNqB)fBW17bXA zIV(!SFh>C>ko+8tHAsofgi zj{PRRaHl=4bA9q5aA!=s9*BxJ|*aPcb-P?s=K&U1%I`K~RPGvQ47xD5S zM^Xf|waG3X?LWe9@v2d;<-4G zx;KcY_0fNLUzM$b8Xq5nnV(0A>nY1h0j7X=ekJ1+f(Y9AOqsf?d$#CQ$;~QEPDX z#PQPWH!};QZlBx`jtNT$c{(^vr_+o&YXub>*QMtdvQMIx@8B0gIwQFuc_6{bcHo;t zLkb=0r3<7#r3XefOUdW@!x-nKM=bsJ?WvQlnhx$UzDd_ICf4KTMfY_5LVkyEl2;Z( z<*w_km=UzNz%z5A?(n&~^6Bfoe>8s(`;V=~dCJ43zWVaDHLiWGGRnb0x6e+9jH2m# zCVtSBKp5vqJQE-JngW@FA7zX9KtBeGCBFp4N~^F5z!U&^AW+VzLCM^~b;p)2RZTywi*QU9PRC>%J&O=VC*K7t4 zxo5waF-HSk8@7W1yR@EbkW&V^vrMush89ct>rCoo6wt4~X!|hrxe2w-gVO31G5607 zzpf9s8t>unrYzR07dA#Zw2h-p_=@G3HB!mEI{+9Ti6X?rya>J*Gfo%Bi>7)1-KmyK zjF}EquyiPwk9Jbd2i1>riL6ZBSM7e@>`}_gO{II8vXs4iTsNoxQOf&w&2lQA&N~0$|n7({vMLMi)XVQgsk?TB29zUKHo-DNkYj zC7ikqEmUlaE)`#Fee1EkZrCKN((;t;RoE$oq}?&>2u2NcXh>fQ6{q@2ng&Xxx8}cf z(`XuJIpqtz85dRlaOwQu(nnx8cY@o}M{iyCGk`qu8C0xT4S0txDx~6=QuYij@oE2Hwv7mUX)i; z1)^?hj98mt!T{AGl+i6($Iuqz{7*+dxX)lIaG#8&3S%^%b4v7PIa(l&axzO@l0#fU5@jbj z#u%{13Pi6sJ)EB$L%~!&lMh_^7%2iGCKgf`QLWd%$G{WbHEI`sn6D*BrP_r3#(+n- zC4(=(HA-o697F+Nhf2`SIKZ%$TMC_p-3$N)MNpwIRk-;C?ln8p_U^yCZF=^u1RMWE zZp6T>qi2HBmBMlZ2#na5l8;tv29Gc)xe&@-K@VRZIV0TqVPBlxLzu9*3$#kG4T3j=RxGRJM@MQ5hyb;+n6}XD zrC?0zYRWDxPAg;!>^_$q5H>Wwak>mFkuPhAc3+yR!!?&UN)}1Lm@?&d*W2v9oD-Z_ zA#HS};<)(7wt8Cdb=GLhFXW&2oMInv()LDg_&W`&V5z0c7L(|ob!+&EpFsGl>QBdc zE!|09Pke+PQNKZzxIlhK&Xs6MCQEX#V(dsA7AlFp4u$)h98)EVNoYjtd?|)C*)EG} zvIV%Xm4o7_@a+-7tL?CR08D2W*3Y#mtRHuxXF|j)Xe4DYHCg6td6DXo&P$$rFaiVn zs2-wb&B;k$zQWSjEOHT8$5yDwmB)ROFSLmb zp|8v}oh7b5=>W8N!+ zV`^cM+mGqCi+w)0zR%=f@q5RpGJ5zsr#be$C~}=pOeE?S4XP00QCH+>$|CE9gvhVF zKv1{{$Mn@!L9mM*`x?wQ3pq6$GuOx)$e`*2+nwmI;1CIXgSB^4DI%7 z`ofEsx^8|+pUZ9F9~K*f$EdwtVmn;m>lBbW#bCw zmZ(>nAAA@lJ;i`;Io+au6-Nw&xEEWTv*t^}T%<}}w`gxUxkwvmOHJ;CN6kgNiq0dg zf<;o0H~*nESz)FaWOyoc&`k=heIM5k7vwdQMtohm4iyvt|HCiUHym5{Vufh(pRPkE z72uAgi->cyT>3=XCM6{3B(<%pBg&vx#>Bdpn@*IzXVO?_PDGI-k2eFY&4CXas@K(x zu}juG)be#~b=ck*%np@DtzBn&2~5e&c}TU*7@U78pho(TnyQvD7`Rx_InDtlM`GXG|?AL7kv~h6Rj12NKu0592BBcCp{6h ziSA-?qbzXom{q`*)I{oN&9#$>``*Q!7fZy|;udkY_`6tJLZlT#6U0oTh#JQ{lbx@M zjl7Uzif^9L&R0!FND~G8SG=M^@>KFp!cqW4sxP&aI!nEz8%Wn=LMcd<=1D&?TpOFH zeWl*0nhY30aSCU2S#2gYyzVI~lz~)Pp6oUZ6vG*woS!n#CjTl23f%oJLLMte_(06j zR#eHG>*{@8199zz43h*E3IWk7c%YgRhhh1>@US z3Y~)MC0Jo#OjznNBMwW$^0DW$suq#nV1sJoghbMynx7RF*GPP8P8tye3qc@>DBQ0V z&q!x%Sp6_WVEFqfDLi{rN_PW&qC)Ff40+M99S!=_jrw{s4Si#&Gxc0kOrAJ*)Xea` zLFjoz+1pY8=^=hL->w&Y)w{=k&iC8!m9n$AjWrzS<38iOX$7;9&ec&6Azyi);=C~zVhU7-{cB+tciF<3@gOTrx&n@Nu(TrAWP zV5DTpS;bkze)Ollc+jYDA|oPwzj| zzkl3krH6r%54;}GXd9um3UNFq!&?7uoyADh3niv}EOz0QBA<}~36izNDxPSKR zlV&dRNY1|@@6uauDtIh8X7&q1ryiuSSc(H!alpU3KB272Z!f!?%+v?x@4fjG`%ujg*9r>2exob_1c>dd zxHrpt>RLqCS_YL3g{p(}gH=CpWy5XCmGFJ_7W^IbL4NRAI@{ETXzB`m6RbIxD4@q# zn(v56Z{DHORX>)nDun1pAf&&9zdt|R+YM!ODSTxC5G+(dLqT@UBrX5 zD_ZSeR5W#Vt$==N*5QfEsRPINe?ZG)9=HhTz=hJQBGC&~-qA+y++)PExEKD6u&W;- z-X}DssdWe{P|sz=4;5(PHz=TbIw?B|sBex>Z{3wdXqgZK)UO}v5z$`9(YL8UbG6gU z+bQsqz@Pd`g$+YP58PmFvu=vR&g8 z`S&vvS)M<{=od+0%pr7i)f@&_xUHZkQxan?NqnSVAUSaTlu;{~(#>3Z{Zw#j#c8I0 zo;WNMq=_f}vyaYgS}a^8+#>8V)qXB4IhxjZyo6--#BytMe97T#qH2(wd+7H1xQ5kj zGPB{2kjYM?MT7m}UvBTfl{P$?f2tNTwb#?5HZUK!Kx+0jrtd7~vVk9kIj+n_wmyIZ zzAp!F&Q(=0w+s2>{i>Ol&s9k(t3boUCv*{N`0|NmA&LvE0Nh;kHOE;TA;+}`9mf+i z?3=-r2l7P*8ji2Ts`p@~+~CWT2{saFbo9?XFIp;aFPYMj-QbPgPw~XGhw`LDNj5 ziNnN+s-=Td)y%A%h7l*##z7%_yuRNsIN+)`SUjYw{t#>Z(Ir^=KCs#E1!loAmie^R z4q3{d4?TGu0O9OCxV^_rs{;@pqYo6TYz;!e@$6Sfs;0i4Oh zXCw$Sq8*AXx(gYghVhc|(fVBJsoNbe7jo%&f{9Nhrf_*<7M(RrO z-B~pggWI$H9IzB6zNV%v_*{4Xxtivk8azjH z*8V0-H`NiXYYcgw%A^ZWBA-=;LTjY(GXr-fmsP7*S zP#Jh7BI9;saH^(l+wqHz>)~4Ckb+}!UUM0tgvh7foiz(XviT89H~Byr_|hUxTLiLe zLrZQSTgM1R90iL6v^Jl$f=I#8hr2_%yrLqtfKlXNMx!yr2R9HG2 zW)xk9OHq?|aO$2|Z=5G-tM4)r%P^i|R&Y}5)ovPyn37A=i(l&c& zk=vt(3v}%db#9oo^hLpoe5nrnoJxy;LyEdLm0@$u6>_>Yr4cny6kFQErSjKQZB+X!L1A-BbAX~1G=hj%A~UOoK9IH zM^k>;Gi_C==MA~bJNe^pf@dkgbF?CCPc|&Nzq(y&dC3>-{@BpfRv?mxKVDRp_t>@$ zl-8|p6g+w@>wT8bz|#=$QS_PdmysyXlwX#6q5<>4)`LFF_s?Bi8X`7v`>mQE57bCJ zj*)C0X|TllF78$s{;WvUNS0(6f)&^;AMrQFaEWb3pZVjfv&s2;6TP3l?r$RRUTS%id#nzF&ZDFJ3ci^sv@~FZ z%^1nhDh%0abzgwQFg^$pLUVG#@ePls=?g7)$;};wi-dtYX<~ZBfzqbELY=Gi=Xg^M zCtTYFAz%s2ySo$Yp9%ZMk&}MZoBz&(&O`iB4O`Viq;rwM)S4Gg(!7aQvRF&=*Qh-lmyyHo-= z=j4>C2lPp^9*6UsNnWHN($?|T)gUqFXUV19`xA0W<)kMhO=_3?gTes)Mf#xL{%LR# zq(DEca^1XglEcWN_$d{ucd`?x8Psc3N}iMSEM&;OHE1SJr{WS~>J8-Z&3Z3f!`8_+ zugAeJCbLi*M)X2!TAp6-hLX2iJ_G~Pi~ZqSt#ncc*_Y{AJC8wxX{NA{QDc_CeQNz_ z*Z;+?Iq0N1EKJ~fp-*(KzSE5Ha|?@griPO6V&ajxxrt}cj}ENgbwlW9(HPc}n7~!r z+2WLiBycxy_Hd4KF023v++t20=id1QZa?P_hs1BE^X>T_t1jjE2dn_&z!smd)Q$WC z15UwF{yF|Feq0s5nLk#Tn=G)OY?H4v`26k4PZBd?i$$qt+!E?)>NYB_wwg~JUoAM` zW-->9>Io)4HF{_Cq0+jLrlg)NGBvX$nA?~#I70BG;l8hxwrNvoxD^ms%*iV-Pk0o1 zU5LcX(q+@OM=rfMUG3$gDjBgw*4+ptCJ#@F12mDH$YO3oj>Ez~)f+{7lfkz#g<&ju z6s;89LaWebG_DJ66L~0rco&h^GzEH>gV{@6!&3d+PJTq-AHvCxC4>O+ChM8q__m!9Ez44l4MJ+Nh&3cl6FblfJ9AdKiM^$ z^vO}WXFO~2l$sxFrGUx$?)itDT9_iuz4t`mZca}Pr;`t}SOyOb|3s9kUmxFFs3tRN zSQ>4$ofy;79^4djlI9rWv%imO+NMCEmBj%n%hLFre$u4a$J%KxFVp`qdMP9t3LFay{$_Nyqu- z+V*liL|#d1B(;+UNNQAuI$-|wy8WL*(=L|hp5W@ubXJMKwP!D{#80s!T(-*8N?5;# zdYrn4H*NtdVz=j9`DmAFV=&CnaTF3|^`ZBaG zWDsRt`G%f4yQ?#`ayH6Bfe#vn?nDoFSy!jqcOUw&9bD?{K2(O{3QozVt*d{dU;-!l zymj?|YuWoaY9~1tIYz~t!aG_8P+ye;esRY0seD_$8=uEt&)?10!Y$Yr7xxImdL**7 zI%TE%f@}W3y_3VKQ&Xx|-!M!y6XZ%=1;+MeP*4&l!dAWPjg~{PBR!U*l=Vif&)22& z%m4L={@WA6N*qnCIk4$e8Wa{;J3jU?S*>cp&P|U_2@%}Rs_`LZ?%(>#M^|LTd$LO5 z>g`%uIpMpWZg|0aM)HtCiy;4ioGA(aJe02Is`MUt+Vk zOFS$dDdH6Y@{RQB;o{{vI;ylB9jtj!%k@`mX;8r?kCCvVH6>YBr^l5p`*AlXv-rwh z{-^z~ocu`ih)BY)lo(QxOODmp(6R;D`BJ+7RX%C*cpxwM&O1^>6c}#u@4lOpQlSjW zc~Nk&!q5>{Zj~++Yr@hoVc-LXvfRR+8}HZP{EM=>%XsekPe1W648=Ewe!s5Me;9Tk zvBig;UvXJm+KKNBJ%1oOTC~=X2)(w2Oy9p~Pg`Gs!{Do&4_-?*P8x?{zC*toB@xs~M5$ z_D|&+<8>?JhAyu0Ty8kBZe>ux5?-V{uk#?EeF9}YAPf+=eqbZlzxyI@z2m?9>mTV` z3;AGI*%IDUo8y5KxjO_)$dLCtg|~#i_8MJvqzIsTs0Er&#Kth@Oj z$0GJJIHH=D{2=cuhsLjxJl@=|zq~@P^h%{lQh3sn?Z)zy{zLk#6DvJ>@7#UCRf}Kr z)WB-E%hOQf6XIDkdaq%_LQfCrox`jpZaw!C%?PNcJMCej8F5z@O_mn_#Q!|%JL;aX zC1p*P@b1`37W|l;QhK(Ubg4;(OpwqdWe>>{xxIBEmzGP2!IJH_7RdoFMG(U{Y>`rQ z=KVyjL{6xFyP_h=%l(~PAx9M6iX$eB=x#%Grq_OR+(89j{9Z%xbzLJQ=z<}+1gCl52r%X*D(59-t>}9cD3znh=4`B-M3G*`W}|*o@(Zp5vdhr&cjXv zbImBa6Ob##ykTSlGIwT40Wxdyk5et7jE<{Z_ZLMZOLCj^YoSK!_1vhUeB4z>&0jvj z>hzvB8mShF=u}??I5F2+?NsX=^*?PKQV7Wgi7P4SvTc0LCZC>=Lt5NES+{ z;&x-PwRpaGxtO1E=6M7OT7epG6$`V=52lKhdE!#>WAR%t3oe$Qpis{*)|xB`0U<%> zI%D2|p;WE$U=}(x1@ACo1@OO;IXol5|SIP~LVGcB?JQKx$P% zUh8&86XxS>!M+u3>%yhGq*_z3vt>IRk?l@~`jy4@JE5mvJq9(}8vY=-MQzRgxIc)O zY|IuQRkp{@1f)9bMIDYnokaA{F1PMR6ttrQs2azJGo2I8Ih5L&sDGsrwu@JI?#@W$ zWOCZa#PQy7KBmKTk^`Ym2EREI0)i*=+wtK;ICU5;d>cgsyZM{*$tfIaW2uJ=g#qOgnh!_ z!r%!anyASvv%4ss0PdC%1Ho2%Q$ti_{4zkaOb*J?|JQBtr--b3)}+o%9J!d~tM4fe z5VP>C^rZMfX}7AnuZ`$XUwz7~d*YV{{MGu`_@8mPF$pvNG^WH?Fmy^DqS@>enQO8Up8GybvDP6+7P z=cAdi(wMIGlsD7!7KY5=Ea3F{ey@iAzu$8shq#aPRe}pK0c+BH(!q7c@GJRVy@dq7 zk`=m{OP&fYjc(f7NF}}ZfF*(%AxM=!0aW>$Qyn4T0Dg#cobv`aTLC?XT1>5@zNYq4 zHO-Kzb3{uH*FxlhGb2tE!~kPefjmYjV}LOz?`IGa%j2}sF$WVax?k~E)OYA1ZY)h8 zB+rR_CccbTpxuh^3T^B|VOE7_=(4!-{Dz`=Z#h$xoi8pewX z+_D&Agy<@6!3J*EhJ5{zajKpJ{^5M){N*evu~`{VZWs^I61$}hJ2Rx0q+_(WuVtV% z1n6J7l$T}z|Ng}P!3R15zlPe7Sprnxc)vCzT)_ITuQqPcPDL1C*6W6%Zox092g5`- zONa_-xZ>xi;OE{)U5pGF;`Cf77pjCrk)dcE3O}J6(DCqC-Os!pLIz6SEZQ%^r9~7d z;~O?%w3PlEP5A5b!{z(rrT~v`uL8tK+#nRw+2yuR6`ASz(M~}G9*R4h|Mt%)zIvAd zJ-}CUilpXQcJx|)B!7eC#U7|Q{7t=~6sa#m5JK`W{PSEQm#8FxlNyQu-q4vizM*KT zbd6LXjhCvWOJCfkJ(229JAw2`r6e#xMw8je+-3f<4YED5<1)R|dn<3s0;mh|AIxD{ z%9uHQZMDU}t!+*2`ex&k(X(@yc=nbd|8_}U{?78>*4?o7=k~hakha@t#fz6Obm<;+ z0^c<iao~OVrF3{5Zr{NZF$@YWK6*?jI@)KL7)>7SmV-2 zn)+OBGt$Psu8M18zo#5nqaVcM&Zij1Y;rXUm{MrmKK@Ethi<0B#G*sYMaP^p1oQ~A z&|zDtgfdTWMg#!I*(>}$9JZAnbMhBFTZ1hGE?_AW5VV5NdgM()<`f#2Ex%4_ob=JK zt@NKsBVSD&*|pVuxDkRJPpADl5-3n9{+`_C)m_fAIPB9XqT5^qluki8DuA%BH``DOs}w?aPki6(t-&L@VZ)vrP=OXEHga zK9fahT<)pCs6##T^a5?$)m{CPhy(&K^^3DVfId_FI{nb`2G6E|V6snPwo7XlcE}{g zCT7Kkp(KmN=7-#HqiP0jd2}xkDX8tzze?B@Y+`VD&*IgG-0T{^+Cg8!W8(8!2%)Sf z9<69`{eYeT?YTv93IVNNY{V048bpGKtlyjt-8GKTFT+2LoyLCklTEp{VxpImFN=oG zz^<4d{HAe%9@|0u$tsNh$=VFx05N|*l7mADK!XL*w`p0PdDSSf{eq{7VRo2DSm!vH z-ZSw0zR3e^Th8SoVOPF=q?|yC4H_qfpVH?yU2vF~9a39;^Yb1H`67cYnzK5UT0pjqeSwQ-D`g zKF^*Sn6w-M0_GURQrp+mTf{^@HZiQK^UqvGBKnvp&2~jTZdbqAsMLceZtwyPozB?| zW4TA6#U_03lHhw+ZKJ`?>S-Q<&P>>u$VDZX)qH=!a6CA9U|B^=agGZMWN}o=+%=TUNiAGS_=;S>a)K?tYIWBR^Ti zWCM?nFrzQ~TiCvgiQr%)Y!nm?`_~E_#90XY*RwFFratPFj4?HRjzg#9;~0N4Y->Zj z(J!BsZSAfR5Mhq-S20&Y^W@e+W=>&yb@w*dy2Q@xU&d7U{)xjjG0Px=U;`5qFuk*q z;hv$@T|>FPyxmtr=@1~+^4rYRy{mZEeiLJM!Vc&?X8$kdcnxK2%7xHeEG~^X>nN9b zOv+q}gADwBzJUlg{NGe7-Z zp&Y*=I$X^PSJq&}GbP_kuYzxAp_`nVyZ1C${m5K_%ayk>8=4VOJmEcX+=?q_@sA za6Y4Q#m4=v9uf8%R!=Kv*FdDxP)h7}JNjnNXuPgjtb62??#d*!9d3bKvnvLHs~h#5 zDDGUaGcbaBJL#37*8Rq!M}{*(pb4Yym-m#kKy}$nnTw1gTasCFx5c&jO#Pnc`zn$TsR!{w^f4X<#jF1P6Z1x8^xZqIi zIEgFgsd6?j=JS`Y2AdP?7uhe~oZ#X*d$}R6GA4LS(4y%{{8Rj|C_=pNORx|i*K#Lu zuN8b+oBjYI%P;!ta_;fO0vr9Um-E>hgz1WTeLFU$P@`56;-fdF*hE!sKbdnf z=UVPIuH+MmvUS)wQlD-Q7Uh?gN!AX8%=!;d*an^ z=NCI}d=U(-1~91LJ8CuX)kg`zGBthMn8(n~h;Cq<|%<^QcD*mZb6xn~OG5 zW2oRT^)&T5^*&Wb?V#drb|d=*)(rKQQ4gF>vGD`>Dn?FLuvIz<;yoJnF}8|Z#kUzC zR{Uyua}m^!nX$*iMm!b$$#gWlojcs^~;s<>dOlpYk=*OTiVJsXQJ1wWUT%kG}CTnjEdzhI5XmFh2L z;-?WZv9ZLIArb>NqgcF^zYB+MF~&`2v ze+fMm!&@=1Zc#y4YNxjtU4?Ez51=^ios3(zzd`$KP0)y5s~$5w4L7U15t>ejrmcnB zNb7jy`zr+b9p%dL<3w;kEaxca9Oo8CkA&lFhB-isKVMc!^_O|dL;2DCc^r_v))FlW z&*!xAKk+vUj&VS)UoXQcoXW?=p95qXd|(=;31^()KNXCLAw#?v4&(I_@&tqYSMpRL z$P=y-tQYJSe3JixGFbW|DA*mQy+VCyQoF$|%k1923aD`}5cR+{mT=;br5)+&;iRZw z+k2u7q^don%FIRaw=A!O-LjN2WAby_`z7rq%-G`gxG}cr69UQdp(Paxo3d~xZ&+bo z%3@JFC(W~5N?ZOa&HODo-$Kbck=XD|^8UKD?=wcn2iGpMdGq|c4q0?2Aok1W`4h5; zgjB>Hs7Y~+o|}wCXdt>7ooNZOP9};9#FvwM)Sht}A^8G;i}a5ZOcBf$q!Sd#ITE-< z`hhl+x=6#MwMH$OJIgH0sHKMTY=@p3DSi`)Q4=*Qs?IN^NiB=g?>d!R0AA(+>if%8 zSyS%BIL-exSo| zEotu6(meS#InUVbU$COwQxWjxL{tg)7v;ph7<*9MeNFhWU-LD)I>zz%_y;+0w#bfr zYFhCvQ~52)&NRdz+WeV>x94ERY2&57-zDRcMhZ>zrH~Gh^d?G>2LfvLND_36lRTql zzFnLA)Z!P*+`&>)4HnbVX_Vbbr72aF--`a!tdVY*0YRu@6~RU0-#GSc)?Z_>iWuV* zpAsD7$_!Q$67S{=osS;rvzdig&!29)GapzwSlV0SVv^#4NHf)g9M4F(CJsDxg^CyU z@rY)VJ&{<#Wy1|HL2t5Mt*-uC0wO1=CcGsOB59sc>}p$zkI_OZkxNxgm`6LmG6qNZ z?*I?YKP*ipEEdl>6-j{2^kp41Gw6B|k3ifWKVG`I>^h6|msi~)f&gW%XwQnbHNcD_~79UEnJ(~IZ;pHd!nekm$OXRU)_W;G<`mkF5dHD(P7`cRxx3RSV+X=&3IiA0#9F@m_jAK#Cw&z!pCeyb)}{en;%S@H-p( z6MoVBQ~liSO(N>6vPrcekt-fH z1dmT5%qPUSdqb`BG|eQE+9^_&_qd3-rl<#Q%~kJw|29|sXAy!v&tr9BFUl)G&?C@O zb@d1YJvCa|zBk0!R}_Qn*Kf6ihO~-T>#5W9@5@nYq<@IeP)+CKcR6vK0{0Cpq}EVb zql=u8e~3Cm8u;Kn5AqTn7@mv(29RpjJK2Kqt6ed#LYu733=&^tPEQ4=&5sRVZoUcs zu4J6yw?it0H9eJp8laQM(^Kc6`$ZQ;q8w2Int@(&UQxu{7`Nq!Mh;7jb=tEuNLwC~ z@nKzgfd9&SLo-sQ0lQ0z4^fqS{mX~wNnKKhTU_;f6jl}zx30X(7Tj*CM8~<`Zpx## zN^tK_Fe;`Xg(|+%e*~We$x;?sXtuZ1lg-fg2%1f6^#dtF=Im1p$LDhx6f=L1{p_kx zPV^Fj?SSJ|cO58!FWkoON*HYia9hkQVeG1N`llKw1P6MDv}G7 z(saqtVlA^9`(2JmlorZ;{Eas&Y(T`yAwkpm7mNUtAszfV{%dD7PWOVfuF0Fc%fGD<1`AuJWa>=c``X#&x09=gZof8R z@X@Zvu|VbUVCT)wJW;T$2okM*OO3+R_*YxJx5YeD*8L}leBsT=n zIaYuWIAsV?r1H9b3c+pSzM$9wa7U%*0da9k4)@`QB9AQ+a6sZMrg;A5&~Dx2YY5!< z{*vLM;fz_7YAy%#6(8_z)#=*cy=ZKY69<$I0$ZO8l1*HktBbLk)1=SEMC6d_Vt zV&$fTTZ08GSQ!>%ZDe)q0>acCrNQnaO-FA>mjwFs85y_Oc|*KKn?`LFTyngfC5XBK?dnP2h!UKNW&i#Cjgb zkV`{fzV%Jn^=Ve*OMhh{v$~(z>92gg1p12YLQk~f{F?x!&2B2b^pE>#wKVlUr(L#$ zbAEkhp2XW3t~$c8?m9ipGO6Nu=JJ0F5{SJQj}aRzPNEm*I~quj-nOv0eK(wl5I$&h z5MXUsdQ5s=N|xNwE2x&XRGb?Zd#4~{0{B0)y?0PkQP;-1PeKO`p^M5PR2wFt3ATi4 zg%Fxx3tdDdwAeL(f~aVyiZw()1=LXO8bA=Rg(6@NMLQ|&fIYZ zn1kpLIP0vv*7N+H1VR#8pu9V)sJSvQQJN(Mm!+R1za?r?;|y-P>`4Mt#X)@dfa5z~ zF4wkmE#qtG7f2>PHY`XZtnBLQpR1NTyCqFz`u&=svyJw2A$Vw>tMk|VnCWzzs)aeW z6dG_`ib^}tVYFn*iuH~LzS97sTG~4B;s=rRRXW+DCeY4+mTw|SQkoOpF9PEtHhH#q ztzVH&vv@NcOQ=`X70vRLgh=pr!oDaITfr4perrXeNr-@Uh~>_bTLg?ZEVP?ssqfe_ zG#d%VG_&GoBk|Y;wv6RCR6k?4doghM6yWSSD6op^jQ>0MzX`A8ZL|L|QlOOgDjJYa zfF;lP3E^iAexY7Fc(!x4h8(Jc&OsNWG6NTgLL*sO=w9w^^a(1{5&%HfAj>T6E6MB0 zCftK$kVd{l_NP52zaoDj%V5R8kamscOiSm7)ArKN^DojMPrrutk4dJ&n8hd;f;wS` zFody_k+MoLI)_oj0B0X4MmI6K89x{btk|50&A^()V2{>4;}Y8F;<+8vN?^QsAInTU zbn87!$~r67gy}2dMKEA$!;ZmdHv2)yU^F-%eYR96I4de*-`|qaW}FUOv&no1ey8YP zV8pgdN@kKW{?`24dy=fBecA5cks|pY^M%IWk4Z<{jHL~4;{SxooGoVemAjU6J-Bpi zN^E`4kggst_4$}uRoT;$aV3W<-&MFt$eoB;TfYyt{xM$J^4ewb7&0Lc=Jkwq595C0 zRR71fkfj~Nmz`n|GIj|ii|=E1z3F7o>UASQxof(}P-H3k%A4c? zb$*fX5ILK?L?qMt{3HX}m>?*X6#_GQ2BjLKT!A%SNSTWVDxNLtt1X7S-dT(sl)%NVa@Se6T*6lSKY^#@ z(`5eMJOX8MdMZWz&34RICOLy_M(*x^I_#NqelPRtn`!Q$2Zy$7+0=F>l7fehf7}$= zIDj*uvdcs6Bb-tyKIhm|0yqF1^v1_8Orp>yjT{pclKeP+$Ky3}n7WRMdp$Xxc$Ijj z!UHelm}ipb3-5l1JNVk+R4SzGI3~y~)=v*09flzf171&K^v68q|9Z-Elsgr+%6E-k z(EGIBWE0%ZdHk89wRMk=Y$s0hBtb2#$+rzd>kx%u-?-qm7%n?KLU+qmb}qAu6Xai0 z&wd>`*D*2bc3fpeiK+~l3;6HJ_b?c&gMpWlA?(CC9#`#uIA#Q=k*{sF={cI z-X-`e*S)^_&adExm+Q&fjgR!?Z1lxj&N^2gts8%hro)?)j1=H35ZbXMN6={jq=-Wq zExp50&M3ol^g-amm-L+;4R4ftCK%(AbvWeMh=%Uxc}-Hp8~4{!J3}E9I8(01IDVES zE!+HyXN}kf>u0J82tKz|JVIhSSKl~dj@!S)$?NsvO-ZvxJURXgbGzz_&e{0n`9x`Uc6Bo z+?MP_Qw(M0 zKTBo8GBcVTZ4(A3RSDQsB8k0!x@_1`m3n4p_E($pp5u#D-BbY0diS&t6x-s|kPbHS zi?bTiUnCslr|~cGEBN3s{}rDgfe|!NCDF;NyWZ(7^bFaJa^YL=f0L@$d|?>+0&Rn* z5On;iEY-K^uN$#6X@zLgJ-qDS315BN?Q!jij&aRKo~StX?P${-?!EHn*oHn_Lm%E6 z_>O7X-Y?55Elm=N;G<0h{2x_n!>F0YF0nJ&m#iz1n=6sdZj6_1mTc6sZmXLG@Ch;0M0SOPa%!p#J^e?eB2_JHI7^vJQ9x%mKK8 zZIt&6sow@AEPC2D3W*%)Pf<>hqoxtIp9a+E`GGZvU0{t&fTvig9hV%qo3lJvwVW~% z2e1)JEoCjmZv!@Goy_pmM#28M>>??X(bHhh01KE({2$>o5h}7aw+n=kwPZRr)mig( z={4(bxfPmjC{LlY4mHven2*S9bFX;ylgnB(7U4j%Yo*3~+AlW5?Oc-^hY z6dxXgzvrl{RtOWsIQ-kTUt-Br!$UaWM*K}sL+fZ1)DiVYHOw*&WV_~}$7V}zg=Aby z3n8~$o&PNvjR(cho)SKIQ967cfqRyaO_6L<=;ZJ`>$ED7}E%LJc(_^ zzATbGa9~LJwxv}Q<!QRs*zb>VIxNPpa6!;F zP%qYP?2UdkQ9}`mW zZxV1gu8b)UPlU8V?!U^*=`XnjSq9Ey_;{--dgx>jPQmThvS0BU0Ygk({Y#F+%ZBkQ zhZK@Vn26`F+wiF$I{E^+Cg%HqaBEm?%SYrnIpMhv$Aw*ZoK4r_YNSA}a~R(@=6&hH zuB+=OzkWLg;ma#c4EKAdROU^A5cDraM=ctD8|_4Ey@+Uo60;+1@E1hjveN&Rnb* zz#xVT)@fUNE?&CKj-L4JmvNmRm~s@x!7S0<&VG&=!xxNA8|WJ>G0DT_asZ0~=@wQZ7vv<5@|or)j7yTf3ob z2J|esez=?olo>M_7XPQf3m^;pd%)-!Jl_0e{K(}2#$)0%uBcOxm!_wne*%RG4B>i< z6$=yQX{+^KHfQ6aHdimMUPzpN6GXD2S{~q!Tu#1HCI<&X55ch(dCd^fxcouU$~&l5 zuMqqcuGW|?a$~dD(d2O8 zJ#N>6%NGMBnoDeM$0JH_d5@c`TBT{jiMfJN9vE#6Tk^V9sY5y8@F~~Ka2x(ckDzTT zb{U{rLFIP*0@u@8%=5Vd_pb0|4Y>mSy7)6LpG_vahIV6ebeTeG|MKH}-8o8b8Er*% zqK}Pu8dLT4q89BMYIaSt*|Wpcj6ZnWHIH@2bcR7LNJ7SH@>Nn^rJFsbW=qNR+aONNYDNN9_JRkA#%xA;K?>D7)u{WQw+8ru~LAA%) z^i^3i2+ZS+#;@joHgfS+XpYsdVj|RxIQ=TH8PTsPYA$M4X^~VbG`n|!`tqR~ooVh} z(cj{-6M79Kh9-?mUvKLAO8PYF>Ur+K>y6*!YXuVrrGKZTDZZlG&6w3Tq2eJjy_-2R z83@}IbmMHkO=}yY>K2bWX{(P;pHK)zcg>1)csz}O65^?Z1wU2;P~Fqq(+sMK$d-tY zN@RWV0`hVThN081{^e$mY2g_$Pim)@U=zguORkN=)?A^5l8 zx=LC8lxY<6gQiiLlY=4fFrer6zq~;nx-B;u_D+OMunAnH@|xx!m2w_CmvZs&_x4~y z-Wau{+%VzNTg!so^M*^x@ClbjE#vB9Z6?+oYlXArw`uwMkNk#ko3I6^wZB%&=rOLj z=FxlU0gxVpCaRex)-*3XlsBr3cjI7$A@NW81I;L(C*q{<(2^ zDzHeG<$aMwPBb4o{%kD%q>g-!hCGvVuU#_$!&C4;a_oD38V%>mzjl=X-+=D)xMLI59{qI$&3qeE@ zU6Uxeh}PZT%nC3SpEk|WSUs$DNn1pp%+Wwm-$o7CbV?_OvDa^qp?f z6Q-}uS8}fIV6i$-qbX4zKJZ-5(%wcpKx7}`I6e#i2tgD%k(@=oO!g6N5&5~<H;=mz~os5{_ zAw;dgCf#o&awlSw9v-9WDCaYlx)Vu_PL6eNyVAB<5)k#;Ey2;pKj~p4{jMcUMTF-q z85m9FFGnJu^lZ2O{N3@A3`u;x9;M>CW8h`=)EGgx&oQo5aw&yM8I&PIfbGJ!-|jkRLhm^o&T zt-+QGfx9q3n28l&CBhovOW`*RuG@*qISwR(72)ZsN*90mzbit5lVl_04hr^fggm(c zgDcgk>4ju!zFc4Og(8n0l3Q$Vox9f2>ucpx2eoN+vtakT=12s|(PzZ1YE*HWr);|A z)4Q7GgJ?C9&-tvK(|sq=G$3xQLRO1+^f-AQT^f8KG7b104lXt2IBU@Ai0lelRI=* z2I4tmxdEKQD6asy`>h>;7nRVY5y*A`73o(Go>6Z8CB1V)sF9U!*ktyZQ~yuca9pM>LVD{tuxP)7k5a ztYC#MX`&b-(a|^s?%Z3~Tj2KZ8O6-CYj5ns=IbqLCc`;hofac6IRcxE(1B-tqW>2c zZ8k0XNAsRh(e9Z7D-mvEikTJnF%}WOCfO|7%xBgLk}VfHYVY->#S#>NxZ4}P6IkAW zSQ;4o6@^fnIP^np!7~MG0=||uPHeq@JtS35gu)-f*HVBlT_kKI%oi;aF>VPgnWb5* zq_Aq7rnx(rlIySp_HL|%19Y<1ngm&5a~A{W=o1l=GNXA-2pGco!4aS~4Xhe&JZBJ%aw@3WU|RrIQIP1In8uowFuWOwiCADN27 zhDyPLK*-$&bovL=Dy{~YGXb49$z}I2TD!?N8a=7}f9y9TpYf|h$bb`c1urYIBFpSI zua%KF%|X)^>VS1AJmn+>N2fch)2|DAI*H+y9Bm}rNwsfMKrsQ zMx2K}JM(^G@)`JeOXB`meb@J4tR&O)P7OTN0``RaVjQg0G4+`C-a}Yc&pdy8y z@X#ls!jibsg8Lr}PNqD_dT2>}k-$oLTa8Aq39)#s6d9`F-xqo@vmv51nwpBAY)NmB zML<6kdAWLgtwrMoX<;HX&M-JhBd{;jAoRnVPycSaD4p%YIVZAwH2ZZ2HS{*WS9@wXRy#C-xjEN4^Z2d+uT- z@ea5ScA9$bI-z~Lj?FljbFY5aMh_!iJvBfM(Bu4~KacV_zCKU5%N5j506zDy&h5Ip zYxnI@j1JsvLXn)+hMV2$Gb6uuL>r(bu1wWtG&tu*!N{Bgd>fp;57L_m%3s zx%4pq6~l#h{Op_V+;;Q);5%CRw4~{23EV7G4kTVo3x+a0pFa9TNK(K*Uqf5|^OAwC zk~_~!GGvP>!OgS*NL|C;GyFEdl?3IR^X0T~N^5!|1rbr~LwzZkFVc32j&Gs3Q6k#Y zA_pj2y3;m|r6n=%V366?#hAm{FhW`XEG;{88w9rfIeVZr{bo${_6!W_{$#)we-RvJ z;3z8d)s>E7+1WD$5%1E*(|a?0{!mh1W?B0wc_YKM8GqlFJuY2Kv2f>VrLFdo?u{_a z#bh8MSqlARYx+9ML5eFyia~{-c>vVp?O%AwtuT?I>>p8kikT6S|D@bP;PobrJ)AL{ zt(J?UDEF2Omq#ODP_(?Zw?Jleuo15i`-^k8i4Ta?xdQQrCu(0GiM$)cZ(gL{t?Yel z^z)Cn^B;-HN#Y}c_I2z(^es9URab)Q2i%@^Q&F<@&*Sa;>iRE8gs+=L_a!eRogXTL z>t>w5WM?fUI=%c&aNU}~;c?oV5jWv5~BhZ0%uJx_70t z$4LZgwATVn7oZRV&2%7oBdH3NW`WFQ7*A}o?#!bK@8wjq7hBJ z(wIq$IecqN04oXW3EP#Uk^O{|gwqqz&|gFN#(PDW&H782jvhJf59VvlpxUB`;oIC& zS$YiEhteNJn6EF}Lq0ygpPeK!M7dP%W8QO-r0jO`4^31n`GAeCw|&s-D_k5Jfr9r3 zRMAcII+&YBdOhdesx7bTU>5Z5t1KPb$SEcNPk7sG`XTzK$EJY>Hd+e;vNapkPYmRi zz3(op^cs*BmMwRz#xHj;964up)@Tquq?MgaUGJD7cSz+%Z-Y8sBNhke7M3#^N}qE= ztcPMN0Uh%kJc|riuCLx0EraOE-6h1_Jo7>6ERuq5FuV!BiS;L}3oFmt1kNg_)zQ+Z z@f$gv6b`Ooz0vXzV7G9&{nk1shhEI zWCu*;#ab{8zL7~r?8c}dW?@;}#wa$^Xk!d#W7K|TY*}QYs{xBHn-hHd<2K|rWLZtT zJ_O!Jr?c`{m8=15d}L$H=Ao+Y-W`EIJmw>ln|2+Ntq-l7H&2_7>^xH+n4EL35X+!k zpAxH{xpz0sLa>H1S73@?4i*rWD?SfgOTgGsghWCX0sPko@ttrD)j&;9V2iFqKhn0N zd~Or ze%?u50QWcznDfSHPZ+JV39h=(NH}vXa4NQA1Pd1y#a14>ag%Xf2x`l!|3Q=(-5NloGb<*5`q~>~J>N^E~kOv8{m)dP=UqVFqwLxZiNL zC%Q$)%M_-8rZ=vru*%G=9qivVnM`A}<36F^oyT7~A6_ zC1f%R7(K#vLVz=Hz<#(ypwn5OAZu1l>@EV3pCUReG9^DkwZ+dwA4Fgtw41CVn~Ckj z*<)VfP;qWwZBzBJty$F>4el4K;8!?9K!~@V2X#mo05Y^ z5k7GU2Q!&}>{egyxdpaw`Ts|M~KH^p*oxe1BYuf$)(f5rbX`D2(Yf^e_IbQ*5VxW(kt4at4EF;lUm z>jT7G%6+>#-Bh}pf9$Mp@4R$mf%_4)F4oamf`w<=Mx#vso{<*!{0qUvAY^yywliku)Ocq;w(O7a<4E#j(_-6{#{m%E3%SkpMQZ%vx(PsJs9l! z40to?bX|D7i8GnZS42cYbAY-Z z%{{dLFLSvFo;uWvW4;bm#7@{E6SiNBdbWTD?i=n`?quB8A!Xi7UaA}TI^@8cjmhjx zM|pn3cPsTI>N~4CF1v%ik*jS#U?P+EG=e9Ks=8MhJ9^pS!3faKP-a%G+MKx`&Uo?( zYBLRI87oFD-uIR;>=$5y+M=B+(e>zd^dNe%2%0n{GA0UrRGUV3@F>y#;ad@0Zy?pc z6@_j8tocd<&%q4_aNZhT?bntgpTBk})ly->90OHeeU`f1a`Q(ddi7INIcAKIjI8Bu z=4Kh^ChX-L=I=bt#b4yUBzxVI8sR~&(Uq1TvHuhHWnHy((Pq2cgdMa`chK#3MAOeN zg7|N}`vnOYnO_3jNAw;^;EujuKv-@6H1NsL2^cBT(2TF5J%!W5BCi4{1 z=@sj-slf$wXkq^bm~_NJ&B0{PXcH%_rhl2>tRu^vZ}K3?bOZI>F+z zN?9`Num*dar8O#?9d7ro?6tGVR}?Pl+$%~I9c5EY<`}}6$n3w@b!haZ{Xa^7#^4hg zpR*?OVRNqf#6gT^xQp?w3_nhD-uW`R-c(g*m-y(TR05jHjapGVXOqq< z6b~h8=fx9=DG5LJ+|Ye4p2Y)0V!T9K!djF}w2>U<^^75n!4i(-h@_oYEE%;)NdS$l zRb~$~^fRl>=JJ0?6r^DNs+0ui(U3Bhr6dGMW2Cu8y$TlZMJ~AH7A*DbR_r$|?AUQ7WJcubZ-qAzPr1jGZMdh*<=50}t6#ht8UA z^QR6qX*(&$r6gJHtY|H#(eEs`enfZcANk<&p8naXk%lmLjGr0KHhNJ2eX_6nx(xL* z>Ap12_Z`n>SQz`i$Wt2896|@m4L_HECDq#eA_El)Ky1vYqbW(l?h-~1OAhbU~k~h#5koz;7DMv24@k-3fw-tRRFe9&yoOs-z8N-4r7u0 zj4MisnAy6En2&l`4|OQK5nBgYi=S~)(*tRw+f+Np{ga#i!WBY3{*W2qdrxTFMAzEr z9GLW7zl%C*xSeBg&}`>PZtnib$L+Rk`bzeCcEJ*P_)_Hxh@n(K9isAN4)#3SL#tj5 z9jf|S)7c-*_J1ksTpfq`=rEv^rH6XCbdVH% zuPd3@4{?5S$;2~5dgT_D`QO(e}}2 z4-xO@dxhL9x0S@yQGw{vvG^aOG8nAi{jJn8MlFMm9sZ}Op~X*%S}WeutsW6l)L2=F zmz*)n#?$fM{P%NQN$*?H%Rugm!KL>t_dx(FhIN>AiUpRgfYE&Z3}g`!Cr%doiNJRL z!JK)|;Dl3n|4c$Qb{{aM!O}&A4cP;aGx+(^iHjiM)r@Naul8PV_}=}vTl(WWu$Sl- z#AAKN3j(*&>alA)AY+prV=p(F%afrT?(#r1?+{PcgKi`|<-I??Jz6~jBooJYYhv%d za{hZgnK*chI%vvg`mU7C{w6v?=rZ-_bqe+$uNwutw?Ye=uf>)(3)EcH7#X@?vLmX_ zP?Q(En7OoKljr`2N?Ougq9ZMcQfszo?VKa?wW>taIdnp%sLz<~(kTFT`D|j{r^_ zOaRuJZ?(|jg5jJm^=@jKsZqaQxURG|f^ccr5b|(QgNRX=W!mvY2)Ga**92w#7Stq5 z91_(-wH(T#R@w>{Pc|?2O16Xu>JCeTOI=n;mI(bg?E=lxvVul%=e%E++`0nxhA5@@ zQEoHtg5>;(j#-wlF|?-)A`mcbL7io(mg#8aaNg;e&#w^9JD4;$~C=AE@A!?S^;LuNYhjiMh;Npxr1*to5Ka_>8pn9%~kypLXB+ zNZdnjQ3eVT;etdY{wDT^RYZWeB*l=JX2B|xCqfH>ie{Nhpw57BLa0R$&DD!I5k6~V zUD@m|%VSmBvlZs-OYSIc|ILQuI-Qs?(TC>cm#++vaJ!vF#qF!P8@XXmt#2J64|<5g z9uh;##Xj_TQ>pZYaQQtjFN#QH)z9{sg zQ5PM8;3JCbX0W#t%mRxH=Zur*1&5BgD!?XEx76?JZ!V20xbbPEc`&iyvz$vH*dZIq zp)vq!U1t979q>v+*VQ4TE^Do%^jQxMWGn9&x~MScGxDf9%3A+Kv1{Hqy=v_b*L_xZ zrqOP`92B(_G#BXf<_naFp(O>czX$5{e!NT)oea)@iNsd!PtN%JxNo)k&EKolFS)9J zfhVlz-<{PVZf3Q*kWzp_BxMGrj+H<=8cu;KnvfC~T}&phWmDFsU_59iWxx>^mPlbI zIzy8v7rI2@4#+E_1e+Q}Q5LaOZ9N&f$~Q_rdO?RYpPtDt;15pNCfFue4!@XNt5jUm zB=1^QVK_&*xe>g*Oy79AhFC$0YmOwgXf3GPPLFGjYtfZP>y()01SuXb2T>+43vauHjIs{>FF zqkFC^9(^v&M{lCCRwe!`+8|aZ8XNO0tK<}{*<|Yvw<-eVw%)7DC;uvVT176) zBgyiLFlaz?m4O7=kGhQMMz*f;3f6LwW0rDv)My4Y3eAz`Z9l1}kOW17bF@re({&X( zau6+u3~Ip>|k&i zm!0E9#PcgNoNSpgxIODhh`7V z&-U#&^iQA#^1RP=-C$L*+?Ji|>SOhY)K%C*{zCR@&o!=W1~VrZ)KHgIN3i#^PqN3p z9oVHl9G}X)xGzt<1ate*E#4))n*q98f?pk*xLuQ9Q+ zRLL1hJ|kxTq3T%cEkg%KnHq|KW^z6KSobk??BQJ5|Jad|-taRQ-%Zg)3@9bA~>Lh*tym8gXp);J7hM|JhEXU}0>GZ4m zn}S}lAx%~xu|Me54iV?1jhF*|xqssR=H{>sl8*4~j@XX|tUlhlGMLBV-DD$p!$Sba zj~{syJ$JP3q~v5j51*{Q7yi`){Ex;vWH`1InzNEvza};{cOtz(BQ7=9Sw&z!%t_7F z70exuY&DDj*No;Z!Bg?n1|kszQ}cZ&LPw#uuz+^YS&M2|+lC2vxi!=?*E?6lwY#hw zT_&-Sw#`e;E9Pv9DESE?JQ*bekSWEL`6}SrE2TscdJ2mw^14o^n?&bH0d%fNTcoNh zOgLlT4$FSZncM>ItvzuJFU*-W-}`Fg{dmmwg=_xrkC3N{Ln=hk&t%!%|IWL=RaH=x zt^`Pe)#IuuKzN%zJ+uB;u$(BfRLXkR&AG#?JcRC$+NCUS=<51Ado}=hF zU2+eQ8GJwLNT~1hS~O3m51~)+b3LMlU!SWtH2)7Ck}|iY$C2z!rm({1j_)I%AOo9C z>;?_Qgu_0vV^h;7@^3P{9c@8&mrT<)Fp=FAOiLH$2?HvH#k6kAvARQ0zxTBd!fgV| z1ql%%<2bJTaS^y6`X`?375x+`i)V_}EyNoxFvPAtpH^@J&`)k4QOCBeKumSg#4TmO z;G^fiu5CKoIjyDaH5?eB&-Li^$;uW|({%%-1g*_cNI7(r`bm15wi(UDa|G~3`p^{G zmiT^LC8~3J^Au6gt4-&rUmlF{ZUdrMAgb$UTbI#W$+y-nvb zLHb7eRl4N&tU>Bp3_je?*`8+`WP>tS-Qg7MEOrfh_@m6B5d&{AhfQS;vd|@2=F%#H z9JKo?y6=|z6euMgQ44AUE#BjZ15=pbz)}h(%#>>5OgIrg^lGZNcu$-0Q#;ZB*iT~i zJiUF{D+XKZiH<+B~SWnEgH0a!}i#*tgg5Yd=NCD-TEI2eiFYo z9xC|#{N-7P>CIh-GzdmbL%V;%8AO$#Pwxy7e{RfI8lCL3C+^*3!mfW1Jd(pW)-_Hc z_6#$BLRyE$XtJ~3vTP^WHV(JnAL+BoWOG)1wX{2w)bjg5(r(q4Q*$C@mR{3cv+#ot z-n^*wIub$y-&*~65l8Jtbw`IY&oXvpB;bdcbMl@ik6S*Zj@3C%FOhLMj=k))k_EjR zDz2L2(jqVHP2Jy}a4>$SdSF^A=K`lCJW6D(AqZyWa@N<_9Aj-2o@N#~>#dqR=S6Qz zBa9k6RPIdRs$anyrm3YHrqw6>ge;A=Tp3COQ=oefX58UZ7xl^EI7~*>rP<7MknjYXZ#-`m_f` zZHeGm+d#oOgFvFTA$oJ8=$&EazN|Q>7XqsYQos)v?tw?lGt%2-=)?b(n3bnEnwZl8qub}l~bsNP_FaEa3E7T>;tV~Ta#oB3f4cSZ# z@Ar3A1ASDXPWc8}-|Yh4!@nohR;b&15Usx(OO?P3h>n{IV$S+?O!|;a{+#ugUzFl~ zzx4UYOT&y8>fmFCWr0r%uHw(_<;05~Y13}1oi1c{y98CXUaS0{9KlQ2)M6j*^<|tq zHl%3~r5G%AY?zi2DWz~J;nAIteIbP1iZi!!OKj&^=>a#&+T-18D3y~tI-B6O4zAX? zvfUb7t$k(wC!ZL`*8V^8iGR^xRio%(YDBusS9$Wt`I-Mew>V$~70S9mvR@ zg;8O$F$^}=8?mxf$aNc}mAPG689Rgb-(+JLZ2b1W$;JVOuCip~UdKN;siXX;qp>X6 z7+dvai2c=NU{EmYy<)BMfUD&1)t+A)FO67D3=bY+mf{gbbz~el#Kdd-RRutE@;xqK zD%VmdqKGH}ObR@}TO9IxXma*@L?vKA*~!`?^0`MS2wnr?tUY2LGGTJEl9uwKpFcX~ zR!aW5k_O-v=FAwmTg-lB+EkKpt^ujn!II=k8g%FNjwo!UveY*ERl9(pFT*%?BQ?qz4>;MAg>bzUHG^((OE6)+$XnbUqID5_fq5f#-n6xA*{Fwe_$Wc{01n4=iyjVTIF82JgusiFVd)SRw@n{9` zHOvzN-zSQSL=H0Ny`me3eqXs(S(R9!d1OW3sLNSr>>5llS%1BchS68RRkXFf=`A{4 zb*;unT6%shhh|^#(xI|~#{8@NWkGCmzn$lwIEaD5fXr_T5cn9_Q*}wb1b0a1kWQ?@ zUq$uru!RVML@3c2AR|Hr1<;>RJP#}B@kZ=`9yn;I=BX(pG@1o+5X3adwB{)CEpacR z>KJJHhz64_R%R@&A&5^+%m1Zh(Rb(U7pqAX98vD#qk}UMql$v}x@M z_jqLB&rD?ID};kgWGljaY$eLoqhF^FR37WMo6tJzybB%@UGtQ?9L*Um-3f4mgabzin+R+|0wLzf!l7RUi!pHKdp-tw7Nxfd(j9ySUipSz zC~rkc5-!xz*jt-v7I@7pP@73C>bD~&Xwn&vFXmRyaKweWRvIYdv^_?DZF!%i&0K|Y z+yNZa>(2|E7ntt&S}?a){3zOc`Zz8W?*xG;a~$!*v`)h8yvgQyftz|?=P$O=4Sekp z2ew`_ddBpz+z}9C?ZIyIP`P2~q1C!ZxJmeDV;1J;H?rv6rd~<_^op->^r>_{dvkp+ zY11f<_;&;G*JUVHZ$94`2yus5je&?T{tC@hxJdY%EFtd@a)oq6X-Qd*(3bHJ#62wh zD<{$s9iOr`2!GS)u9lT0TaCJjG&AQ_C1R(Rc9#vJ9ru@hAexkrAaCYKg`VeFW*LHe zfO>(c5M$l13$y{h{od&s<-c?tdne&h}T-sXPx9pzyNp}StW^W%ME+w z`kp=c-rN+{wYH z4*4JFhs+YApbLE>lqb6j=aQE!eB#L@9}Xt36=57|>fG9{^Yg-SRYvSuazAaH_OIvH zg&7b7B~wUjPZ|hWepCLy(#h6f!DRDcQ@DFBv)Z#F%tfP7GjMO{6{c~Bp~-`T!2!HT zwo*4T>6FS=d-2Pz{0=Q4b0APXyS5iGRMpmb8|0Eo#Sza{G+qxlMP0sQGyBRKt3y5z zVVzjFLeKu~vE15LLA*|z$Ge87PY`HIHgGdRkJ2I~n z?baNA=QU9V9^!FO!rz1=9`qD5UvbvG^HRbQapO(unctbX5mwJSpQ*+2WRrXJ-q%~kI92BRC?T?xU zt>$gyMV^p|4P|SO)XOlxrj7F2sp7Prnz?j`nOXed#jR@QCtM~eZMUb&ce|3GMUYEa zpmolz)1?}XL7|-oCHK(6RX+!BJKCRnj=``3sOKY}`CwOSLZ{aru%I`n958z9XId+h zOz-ztZV3-#!BBm9uv5O*=-b5Yo6gx&UKtE7sNm$HXJ}%#GUd*cZkY^q%MQN1YNa3X zno8L{CAQC{h>$icl^d2T^`174ti>a)FlHDbtpHDb)U(USNh5Vw2R1n-S4toI^>qYK zR8^IRlH}>;W)#%Qp0Ea%IRGl+qjeCocYgJa@27?6n2+;V0)G`$8!^y9D2{dO4q!Y? zPB0Qp@Rlo0A)FZ}>mYv1VyxivGa7-6X zRFc8J+AYp#Hf(5)-jxv#{urd@Tcj6XRmhJk&@R5bQ@-MO!JvgXUFfhv`^KSUb@Fv( zkE22d(~w#&yLkT|OXJh}e9t#L1R<4uO9UTI$QQ(D=LsW=ZG_s7RoP%Rdup}0&B^gT zGe-M>+|{B(*XHZAj(_o?U0`GBST}L0_JU@e>*XsiGcj}*RI$LEQFH+2v2Klh>0Mex z@+hf@nLTZ|ctO^y+kOv@JbbVPTAD0NTHGc{YIM~$M{i;N!K5z)ys2U=eC?Y=PD=jNOP%i^PxPtmU0ylZ}M z<2hCbcMweM3+=CEShM`9yq`-LZVbR;L^E=n-!-3HdDtneIgg>T@uS^eze|KPFo zSu#$s45$Brm&{ViVHL6Nv%F1CNLWLxpf->zDihU;+C^|D9MnXNWCLBTCgO3n0a?i2 zEoo)g8N0nnf;mJjc7v>mbMy2}XH}eDE(^j=>M)%d+K8^MNd4PZlnhNX83g*>d2h zXpL|tjV&ZVbjg`b3NG{qLKSwG(0z$4!w?_30)(zyQeMdR5}C3GH{4>K7J*afRrD_U z3>^~T8$zQs#7!pRn+HOpS2r50d#Z#T3~f9M517hWv=|ygv&C1$cf?P{@5NFvBGJ%% ztFiRs+;_^`EQ=Fjx&V>%Ea@$eY!TF3H~K};BY#yUL|DK3;`-fo1Nnwve8)X!+2Rbs zTWL_cl=91r(?a{2H`N13OkfZ2LeRP0mS7AsBO)s|WiAbn&qG?&3T87z&i74UICna} zVE`FVSKW8v26L9`j|QY}^r#n&(H`Wu&T+YeO&N~fbGiGHie`6Le;#rZ-`xdNbgPGi zZU3NWiLG@*;CrWQP}a-kM9E=sfubdAq%i=wCZ9X_4Ap^K16^ zm-5#}J?u_85@g-vCOeH~=nMIJ5Z9(#_v7aD%T#grvQ4L^7XbPCy{5W#w6HniGmrJO zzkL83#X-Hgb(=1J7eBc9RmA)PPW8C5{8$mJ{j8Ilb+0XD19vt|V|jIzrNY%@Z;#w` zUN4n>F&q&=Fkx_^^e_x1U^B&ItW(luj{Vmk1e;)nZT*rRx;K_fJ-$WpOyGC2kh^u> zg90CJi;e}+g4iB7KrHIIO%98tKfcJ%t%eLh>;6z74zve&elm(KYo5nl%5B5~xJohm z_nO9*dlx5UaW8XQ35PJOIH5dHPkXi89{JdZr_%x<$|Q7Kr=?tE$q%CDHC_g3^3Y7; zG%|2Q2YF6pAMzG5RELu5L`@wc1xYKpmptQ#r5xQ4PbMxmGrMnIgEU&wz%aU=98Q}+ zvvVF0eI4B80u0Jt7!;##`5&zo8~mUiTwr*4%E*PwUBFyuYVw12*yN76kh11#0{*G+ z94YDURpTBj3MK>h$hbXry4A>>2Lc>GOta}Ma7I!rc_0x>NONcuTWJ!eq$$-|v(D@e zCRJkVv+b4v4J9D;XTSH|zaVbK3F)d;K(fPrIhi4o8{QzuaJ?XfaF9EbSVE{FAUkFf zpY56OeZ4Q73C-4&iN`hpwQ&D)l!DcGZHbm?o3Z1RXr}U(FBI$nME2Z)vC7<~;nNO4 ztsXT3TTA&B=0>^Cqj9GorJDmMxWJHa$+zOU@YeBQ$_?)X&+)2H#9&AY`z-s^tn326 z(tQz&`os2fNme;ABLM6|cCW7Z71qC1%uQYI+y=@M9`%-|ezAJg<*e816BoNRXKG0mckrff6~RxE6O?58iokT9k~x&%7~HUI3cv_)AxS))zgGCzns z-W@yss0;RT1|g~vZ0bx& zr*E7RxkQZ8=-3O`jcm6yrt88cPxlhc3Vt9M3HW~G3T*Q1bK&OKgf5^b;8n_)F}R{j zSG$!eu4=)L@kN(vx?kocT%zKS2+!O|xCEk(COjZ2jSKW|Du|F7qBA%AZ3?w#rIL2g z;8geN<@#@#H=VEc&+fh=4xdRJ=$tT&Uxs`imNk7yw9_R{{x-dJpL*cRct-Bw^G;er zIE^T+pBtDv?X=zZGU4LbAopm(-Y03Q^vSt3YUG-0h~1;737^kzdNs|a3ZMP>?KcdX zxIX;fGm4X|#I*gj&4=soBAQ~6q^E&--sPotW@&iJrk_4Py+sRo7?xQI{%xb68hC@G z+n6}L8K5XtYZ=Fo=ZS`(kj#LBvuG;sAquC$XcJF?Y&CGg(~#6xmUFm;8+UOD2uO(dg|k=?;6a8BeDhr?0GsWXNr~r@wFeI79<5Sq#D{6w3#?&mRK3s_$IxQsFoKkJj)8{^F=R+Q8o;rh5zJVF z)4?iM65+onw@Ow$i(ZQkuqIf^%_5@iR%?@OtTRk>SG`w&Xk9o~3A=#16kAWO$0^yU z(u(S#=ms2jrp2?Da^1N%*`NVBg1@pS*^my#y+N)b13zvA^aDfH3Ac<}%N?hIPh5Y? zP|4Sd_0&WOlW`ex_91uUUs$e&)I{1XU9eKRUaHSqlr9%5O_D0i^Sy6=Njk((`aigO z6S$v--<*2i|NDLaU%$NPzRob5jX7s#?)$ndR`Or#%Mm_;Q7|Wr zfz83D*=(4^bw_V373SKpLit7$LwlKNp+~SB>?&4?0bDQR2WCdHA^qm-8Ubdm-bgx0 z%OH)}u`KK+X(?fwx$Ftk_b zzK-S|2vtt<=qs7AOz>ZtAX}yVom~e7X!4-SX=hF6E z76)>v|0WCKoZwvI+~w4B>UEqPz7gM=-?_DX)Ag>O<_Bi--`&oE1BPKsi<_hQH`KP8 zll=SYHaxWL4Zn{+ObFK|G0poPGK=+N=lNF^jx4I?bIE6$s%r3`gl?f!ctKbutPz6O z!Ydj?^kFAfJxR1g!Vwv~dO5zjdb?<}5ezEfG^EwCCc=xDS4{=dPIOe|H_-1Dsgnaiz_@2F#P&K5NS%ASc#*pJ_@s zV|UcuY~@(>8XhEOUd>NG2$rNr$!!&$iW4wG=&rn84s`NfxshTTX+CL&Vxb~N0pb-Y ziY!HeB9&IFSnb%MAcEmh&g+#%$~vppG)Hwx?6Zi9sOir?kbaQX51biTKj4yK6=937 zQJYRE`TWdwEj`I?cg=pK!I7?jUi0O*_bXi{mNzL&2OenFS9u72_hMSujj?Xt?bb2F zRytNPjl3I2`jn8g?*Z6n{lTl}|9-*7tT@Gn)1|1}X`h29pDCLracy@yk}QSFk~eHud^?Wj^Aqtfb%? z)k6`FsDIvQ_VnC2#Q(6S!75_djA+{_%p<=i$U+_ltpFod_RMl|GUVxk&3$S76^{Ym z+1#gRmax>2m-3Fv-ya5245RDj^1UIzcYDRZ7z~9CR^Ci)*sDCOm1~nZ_qCwt-_bLu z?kW1$`taSOeZOeMW3h0(x!q5GluLuYJ7kR6@sJLf;*t?R;Q4W8t{zP1Z%PW(ztxjP z6NNsa&QK&arG(SK#8%$qG_A(A^)DHbmtt*4E;8Om-`a!0cbea?GzRut*DwjzwuCgV zuAGSJ7)wIiD~ZGQ4hl;n0z!+))=)|jJ1obrVsdI%is5pl-IsyQV0(GG$%j0kO!#;y zCsG+_Qfi_G7nCmGjMEhL-;ctsp41d;I87y-`#faalRD1&he^lEnBS2?-E%dM73DpK z2B#Ps)PMpE@)ayPSBN&gY6R&B6)a6?6}|J02rK5d#P4jd$wZT zlMCqbi=zxP2nn-tb_fzyu<+;T8Ad_WHMvTfd)j#0r{ke9Hy`IAgA?G8dvn{65A&BZ za>brVP{uLrxrA?5zj`9~CmJ4&)t|kc=Rf`dK0N}%FsZqnkWKX-GG0U1NUjFNTDX*O zDq^dbYluS4hvd2uL7b+=$KfmoAuZzy=Lt+r^5M*UcG%NYwPj(}m11(z<}4uHR zD@Hz%=AQaz+ZU&GKVZ($#dH5}pwwT>>owe_hNVsF-M0$g81xIAot+;}SypIuTIqbt z1Ki?0V74$nGkY5cul6<;>UbBDjVZ?${pwCf&g~)Lk6#sX&GWoN=8yW$hKsNFNcUu_ zfdX>5bT)WlCh~D|7@vC5%D*WC@y!ivI+a4~ZLhHFmcONeo9|PG{dLh7ex7x%;EOK; zzp6lZX3b_rHAkjcz2SypKg_?{oB0ZJUy1d%At@J^P!SiWD0WG z;c%fFRCcQ$jpxugY|eBqtDreJ@5Z0_Ovt<8l@RfZ4R#47!uuqZ(CQGC>L_ALY!T7Y zgul%G73~!f4~{x$4K8kGFf%C&x2xPnP~Qo)bYL00bhqiu9iqcqqiBT*@VR$?tL0&; zO)WiVrc{4HU#15&dX_woAa@FR+uM#y$TQ4p_!~C_K(~>fwslSy)CYpMYF$$&l)xB+wTFmg)*eHmTKH*m+dpN zJz>%a@;xI&Tr|5WgA&vv2ZNzsNyW@@hlE4TE{hrvLMi?ueS+*SN5!8IWO<{|XNA&%pDtp^cSE2h-HOO0zB;v@} zip}vXm>IJ4VO;dX*rZt5K4PxK=!OR5*J@fdkYBc`x7~PTtI0DDPcure+a3!THh91^ zNWM7JgfD*^IT;rW&dyDko4W;P3ry6;rfE-TFKO?>j&;&38o0m8!!wfR7>H*Ov-BZv zL1^v@y-=?y4$Y0{q;Rr0pn&sQZ?uZ*Q5$QtaeE}!Lp(mtQ8)=RxjtJda(WQ4&V2Zd z6?`Fo{0-^&8?BTXd7zg1UHypP7%s{sKf1AGzNXdSCKT)dY2|=GG!`7mml>{G^DS?? z@St!|-`7gwv7kucH1+9)qgbp#!#(yei=BnXZxJwr#R6NQilFTJOXmB^E(`bWdo?U) z+LW>IvJ`URowWb++JxnIygY9lg=!a@wZ5s%2;r;;v+TCxGxOB8m@E3m*elwoYU?Ke zD8*m9^<7khD2Po-{vg&LeS0*2jA2XQ?1sT&#ZbT>224ax7&lZ-e)vqk366 zP{ryaw&jPKRSuVLU~*&y6OHUJ;762hHD*1t?96WfM=@US*JxE=rQ5##vBU018}I91 zzGlCj#X~`2MSRq-2=Ug53y=lKLAv=GG+}()a1c}yTjAQ3nmdkb-C&nHLD`urbZt=! z8`cV7wEeLBkOo5KC!z81?n>e)S5{w5RPd?W-Jg&q*U@6RQ%&@bTG!G0omf`8BMin3#(iC7P##2GRiZVvZYX0l^+(OBAIFW&cVoMTFGkTAfUWr* z6mZ>L`yLMzm=@CGu6^wO**ztVb>Dp}40ZHF74CVv{Z~BjLm#@&-^MaKF&FDiJjCAw z;{q_8C(M5}Oz2&kHf=i|Ab`zv@7Q|4eVIEp0*-2eyS}wwla1g~(C1D92u-#A+-VjvqRHT0-ztRg;(hPYHv>m3 z_947r>^Eh{0b3RpyaZ>IU*&?a{;-11_<5H(#Y!Cv6J2O9sPPvr7V1N1 zqB}%9l~ivf)whNE1GdL#p^o$=PHCaq`_>R=D5+mss4QPZb5%*LZ=tUAB{nLlO|ZFV zO6qeZwM9vN37uC;>T4ynT}gfWNlAV8xpU#S&TjD4yM@~3i?sO?^)1vP-v!8!FR`XsG!1<2|!BEN;&8iurn@rbcuNKzP*5{4WJ zn}j4NsfkMJ))wlN)y2q^)x_;eYElbT1dnyElA5BVrYfli{!&s8DyfH+R7nf<%Ib?m zsgf#FQjaUCC;m}VPb;Z;^L+bP6VKMp^EF8%o}1@ulSs^;KhM`QkyzA14NgRY6Q2+- zwNRrHk*GvsF+5v)5|KTL#LF$zoWvzaP9lE|@uHGCq@*^c54+YveV2&5OC+Y(woncB z5i?q-*87P2KnvA%-^*>k<*X$lNrnWRm6S>zNLnPHCBGyjxt$z%$>Bpy9wXl&KP;Ea zm2z+&ig~=3f0vso#w+LwwgTXS8Cw+x6#rHF1Nh_lKTl^hM;)OCo7JgmnYvJYOAV8^ z)m>^p)L3a;G*dM=tBz2UtO3U~`I_sRN1B(KFB(ik)&d7Do`H@_SMJhEw7FWK(pG7o zX+LUzYDehd>ZcwA=y|_cd=KhR>lOM6J$R!3Ba${2n~X6rE(Y+$PnfZZUBvES8mt`y zJs2+UhO4_RAn{3YB(RqxC0!tuk?>GpJqe)!3eAbepv|Ezqiv*#Xc;tcmR3r8Kx?6W zrv0Lk=yvp_ZWC`Zk`4PA;>QeeKsRXinCq~CJ=YF4c_s*?ZKLlhx9!2EMq>M z`KV(`*>bs?tfr&!+mt51&4#@3?2fU)wLV@P|9SPEbMJVaWQYlOysh{0!UN61g2RG4 znJEjl&wjz4AN)W=G-o77`qx7;)s0jE+aMv5C9w4mI%_y|-G5qgd4S;qf5VJ~Y2t=C zB_6`NK@9P@EP;QhHA8F=#Gx-NF!7(gyvpm>n^+!K<@qgkpg)est@Zp9+avJ*e`9+# zqu@FL5irC<;{|M!XM*7YM(8Fv4DOi~3APxaHXekKXhGmnOOKRk;!&X+bpHOcUWVQb zE%9(XNH*P!Vphjh$k|{e?eywL+r{BPiBbS7~&;#hBy@k9t^Q3+~UO$do#p7 z46!eC7!2_ghIlGNJPkV28R8iXaUDaffez#aYG8<;GQ`c$dBzYwXNX%E;ukHUyjKkI zYlgU$A=bhzZ47ZcL#$(n-@xy9%Mf=gm>tQUmTbc{EMka_7~)|Ju`xqDJcJ=OVTccK z%^2bl3~~NQhM2?0Nq{N(yau!W5b@g{>%UaS<2n-{u5imsHR{t|A46kgm?uBXQqDJo5nqKQ&; zs}!B!kyIo_cSzBlQgoLT-91-|?vbKGzU7lQZ!GBo|U5K zpp!2}&r8t@%+NyUT$G}hq-e1ey(~ow6;d?V1Mby!DS9PTiq7!3Dn(UNv_y&`*Y0?W zll_ApMm%({_c#{^LS(mnqB0}d!jq9fQJFe65T1O@i^{a&3QyWVTM_|*k_bWejR@h% z8_?dyf!nZ94uNuLD{-I_79K+2A+!g$5IDdUWYp`Ez?uee z5HN@nWE;l`PZ~pOh684>K!G(Vutp}{XeKOJ!y49b!#KRgI9O}0k-jhE6DyAZ{uHB=!8Hgw7odc3kw4f7=U&V2L@pQz+DG$2MzE&HGlU=9IuXf1KT5*Dl>U=8g!92f@+wh*v|))5CBVPOIUCP3?o1Fo>(4gq&) zy>Y-B7N$U83bZqDUxNUKQ?49svcS1Xf4S`Ai5wdW$ z@MIP|A8B}vG`QsutZ@k1bR0;Bg-i%!LYs{P*|2a50;izONr1Oh4lJC5fKVEhS%B9l zfWRdPT!Qur4qSnS5(tz)djkheJi@DKvEutqJk^*B%u z3r`{N6x!!F@EjIiLEsg%Z8*>d3vVIt7TOOu@BtS7g}}eicH%%MEG*;-PcG!bGnWj3 zDar8ECBriZZ7*J<7uH}wfCYg-yhdPhdH4WqV<4_Pd=RfO2nzt#0C2;6yvBT3Fo1vo zw8l7K3=3uuFoV_{2h3r?5(1XcTH}Bat@1RR(E3$74wh1MMh z++krh1ZG2vCX0n9QCJ9tfFHC8X&cV)p-tRyMhwkX;|*tWq20FO%sptPWTe3(%_t8~ z+Hl4InjNsV6SO-woC$_zSK8q-YoOhI`Aix#qBPB!LTJUEXa0dE*_eF!Gqig=FPr6- zhv!U8+k8v_3n^PJFN7wwKzdmSZThv#`|d2;pZ4ss5_)L^mm8rukT&{m543+zyKAW| z4?mc;?5+>Ahj!i#gXVDB>APE@J#zPMHZ&4r?cFkHGeBKB{7hbMnq$oi=pXg38&^>t zek?7rZYH#uDRnEMk*4L>iJ;A@uFHW&miE4`0@`fjRvk3Q(jDW0(T*u^`` zE}a@mgg&|W&X5e+%dJB|S>gi{aUjR$R> z-dWak$)?%<&a!8ZZ7#rV&%fF{#H+TD+&)70g}a-H9duuE-6q+UhrfzlNJj%o0O58$mw?pEV0Nr>9jD?N%g~}l5#v={b$ohxe7a4DiaT6}Zj7L*xF#}mZc>D;ifbxE_ea>N zxV-!E>6P*6_9|{we0tG&u7iqeCPPQaP)FFfuMRMDz)8jJhP&6J1I{XLAw^)GM-jMO zUlpIOi0+GrKil!EK7bL&b#$7<7>$@KkYsbp7b^f}5gsV6_f- ztGFz9TG%?^qvCq%Kz5uiViEbL4&=u%RNO%wD7qRqMaA8u1412`3U>q3fj}LYrs7_L zO%_uG(^cGM@#)L6I-|&OIuNe|)Ht$}l?dxw;rC_mLRH*dIvs)~T^FII7TaxInN@J?VCso6_Z+-Wj&x(r=9CD z$+Exl_fh|C=Icpa^!o2r-1mv%A0$ z9=n%Pq~ea0p(PT(61d+#m1MOJoK)_IpIRzIm&s7r9V~};P^mH`gS^mCBi86F6tX9xK-X=r0%g{%# zT9ORiAwxekkav2@&|Narw4Lls5&WpAc5NrSynw%j1?}YB;gggybW=N7BtykAG)vM> zcBKd=Qv_Gq$-MZmx>S{FI>82q4j7rEAxBG?b_v@Y_2 zn-Hl^>>?|5;6Q_{i~P6s1Bl${A|GsrwxuhQeE26U{OBT+I=Pj9H>kMBhQotgfsl`f z|6L(N%MtQYieMQko+8k~7Cw^6JrqGNMPOn__UMCK+b7wP`{C!>tLNL1zflC6 z+c(;g2jIQ;D9PU<4C1^z z$OL#<;HeJvAkWu<1v-%BQ3JmpwUD9LJ;)SzMJ#3La}TndBFH%eTlXLrPz0o|F>JEO zLyBNr*K{@+b{Z4AvX-;Sli(c(FAbXJ=_eUiDB>e*udPATp9OT z1Of2IL?C9pgEFp+=U_+?Yz+y?7(92%6oEo0tj zZ&DQ)j%hZW{ejTJd}n5!Yl4j1&D|FVXMe{;ER5*=K5^KNQ0{P}KuhBRv6|afV0fY8 zZ(eHd3uIYw7zSg~VcgP%P&HgIaI#|=kAIZRG`1`-e{a~G%rzbnL3l|>NC7Z-8Wk99 z6w}45ApnKsa;fF7C?~lU6?KNL>=($<*>V_;6WD#knrvtPIb-0+D5QTC0mR0RL}c7q z=F?o@B5p0ZjFq%KmNn#Uk4&Q*%%|5{#M&VR$OgN^&fDo8#6$EmZarKgJVmYc2;sSX zyTcp%liVz2fgv>x>_P2`GX;+gEIlcEw}v?Tn%y3)XETvK5lO0LBuH}M^J*Y8F zK%hlD^q48AATR`a54O*mX*vtjEpwlX1tXCpc}|<98Py-yA+&&#+>#14_axUf;sw$d zeAbHd!2n-A#^T03fXwFdUf!IIEX}H*hV?<}TVuttMV}%H4D}K2=5>aOIk!d2@j13` zWZ+18)`Pp#225oya34?ZLRWc%i`TF=XwzqN0P;r5gb~?sCne|w9{uz?V@@-kG}_p z%@g3Focj7QTNW$*eDoCWl&C3N{z;B*QQxN3(O$BK*2hEY6PWT)o^SiY>f87&xu$d} z*>{{`lg=LL~1>PSukXFmt1XIrzKYtpiZ8?87Tc7hXHU*m5Ym=e8B4-4j z#s?n!fRIl-lpk*p!{4qx%m+C8(|ta!{QI46DjYA|Ko?ro6eN1Y)u<>GQodi#dGm1iseQM1?r~ zjoJq0P6mX$&WI#)ZUZ9mbw*TjnsSX*BJF11(NarkUqwfhlWdC(1fXDODCNzt*3wtcJWvFCPK8YFoZ;6=fcmh)Fu|%#;MQ0Pbz!!>A@25?*V)!|^-epb z>e1UK9n2vRy@C07Fda{;cZA&beRgL36&-Ol80DUa;N+fcUn!*a>tO#y4nRz2$QK?v z>czp3GdlC5o^kb(o{NT)S4^ecztID(VMkSsl|{-m?M4lYBW{*}Yy^xpYTz5bRzFeo zKkib$S~-=Z;jw}q*XM^=P6A-;p}QZ(pRUYt9WocScrNNOOg-%E4Wc!T9B1!x_KDKk zpu*rnXYh{GR64e5fLiEubCy+KZ4hv%hH^*2>-)ymk@->_7_d3ZC!WvcfHBLxu9STz z7~_IX9e0ic>$EO|#W$P{6t)hvoy!2m*c(l$I<^To)Rjh$?<^NqbR3I5$|v+0D`yWA zT{J8~_})8s59V*L@VC${$qfMjneIdiF=0C^bJO>|Xgxcu^HQ zyJSs!4@tcL?@NU?GVQXVH(W+4M=2-{D1;)_JE=gWnw?tf^nP?L7k4MBu9v zCnQcZFG__j8%eS1n-CCs;?D7|iS?s$zVE3vWNxQjIQBYYDtUdM#qx*uXG-INuqAzq zVLez#UK25wW*HS3w4Sz$CZT~`nu=CMdq%^<2hS;Jbe0GGzoFF9+``%hnBDl_wF@_j zw4eSuWcU;#3_NeM!#-ojZM+FzB`}su`#WFcduSW;8}fc>NfNqB zU~I7Po)9==5E+0!-Fez(MXG{j4My0XQ8+Sj?)-O(0fmWr z_c(PF9*ca^`-*7)?|eg=-wj~p#VND$iBu=3_m_-rKdQDlcL&eW!8NE}-C{d^R{v6y zG0D@57f(rYxOUdS@~TTf{S18 z@ayz#`fhy$pNd@~fhtBIb{boYC1H<9PeoTSP_PlcN)27&3^R3xfq-~d*D`=I=XpbPMbV+Y0WfMYS0DL$i~#+=W@ z!&af3@Qk1z-=40#31o@A)SQjH^Mqh$rDt_!XV!>T3o$Bo|2 zA~Nty zXDY79!9Dp?`6rAK+tLpBUBBCPIHMw&==tlvW^h1Nzr6! z3N$x0jlHnNL>EEMdF)-&VTZm z-m3If`kv(kE*kSme{<00$T;lZzMe!d80Icn`fEnkAa4hDc*sQpu3$})r`V&<^HzS5 zj2hV^0(hwJN|H>pht%d`xS^N?)T9Q|o9wS7LnfrbwwbrwI*=A-t%HO_36ugwy$f(o zaI~_Kl+jQdD6nqjpazFWy_jscX{G`vy>{aSFhM_a4Rbs5AalD=!K`3%HK2ppq=w>I z3*YwPqOMJkL(Aee%(34-Z^kZGOgamLlAmA>WNu!;&tb&?zm2gm6EY_l@TvUb+RWmI z;qH8OeX{^h+L@TG3bH{;=|zo_(a{UAEKh z1D)-F(Nr-s0?R#oS)a^5#?R*utkOT?`yBJZg+pmA<}B9!&pd;n=Wju=`IH_@p|fzx z>N{~kYi>jwU0dZ-C0u*YamK2d*9c(dwMfE`NSlO_scs^cC`8n`AksNuW(6aCbS+kE z{fC9u%I2yE!#T8Lm_Ec43cj^D1_1S=>1# zCC)q1Rz&m?nFsB5Ce-BpDMRr7d)| zhBs5v=1EkukMS{ancbTSX|2UHWO;{e##|C$4Y*H0?w!AIp+fQG+=YwPGZF9B< z^y8~nYKU=~O(JppEjw^v`~3%Uky3PD)FgVpg}5Ib*p}@vOfveww7Jm>=@P(};AGW! z>I|NMsg{5S$(z($&R1Oip_|L?<=%1-eDaoExO|=b#+O@mxY{Wwk>hHo{YR6LY>#iJ zLXUxDgr&61UD&q*s~c^~&h}xo=5MjvVMXHDao&G8^Zvt#DG81tE`%BP4WNpsF<476 zEM;|x-Ym87zOa_U>OwDkpI!RBBfM;Vg5%77CH4`<&R&2ya~M85!Ah$T&~TnVW@~St z?SA6x<|Br17_qyM1d6F+$%YB@uLuYRZKh1a+xLkvx!1clTU>1T@x3GD#`E8q$XWy^ zRe1cA5Ii{8F@pLhPvN57@L78Uu35LuJeDlXH$EW zes3ZbfwOinIiV<*rQe%LEzCPYd0n+DfAW&i;QJfnCq~-Tvjl^X+>LQ{Y!Ga>>YS+k z{l_|X=S?RN(0MwRsEKDY9<{pp6;F2oK{ph+i#smCcYjudd!@wi8KW94LM+uG#*3*?aIf3uF^Au z?D$?`nUK4Icb&g>@rAxPPQBkt4s1VmX79$h7y3EtTJsT%(jUI5eN%gO7rAK51iD2J z?e~Zy^Xf>OE2|Mgc4x=zy7pG2S^q)5T*xxRYC2}}v%Mi}p#d`FbIB2D702v&e_#X7}KMF>4daaB>NXjYgw z9uw%#s{0kj>M?3p^$kBYs$O;dd`O`P5X^TP^G;=5;T?OlT$Za=sRydm&(t4pnBm>r z&j|)Qjeo~96A8%9VWX<+lYQ*C75mQ<_G^%RifqM(`>n`=s+RMFDh2Vm;*#d>y*<%2 zRexQFY+86mF-7b2v_9FrwH2`p(k^b{4@l>3)Z*{a;H0Ac(z z3j0lZ^&bkjeIG$n12+NpdFrVcm7e90lXrz0ygzUP=xLTqRYGbckyqeJ1@Pk!W_bbT3*E?H_4q ztDv6H5JpIA2z%9i#KLS_L&5!@{Y1xY4ShYM^Q%W25l16^J>V*>l7`EZ{Ggf9ZRqZF z;7|W1SxxU{8gWk1ck_2MK_lIV1}PkwW06^-l+V|W=F>z1j~(^g z01*$SC1Y4EFLd-o$+iU*R~A-wy6204k=|PWQuIZHiO3QMiH`)#I`qD8rDP~-tHeu$ zca=abfn6m`Ssy0&#h%s+SE$6Z7 zaRE#~|oDFMJsTSAU8UE&j*BC9HjAORtG9eb!^GuY! zSzi^YXN^kvS@Y!J^4UnaUg0CBsGY9fj&mymEwYhS#ylI1yT)G=s#&c8RoLJ6-}jd@ zUNC=C!TbYeD+8TE)vMLp)beZfT-gou@SUrr&4%|%{m!Ivo~mu%sRz_1RkrShM$X{{ zlI_MDHU=lY(}doRAJUj>O>4pJI3H~~9~Va6r9Igg90vmJhVN`92FI0ZuWB-O1Udn| zc7;$VbkZ~QbM$`NjrwwtK0|+2U#foqWA>Bo@K?h5DaxA3W;7&l2{k#^GPR#YQ7O-Z{?15GrXPQ#S`NJOWz=^k2OPTT56 zC7qyOqTi+8#B_9!Gwa`1_#3td(`dp%W)-JAo|(eTVmfecdOy-5h+~si4P^Si*E6+b z6Ul<(siOOLSiFZD3^AV`;PQ**`9n9CxtzI)na%-pNYuZc{+#2c8RUd$Z26vi5XcYX zujME4$8*>kHYZvGp7N8Pq`bx_CH%I##@r4ZY7L46La+&JF$K{(LrnJHYjPSc>I?+- zA~io)glC=ZgjuKUSPq_c+AR7YS{4~A-K#b*mef^yCq2_w*e-eA7c3dn(KbnVteud) zbrejIBxj?C*Qc<+UgXiSHP4f0=KaoC#tZxuw#( ziMFTZ-p39}-zPp1A$LRrB5+amS@b|Yy}LC#Vn4fYS`hf7hG>7Skvryw`5m89%dycx zr9yhb+{Nk`^$s{-DfMmtQT2z;VX9)D0x0#uvmNx8Zw{Yraz3TFtS~4qXjF&xus^DQ zs>6zV*epBEJ-?`h!ij4##U^lwZbdgA9{ z)wWD+Zr6X!`3EWDCP-Z&u*;!7}ZiXWxGxeE@&< zk@R+YFMW`Hu|7r*(w$TE@2~>B`^p;qYrS3%-1+~_g9EPubH0BqXer}=Mhz|IS1eZ z9#Fr7gR6HO;pA`tPT}9o!KZ$x3LCyy2>kiygny=f{t{m1e^CR-r@`;%;{*^(G=5Pk z1y~#nv~j|n8mZ7i^Pg;Hy$}&mL~9K$-@)_K+twyO$XF{%5*>-%3?ji%(K*pI(SKxA zMCKA;FWElsQs2BoU-s@+Zb;oA5qo_5CHo{jA$h9m_PCZ}X8Z9Ka;#F_C3$od*>jd8 zKlM2K=aVuf;*>W{&O6C6A8c%4z8HKbH72}CpVA|CS8;% zYcjUYz@X~<8!Hy;Jce^(;IH>HV~2h|VzLA$4PW+^p@)BtX@CR1ZJmN!2_`iFjyIF8 z5etqRJtcl?IISM|^e{7s|C`n?6GrEZ%h|zP z!gs|f`Lo?u;ZU;%{K`m5-JEpIY?}RYa)86PhEwNOXYcmG_8!dv=&RoU-*_{_RNWt@z)I z<0g{W(A53-&-&pBaGBNC!>;JYKKnFQ0$O)ieHx=F)->|fBFVK#qR27p+l*D8v6 z;t3i;5&=8WWXfgQJker{RibiQBN^;szZk9B+DU`Lo^)sW0>>Pt>r@A&M>yT5up*UL z4N@2Fqi55L=uj<*K9$o=2L?uNksvjf!31{kgOjyb^W zIK7K)!vXFbe@-Z8H7CV?Oj9an@i}mYb4c;$0RnqZ{y08xlCd&LIG#x4QU5p_R}@I8`|De4wp$lIfS#FT%BgZR?n|I4j7t9--kj^M86)QS{YYMaWkT&@LB=Wg@X?w)Vle z%!(JIkG>+B9Bn49YecR-do0q5x=Mki$F~f`3ze_HW=gOO>g3Jm$pXTka%!;4# z5ek~Z+(Qwdh{!WShVvB%%83Sm-X+RSGCV-~-ZV?P0tv}A;g&`P42&B#tho4v1;wo4 z48{0`lE)RVyjREs;b9%u#?d-%*OhMVy4Yhz0P+hXR9m}>3&~YZhO=WfIbl2R{C>w{ ziCAP@E3&+?eB+hSJvyd|Wf}9T<@m;%R&eP4v2gs=X59}b!;rTh{xd|!-~7J6g+ufS zh7{-jZ-^cq+UC%?^LpeeZ7oj1$+S({JNrV_q%Ll$&lGIlQO7Nwb4D-D+Ubn!w3~?_ zOX>~kp7?i6=1=T>^X*BWcGfY_QF14jToH?eb043(*hLu*Vv$(lS4Dcz@Tz9zB|~HN zt0*UXHIFqLiG{0w>)I%$hZf!#9}=n>M>ZF|@%X*^M|cbMy|bBwxBEPb^N;!neQ#62 zCFaWxF3*&D+e*x!_Z{^COTu8jv~Ox3cjYtY_fiO$+Qe`!8m(bcOhO~?7n%`_e=pG# zAEy}Sb^XJrp&HyX_r2YDqOHnh4$sMO$x5;B-5oqa+dh8D@HCG3sLrUwsZ}mxzUS?v zBZ$o^Ah8!up2PF+Sh6f<>Q3HpAuBk%IDZNM#=`sj5vtfNy?|U{MEbRkTRNGiG06?<#N7u`C0?CqOE}BA`cb4_B@nRRf@2i7M z^sRIL%6o?2Tl$!XNaOcr#4X58?fY)=WwR5>*8(`-tFnL+sX6J>+0J9{03S#CC#T2<*p;X*g0DLO! zyTVjGUQJiC)w|Vc(dshhftxP;d#BVbS*Y=iYyL%bW!_)5MkV)c_wX6`rOuN(!8O|5 zesbm?GLI)cjpeDa^Q)Z#&UT-RtoW5z*0xdehxoFzM)~Zs2!CZ|vCJ=8jr_`jlaudr zTI(`4$38KTT?^A9S?U7y^e6KT;~NY$TnWVL{4wL9#uwJd#5t8LYG zY6*Jr#J3r7v=3Hqp2d0VgFjXnP0e4hVp<-~#J*48^ad=EzR~yTe-C4@C_1MH_z90V zZ0sp--iiI@V)+ir8}4CGG0vCrh96kB2u>>868V!x9JPt)Y#4c}^NCFa&^1hwr<2yZ z6zz{Zd7@!NJJ_DN?aPUV6HTY&M`b1QMa(JB7z6LT+l^TaR##FUc|7YoR@ZA#X6{BTYocX7N$*%m zkDZ8&ZEBuEWmsg|yIx7GDWbRGee8S6r>Z_0oGxP@H>HoK)7=7W18k4an$VY8nC*~y z-yKp^(Q%HdqWcKPC=Y5;u*-kW&O>lc*JC8eRh75llaZ2ND?Gx_o&=0y!@wTM{3WGp zjW_d6nIEg)uXOL63}0H-OrasfDUn4?@b1ZJp{rjkzk-faU>?wellsRZE8P;Q{ac%e zZ=&H6*7XH85zpdSh6^0ILA*DDp@n;+0i+0bf2f9uz@Oa9zOkCdy65(>KD&qQJ<%YL zpz)FvNtUGGFmFRh>7U6=N#Bu5pONzGp)T@&At{i2EO!2wCwY4&&tmJ)Cc14rc2Dk4 zdUrHGplo)*uhW?O5T3{Xj0v(fBq6lrc(b~Zey%V59Ke0>DU zA|tk$YR7BoTDEqPHd+g|Y7b~nYKyguQH6~A%nmL1riI#rpN(@T>zVq!#m2c}2aXSC z7H0{kSYHuh%^eQZe2*(up>-Kr?O>S4dcgSl=_F+Oint@(fPuNItHdbME69D@*- zlW~Pd7(ixOrmndWVM@)Nd-h@;wwM(iNzEM*LrJL2zdC&V9D{Fg0x6$GVzD-3FmUL1 z+zK_HMp5?e#V{dj7&-(Y0k&$?xl=$2w4>b9!La@0dS( z*>4bK;jlvi!nLOCv<^vA>EWyZpqx}S9JR@ zQ$A%ETr@Sf>*Yj4-tUQ+`hU3k@31D)_x&HfCjkLLLkH{7#ezc-)U`~gf-Q8hhR_5B zLV%!aAprp!8bJ_T%K!>0mH+}$)S(DAbOZ}nLlL_UihzBd8QA^2zt8WF-NhVxc&wY` zp8LAa^L(8}s9d;kwrA;uBYiOVsLvF~*j-7qhSE$Ci(1NUiT zoC2M)y9c{Y5|zY_dit5})pC#MCcfTn8P(RJq0nB`Ei+TRPEMTv6f?M^otb^#gsa~Y z2DJ#X@0*&b6}<~%zZ0yyPyeKvK$jDXR^Dem-?*Yx(W8(KC{)OCFw(P44{&@HOGoWzt;MNgnL|nZTxi9yNuUOD&<+QX_4lppeq1sgh6s{FMBmG&v?5 zx@g>uqco*;jflg9bl>OF8_=o9@GX|J6P~PlLAYzSUWwcbF87foz`1fKjYqL9LI`>% z93Q8#-MkDaf|zHQ5B?SI#S9ToIhc=-NFbtvrXYuq(?|^hT96kAi(sJ^gatYWEoihp z*yT$z_@^moURu|IxxezSH8zdxaSY-?sGx0hq|;r!sHJt)2k&ZCXB0Ued{{vLs~}>9 zzn}8sXwgG)c4=a~c`Ue_Sc~11Ob!0z`BIW_*5JN#HG1lzThgx3mjf||ZKjX$P52(u6r)1yCSZ-SuMVK?C{F{w9F@Ac0Kf}r#!&JGxmK%9ap`7^J`D&eU!mg5ld_y z6DUrI;V>HCHo?YVwLzEuTZ;w9?B2ZV{aWHVuqEz_c6q>-1N7r`;0--sP2CzBGcV(2 zh8p)p!4N%fsc#G1VyCf9aP$i+Cf(+-=jFPyKlrTjJaXHHum3HW%5&iv>p) z?Q)GjDbyWU{KxaPoTq^-y4?8$DE z-ORo#%Ak7lw%8QGgVf26SwaA~H?+?S@sL+KRbew@PmQ7#KFi?WMO?_Wfd!lcq3Tje z&^n*CxcLQ*_o@U2R`5gk0bahSW%Af6ql%_YR)CbCrWb^;3#jw zCbdPx(+5e_^xG9;1s)_lNUg^%GwcR{n)zEE~T>Bk4XgenhswUApgtI2b`bLTo~=r(hE89c)|HoKI~ zj;druRl?rDXzQ-fk#gyA!865EgkY|4iICaG?#;THaR@t&0ST`KE4$q0wm|+2A1`;? z2tGI{<44a1pLdJC=|*AI!aA#jxC_UlvgAdljQF&{?AnO{$tnDS5Zf3glvsEnAQ%xN zJCWzaIw#xEu{5h3s3^uMLif>sa^vx#(;%OY6|`+B_+Dh_y_v!Hl%vMSjLwm!=sXtf zOnEM{Y%l_Sk& z60cSS?7;>Q6?7cRRQ&Kz0je2?+VFDFGicRi^e(#g92n1ocse|Do}GN8RO{PoEQ5D~ z$K~#JF;SsWRew77UkEzMbfKF4;*I5-p4Y!o3Ee22;|<0DF5jCU!cXAu;{U@x#|KyW z_xRoXul!L$L*XX2u(*LkP-Gk+ zA$G$a2}pi%USgnVmGnpkB(%gT8#P@9e5YJ2n9iky%?<<#}dm2m@H#+ipN!)@uRB6KFVX+fs9h&O{Y;dzo(D03eMxnwbUnY>HRNxAX$6A7r!i>q#YHl^$-k3MGU zw2b0YG{KC@rcP1S)NKkpr#y}ZiAQOK+XacHC{N)?+t*ha6zchLYS;~>A|(wVTXUJc z0X@g*HeFzPi?hq{ZoUt_b28H&;P`QuX%=`tMy1>G^;E;S(3}}7UVm&5HHe&6rbAv( z-%-x12@7n}w3xbMYIx%mU;DhBzNUnh#GKrE6ZPQ+I;JLxJ?*v{L_@VS0F*xbMvJ6M zJEV^GHfDBc+Lj$`n`1vhH^1AV>&h&g2F6d9#v!T9!fDg0^ZGM((kI}CeSLSS^QN$5ws z75)@D&y8dGqMdZ}%mSwMF}ab`D%vF(Y_2sOjKK_<-*9n2UN z@P&E!hvJ*An%0AK{5ZaMl4(6d$9{wVz<~xat)b3!I-wcwLf9hV1lU5P6UT`XqJg0M z#E1>cxVGy03d@dO#8shYzX?f#Zigy1Ddx?i+a?vYiaUw}3I(D6?tszWw5(p~BdJ!x z0z329KkRB9NO$s^)WOt=Eq2rl6n~cb^?r%{IQooc+B;j?6{SLd-~S=cy^a=)%FcFU zO`;%1LS<14C=2Qn&ok<%j!1fV&KmX{e|AD91O=>!qf)6H>I_v&JS`8fOBB-Y0N?7w0l8=IrDg=A7kR;Se0lE>8a_U=C6G(0cFL7s1akQ`jC} z1aGSj@QQ%9(%16s0bc))4_F)A7APV6%x(*e5gVB+vH}4GaRFX&X3ILOx73&(pjUic zX8!CnL3%$TLrv~U_e;^I>GAdm7tA`pX`)f}w&|it87I&!c53f;eNqhhamTWPzM|X( z66QYhw>j7BBv3kJl9zMTo;2gFBsY@V-$`7Cd1Ie<H1k0 z{o+9kT*j!&dB3y1PjXSToSh^$<^$g^w*_mz-#_(t=#csDkR$8CKf-gus~h&(wF-NL zgKSEy4E;%fZUyP;2rEq_vuM}k<^(UyKAE4zFXG=F^b&EKzt#G5IzCywCga0Ox5>Tr zyy7f1;RK>=_RQGXwho2_Nn88P1wo&U*N$>}ZbjQ-K;J^F9PBjIDbJ;kMqmFHD=xnTY| zxsx&iv4^t_MzaLT2Q(~r=WG| zh1kTrCy}tjkvp$UE#w0EV);a-A&?a_?c8azQJS12wke1HMieX+%wH+iU<2_efp50T zM>!?e!cB2|94x|D;u*?u7j5)UvUK8X^Z~PLsli+D7kD4eB6RP@EQ6*JA6BwmP_DC_su3Ie?3@km`6F4>01b`{e8vQ~llRbI&f;o{yW4^oW<0l8xj; z@-_M3JE{IhchW%7vChBNZkXOD{l_(YvkP~dV}G*PwW|aRqT;DED);Bh`PBoX@{_ox z+(PQ+*Cf^t%AQkrf-!B~`7&Mg+-cJ=ju0{tuH)P-m~W%>w_1E8J3j2VQr3Dor=9~C z*?EYg22X$wgvMR8P5>u@cGCX{fH%O~;QeqO%vdM%;KsIzEjmjDGz4heA7{6a;S@&~ zSV2rj79c!CfP6zzk=*NGzD*%=32ELp-{v_zY(OZ`LCsNT+kHvxjxO`R#qCQ1qeab0 zYqB?Da`8_4J>prtsUe;26W{KXEqGlpkbXR1VAo|w)X{s2NBx;4y`ahc4|aWNiECWx zz8#;ElV)>Goa0JmbD!9&WUH*)sO2J=LC3pHGTxm37FAP0?{Gh4RijxapSK+?q<6Tt z=Q8%Ib2iH2PHEtE7sh@S70lk3)RcM4woLF%CHrc~!=T~iEIM0+r3}*3iYX0;!$*pV|XgmHIfeOO}BQRq~(%* zuK&P)lYUh^SjD?eRK-`+ciY!D9dABf1fCMN>@{6K9y(qqzdl-A-vkWZ+K89Ufnv?& zqZE6X7d{@(ReaMwL=5clx>z{(Q?hC$dINp3;PAk%?V|73&lf43%rjit=PCVqX>+ei z_O4IBaCvcWRZIn08M>=?r{Y_MYSE2fB=7UIr^hpNuv^esE< zOLEz9s)TBw{NuKDb=zz1B45AwLYg?oC}usec_Wi<8(kSnqp}W(MPkv*B&~tsy*Ch} zgN&4yk?8B>Z5Q556ug!n`0V}XG@ayFcPEfuAs*H# zXZ3LY*ZiSiu)wdkHOI1t=vDq}8^&;#vfIzK+Q%Cwg0j9uUt+ocT^U{0c+p0Al#?6V z$q_W-5AoOdcU+xd0I&iQ_zB=c;hfUcyg`mMOz7|BZY0}Q>2fEY1Gx(E1K>jaykK72cMO+ZW zBN&ZkM!1Hof`iC7yl$lPgVB(+P{X|>UBwtM)%pqD6v3Rxc5_BwbeTK4qAmd4fNq-= zkiQc>ya2vrdb8&|N=sk!%$eZJE;{(KEz6kWb^WI&nFoj)yobY%o&!v}^ktU&=Z*1@b#Ai22?+WV*Uf=a%5r3&;7^TAgY!a`fw8a(I`9VQ0SH@z zMPpJd8a|0-!YRzh&^I9eGsc!@AXGjTkZ*P7W!b{B!Q-t%l@{fBpP0Tu4NYA5~+z|hUe&I&QLUNIuMZV_lA zRFh&_`fi6FMmdttgMz%kC8D4c%5kpESA z9yS&R0}@*}Q05P-AzNT86d6xg(V4|!N}R&qr$lkAdg$^l1PG-Q)y*0L?C%Vb9} zkt}e>{7u*H*!wg9ki0ZYpcY zX!01Pnfc*i*AHbQaXEk1GXBbFTB*r3_xZllOO$Ptc#;pQqg?rh#57_)@tqe)wDkW= z4b|kbxlfXtj;s^5Y^9g`s6dZw9pmJqDw#2(!l z*20;9oZ&d^&G!dcaM6S>V;uG;hVAE^k;P92&1=TNMR1j&(&oDpl{UYDL9VH_qI{b(OM71)cJCd( zj~DT45_^YcV;4Q~vU0fG$5EkN_uHq9+#hr`nKya1*BX4FSFwYJ^g2ShlUcqx4ce^OqZr*5^FB`X^!?k9E-BdbZTZEOAa`x2`U2LKpoQ8-J>#~om=?#lUo`Ih zV7rJ|j*_FVb4p|BO@utKpp|yNG$d$9yWfj;_niHF^ovWlEB6+8IRz>hn9Z)y`*r-Nqp2+oT5TY>#>nd7*IPa z&Wv(=py!F_m_^`K9Iy|^@KXGL*9O4c8^#=b+qjJ26Cz><@ol)&>1G)nPTp(UG`i(R z>crDVp6`fXgy&d=k-}Et@@TnBfm&EQ#Wi4hkOMTh8`j4>dM_$^c*&wu0aYU08%Wdr zsd1<8t2qoHY*iE}lLp<&BBQsfW;4V2DpDFrCcgaVwd~DQ(Q&fmtrO^K+G{#uS)N{3bQPj7HML7cO6a|=F*z=#tB9ekQytT?A=@iaLi=2?Nk2RrG4eaIk7;Q;u z*W!8g`hDex?gmj_H@v!&w%My^Xr~s*tK=IJ1CA#K%+bj5o^tpoSQVct%n4s$dQ@*_ zslLx9Z|QB71*S7g7e*-b#Hr-Cjej(<449j}J54I5(kpEUXO|(K!oo$W!U$ zxJTyVP4q=yZycT0{vdjXj$}-<9;e5?4O; zdg?QNLXVzURM)O|UCSVJ20S2kgK4GX-=M|uoIMLn(_;-MU2TH59y{7PVwwlPxekEKLlUQ2KX{LxNSzD*erLUTj0^LBC)5 zi}h5mnq0QLRKPu8kHZnO2kp53PRN;Y5ub`v3 zmD6Rt71HGdb?I5CD!%?gEWW@r2JBRdvk~z-Z*8-uq0|1#Ug^qSQFKG9dhQFybDmro z(;YG0q%d*OBNmAA+*TFpB^EKwJpIH8zEOowoUOjsKd#4i_(qC4o{tXJ`R?L}4)H-x zr09~@xjt9VSb9ToX>+5e-RMS7+b5n8`MOL~UdOYhtd5R=zD<3u&4I(uBCNZj*x{qA z@$`!Ej}%(Z!swd2j{VTb3b3E^?&T>CO#KJEmFmE6W&Z(hYx@IPX*&2mc*JSV7_Ifc z8%P)Giy)oNAAVUGu|D+Q>>rwgEJoHK^j*bL@`_mt?qut1mW&^6_5eDYxECxUMR7K7 zj3?_)MxjYC7lGM!CB`q!WAxX+Y#|JsQ9s*{rR(O_8!!QbTvSRY3}!`&t}iSxeujRU z%V)`y7yp+HU&>p@157wPi`Orya{Y+IJ35@f6o=Qm?>u$>q?J=_toSG&R4$le6UyJB zNLL(Joaf`-kZlvceZ_RgUjAAhv)ci#uyqbOHU zz)|iaf5tl|+busSIWNcMpjGZJ8IbQKhC2@EU@Z{fB}6J-Ejxod5biD8!|A8;_HgJ< zjp&bL3gLXt*wz?i3LApUql|5#`|@5nNIt`4X8W)jqJ`Ll_Ypvar>n3~%uy^>tWmU~ zGYC3-T7p+9Zakgt_(btRQA{{f)O1Jvx7D95-Yg3+QeM6~(0V?}+yP_B6cR9jmKw5! zeDNVMbb!o$0LD_c6trnbh4RoT^P z%UQq4QPiX7Pm2S^I88qJ>)7Zm0hS>5{o9i1{clThIA=JuoI9L93J%wOSXir2+Y&Hl zl$N!I`eYUqgV!(7yEB*yPt-Z4H#i8oDOa5zR2tku(H;eD`p9V-7o$>W-lJE6Tt^-w z?-B4DStB&IOAK3aN+f6E;vnWPh1S#55tg%q1zw*w)6&e!!#vS-rTIep0Unoe3doRr z^GgS~2^OTPro~(K^XHGYqrQoPEVKv(1y+fI7IcJMt;@4@f@Zb7%zKvTY+$pL=Yd+j z2TxPecwdQ8ip#vayiVRjRLW#?E%|@(m-5%~BRbdP!{L9OEdeFk87AH70V3zN#Jk>5W!ouGW|1DGK6i|MqCb@A zwb{qxFJt|q{_LY(>A~}i^;tFk>>98C6n8GHP^&<1nHfFI^1{2QBn zX~)u&SS5A?1IKptVry_l^RklH$h}Tl1oCOU?L-g;t?Ax#CZk+gaz?%wb9(NbNWTsp z<+u1;UE7|S;oXJxV?bFx1<#Q!!C9CPZ$b{@;4N|q|G(5YQ7)%TsXFApkd1^E{lA!L zcu0Fj-!Kep8gKfPiz|XDFr2agp)8$-(UWaA_~j{#uT?Aj3GiG&Dj-saG$%I;J;>Fh zWfUnPzcdEU=*KZK)BzaStSC>jxl}C-eNO%@Q>N(E)P~{uZbz*!_nep09!@C9>A5+r zy>mGgNHIaJL*I_x30oD&)edu?b7WeVX3ZZqh;h5WobC5&7Uy=qsj^bys|_UNOUg(m zm1J@q2W;?)SNrz5!!J`g8kWMDFsRlyuqib>HK|3f)9;y{>3wj!V*pk`#vv_Ei0eNb z8nkegbC1)_ap#ZH*@ngXnCTd8@MmIPD-0tL-wj?;1Y{x~$87MbLRR7%@$EQ3S(9xY z2Fqu(e7_i^g*bW;U^!ZK{dqZ}t&x#<>>A^b#CM2_VsXm$IU z(qiOibd&|HZYTV`(im~=yPJ=!-Y#`QC{&AQ${U1tKR+;lB)$N#)rMT|{0LW&J2TR3 z6Su`QbGfy$t@#G887`cRMm8HRV!=hNwxDhGjnFszAAAkrZRbuuwvMsid#7HW1+K<7 zo5){32rRuU)^d}Ml`(48+|rRr-NWH7nb4qW!Cm}NeW=C6)iwI~!+L0f!p9qsbx*($!06&z=Wjq3@kW(% zro+6U=EeHZVy#p1YB{(qe=aBGOew56J{$MI0bRE~T;Fq^Q-K>O9^+u1Vi4y|h^Hb*5w8Ggid;ppf(m)k#Y8nvE{l26 zMJcpM^G;gno=TT~k;_OvDI#}}|5hGprcVv+{*cl?Rlpu#Q#V#{vs99lZKyx}yYrWQ z)sQaL%Q6Z{#GihTFbeYvkpB>9I4>~qro1C zCFTTfqNVPj7<#tUvhZSCCv1$XYCYy3{*JG7)gbn!Ee!wb zhu>f4dfudeC0)K=lb$TKj2mOwHzny$C3{#gv%YSgn5HU&awo{F_GdwCR<_qzZ`Qr_ z$ywf_9pRH!Sm`h#_u7~kor7Ae1F*v)JrhRc4vKN5Bm7zx#u}~3{h}v3s#=f!{-#&> zmKx8R9pf1n^8XRJEe{ZrvRf^(am~eBFS8d||8}#mg5$7&K-H{KC0Z#13*194CKVnu z>kquRW4Zrw|0RF_qYar)(BBn4umrM(fpO>F{A@ocEz2K*G>amW1GF!*PQ7yo(CI(; zyVjGIxkv3`1wtO5r<&|$S3b%13g3GEAJ>0e@Ed%J%Ju@9ynkalOD?mzy9S%UF}_xL zCEpEy!vDaZHI?_Jj*&GZtmX-sVnJ>$I$UF3^tbSJ<-WT2EL!QtsXr5%U!lWS+D33= z`WRptzwFLg;eU5UWl5rexS8n`T4%lq!mSfE9?};^$uLlCOJYgF@VDIQHPASoSRW5! z8e50NrykkR(?gM>N^vdDRo1Qe6#HEP=pNQ2-BQu+#ji)Q0@5q8mno0Z@9ntPO3GT) z>RA(;nkP0+!Vt_6^T9$fa8J&_ht6X-){6CD1K2E;BHao|rxJob4tjJ0Te*weUmkuz zx0FG(Y#Re~ODp8eI_tgsw|qibsXds8e^Ro?P2rKph71QxRGLXjuU=sKlQs+9`1S~P zAb#jEtxuPr+x|p2F=P5J;va&}L=$!Qh`LcvrCM849*LUk5_D&p>bFZjnAA>D%vCsc zI_TQ6#kMqxusg=>;g{g&qyGV$o-lARw!Zov#nBFt@sK#pVJrzjsb~(`ub4?1kP38N z`svS*X!q2m?5S?-^~n(MSQJ7gkh@4)94A|Lij2RukkH}AMNLdQq6)2a{~+lkI%Q2c zQQ$m>?&PEPP)Df?R2|hu>8cccR)+dUK><#dCqDRtktj^mna|KFP9$e*6!;8fa!zt8 zIX5^@INw;Y`H%l@QEM?gKSe5txlJ5r_HbEDQ+rfM_hbN(O@SX znvCErr#*Oj3Zs%m4c+I_{P=3rBc;tN^^7y>B^_6;9p!yR&wFbCH8PctYdJ!-9Pnki z;i1K8o|1oy*vayN&Kl2c%kKx#$%+YdU#N7;j)nFOUT^f&>@zw|dBpQ7BNx3soOg81t-i-cZ9usCgd82nt z_$bUqU?VupG*I{FA`gRU8O}7X{+rR6O~o?S;XsQHkRgcmIxIXZJf$Fn-E67TE+;{= zU+O_$9+dtu+9pKZ_IpeyYAPx3;XyBg3&RQEs8&^BdRFx&1zIT|AGxpp8dR|mbg&C{<*D>d7IU(Ut-rAH+>)(w@YyL-A zetw=%+OZ`cAJ2KmUjZl2->iRmB;z*TC?h&FMEPZIXhWoIy7TlSl`{tkr6o<0cI$2u%Khpv1$H{ z!O@5hZ22MNIj6pXYM0es`^h}AZt(nSujsD!&<$Qs-YEG}53Td*2*rDAD%$#@^#i78 zF@1H~a$oCk>rET2M_bfXTQ@tD{Kh>?GOfRcm4r$^_SiTMk!sX%_0exXr^d31k*PfW z$A)FPmdvowb}qZ^^wzRXY@WV`o3Y*2hW?&QFRQ-BgQu0Zs>_I^;1#V2nzmCVp!LyGy1fT*;x|!0oJ;C#n^yS!3LPvQbd;OiS;E=0ter zgkP;(c&$&D+N}3hhqLe%IM9JDe)SSI&Hw$b zGbGoYLDh=C1ihK|s?#LnThMD0a|@?pOU__60*$4ND3dLw&Hqvv?Q_Y|Sg#?w+z6dPiEW@&PeD|g}d zHk4&_6E9NAGAMe^LYRW8n%zEaw`I>|bGLI-6o(Y26=jDS6@BKOn|i|`G%3o|fqS+4 zEv`2E&$+1F5gU-9--17(o_%1>ErZc1@Ad0ucjelclJ>8EwW1^dN7Xd@O*Ysbewioe z{6^7cAL2EA+p9RR#ojt#7B_2)?X56f*T?t)vVi3NL7gVB#Yee;V$Z${y|+Jp9^Is= zAS1fw(+jzuja@%Gvlr9YryagJ$`qHHN|p1Pc{K6W@M5Pk+n?mIS^OiE=lL&X8I|9C z*RXy4*_Xe7)`rbKEz}FDk7B}S7922#6XWO2)(mTH2&4Zl=79e>%xHtz*y+acs<7AJ z0h@X^{&j4NHSKI4*(8F-1Cw7lTJ#4*K7KMuU=a=bvQE zL+x`zN5q27TkL#~G0o!lnD?y%eYbG^FZ-E>JbDr7IGVfpQ22^09qu+GXPv?>8R^LL z;e8F|ZCc`x>k1`tjd+@>+T0Z0X&2UG9?<2d^q0sRD=PV;P`hj6tpN+=O#2v3Ac z|FBCV&jwG{x+Q!TVR9&(724h905hW(12}7!fDp+hg9%9~l0%Zh=M$1HOTb+T!{k+x znIxAAW_OvUgZ9Q!!Q0Zp)_J{)$^A`Xsk#wO*%cvp?!+7I(fgXe1U-0m{6WW&jQ%9= zDenZ(nQ60&4m~G}j>@v5lOpefJ8gkG@q^Jx(YvctU#Gr0{Ci_x%6;ZqMl)a2-D|Si zy3yM&Y36I(*S4(#w1`l=dzks!sw`e`AaG_;7Of&Iy~r*Vob2vAlblidI`vq2c^Q3Q z`H%T}5jUgnj}^w9mDv@dFZk=^q(Gr}GL4r7}VP;6NkOVu?m zm}Zh%*{HqVk>0q60AV|dvJ#UL>z`x{Chbp&Yy}Sa_Q4wXOe!E#TV8D+ z*l+N*B2RB9t(0zB)kmAi{k?ERQ=VSSr%ecG4->-=o>;R}cHe2smYtHZs`nj!(6Oez z!ytWdN8eC7)Q8-=ud>4ab?W+sL;H8z1KI+FW>>7Y4@26OrJJ9ktOeQS4`J0MQ*(?w z9-mmwu`~%6tM1`I^elTX{wZ!`Ciq)&KD?TYo zz$@Q+-}=T@t>O)a$U^G=Fo5YpP>i3lTg^IF<2@7i+SYkCjSBEk5zYUuQ0Yl*h-`gZ z@r#}BTPpC0`hDPi;P-zXqDITet-+;&u}Nr?cAt+{Xbx=_Iv*JS_<(7WGnhbHy{-|= zBR>d7hFn1LnPOi9K1rrY7@aF-q^7EFJD;=d{0Z{M32qIUG@yW|p4u)zRJs-u9dB zemgK*M#}~%Hw9s`$(#2v1Ho`t{a#1&5q8nQ-p6jN$8JUv?YRfh&-a~=>qF@0xtWkU zig{uGv8K;rMl@?0V^*prmjg2JDRK?9XKx21Y?x-ox@jqLFuO3r;-67>k%sec2mev- zk%NH?O^6{Lht9_@On>`lFA5}AGmrwhD!CcAN8aI51vso?NGr1QiRHvG#c5s&0k$om z?Vfj~@Y5zYK5goHVLg7Wr2@Zx9EPChjrH_)cXxM!B5Cy#y^>SO zkyQ&=Cfq@agv_VV^~*i7n@o$5P?Q4F_}<8x^fOqSzII#m+4Q^4p%xESia-GMMlzDo z9THxn9#L$r^c@u|qv7iuTaF9ooqaV|gbLCADYaX*~qeg z5Wf}zDGu{&c+NaCd_C_s-!KPc)2qK~-fiA^VU7agZ@eQl<=d}&jNSLMCqJ&(<~QR& zPvBGhAHLCt#FnxldRBt;%OvT1$rPBPDn+{`M-n3D zfvCPd+K+TTK?H%trB}C2z9@p)B^b04p-40k9%yNPA%$ zy$Qyc9`gN|Ssq3{^0|y%VL3g>yzQUCy6shM`;)ff z5oh?PiDR|!OuBRC?sXm*u^?>Z`76qY9?wWpfP;!c#ij5D#bfG~;@b;&hM^%j?F|F} z_UPFrIXMJ=*nfNYg}0A1`}6=^)H@^rg4Y**Kc1;2>7x267Hq%)w>TqZq{~ny=4g(A zYT7Px!=AZLitl?56UgS$l8| zy>;g+bIlK|yjH4Sn0*&?;o`N)xF50}`5SS-k0E~s8)q~8*T~x#?+4g3K(fOHXnzmYLEUmQJZQ!om7yH>_7EhOF!85k|VLx9h zWAZ&l4P$5`&Fkn?5q;d-d};$h$}L-MTaxCi63i9_3FC!8MC1zPzpgc_NdjcAgmLe| zi%L4-wH4VO_o=q|w(u1RN)y>F{!Hj=vtx&Px?=}0m$4}i*e}^6gUmg3r$-s6(`#eDdx7FmF2Y!ns7LIH4lC@6gIbTdS-#tDw)AZM zwBOLF8+ya|SCY=VXB1zfH^&X?teDdLvd_D@6|*65O#0cHULEUp$!#Ik3iLX<$TsFi z>uk|$8&$XDuPB>#UM>I8kQ)1k#k%*S;mpZ}t^UtfOt{bNjyJ<3=-f|C`T%XMNlI)WVy1g3n_@j&Sr$y~j-lc?B!8CfOIDaHrJd5L|UiJkP z=WC_zgX=Gq3~@l*kyS_}0uqq}NC86U9FY#>9dbEt#j{9<{5o~D zIi7k8rQSP6IEf4<@v3MOPRCbh`0I(;T!|yI+yAa{>blW+ha0Uu_FvN`@t}U0GG@eb zF39h(cROT@v0X7IdeC%oYF+D*lM}~F<>m0s@VK=u?TcF63-X`xK6*G$wug9Zz8-%H ze=dIse=T3g2T8+}}FGWHK?gf)?Kh zgw$>b4@m!%>n5d_nl#xEpx|wBsd9Z#Yjw8!XI^g)=fMD{w(59o)tuUR??(Z9G#kZ0e`s?c7a<+~B|HFPQyJpz8 z`u_7rK@aJ1!uxL~d>}7X7MJw}KDx$)4-On;L-l(b7IjPVf843?PCq@o{p3T;`X&D) zYih=?rQKbR{*NrP<7MaVylqEzF!0wgUCjORTMe!Tm!;JChrfctyMlU3v%SPt!0PRti_Z=|!B)mSx@IA&&H#q>we=41KBcwQhV_Px zE4Bio)UsCHRHY=}rU;2`?+yvA;*405roMbSYTDne6cy?VdM~KFH9WBNsv+bgH!cniH#IcN=+QNc-N2P z)9gdl*8DJKbp+3lUy_MxtIJx|lp%`cA9uL6DnP4pDDKgQdpQZLikJAQ-g^~uweD27 zPUcVKh8ny+5DTxl8PBP@-WT-Uw)FM*<*|$DZTe`FwcTL(M|(Xl@qN8CDqN42k}W_u zX=1(?nLlM~lPi33tQ@9){}}D^>WmBcq`#`OAL1piE1gQ6N{dUiirv2<3twFv9zDX7 zyI-(U99YFA)rJM7Wv#{dWn5~F(h1ay)tNq}?S)Tzd@Z4Ry=4VEz9&_nvxo)GB~bm> zQmcx6ZNPVd!RBc%QoSWw2i+hk&~v{nm}Y)kIK}s+a1CEo0>(>bNES*wB^Fe?Bu$bl(Jhu-jtgjv z!x|pX` zDoQNKv;BPjt;LoQ2bLM10 z^-32kABo1vr=MBT61tdi=z#zKqH}8!3=~d7*7WFI3^`HQJ*Nl(dGa% zjswS?vx@VDpU64D8Ha->WHYBr!EpD+!l?>d7~DXHxqC1(wtb|>HZVxOg6Y-GjG7x5 z{ntV(qoLM$WC$YFSeFS1f@)Oyd}m!IqzRkAxLQ4O9|2aJAw&(m4qKrvaxXL(1!9y= zN}wEh1Y#%u2=}9b%1grY4R}*|uMvt0&p++sG3XWSzARh1Jh#po{LOnJ{~-U*nm)t> zYWxXnYMX5NZL^l}Re1k9DEVgXT&=&%OK%D5+DyD$I?ljCL!8zpMO*OKqCwe^6t`~3RuRHM`{G9^qOv&6t( z*kNMb!P@35l?xn3*aPSPnV4iaU@7}cwp13E7M`ECahG6UT54_Kq11)3emw3-0R2Vk z*S_tKEM{!h4EEqI81Ght`PSAmf*?@rtF2d)had^aF2qaz%ohBN(ei#izxIT0#%_5U z7PZC1~{u_?P8E{Ak*mm~Hx|$N5OI0Ozle?8}R$VyJHr(8B)i*9cgSzkD|>(FBMDvyd$D1DV0g> zC+H@jc!Rog%*|Sv^W=>QM|v1`;{13JUTD99-Dx>~uDBIFfkC*>6A zREtB$u|jvl55 zOXp&zkqjN*jBCgv+QdUI34Ala+ylC0dNecyXXvjW)YD`%;ANhwc#f_!8$=Hx<9Rc9 zU?I z#Az*0!Mp&?2hKOw&)&;F#t)bC>-qNsO5b{2(LQk+T{_J8e>n#Vp?yj8`yQISR zr^^<|=$et#(WQ5@LA#JiijR@Nl2qI|u9}j{FACyLRmMnYm*nOmnJ@i2UXc;9Y1>bg z4#*C{r(sY7FTi-2I*ty;5i=Z2bsWLnj5K5~HZaA({IZo;a2f(p*L=2%1>(>W@=&`9 zdY70p9sSa>6s4_6CWb zE4BBh_wU75LDiv8NoyXcR{du`l+oAr5gm@DsIQ10J2g6j+2v5+p6~ z3vEzt{ySu4B;yu}Xwz|gq*aysaKDX{CA~)SHj13)Yc$i_C~9)u=p*;yg1OJ@_de*V zFSqjWc72xR+VMT$OU{=~!(|@YW4kL-{q4++e^#7^T%V57Dz|{7t{oA^Z5bydz}~Da zqfWA)d`T1LRb}I4(iyUaGEZ5M%m_=9<;tqSS=kkt;FlUUQdl;dsvF5~y(j7C9>(RO zNyAX6kJg!gK-kyo*kkNH_8ZG+#e!Q#K~P5Plmc^4CX3B%lfWkVZut>8V^M9D_s9q2 zKm{MMsD=y%;5EcH94O5k@%SqtBhkP>#^WD@_%ye0ASkAhH4cS9+kWE6%u>P{c}N7l zCcYCR+$`WLQ}wmN6^MNBu!vDbzGO$y;vTBD6+4 z-Ow_NiTj;9Z_i?GV9ejn@T5V9k}o5Sahd^XHFp@5j3!18<0oU=w~$&uaj)7DQblv7 zu@s+3_f`049AT~ZszXjYO?z~!bw`FErj~Uu0NEMX&C1>{$$b!rBBP$_@M_a&%-PY7 z-g)uRN4c$V&F*X9L(sAOzN)?||AIVbNKq+k1Uq;zQs@y5aU4&^y7l~bPlTMq{UA&F zIZl7&v>p)EI(R&vwJDMiytNXyCm_2z2ia>~;$m%PQc6ZBU-f47J| zt#>9&Hhy5wu01XAy_wPEA1^H%^$00c`UtH`S10O5wnu_4BL2T~cg`aJ?Z%&WeXy1z zuJQvv45S`JLQ|1_G2v>Lv^eNacist?1A#CEbD{C^?Z8GZ;UzEdnq$<|pxsd&?5NK0 z!0mC<)CcV1rLzXBkxT3LJ1Sx>p1*?{9SR>$yg9M|^g(W3=F=zHJuLMa7N2}O>ZK5# zcstJE0PM92&64_l=Mt)%H^x5h>+Bk|x!c!$=HBcx_u|{z0uX)IkUZxzMLCCgU@z?{ z(o~8_?;+X9Hl>2Dw1831Yk_524~>XpeI3xMv^$55AaP9Js5-B~bxlQOYHfLQ+pdZg zB^cIJv`xek0j?-oly-B}lfqnN{zklgIv5m3Q)Wq)O1P&I9HRuO0{{H8VUp95OA?yv zE4kD!|DHt8fWIUl2kNtbHym*_xHsWbBG*8a(&5nN_R}lz2{LPPgtU-3wH`UAV+lMP z?-(3;zuA1!3-^!gcf*_8KUyb#-i@buHopCLyao7g;hOa-^sG7}NAP?V(j6tIz=T!T zDn_b2zf+~?&gYZ1kL3U_g!nDj8PfWzHn@em0vlI3+BmVat)3#Lm7dkZ12a4<2?M!U zDfR?whh1@FFeeEEy{05{lrQ10)5?Ov)0< zI*P02kF;GBuskS$!sg+3$wLY}M=4+uL7Q=z?Pf*YxkO9wH;}qpuLIu0f=1Ao$#7}PVY7oN9nt1l8%I^! z*d^;Ge*TfmyBeRN@65}y&3bFn?HLGy_hA_^4l4UV;f=6AL{cMBv|+2k6|mo~CoX z1*jUmzpg)^??&-x?YERickvgy7$Ep8__BmBYV)`D z!hlv^cvAGSG^|KJ)_j^|v|2CGj!>9w=;iPeDa; zjbAWgpm*|HZ{q|EmKb~X)zz(nL!?(%cOxyqz*o^yDe(iJBq}{-(9xRM3!J79Ykd`0 z8ibNgDebD&Hv~6HFJpZbW&duZ@LsJaeSAh+VtW2)NA-0c+}oVU{PS482VEycT?lr_1q~vZGBr*GJnlA9dLk_0c1eeYrtu2fj<1( zEeAm=4*Kt@bC)JIVr})HlhaCR{kE+p$)mSxQMN3x z-*Tl?hr6p*)7SE(wYMC{!7g%ub|r^vF}M%5ersyIovZ1uce`q-9q>iIwwU{m)vNrS zwK@*^AyxJEr!mqbm#nm)l#k+l#!2{DcfxKAWc^)o|;oxJ?&%?pTj)Jvo+SZN(CXDQGtxTX#)KM?MjgyZE){AKhZxSmanfd zE3htTbz)=SgGm=oNvQDD#k(a*k2H^e+De%iV$1!DudI}6Jj%AoJ{Y%5gy1kCQZ9Kb zdi_ycfq?jrfB^x?pfLMDf%+xJ!07_R^LSGXz^h`$uCA00UjLl?AyQeqZtjD!?m#h3 zHZy27%ie(k{MtArMPfL7E4lj;!Epr8Y~8J zur!QM(~j0qw&pi9s<NPm-m~ zS+-9$of@*C;#Djx%s@S3#HqA7G z^e~r;0(D?TO~clT?Ztb<9C0?|a}MD9{Ja{-gf=n8nFWE&oAjsCTXlx?XE@(C(%s<$ zzt%Vq7W$b&ArSVt26Q*oYY@L0E!%M<+l*zya%CN0sUF|sOw%pJTjcJu>i2>S#V*zv zy+5o)YV^je|fsXRHD9(jvzki%Yqg) zx)?U3(P+pFYc&iCNE1-l$nmQ!o^i>|-=f7fO#=AK9k)o*| zPfR&a0uMwJ-uIjDJaG5B%L)EFk4YTON=l?SO?NjTMO!6>s>rVo%JFdFeh&tJd2b)V z(Pwz0;(h0DlyS;|xUeg6VQUt&I4R-<(2Yb#6gz@HYw|guM1iXOe#rM3ndvq@S zXr2)q*Z%(Cf)*$)9n~PwFxv2>!3f>}I2d5|wA>HqiI`?!kn(C}TEXsy_cI;nioq3$ z?1MeC;5N=}2k`}WXVmm2u*D-II6{t_knqLgMQ;tY(L0={4uTx_g8Uiz({mE_y6MQR zT)0N1BYNFF3TgSwe1w^;*VRUg*fHP?*2%ZZ_sZpqGMU}n{2ZT}T&EXY9M2VJPlA0%+|6WWebMY~s-q6u|0WuD z`FD_S8Lt+A%`ixhmpEBaov6OlFe)Kk$F0CDeFY_YE%`g|AO$GAm6$IUq>-+X_6RtF zNCEgo$rJpqFh-CFF{6_d_<0%ng*E|QD>G6SHQ|PW4zDX~$zj6N!b?f;l4rh{$ar0O z@h162hfwpLr(i_bIS`?7Gw@?}SE64oDcd@K;;{7n}F($tu`$yIw zbCVCWM4|Chdt-R|@{+}@E%HM=i)lV4Stx>3pg&AIHjV~>yC(Qewpj2~{($pMuEzr! zSPf%nFGPf48y9OV({InTpch!{F>FUoa<=mYoXd={ zMb+A6j4j8$raZ_-k44XAx|^5P^1mgwlf}CK80e?b%|gy!C%0!-CRrzBp0&Pw`0!Fs zxC2}nk)Sh3j$h(nQ@$~=fF`@U^}a*v%~>u0WNek+Sx zvHyrv5X&)mM*pGuIfYE^AH)*F$4=%B!{%Ochk?>;B9TCkgZ~a{4y|`LS7pp+JT+u| zUqrAz-ljFhWIiUyd;#W7lv%CS`@0F9TL(Pv1J8OF;MrZa6tOeT+_D~cdbk@O;2h`d zpk#6467pvPGOtkZgJZS6QmLKie{A&$V72M;%x2Dgv_Q!=;?l<-9X}@>VQyHF5SVCgcJAtl>3=KyF7(P>KD0K= zaCO$<*)-KO2fk}}8$H(PEj{!0!Y0%`bpUmBZJX8h3srQV}HrGhuqZ&0bxK!0$|P`9IwC@5ispjvk_(VOTaR7=!}@&{2x z2EKvdiMH9)2@ns}@?QE+B)$LN=s?SRB|j0Qr2qeA*Mk4Dn{a~IM27c`@TYuS*n4xKh%dI@ zUV?#jrF4qZeP_`=(NWPEQ5Xf_z$QFY{!64H-n=Cp{~cSXPU1RBn0N^VC)Wa4StITd z{}iusGLULX^d%iG8x5rPl06b`B~-IOumn%<-jqNfjiggDC;^Hx+e2(?!*{QV;dDkT zL&iU5+wt*b?+MwK?#jr_mTB6i8+w}GkXmHn1BlPyfb3G?Cu`FOD55;DK#tcL*}%qJ zJ@@)vWx_Vvn#RRi3jGGYOkd`QrIjVpqteGR^*^_fJDuSh#`i?RyxkBSb-qeIn)dnI zxj`|jfZgk?@9fZKKZ}nL-UnAh6Sb-hO@VJsPgEjy?_B7m!Mv>EI`-ve&!m|3TjDU> z>^vc6$!^1?_h7RV0?sbw6a3va_Z)3Jz7JUs_|iUTp2$N&JdKg#oO4GyI*9~3dX-5h z;i;#sMUz*EC&7PD{I&gZ-((K)2M0tnjk%mVItY(X4R(drSU+LSZ|uvj0|a<{+R*Yn zRKndfk`<=K1kC214b)(6zO?z%)>zE9>x+YfffF`)fIjJDq4){<)?d;X94l=P7LU0p z5B6z*4j;YW=A)?yv=-@ znfMr7#9(&x8Y<4e9HmZO50nQCr52?QjK`^dj8WlP1`smts$6WEs2@_pQ>=!XEShVZ zk4OFr)`k4Dm1>&R;+rD-9}W2-|H<9my&n3V@O?)+c(iv{T61`Emh2>JBy&#@tHxaw zXJjIUrhR(%diLBe#ryWOIo>85s{^;aeV#M>!%X|Em`8$q_g>rYSf{{4m=fS6`RtX? zIV;f$xGE{*Jo5lglA8R6pRD6;&^HV+yRrd;h2~>phuE0NUB(xBwe}`3F!f;`N5L^)!3LBEW^(8{(p-;k% z7?>tnC^8aRh@3>eqA<~E5np}f=&^^Q7uWl+&!WbwY;;1jdafd#Ck8fCC#`8*akLl) zpmv{{XH=_qk8i6`b$^UlUWorheXBIkBnEHoU?&An@$WBHf2ms1q5F(ZnOJ|AO9J*A z8!Jm|GiE-JAm=Fslq-^U39VYvPZ1yT)@kxvzk+CQph$e`iMTB$$#i6cK~3(yZggLeWmRisms6=tc{@il`R))b3PY z#HxkvOh=~phc2p9Tp8*IHdE!H52cp&H}mo8#&6mO|`JTIEB< zlgMN12iS3+X3Uv}PR8l9jF#KiCSW5AE?s@@zSN=Hc+$2W7PFL8$OB<9SGaqJZv>wV zY1#RhmpKeB<}KRU;+zp`Ykng*H@}<*UWQyYzj#N^yP-whho zv%s0ago3fm<#uO~uF&qCZyY}UCH9G%eQ4G`NgJ)XS3Zu@Qqn%LuLxgk&Jrwf={tAS z~ zq?i0tBIHtt(3j6zaa9cO3??0?nS#!6H_{sN^uiT()ZJ&>4AU&RM<0l^w<8 zM{>#6PWj;HsZfquGNBC5pgI1#nmyg>U$gSd*7Yl~#))?`mc6L#w%O|cbl_h4MSIGc z$d{a^x&7mS;#n_b+V!Dji1NGPbvtL0khLsmbS1pgQP`<+#+`U(=P`wwE(xS7QxIeV z`ZBd|O0V)eogvasr8!7wr`h~h2TD)wzI{)ZVn(r{+?r>uP)@n7tCzp?oz^4YhmMsx z2qK|P*3zvpc&7tnlP*+?6Yq2;_$?5`P)j9r>-usZ_pI1zd7n!)Mo{qO*rD}XH=k%P zCa<(iX02{j2&FtV+BZQ}Oo{qX>IKn(eLH@za(IE-#{+kh2{Rn`&8CFHqw7N@RPl~aA0r$W z|IYUqwqgA@Y&9 zUHtaszS7y3YVX&df*vKR`LMXM{G>Q81V_gJyskFu*o-a}F4cUU-hJ*3!}nVk4vel2 zM!)c|NDO|0yT0^|M?>YeS~f`!s?NKt>Z%Gl8y+vAZrn*Qe3xqY+Ex8px6fWDBis%4 zv8nXW&YTV(o!Pa3YxtH-U4_K*4PPJV@D|9jWrpw4JPltTQ@<8N`Lk2URM>?KPWh<( z$>A#Y>PP!4`TJ)ew6sU3qN;W%;=xDy{HH;B8icjpw9cs8)Sx%EKpTn2vyW73K7tyZH5O;VJ>SeSe9;^;?5r#t+U2p=Ju3tf3Bc-+oO z%g8}Hc1J~(VAq~mrcR*?6b>>KB4#pJ2#h~3gitDo_yK=dy51F4v-hieT_dmL+|J~6 zjNye=Po_-)?wlhWJ|~%@DY^%LORJYEVHiPvBA=^eoPG|G2WA9SRB7`}cs3g=swyOn z5&*kfJNAM)E3)?&3q6#uvolS%ul;~3#-5yv2>fSn83Qy)7+$5 za(^c2;dUc4lH-aQ%F35#k27`JhPK(NAZC86H+BZE{iqW_ikW&@cozT@?UkA<(zcTc zP$gtfY=ke8X|q@~?KzIl+O+Cl7FGX}`be`h-Z&D2ZT@PrgT)$SigOpJdK-nO(A8?9 zpw+lyJ6rbly9SN6U2_@o3regv37RyxKnvA`=HryxT3dZnC`3Nqg%YNfL%gkZ#rHG^ zpyI4M=9cc8Z}+S|9c zvHo1t0XvAH1A9rCi!H9R}1124iM>h$!kY`F#C$;(=?*dw^A4 znP{^$Q)GI$O&%i6iPZQ`Nty^wI;W9d6j>{qZb+=xVAv5huXsJ$5#|x ziVSQuRwUyUWdVCKO*5(^`PV>p;rZ=mEql2pPo}q8r|G>_EzK`Dlh;>o%a8?J)B9I1 z`QE1Y;&j>NYu?SGh_~Kn3QV5NeNp@wnyievz~AEUkEXY(TNletytR_qrGvS`6~awI z2chRhn}Fw$>edczG3iN^v0CEjXe@e52%i_}Nr#d~YHgU}j`zLJL1BqO3urz^_(21O zQ@nv{Sn@@k`<*^R<(*5^w{bNoe^V(Vt}pJtI6v85^J$=z6_S$^tJB(A9ZC5^R<}V^ z_>_?v;{$MXKfemOAO!nK6~abgmvBg^B$_Q+Ceqj-`VCD+0iv>4(RtDO`Jh|$O!Q9l zLqw)%igAnQNG)l%_>h=J>yZDV{27ZN(GF5*)3e2PlR%9lFAVYxkbE70NbpxM?l^Lj z9EQz@AW4!dndo_!e3htBNix9ws*f$ios>szi5@LS=KAVi{iF0z{(H# zRJ-0mhNqmvh?6Taz+`y~Zsb(J+G18Ad>zabKHpX$yGD&V{YDP|IMxRxhZC^NB>-dq zNXN(iZ!l6;fRoXZsRvh+63+K~xRAgi-Z9cyl8{tHs+ka2z$ocHWl~_-L0QTOh0#gg zMapeT15ZlnrVLY}cz@?mms1TO%E%%+QXTH$sW=%sfqF%sqrm*&k&bvIRZ#Ji-VpUa zDZLHob`&O^CR2LX(Z_-ps3EHlb!1Iv00YJv#%qQ<ARfP0Lmj49%8RvtpT z-aBGgTe3`S$*L6XV;yDTem4;dRIz3b^?Upab9?14`#olI<}cxFfW{y%8po02%>n;) zzQb4^XYn*AF4R#NElylb-oLWR;w5m17r{&9)0fN`OFFbO|7>^_<`j%lVI3c&a z3%<$^3(m>^hwnR6((hr`zsX!bV2!zs8lBcDzt=M-aps`zm6`K9A#ZaQpIwP3W!1)g z`-wzSr+$-v&T66FW?|MMfAyUfN{9t=RM>GwI9U(WEQD)1dgf;#EPB18lckfDsSksB zqRk>V(P0r!lq7oj>$V7xBvR3dd7nP~7EKc`6i3hI*Z#B;_fhtX)&IncFNlf2eu};F zlpO-<8}U@?xHy{vFKaUiZYah(8k(I*y|l{`k>t`^Qm0hXUAOH6f6w-%zz_tDRUZ5! z0ctXe498;Q>p%RPj?i`J@b8|IcTBCb^w!o^8K|`N{k3D5C|@y0r)wjHK}qmfuvhMk z7^Q^CS3wXeGAk-q?o6vBBv<$K&I)&#bvAXUHcU23R$Y9LhP#Y?*B%$*mswlg9>%aT zA(>`2WA#_#u(if?6_4d>8`pIj(>)fvJr(Hbv?2||Z%nwH+h0-7oChcIC10J5Ue!C% z)_iq*66y024R)CCHfw$-A$Z!)zV*SXKl`A#twO%#d6F2cR^q_|pO1dH0RG-6c<5x$N(L)mIB z=k$qCyb-Z=@18*jYvM_UtJO52c=NMQW~>s1|y%{uC1Io#>=GqlrMmNK@OZ;F6tY;z4Z!lvtJ(%c5)pPi)_ zUrshpHWOFkYRy@?GCCKXh_0+xXzD7F9y!Nw{AizjhjBs#CT(WQEWG}86U%{BiG#+9 zSP*2&Vm#p632{V2mxQ(Oo(A~p99NETCP5!~@IB(N2VUg#q#NZ#Co0J}a%(-I9(&k_btnBuDbo6CReDgKYIm$@I{Jc3~F`EM*9SzXO-ZykuKt zgVf^V$|^|h(Ty938&`b^+OztB3_O?N>_W?!8l7qKg>obLIREY(ys4S?8ZhJ@a@-63 zUn?}gcm8gsDuXpPhfG*0H8ubiC14KN)l3xxXBIl{;j1A3cLQh;{DCTI@3kk)Wu#Ho zb`qNuKmswObkcRwL(&TpKFF=4e40)%pgi}Z*>`xGd!%fZ<%*K6g`FF9pOk%<1!Cu#6o{;cpOnm2&Ld2 zueWLpJQ)it8P1IVL(|Vm0V;!$`OA_Qz>i-TI9mmHjy_@HRCF~=FaI!gDN*+QB zM+y9D9+rGMl31rr45&Yt3N(0LPajL1efCJuhwFn)_R-c9(>Xgh5j^z%>fUv$BU$(a zSMen2`=CZpd4u3_S9R?JlsUyMskMi5|~+rFnTwJd71Q@s>&6|2bc8V)1eAyC%3ZM+AgvU102e;P7D|GU?r) zT+Hd7ff%e2ZxOqTkCZzmw`Cvp(RXr+Es9vMl^8IpSc;a3;RzL6^pNQ??20VZ*f3+v zxz1st*cxCyz$DSdtJMgb1mmazmNMo9{N89BdZ!V(8CaRKwZV=z8q3LLP z`V)2b9Qs(O4Yu`Z1n6on;OJ_rV5)r@yK-levmCh#r_Vi1H;I^^8Zq1T_`9~(_a~gz z0^L)k2h;E5>GTXYWJk;+8_e}Z_z|-u%z!xYVGjl0!1p>Tq7t|49Li&{=o)a#d&t}{ zW5EB(oVB5cJqD#<;q>qR5p(_g<_v!~KXu2y4S>K;XBYMf#ZN59trb=l)O&bbvnOs!5?u5fBI*1q_6)90XP zC}zS+BPQNF*P14Nah~jDA$_0WWmz=?z1TCFzT}Aa5N@N4Sw{(f?c~y5mtB{gK_?sc zX3)OU9h1l(GH4_8I!!Y9V+IXksXfS_lrw0WOqYK06K15>1x7F$Q^DxcUg)Uhm;}p5 ztZ(Q#KHco7Wy`q0B4*GmI^Si`1PB2HJ0`L{F#=GcIrUG!MR8aXBPKTGoMcw`Akv|uXc1y(e|5@(oc1GuVZm|8!^bq3#k`U4tT%UQ760fkLxUFIb9r73V->@<7V}@4BD`VvFCUAO9Izr;710H#C6M&XVCQK zbBl6b8U*LZenAe`}ZptUPnJz}4EjLhu1jJgpN@R13Nhw!0KZ_?@+-o<3v zQ8D@P;Pic%!`3G2ge9qp^vZ`c`2A#Rl1;F^93MXxrrI*O?#AZOXg|ZD!9>^wRg{_v zlXPkD`*-(EkZDUpH2qocE-pTg`weDx(85(rzjP*5Bj+Ur4a(Lo!{p_2808iM0?{OU zteO03S-Hiv&tY0aHDfi7hnXZi+WV~kdzTsgrq4L9)%DHWlEj();~Pp_#IzFUTrsx! zfgGh#Jk1#ODfW_r#_%Q?ztvKVnm@VYJFjzXti@1`qVgXjLb(+*Abnn)CF)uX$2F-# zRaLl2*0+z!J*DGvjo*kd8?9^&PPC@sx!YSDJa;=_S#UQVS?j3vO8Tg`HRO5Aqh2>T zD6yhAFZS3j*ZQqtO{eUb$xr-pa#ypJuWUc|taTxK=J+!g?OV!2Q{H$iev2x0Rr^t# zOtS07c=t|B{kuTgA8VuJ105nJ*~iJM+||_0R8aT#39@9kSy8Xyo7$UWsx!2MlD5d* z<**s>sgovoRWK;GSQ@<8(|v}qrvq2RdWhHfx|L0?3$EYcaKXUq0_LWaA=tam=q>{% zhJDfK)d?~cfxgAt$;KWoB0teF(b?NUNx&9a7?Y+JloXUk7lehr6FnZS{V8&0lWqwN z3}P*84p%-#S5a>%F%9{9Jdp>gLVfC4YIv{#H9`F8F|s26KB4HMiYhlexQFsV{F`Q- z+-RasqrK=Az^U6XrZUFRRj)+-j6Res7OZvWs#=y?Ys_Xmv=vD;tXJl(Ew^ltC3du{ zPOtGQv2+ZN`D8q~wE^&IgYnB*7J#54K4GO&u?#Px(myV5novG>({bgK20k16O#l8l zaq)>xKitTb^mTR6)B*Z(#c}(&rwt0&`h8+Q(pS4b zieP;E!PRrz&-4YbZYz%46fOtuF6^ZbSjIjHEEl(htfQ)+&m*Jr9BHn45o!Hz%iz7m zO+}c~c5?0Et><({QS2Xg!}HI32T-L*3WjYb+j2){*mHf@n>vO)aLtpOs!Wl>^!(h8&Ire~FKX@CZ7%#ktdz8To|M&N2I*8HsTS*GN!I!XU;%j0YB@Nz-<>JZs!D`7k!%YHC$#@bi z%8W$?5;6KxqPhZ1(HW2^LvOI{+=11oj41=!jISF@(Ek>M%4DElR<^&VA8$P5?dj>? zA}6?i@bZ=GLZ8_s`5k$s95l&$*vo=XP)q?z1LU8zo)?_N^ZYC3=7RtK>!H zDv~^S2i60neRR?ek`L)HdWv+Bbep7nkRm0i&nXLWnkA^XvMvttyx#~B!Fci!0h>Y= zXvECkBeh}vvC_~uzDFADH&TDJfs&TH2Iq6g+u;-WN)~*xX=&2D1#4rv4#hTzmalN% zXuJt3r0l39;#Yd|9x3w0A~zZNN?)ggXiW{vN`I7&JW9Hs;>n}!Kk-WAG(0wtY_eB>Dq+;k?f&;0r06tL0ty5c3P~4ad?urM*nv9kI*rjh^xQH(sBzd0_7|YI! z=SC$9g$RPAR2L`bUe037k{p#W#o!a;H)9%WAq#&BXg5*0eEb~Ge^2G6?KdLQhc(d3 zJ6L$tT{Pwd zG4+$CFfMs%QvE0L6*4qCeb@y{eU}{uL!IMc3SFOmIeg%MrcC|zf&jNv?u}ag%ZUVO zlG^PLm-miHlO8Tjk{Bf(TBT){Q6rleJ53Wyg0Xk|&E}HeVy<>+XO2IW8xb@<1?PU) z1880OqccK4630mz3!!B(*gQ&j%2UtbLh^gDBx5<@+UHMNZd$`*`dLT`0l$fR-WreV zUb_8Z(fQoxTV#f-{)t1c4)u!v=S-1JI8z2SBle6a2+pdWb_ zwoul&%){FH{lcBiMsw+DXNPBY<^(77v9;4IdEV{&RAW%Z z&6)#;Wlqwht=sV1dLO*59Y4H~W0*7vv}Ct)2W5)#ty?K#*>I9Ff4!I>D-XnV&s*p^ z-Q{{ao2C5?JDg5=zGOQk48*Wo`B5c{<2gyY8rNOzi$rY~2QfGHe(QYkdNubbxFF|8 ze(SDgI`D>A|H}JdLpKjH4|okc3v2+I_+|>mmk2VRD)_S?X;%)U;)VF zAiSG`tDLbBT%Klf-f2FZBXp*Dd_>ra*R3LAeeFI{vTG@d^p zF)fh1{1kCUI0CyzfDUVotPFLRtzlF%abD)9J&&rH|FrL|e>)vh$FLhlUyRC(o?$R2 z5ae*gXvcUoe=A5fTA)3ILB{FI?F+PzU`F=>>^%+|xnM@VMu<`9*;dSP+|45)*$80U zEqrB0pN;;GUo1RmG{y0>5k~Q~Gdg4RS%w!XYEb0Ha?9Q?T2+p695rnb|K-5Co^RrD z@!EgV)|M3=n{(2>u0x_@`nP%zct7!Z>K5Z(XJ2nB`*g!EkC5FNzOE0V z!cM)S_NzBx%AmclGp~NM{TA=-V0v3HZ=%K3&Y*>@kpA7Tr-b)wls8qdKtL6A&;>gL zK7!EG^|{V-UQESa2%-@^!bQPtfjDM{-jmoDjZrUN#jte`A>e?@Ea6h&df||aCA7H~ z^%KMhi$&Lk=j45=c%HYL1VTpViFQ*^QS}$AS^FWc2n0~R!(eN*s6}*5G9pqHLrgf` zh9$)^ZaqocG(DEdZvJSinmjK0%HVRjPMCNR9!CA-xf9CAR+YLijGD03 zCs?)A$n4S-pl*D7X|c3{UZL_`S}dL6QKfRpZu6)BsSJ>C4-CVzq~SnmgTErJn`T#N z-|KJZ{s47&gWAu!1fBHDpnGp`!-VxYK#6F(vn6UrlJRA(-IqEaJG~peeFJ8$%X|k$ z%v_LpVCf}-f5do8abt%I2lqUuYJ{7fL_FU(B6x{HfTKSzQ7>N8!_=3;Awpx>kvaWD z6+&y(QWHXiXG?XwS5Rz}ba-R&h#6s}sTuK;1Soj!daa4567%}Mw>EZ`VlHsENaPX= z%@NTmO9asliT2bBi0!&2dL67q3>+KogJ!x*glIO>AU#cZ**~b0WbAT|h=*E(9HfIo z&;{6!b^dw^L#^A7I;eU~4G#=Zn)XkCyGLzclJU|@s!q&Ni_OjqHz&)-;?9X9R*NrD zRgRUCW5phBvEAx}%N{niRym)2qW?rs+>K%wXsw#;D29ZN<*{A+q{#6iRPp1FNGYl< z#Ow4xno3L4L|>{JKKg|-l;6)xV^pU(Xx@H%KKA=?`b%1+?q~7a^M&6two|S_(eKUT z+l1j!2O?N=X^N`Cqqsqx1KGojj43V+bTSKoI)5Y01A``+Vr^3gWjL6L*+x+1Pu!Zf z;?=UNwA8IR&pza}ix1)AGHsk(Obqt%U&Ia`b>KT+-lKX_yNDIBo{4WmYdT*#EQmYQ zIei>`&C=rhWyPEnYjgbL0L!=aUX_?gYY{`{OD%JLe~qJ)C|-;__wK_aBi0LAF5SuAo-XCK!%7Ar~O$ zzjp$Xkb;>Ct%WW^KjAUqSz(7zIEj)e{{sQG9H?PF-#(-AA0<)xxABk%Pj&iJ?bhE8 z16y+q)Fv6j6J7Rq#`ZPj1x*O)2LWyK6yK!^wBrN0QN4@t=5bC<* zp#;2;(Dn5KI}Mz4*T9b|GB8iJQie~l&@|NA7#RJo@kH}|olCMi?YD-94~QsufS^-Z z@J{wa27p{sULap3-+c0W=T7;4ISAeMy%UF67t0^ZU&)8Mz)kXcsuI-ztm z=dAfGwt4jMdh^~iZ~n-9jSIH4v3Sq?tyl8x4kNYwQymu*BMbhX4^tAc!lnTaMOyzR zOQD6yulz-{e%k1#Gs9)pWhw`&hakXK1e1hc_m(~MwSZv#%g_mE?cKD^r=T2V9v_7@ zco$$|DR>Tz9i{-+a+Df`c#|CBcx=E+r_7q87YDss6Ba@3&5Mp!PLPK6b&3so(>8M- zQ_C#a^y*C^U{lB(WJhEp9hnNP6*X%DqlT%7mF}8=SsLc1b0A-zc(lxNucr0LD?Gw6gD=(-XvN?3s z0VbG8gNm_dTfL`}!UV0}z&DaM91zQhWB4Wrjty50gDX23KJ1g_`T?=^KcfX{ae!=I zHGW^P-aH`o%HGYwf>*#+kiUfxxN}r!fwK+Hj74VV+Zh_)IJwu?nO*<44(4~20 z)@$$7kGtiyvVpItXLxPi8sT+)m-ySFIo3KQ*932F{u%DOX+aFo=FJ{@Y8&RxLx|SJ zrU4ARZY)szX0SY)HoR7paV1wo$cN>2W)8-gjFr!NhASC`O*RI`2F5-J`NoEL>Lw{} z49u#kXv)`Dv`J_n_<*77XX$F$X$)|UL6baZv|BouY@(OzHw0!o-6ZS3mjG|}=pk!V zo5I@Ge3RVKNjBH4uF2QOA-256pqpU0lLx*tFxv#F8mmHP%(7%Tvw&2BFM~get5~k` zW>zoD{}&7IcdH(P5Zf1t$k=4L2bU9lBte=1%iXFRMf)MdHbQ#>V*A*ekSh6~CG_vm zB*Zqt_7))7e4fbyQmyQ$h*LLMQsSipOo)dQSdwNBxhoQJL~o`2soh8~?7OmHZiJ zzdS2ko*;*9ner?b>z6&p#gp-|o{skz+|7Ka&}fC=V{f_FaEDjmct^R9%HK`cxWli> zpSFqTpf?tR#SiNz4eP(SFz_M^3$rjU!`vM8^%@5vbMCE(LsmpiB_LD(8vxlw!UG`M z0#Y{VE~%C@G~dpPI!c<|(Cu}+irsCjPZ^%KV~kP5(_xviHp4a- z)=SAT*4e!(9yzQM)-zc%hN*b`yG!${n>U!@G2-Cy58uz}Y7i%mb2{%`YTj#C(#aKh zQ~eji5&+0S+~4sJKQ3o!p3aI=CwksnGUWpTa@)xsKT64m-sk=(dY}DLI<2ku1AKd^ zh5q)*Yfpwr_`HhTt5Fk)y4(E%XP8k8oGSEQWA{^Pav(`is=8ahQd6_q^hxe7^97H7 z*{JE(qq)B*y}R`t%9_aS^0A*j3w6va+NO8rwP$t4+Ks-C{eFAn(ZI{oBd|%<5RGr>&+BBN~bj4=A{@`GaLj4WJ2k5Ya^`BW5Qn--^zW_V<0w2$t9s12}B|wyaB|CUC zKeb0ONP3w!qWYViMJ}3v{y)-m4ZD(cAHH4BgTQh(e>avkzKOSJ@>lUF6BKpwZDzqy zY%?F<#Q)~fG!Yw$E9Dh|?mxZLm>WjUoEb|YW>B`?Sg6J&5`Gj>y9hm+8s1*XyR!xT;J z2OSpiE-%t0IJt)2*@ zInl=g2!YYioLx)|*W^43?tS0L`$EnDnJIlS=7m>)-K;LS~wvi-f z(!QxjN%ld>1PmH@)$qk}e`OZP*&E_iE~c?*_lUKmHWE%pwz4dnroc0u1eux5;?W*Y z*mrf=f37)Q%F@??DgmHPpWgj+7N6oby@>-0%gM??^dEB;9Vadd(bBUF)uR$tEk@|n z9aNv?@rzF^38D`{GtkohFz2cNG4DR4zM%d~wOVhkumh!8=xquKGIfq~3~;3*$UgQ3 z^cD&$%U1=_-=jc|zBwC2pTStnSj(_y>|qd&SwuTsJ-+o!E+c6q=}jc?PvZ&KJTO!& zuRmY3b$Ghm$w01>aYZF#%`}DC`)?!Ks-pRKC@ITetcZ~OgVFfp;$P=^Y07>Frzsq~ zi?zdEo-vdbhvC6)I8M?cAI_^qaWt=I`ld1jr`Cn|g5a#nhILO-9G}>rU)n-HPBflE_F* z@Uk%$loc>zD!nQt7C+Y3N3nFioN0)|4!W`<|F8Qi9I0nj|Sfpt7ny?L}=tU2*;giPf-`GeGi-^Bz9gV*a9b z>(2KQc^x5J#Z`Z#k0mT|XK&+vQHK8M-6F?9fp@TJ46?30FJ2%*)Elw=*_ug&u>!5_)n>`<&#&9~-u_O1cyM zEAVS+52X|GdI}!jBFbhTxpfXhsP26T*iH=h$F!f``(Y>^hEzCLvStruVByQYss2Iqm;8@XTw^mEEKM#JYpCovTE1B)?%aQ zmk$h#QpExjfAxgzY=_Q!;c?nBAuI9hwS>&Dbw;{X&g^*ac^f9zWDSd>&~V|Y8SHq= z_-{v|-edu14P{vL76b3N4Bxx*lh-BK=mD6mm1JW?YNgK!uL*yK5VDa~$o|7*PFMJy z^l6ZbgDholvtn=bW2af2+L+6RknxA%8kY5fag!k+H}sJsG@7}22hWn`OatEZL$t;8 zi?o}x3R*1MMFT^$2cp?@OA*9r&9Bq*rJp`XM=^q^)61k6srcOm`{XhpWV}Wt3UHiT z<{CRi72@9U$3s}fl!Pv-v8s8haiI4WIMT6O~jdHL8&I(DlG})E^B;&yq>6w^3=S(+jjY z%X0NM{r(|J|4>8YeXH1kAy(CRDw@Tqn#VY5$n!l#;@TyS{*4B{fUlBnR8Y%zKEiU8E( zQk*;rt>Z=D`+4=LptpYfL?V`Z&FdA8@;v0@OzN2e%h+d9gz6aqlIZtR6}#o5CKI^= z^SEzPz=@(U4#(7{_dZ)Vw&(-1F@~sPjNNun5LGxA+pr9K z0QUq@h3@4VzIO-B{R;e!7Qo&RNTI9(a84Kafv8oR+WfM*dN7JO%{-|i&D6c{<<^pz ziZO@pUds}=n=VoRCi^&GcG?OBO&f%tW_qS@g#>IZJacbr(F%#CMWtRkQi+0UZ0p($ zA9v~9?tL8K)n&dC-0rrJbgo;1HE$)-aq8FPf53>a*Rg)q>iA}7=rJ-ABK+8k(RuaJBkT!1OKT{7ZJ6hmZT`}3}b}t~Q=%(y-P%yinO$uf~4*Q|S zP34ChI1x7$I;}g|;CWflPETJ2&U>eI@c(w-0kChor(hRnZPTzv1ZVS{bJ>CAXvK^| zjth(R=b`2+^l<$)-`sXX&AdOE{OGHh-QFkCySZm_{0>lE2og6AkpZOY|M=L0M1w`s zHvQ>{+LERbwcVjL_Di15)Xby=@AE(65xlvL>;q>)5S(EPx5*_lefy&?YBIz)Yye^1 zWkqW>L-e@TbD4uIR)`i!g44`u_g~Cc==j#t@Dg@^c9WnQz#u?U*N8MoWu#J0qkpQN zLOdZ+`!E%^pu*kl55)uNiYm7#iU&R=Dh7A%KjvmYZp~snpDQG$1yE9W=6MssrxXR* z$@u@2ga!t*Oto+BNY#7a>5_RdZI^ZOlhM_!|F~xVS)48D5l>bhlq?#=?B29Fy|i}8 zL{{2Ym$mQh-w{#PnG=!|GL`)*1G)w-9ncA|b(xA#jCr6dLn+{S(q$`3Ed7|yt+Z-QSfQ8z* zSgXtfY#O}-8^Fv?@EMNl1(4NoW}J7yBK%2TyZI%|FkHOKmtU#)0LAFi?V}wk+sEB2 zGIgp`_L-*Fs4OlL*N9(=Z+{m55l?#!0p;Z$Q{WfPV2nY|_=~dam%hd7v{t{2$4IbZ z;5!U1-e3KTE5G}a1$7)6Q?Z>jEvb5cns*yhjBvyc-Hh+;*c=f2`L2oDtgg~vLh{y_ zhf?35-&cWCcsee^EAgf-{A1Ur$jra}xa_dZSok}w0%dKTsYM<*Z3vj(F;3DTK^oNr z`yjZOS}OcYjOBMs*&MK%23%>BeVYT0(&A_tv|F@lnoI}fguBB%~K)SBi=qh`HyHCrnl>o-Y!$mB&y?r9~VVI@NIc$jW=5x^m;yaTI8iR zbB%YeXRjYOs>{kZYvG>c8kQaemJ{R(8Qw%-8rDA*0pf0SgP3O}fi11U;1?<@YGd2XRQfO3&^VAD~WWdJ`dVX=9ao$||580F2q3S(Pd{5A? zL}k-SV!36dLRWw48t?aEjmq;1l>SPNGW`D~|Gq)Af1>yYUpKV^~f z!jRX&9jO~#z(8`DimYhnWs4Hg{NZsVq*y<|VK36%_(2-@6Z*@4YG0wf}@Q`h5{4EIZiKnzkTyc6N9L z9H$Zf!=~`+GuKN-l-Jh$6@vFAd&I|TA0B7^_9Pi&3>RQUgPcGI?$+~#pNfy zZd8U&pdGgzZaZ8kR2aPW;2dMCH@R9;s8sHAkNe$1xlq7(r0NL-g=$=V?q#Vf*T=h2 z@v+0|jV|_y&e>_}x>XH^f4YRB*SJNU+3~wQvt6j+z{ROFH$*{ZMvHw##9E(w64fccMhsHN!>yeMyDGsjmtXCJiC{Q=dAKjG9i`og}rt zv_?XWu1}wzt+jq8!UU(jB+rP)gu+yMo9M1$r`AIB5nZJ0zFZSKI+e|6`(K{fqHB&< z1gh6d|b=Ee1TfBvVZt8iT6A$U#f>J!Cv9AL-s;J{p=$Wu=+c?l1|tPS2o!K{e6nVJG4!5RT;lVFeFm_Q&!4L#V(T{`Rk6x=>9>x_e!rO-D$Y?JZ~p!c~|(_CW|9i64pPig*H+ z$Wi1Y3K4-=(RtAg(F4(Q(JtD6XaWWV9DAWT<|cqQN-Prl!vj~aRnmIwJw|phN@8y* zFct3=ZWY5fXFc}L1R&m1|Nul7ic<9CpePGR#3l7|Q?1erOjh(}c%1xwTtu$M- zPs)?76lY8Cu*i!LTwzs?prXGwcj5#J5Qa!ag(X@n?|v>eI$4 zOuOm+R0X03ci?z)bO@MnM1ZZt7`pmTebf~qCaIDD$MA0ACxNFaQ-DZOG(3%^D{!az z3D3Dk(e@;>mMhCKiQF@eL-rXmraz0D*A1a##h^KIq*NC8sKq$8R^QutpHkP`O`9E4 zF%Te-oiyvGnk1`i#uWJa^BYrSQ}b9X=GBoEGBuHdk6&SqbRRlvbU$3**wEn_%}32& z`OG}n7`<-H4A51$K1oY;<|!c*xVukXy7Q3|gq^P%bXIShV9F5Bu-BfX0tRWnW=x|m zXGm$=7+j6|F!@6ZBj)NHsBWYl*U-9^Hv_mESq|<(L($XdCA0vg@xTiM?b69*TG&|5 z{JN+Bv$$k84NX|d1At{erbSiSG>F-?Pr*Bp13JJW02mZYlQ>_x1kz zZ(j9%+}B={1R4w#%i|gcic6!)if-wk2c{&jbP9JMg`U^FCnY-Th<8xMo@ijJWN{$n z`wnWWguJo~d4;?x9%$x$A3Mhxb%NfQ#8YH&+jE&hmsDeNg?27A6VrfQvq8FV~E)8J#V&LZShboJF5 zZvv3~EQm>`*fdUduuS)L!ku62#ZO4(NVwe62rZ9;lMfUf&k%at?Fy7McMrF(b`_2T+dgt= z0ko`7TGSsOQfTFsUpD1vv@Aiw6w}=Ay=;5)eVTm3bO^$=;3&rqt)a`mry4644y6-F z4Dpa~nF&gW0D8J-%&f%|rv%H?WHJEhFaM^q&Z0~A^-@B6M(|{s5pTGA9c4flCDV!k z;aF|mK$p^c=~RX?;|Lcl*A$6zz1=j^caX%kle(0PsB^k!5n6+)Elv0Qih|SPOX32t z0o%bc*mH@5^A;>=3ihnFI4TWe=cF!azV#05QMgp-9kh1o9)&&1mxUKo+eW0-Jazoj zQA>DHFJ{uTj-kuqGK~4!S5K7bfoki)xEE;LnP60(vzp_|`Lz%Y-Bu-ALaxH-4XO}{ zc+utQDxsm;HG9IKX1lktr?ycL-BUxQRzjsZmQox`WgKOX@MUV|@RssW-l)@zU}H@e z`T1U|+)ZM0t`?hne!><{uxVdlyi6r|@bqC93RCZaG8+w1B}NEYdnCqRL}Ax~Z9Z%N zO`9%Z5%-R<`^|IvR3TC*PnLsFuVy>)PGjI1H*Jpx*GK1nu{$t;=Ha#Gex+n}@;T+4 zX-ihGuT=7lY&RwE7T0W_?_KwNneFp^O8%2UJbzSE%`+_WWx%y}49berU7>})gWW%^ z`LqD4`Pb{a$Rw25s4Q$&@AWmjRJh`l!nGEJzao|+LC&Tyt}JkjFJ(juNfZuVqbls9C?yWPorxBqZZ`<@1NsXEli5o}%h)WoBfDJ~!j5IbHqvqIQKTZQ7}3_8 z`|NQZ)TG1&m4~Is!@_xvbAUDnm~hr|ws7`wc$|1nHm8IG>Nu}BUpXTj8dsfbz}wfNT2fF z@o*j@m?3~cR>0XYp2YRf9dV2gJ`uDbAS!lWDjym_Ps&e(PSE1BW9i0%Rsrja;D1&1 zLcEg@Tv;#;2^6BVRN+|Jf74f3Jo%`X})^988t& z$C*;na55l0BrQV$yf{lMq>a)psU};l>lg#5cRyjTz-`zZ{4E-RC*y#O4}6Nh!}TMl zA!I0g+skd!5Qs-5+@b5$``?;M)P=KJrECb|8qo zRjDxHlm@Pt=eKKyPSLxO4`-n?#@^8b0fgRG{d+S$e|hA2^L~R%gYz`(50@Ywd6F04 zog4r!z*}%dWn^LZbMETu&v1(-CbKDaE)S<1LQkR>SN_`1AWEP0^Tl z9NK+U5GTkG{JJHmKG_*P_P`^KMs1R~f#^d*Poa9kYn(;WGS^h*q%Hnwn{;-;IhhSZ zIF76*wvFBq)(hVY`8~p!Ig@Tsvx9pzM8vF03cIp?|CHZ8kqoAS>0&Zw zrE6-CMSZ?SYAQChLsl?MBn(T$t~sx%EWjROqIqCV(`xiYg_)v!ewagc!oE3Ma4N|GJS4zcg z`&FiAtUhITyE~_)z{4N z;D-T{0yTvg!0)kDp&iJ@Gbe4bn{85|!=mKHuFu$+$RbWZd)2MUuGI4h2srANN?axG z5)A}w0aBeE1_;9NYL%OjDwNDkwAZa(N+Y8fylKHS&_++AU8miriD@up8o~hK|A>}0 zGRbk-40?#Bjtw2S(|6N_ceK>c(1rAy$F$U0(3D7rOE~&823;e0p&Bx2A;XEK7TKhC zGhlU;lOUtY<&O4(FlyKwBcC$ex$=^O2bbm~ygPd7-Ju-4V|vs0x|UZ_LPuo$K_D^* z=Zv1H2M4ws@LSLy_(c8S!k#xqc(CGU)5~P{Clx_cOMV*5EdBLGR)L#-2l^ti95p+d z)EJozO%Fv2KWYqQc;Ug0H+PZe?|*RVRXz}x-XHuf<$p&bLaXh&$I-CPe{kuOG9WHJ zzNSamDKNX6zdVv{*B43U$t&N)r>UApip9$4vwaljo-kztJb96hrz zLOoS0H~_pmY!+q~ahtKZrpYKnFC@yek+CfI8w1kPZ+94aoP2lWw5sX6xi5}ge8cZV z^~NHU>zyr8;DyyY+ZR63-deJ}G&&^&1Glv2G&e^_C$B3T_T5?njKMyPSIQ2a^F9-+ zGTK_w90v@G2be;@2@fta5!p-t2{0HX;Q1)VL`NtjnL#Jk?k8&F*rW<|e6ptJ)K7 zO=D*?>MU11U7PH>Qyc1HW&o_Mn z)d4>%$+X?qI7OhWIY-|%IAGZKcDA!-7&fv&*HU&kI~a8peC*c@o2kwY9#-7ie|&Jv zUpRdhfCi3qL-JwA{&vJ3c3+ss4%R*kw*op0uYh~?t{Z~YZJPH6%*OsG9MnPh*smq( za@}AFqd~@+L81FGjzF7CmlzC*|3||^Z6Vi5Edp~g)3w@xW~(6Bf zHvA{I4&6)tjiWBx4WaqHb+5n}F0&O`%@K20{u{NYX|nuvt!p*QP1rqa*<0BA*u3>x z@^UgSDPf8S&fW83l1=MnJK(PwR;TdA!qb?-;vghzp~&io@)wIDV~P-^-a>sjvW{}? z(>KX%0M=RjO)OG2OK+$&@W99W`*~B&zYuSv&*PnBlx!fzQ0dTNJBPI_KKvJ2 z#XA=iaW?!{V7XAZ-D$HgT(Vw02ZXMa6eMAL){q)&eUKqzDlzr85XKw*ouyp_^vXQz8bJ z^auNLK`J423{n2(9Op?!(1bOp#d&7-8t2Z;nOozM-=<217T0l1y7Vg)LYG%oG&84V zVijMRYE+*3BAPi(cg(Uq&BeH}gmiy^d>S@AuB4R~_M(?oDpjU~ZtktXzhPEN^aP9J zrXq9R+0*o?f&xWuRk@;W-8@|$v>ig%A?ops|1Z2FKrrF*LiHsC8NEfK7;^Q`N2x}B zE##|3cGStA{Mg3mV3s%!=cTn zWatq}@sIPAYcqO3^n^f)37lv#cu#;ID6ohtlw0dQaU8b1Vb_OG3t^m|}ZD~{>#aQUBS-+AEN>=5Pc%-AcmyYT#HJuUZxWKpfs(YDd5{N*PO&6b9 zt)QeCtnv6|f@a2Qg_p11b;oHRJ+Ws-q%ASN&w^K_`thAHT%Y`NMRY&|4IdZGwQA9{ zzFK`IU&UWtHn^DO;hEI77?pLPQqyxGUyr2#;^YvbZ(f+kAso0YjdWu|D_c zqTx;jk*3H<1lEW)-CVZeF*XZJ7cGhn6!Dv}_ac)ALFR6l-|aOV2*!;qf*RO3jm6~- zp2^&bN3l;t#VX%AXxkRTA&+uf5g~J%FJXRyFy0vfB|*#ILMgDF%h0+O*qy>CxS~T< zr>e_@DO_8yi?J$Cb4*4kdnb#HP-OV$V!hRW1?*uQW0;8KGZ`!E&ncHXIjf%7DLyRD zSY56fhE}dQocCxW4(up>EM}`(OJ!F3QWQlgQofQ@M`|ivC*3ODFFh?e4}@K(-zpn0 zDmxjT;@?MVy1_j36qb&S-Qv*i;tOa+K8m3dl+3`1?)g5*8C&%z*cO;;OzP0IJ<-%i zf{-@ZF)9y@UEnOpRnK{L(hc?lyZYyr^)2l8Spu0K?3Y=`Cv5RcO-|CjJA|_t6GY`Aut@Z7EQ9TUC{mOnx*`JgXuYTh?GaJ1y;h9M z`Pft@HoztbM&;)6J*(raiE%=D5Rmm<>^Rx@;kjg!`iL3c5@v+LPm66XdpQJQ@KUW= zPQ2E%S2(C;{S)svHyTB+NF@53Za=?Cuokylm7~uC4CIl|MmK}cc38f`SCc?U){T$zm{l#Qlq{jK)8;^?2*OdmeATZ<9X`?~)7mTKdDU_h-GP zg1sazW{ORlL8yUE`;G$?fA!?x0GX7Ka2~Rkm&Y^iNaj61E+=WsOelXyku>@xC`I&i zn|(HN+tLXqFW~>#pkq!iMU{wJW7Gk~{Y$EzGb%#^Z)w*)rKAtpjzdIxLc&4(L{~v#_=jH|dDoubp0O!$#FdXsu^dySMd+>V&~1vd zGSAp+<^3wo`m^=t)fkrpRcYQ5j)hzEc=Aam8z{<{RGJvA=A=b#@Epu^5THSjvoSduQ&~@{_VP;%SWmqTSRc4O zq&9ypZyAqu`_1>?cRZAix6UUe|8#QdeYB1D<)EmR`GR*put*%i^S|-=5Yj^VE~Wx0 z^u~mn=qa6WdXrPe2|AmE?s%L$ zb{YH%i%=eq;4~9%5N;RB_$Qj6h_Q)7S3d`bF z>M4ZZSYHA5R*TysduPioq`jXdP|#E68!bGg?B{uHpdsJ2vFPt5xuRbe3s)-eJ1l3Y z=9S)~fxLT;z73h{`)~ANd5`-WGTR!iCMwqqO4Giyz-a;kZs9Z$WIA_3N(GgLEx1mt zl|N;CT{hEUQn}HspW!uwj**}K1rzLG=g&SnmFd1z#3{DZ_LiWjRMSo6rd@!9CX|_q_JQHRv zjY-a~b@>*`mDrR3vsG#)4Y~S8G~=x*8&GKpuqnAdVXHDsUhLL4vMaShfs3(%i_L?B z=-m>1qwCWrvDMa3n1~krF7y^;FUk99QwWNN<1?itC5*@Y0|Ac*EqlRklRYY4@^+ox0Df{Dm~bs6vb>0serNTd~bYa7Ew$Ta9ORymwwe->wCrBahlHDN~PpuZbid~2hk<8`+?lb zu6>zvtrhhHorB>_u>u6)a6#!;Tg>}vKj3{Q4_ z9$ZL{9h9$OinglvA~PV#k$V`&!#%R%A>2c{)XLzoOskCbXa`uLtkT)@Y(dFXX7Lf1J0&cC zY*R5*v`(n87Vm=gmJUvvm?~zYCT#P<;qflfQy)+z0g5|0nIO3NFcn=R{%#ee+PSda z!3)9Hh8>+fk?^q?MVXX5e2AJoI8=_6iXMqR8BSx!^yi<8b+#0WU&6d(KX5YK`j8m` zU-C_ppj>Em`0D5hrA4=wxaQE1#T-zDHQ%aNe_wvg?KSNiZIlM&=>gUC>N_88t8#I$ zq{lt3Tyr_M)hK`-K~JUwjM8&Xr$n{y^U0+O#$@`RVf~DHZRDvAg4C;jp@YBl>5SX& zKRA%U1BYWD99a7pJVrbtn^D4O(#ULJfby8yfbWc7JOxw}r3uxAeA1M47(IoOH;SZF z6$e5pMHNj%5~tvX0J~yBUO>=O3AC5YLQP9;MXp^b*PD7 z8zUvNdhfpiwE+yC1&{WwHee_3Fz*ykE}bXhH5|ywuYPv4pej-VW`%v_mA!F2RZydT zW^-k9KUfhSPq^1@6*$HO33k=Q2~0Bt&M(RZa5^8Y-iyn8j1zp|-!w3)rU|`1RpG!n zYAe3#wOO)>iAf`QHyOB3IL!d#gD&Q7XR}X*VfV{iC;;Reyn~*Q$o# ztLDfF_B>K|4Q1EOk%Mh^6-S$_$m;io00q##^UW3U;*t3%kTP&vhQHU^yihO3q>%+f z>yD+TfmN*ym8U-5=*fy}j`S;BInkc3Y~Re7Q}N+yN_WqT7_gas>?31-`q0{Wz8=~1 zFGlJ<@9`6JQa-PoIQwPa0GaK#LSrK3*9cvCR@8kuh@HcxJGE#_O{8n3TcrEm@Xc?v zRL+Xh3W}60TA6D#JX@w2ErZ+6NJ)7BRr$6<{1dg$+VF;ToVoWd@I71+1olzYCIddx zy{gjF->_DF)|q(6MdsZ}i%i{L{(Sjz{D#%9Ut(07U!#6j*|4E<(F%oG(FlK$>9YVN zJ4%}R(!wHF8ptNm{ouQlkSgGsxDmbvmnHV#lw zbG9#WkbpO=xA;#eoTTDt2xq!b}v1^XDGf_R3! zU|g~b#sn~EN413oi6fkn|J=gDXZZ^CAk%%(%>7_q@L?Dnav+-(k7lEw1g%3~p|PWh1P6QwP~Rjdl^RNXah1x`x(29-N%;UJmlzdfEi~4XFJDG5YBmqk>M-+ zR~VVT0=Q=|GJItKg;{&@a^KioPwv@3ZWK3_d)4>KR-L^q2-qum%zeZC&Ly}CJWZYv z5By)-s8|eM@|Fw#@U{uZ;Dmxs0oW zTs6w_CGm|K@t-WvZ;VPUt>@|nOW&)Y2;`WiF+H9_h#cgY2Ix_#WeQBiBOR7fEobR< z@2j&?HrgN?Eh43DDbg#_JJNdTdnw$bS)`3cF#lN6wxlhMi33aA8Q*~)!cXEC@m7=D zIG9a)i^p#1*O4V=5(|kqcm8u@Ht~lONX%N1NaR9DzUvxSTgAll+-^dJJBbFhNdFxG zVrcJ^V5gEpE2ZTfD^qw&`!Qi-Z^bq{Ll)$i%E|AUKnJSyMRaqz9o>U|fKGnbQNG`} zENh6(-Rg8MtWCL%4xYvYm~1zi&M?`uM8lS|nR9yYHa~_7vZ5)1VSz%9X`22`xE!yT z*7&fe$1N&Vqd}Nr`Y*>cDphW!>OUM)N&03ZIZ8U;Q0?GQK*VA5Fr`ehwa=~9&BOL? z`|vn$U($aZ(*}a%G%OoLStYtd$+j<&Sf)b>bvIAvHlX$kF3eO5pu7p5im-wwBQR=a zxrLHLSr#OjVwt;HNwv9-0qLISCdab;<7xlPA0&MKd5ey)f-}cU%7aq47gZ!uCJytBiVM*Xi(-q7}NhkmGdgZ7i%QBHCW#DGy|C;3nXeK%xJ5Mu+p!} zv{B8pxpH;X3(;QLVy&HNK`~&1QShn6zsa%X&#fz7SDwP3()9C|$IdWn8rh*=fq>== z4Sx?rN1eaKafdU-0>IY349txFUxki{c*xs3;`c#zi7c& z0hWfb==bj(m&iOXKRK6rQf09C+RO=JRWVp3HW%Af%PVXWLjk1NqkoEST5`aPf1gl5 zX4=U~XG@nzS4pqTaBTwe#^s8;o8*m2L~pt@_%JZn!=w_aaHY8($%dYT%aKC8Z5>zK zaKDdA76)-)!@hv$;}}jFIR^2G1b-H>m{>`K669iDb<-h~WSHLVCW+91z2yn2CB)>C+so{9!zJY4^Wj!t%bIy1s_c_Uy_t;J^mT{g~U-U|oYs6i{ z-NfCqXSu>X*~DJ>;yl59H&G#1{m{j1l%U=SQa24X^M;qfe9G?7^3MRJ{ zDJ^;#KBkPk&6}$A{A?vD;Tk^Lbz*QRWSnKHDj*jZ8UJi91SzMmZC7+u3uAu;N8t#V zc{xW=Do~ni(3p%!Qjq11x&{p&z@T8FaF%f2^2YcT!i~bMBmBnrKw*?{T)08AyasMK zzrHxqDe2YD{3(=~;&mO2bT7@%YoFa~of9>Z*Pho69md=9_@a_-QYV=?P$P^XT2u5h6`-V32eDQ!=|xm4Y~Cydx(gYd z+@^ifwEk_yitWFGM~>=hj^U#IS#Q9a(vW7@MX|{oY}WaoM|-Oh>Cx6Yn%+3((MI%0 zk9JxM)$os3{iNk%xOz6(>rFB&?2V$Uj%ey?jz`|Ex7!oigltur;y_{hhi481+)z47 zkE3VM1FxllQ@>{SwoV+8zj;$?cvup*z#cP79~7^crc&N1+tZc@expw&idX$m`Mh#R zn-%+4u)5D;`oi^{lj0W4*440Pz&7xWrMt%3rI?X+?lv~iU5}#~L;t!n@BCraQ#5@bMR&>%gix1#qzw$b*TPA6PkfPXfNfFaG$Xrq6YAkn5I*_8Oo zoD4{^X|SJ;$6j3zXu)A+g0{yT+PIExiv`a<4Hho$5$SQ`1oBdT;FW7gty zC)QGiH{+i$oQ00`Pa0Jk;4$M3FJD)=G*e+3oj!dUj% zHq??M!*04x;Y62?tFUa-ZO+1fz71v@EjEfgtyfmVo=`q>J6MMiDuGs_x2RV)s5FE6hS;j0Un6=C{W;^pKjoHooYYfxa zW4LKt=5_9UuGsrsW5B()+#lRXz*7v}ee8v@bb<7IeX`g2M@K?a&GDcXbpvgfP;%yF zTjH&GS)Od=CiX;v-o_wAYF*{hkHOJ{{FFJ1UA3Wr)BnQMITM{UlNmPsQ#Kw*fG~0vT@DwW-FOlh`@- z$5H0x1&^_pYktuX>Y&wT6hUtGbz*OqUDnyfP=^2lU=0ZbV*r9jvF&7C%hIKC*$b82#ijK#=xy&ijI_WDZ>3CLa;2xBcIuzw2`6uuTAHimatN3Y715P5Xsf04Y zT0kr())SLxT$nF&JBa|73C`X=;uZ0g7$JNF1nnlJKwfc5A;*52F~@!q_!NSad=B{=0vai^=}YL) zhe-FL2hpSH;2ixL{T}@py^Y>Smtm+d___=;hUZRK#%(l|!LdIrcY>S6utb;TANa)k z&1;FLR3sp^!dBtbs3#2Da~~P}e`u6wzR=0=2@hV!_8Sz4kU5vnt~`2tix5XfJL`2l+V?}qg2KH_7Mb91&;I`(YE(FKx*RyvY`F>L zgl;!0k8nVnSjd6Fc${X=N6s*33Kz_SW6Sup`5^bC@B$a`rQ{9&lyp2%5|u6?BPD%` zVi4*sUMMf;G_QV&Q$DYe0;SglGEXnhA42B$b_BMIKQ<@{z?dFNuvM^Mz!xM4as;4M z@JR4l@J%o(kQZtQ4KH{E=B^XUVQW{}5(Kf|06e9|^hYoR!c1W~gPdxBwMd^n1|Aiy zT{WM0m3vvC7$JI#Mut%uYF`Q8~SHT|Ue zl1H9zFQdqd#{Icc7Z(3cV-{A-{@e8arA;&xflZHDSar{qc<1p<jP`c{lzzfC1t@F|IL;cO#|)b%_sC^hzChj%O@h_ao&j6 zlD-#>c>$))Gx`HZR{JAA6DWY{fy|RIDcd?v-jNSGa>lS(yIBjPvI#;yY&`=&X8;!vDPffXfbJC$bIjSBIgi)^=DJ)W?3cnhy(I*;7Rh(BiPK zlL}^%=6;&Ux=ZeQWipzr6JNc2%kJ7V-Gz zJeVOL)KW-NqSC*yR<@K`lwvHNeU69+DtS%3ZXOgOMSi0*`*kBgNQ;SJtze5Fe_@D( z^tJ%m?;(;BL7m{0fZRXNNsuj^b#~G$VW7vsuCtlTg=(K^tdGar&nItg-;I7+hAOd8 z!%xYEpN?#LdBT`Mfb(d!>DB6WLnoGp6J}rL#>+%rosy}h`?2Wi=JqL>Q*wJOKfk=1 z61?2Yd_EK>$iRMDO&&mT0;D>gvB~a*DOfXU)Va@Hl^wFvUM8$w-`JMCc$2g(p^8Ec zZP&OfnRK`#kkXdm|LoTSyrOy((uKd=mE4uI#VcHU{q9^Cr;}A-pN+Bl&)Q}L%%^pr z6d5Qz?rS@HY*$!?cnn_Sp+&KTFIJZf?KSC{Q*1oJ6Bms>nV>348nN1J;|(zfe)nQrXhp zRf{JqXiHYrzOS0;4?AsaqKZASL8Ty_ooOfEME+lkPk+_qr0qEeYjL-$iVrBgLDXpnhZYU-@l$5sYFFz3Ere5Wm2 zk0Vu~+iin6C6XSL!iweWYp+3v&Xt(}l=_r2fwM<{VAIg_G82Cz0KGA0bK31Cd?VERqOTKhBml`sT<7RR zq_{yQq8sx#!L(uS`af+ALAEu_oy_Ndm``l|H!x3~IE^!RGuiI`rxjyU??Vt}e)O(2ytZ4Sq!aCGNmG+{7SRcU-kx;^x@&w{ zv6&5niKd#4ROS&S&doLLp^*pskr%F$|3n}uM!wgHkAh)AiV+eKy~|n81?0uc zn?z>%mhv5`9iH+gS-pAjm3radC?F_23D(cjQ($3=(Tk|}0ieE#=QYRoqVM~F_lKFw zyGMGbr!XZB>o2i9pHG}v^kGm|zS;GBk;B=GzJ$GByW4Jyx5eAAM7>z*((ku|w=(~D z1UoZ5WV*a4CSYRl-RB;`Q!3sR-=*@mx3NYwLOmx0b=+>e%}1E5(V3xM&M$8@-lD!M zoG`lz`FN|MU-MW1ZY zDvb`IE^Coh)P&`Wo^iGpQ#cP1zG7!jpOUYucl-sbo%-~i1{~{s=Xs3KwlZHK_rv;~ z*H7l|-d|+#xuYwad`I^PEoNDC9vcQ4>DsaWDg$LNFm(kj5>1l^P-L!YP z664GVw14>MD&a?bb^h`Ul}i@NjMTlsD#;f^9AAStH~0r@mE`^V8L1oLum4t%BSLT| zVr5#)c1CJN*k|Dx`vpSQa+mMIc`}StYip~UN(&$|=dJ9O!pz;GGxigYq7fx(N_o30(%xcYOaVQ<5Lt|CoY9@(j9;~`Lyu6`9cAfMY<<*ZcW24C=m8-(c& zK*%m{soj3KfbcVR*4@VDvPbVFjox;D;wGQFy`_hIT~BK)!Phe7vmUaS@2svx_@lRD z!;sSZkvsm%XK#^ISI%TFWP_|2qHdCjJhDywsRiBe*L|=}y*oKauzpRCfFi8MT(CCN zOBO1tai4Sx6~1;N?Xi!3d8AMuKabx@=dZx$ZGKF=A-=%7*=~2!{{cRDC&z&Io(sH(9hRy&2o(`oUPvO@JnGz>WdY9ud?U4skIK;P-S}Dkc z)VcKFHpoNeXum^8+d4;d4K2p;bQr1Q1Bjs|ROlD0eBNH|56GPmf{3Z)d*D+R6anqpPrl-&d9zKU%J@*^_PF;gb>_a$`SYF<2qKw5;W1!(z*2?knm_b}Ih*KU#{VPh-Q$^j z?!N**%{kBgGnxcPisfAfxgalS4gVYC4`VlKh+3fbXrvp;vkO2Eqmys(>~aH`Hvqd%BRn^cePNlxsB0*cxUUX2E1-}8SLh$C~71d>9dM)eT2W)>c z6F&z3%1Hf{cBpBWNd$F=m_Gl&o!-`~ZTSXa%y(C6t`&&Q9-zlJ)z@v8f}rM)qAZrS zBum=F!jm+fSYi#_X3 z!XvZ(Dy}>~UJ^+q{%DbU`gQdSyqkxfKdcD{z4~u?Nz%*GVyO|ot!6b11PZ+P#G?-PSNzDQ zXL`;2anLVm&GZ4Cco4V-*VWm#Q%G!YhR6OLI$wfkAF606n79d^`d^I?1qbI(R8m|B z!Q_vksqS_jbJ@s5whLRmXAP5mXy+VD;+8f~V?wdZwt#*q3KBu@>W{dY zx?ZpU8p15y1hpMHp2!0_qvr-?y=qrVoi+FLk@x!V^~94=3_}V&&f0hdoRF^0YM2iJIy((3A3gB!5SZW zodYH$Ytm}chkL%H2vQtLOBLjhib#Bkmf`x_-7wWx!vj)SYdyldK)XpZjVh=h+qd{8>G{Nu9~xBA?{OckKV}i8cLbFP76A@%Y?{ z(@F>a6D)v__bL8c-rdCi#=j!a5*P}2V}0;b77D;x!Fe^lAVLr)xFFaCJ#SlZQHv=g zXnK1S*58h#0chgGf?a*Au*DOZWu$W|<7Zcc?ZO~oq%c{SE5s|m-V4D`;fRndHWn`s zJBT-n1H@1s6{R`Td}tNoM9q8T4l&S^YD$(asZpCRc?|=?_O>8Q5-UlQT$enOTt!FH!0tvlVgCm1EsnHnwzO}AXV!gABfnpBEOap~Ob^47 zEk2|LTWpfUld*nJ-F}O42u70Q?Zd0&FmozDBnP-whe%$_Zee%If6Mi-$gu($S8Nh* zAC{zO1__w$2|MmBERjbex3dkM2Id+{-6vt~`@v=+e+YGJqjd z4O*lLe-5pWp@uf|!f3R-BiMiPs@P~=|M66&UIc%AOvlmV<@jf(g9Zj^nvAK8c?>4Q zh2hJHU;tRp!MMp7v(@e8s|vtGfjO$I+;z?oJ;dUo${U0uvE>)hB`h)OpXr0C&k^yO$ABU}$;x2eW|gu={XN$JJFY5wBKzYjJ8sjvwcL)kQWZBis}9!5 zEQS%;Zf7?bJqWZIobc|9bADo8jD%hNJ&hi@QysJow$1VA#ss@L{qQk&e%RKvdndn!^|PQTAjDu~97qTx3wu3;zd$jKhLZDE|I;YAIt+p5)DuYU7 zP-f}sWa;Sw9Y-qSNSUQGUYI(RDi(lx!52YJ=%q4gD`R7(XI)n!|ol?JF=d*~ zRy)FYoB$5~nyu&xa{4SiyXQV*l;K*Wh@-JY^xb~x$m?gwhH%-EC zx4{A}4l7?gM{Kc%AhwX~6&uY~Zb5ki9b)t3$t@v{G?=%P+k5IbPb+!6iGGoxQM+b~ z_)-15mJkZfPIvw^LVybr%#LQ$DSyRtSf`e%q_Flq4MzJemAOgG1Ma5!LUrk?3EO@5 z*Hf;$4*q4FemYtz?W=3`?A_{o5@CPcr8R5HfQ;)Txh`MEfnWQVl5nxEms?Hi1IbIt zY98$2Zp}Ye=D3LP)^Ty-#z9~SKDRj5@3)+ft-{7C9gKw1F$e6CvUkMkbw9zBUhAmu z@?Ctee!sN|mc#>>d0VhR>eSO7fJHcvW^NP#gYuuM!nESwZ^nfUp5h5ek2Xw;rEg5gwT&_P2p_Hbn(;uO!mmQ zvKGn6_S2OLJRV#jKFHRYrQ0I#czcETHhY$CAPtN;p^h4%((s<+LD+Q6*tm35n1$%l zx|*?t!OyToPc!<(pn&0H`l94Dqn$Cp7>7oZ{ zrn25_%FY0GELWBv>*3pI)^9fKk7GqXXKiA4uRJPLcaN0Q*+n%b5(oBfx&4KP4A?;n z9teM2{&=guO_+npDVPZcD%i!+Z)_vE7DvpnfbE;WjpNVR&l#1c;WS_k9PkVK#nIq} z5Ur!8^K5v3NKY|nU+8&&tCFJX19<;RvRFb_i>1+*+?Sm`@br@NfwI4dmXCf2JVPux zZOoqP_x*4nJyw2ichK6F3Ew3lxK<7Q3pfqsWw^%?Txs{ zR{Y{-4CVh`wb=ao%+Xezhf}NT3t+2GJyW7twW?mSO58hp(i9?viH&+S!=9uRUL##@nbCsIp}o(xM({1IAk$tll! zgP%2ZdoA9(xz40ibQNBkuzl(Ysq{m96@xs4XR&)p5f@VFPY6?C=O!+cXybsG2 za&7<{Am=ND-j^4zJeT4}ug;5CQeHSx zHo{U{N==;C$0!asyK82BHfO7}lGDuj&KcrF;-V9lycJM|1+TBZ2k`X%+@C*q^*mhr zj3_Ui#GlPy#=k4|;)n8?Oq4cSA6{#;v)jn(Yd(LhNlALdBkdQ0q$xF$Pg#s+RRs{dUif4@2o%DPjPN0;P*^E!7Je663<+n@ zXeDVdMzFN7j)ovym#tzK!z1EOQnt8IY*8t07JnBHiGkb9dR+2<@4d5N{#l9Jc~8Dr@Fy7~w%K|q^Pe^qnD@GsbFUx>-j|P^~$c(YFPjfcj zApq8Kmvh?mBlyF#9-a{+jtBnhZiZ^)42_Cf%gBd}SBztswU)gMRdkXCUTO;sBT+ka ztoaj+8Bb68XjR;_be*e}2n<*cpjWTPZ3=fcWvvTMRub%1YOym;uUO1G%(~+Lj zYwl+5Stt`z;8Mw2=*}dEB)>zQ9&z1OH4bFi4xh;Mopvr+lq`x|dSJVqLG~V2$+ijH zWl?@ZR_WYCC=;WpCd79yADleH9zJtM)hei^&c#l|hZBdR9umU4;k2h|SE_O>(oU7z z=R>Mm_te@h^G??OAFgh{?mW{QzLyp;Q@Ncwd>2l7i_5F<)}}fn+#3_}%N8p{h;^lJ-ZU^*PR&NC?aBN+#4fG=%0jz23felgLMdKp`wG z{SkV?ix9(!8|d@i1t&ba(&whOh?$))K3lQ&jx zkqkH1tG0{DvtAUqPK~_iVMgb;$agU{;yiM_*10be?T-0kup;@jMY4agzxlKG(TFL@ zfBUMHsPl9V(6>lYhUFolS60A1O2_(!&pHJzSM~G5bwxgZuV%qx=5RDjGB2~!2sz?< z-8?LN>)!N0R}h%@r1wZV}6~p z(>sj}qQ*I*LjwY4o?n5wqq|VNP3K1Qg{Zz8Xv@2&&#jIAm4^A>%71X0jTg-P!#c!D zUjHA7|7dG_<;et0rS?r(dpL zRFzfZuTGGcr_q1YAC?*a8p_KJa)e@j;Tru>wNi{;^+_K8;JL2RqJN_AtmACw1no_a zzh@vKGY9ONZ0m0BQINBibc$8M#bSx}%^;=ft*l{^`Lhu$IksBy^ZSy{$sF$395 zAyLCOMp5BdBWH7PTy?w@Aqau$%wW-FWWV^NIF`Y@EiQAd_NI&S@_fIzNkrQNmpMlH zTK#4fqXbFf+4&ODQ|F;P9gX?s*1mE8i!>|oq=?hnF#H=IxHKiuc5`F%$DzD>Tmk(< zGWXHS$SZ?+^d40MQ6LmR_a`Eefwpg*i}c^J53E$O!EKg4X9i~xCy|sx;&7s%&Mha8 za~Dd`e&8@*nq!7hV~7rKI`8hbl?N7REPQX-61eDUdnnI|rL(A4a{D>L{_M5yIpStwQ-=I#%!|<)`MVNke;Rj1Z1__I05_x`vrm&i6}Mg)Y&-h zb;0CE>Ci=D>W=5hxML9*7OcN4S+zwtw*AN!g7?zO%SAMmFJCU(oWoPB04iABw@I=U zuM<~h+9U;wjV7S5%n-dNK4$;r2#dcOEY8kk?Gcu-UbD)dDeYfNz^NP5EoN+6HeR(E z#3mK+6r(--FHW*S276h_Kfd4DhQ_j#?o4u0-4xE;K$N3Z=;2MkHBEC}psS3&=`7|h z@zSD)oZ@GvIGLP$A*YO^dHLS>q6vS!EdFZ!*~Pqs*LPrHnoQ<0SiFVy9x#ROCTd}E zT#d!yX;oo7=s*r-_CpqDs}vph{*w5;>Rs5l<{!M_eF!r4Xg8i%5w|$oh5yGlUb(!u z1`qhGxK%P%7N>d9dXnHyWAt>DCc|t*YjGX|7G0^*g}tV@vqZ|`?8^dBEXe9woc%%2 zCBOu@t_Hy_=j-yX_BZXm=qnSl*+Q^p==lw!)$i7mlTH;X?azsU_IVw)#-^_@PK<}# z+P`Yg62qN3|Lb2YbElCSl6KtJQvKNuof0>arh69#BtI1Hc~@)NiiB0da&h~YzkwH2 zjA6`KCw}C&=V%fj%cPaLjzm-GAoGZDE(-cO4$56WZB-37bb9D%)cytb|6B_tM(Qj3 ztu$S~xHTHC&0Q&`4*W>Vv^jjuOI?-Y9L-HY-({@0~4ZY+-` zgh`t8_c4U`jQ{D-%TnoYQAs>JFB%qagPptRc=5JVC3k{~QRnKKwqGm__WZr+l5aa( z!Bq8SWSu9i(>K@mO)N8QZP%-x?W}ffhN@!a-C>5d`kMNA^Qf}9;uYv3bzcstX7-X9 zoHe6cKcc{@GYdS~m)^%S)PSWx|PjeYiCYkOgf8`vh) z=kSDku*}!7h!nsDXQg-ldoJ7ip2)nTgd^RbI8?r<}#w9sUltXwa@T zpc0>-GQ=&n#Y)ntRR`&r$ooAu15g+0TLE6L=yT$!F}cJ4^NMF^yYH$ex#9Pzl9>|b zabjLX-$qF$J?(-D-hzBtv^k`7D)ng9yVKl`D3deQ`pR^#XJu&YEeQga^I=O^xtP-R zEb)Yi)LIHwOSeb^-{>nNK8q=^+vFYg9d}ZYSBr^E(@Nj5jxU8YnFewVXkY%KW9A`` z*NG{kwG1Q9vVD&erj=5pemGnOHu}vA-HIy0I<0f#Nu{dwwdfCY_9U zQyg<$4`6w3$f~~AE_vkJ`c)pcm%r4G+>ZwRh-@ETFZoIo6-Y&a-r%WSvB(VNkJz4wu9Yt!Vyp!Q4EuLbrb8bK#M$| z3r99t@Nk1!n1#x-`0F*tX-u1mR|CCiVH#>t-2jZ3E`$-&WDDAM7TH^K=@lEVwZfU6 zL3@N|scw1njUuC*dSk0QERm70o=kXk|IHEty|(I&jra9chm(u)cjtI5kI5RE9dqK4 z-I6c$o0q7{-+1dO(8d!%x6YAwO1B83rO733HeR2SJ|$I&=#+Mm(aBaA6X-Ay8J%xU z_o8%)jB;CTyoeOPOVdk9P_dh{SdD9>v7_Tda0b%(&8?@?s#v9u@=a@mtg6!YU29|s z1j-MsKix@(Q@1bul98<{TsQHu z?DK4xYKQH}un1wivXgx%F(do_H5Fwg_Td(=`p2qxCKne4H4#%KF%mLvFu7A=Rg{&# zdr51ix5|PqSL+ddEe9`l_=3>Q-T>ttJb#OEc}4=qxAH3I;*;NBTVfhG?hY^zguy^i zJ?bz;i-w1GTU=)%hxg7f5*Ec_tqmP!0 z1!9r-srXx;U7ilQe>ysaG?!#XU17R{6bTKnNC!xb+vX@UNkS3^9_IzIU_&7Z&~#|i zX*M+S8roLc9@u@TUvpHzECbc@KU^GAA z+@!JFHC(YXr6A<9=6+D_u3!@a)X*HX2wjS9L;6|d3Y+oP`jIM+Hg(Maq4`&?b1DjPr%FFzX1$QPywKhPx z6@XWF;NCx-9d?3l7GN9cuz9qLf?ER5CmGvjrb*)PBv5UIQxX>FUhcdUs9tq1^LkhA zT<$(wSioK(1aH~)JU8AcVIj{7ma)8KfOesA@vBO8@f42ZJna+?)#jl7jBc6PwXnH^KBwMxcyr#&6IW)uSNMFtR&5)F{N{BNh_-oRz*8+ zsUUlOtovPfl(eYw^s_*tuhti_SN?_X$V}#!iy`;xJPny9v_X}&2eb9By?Ftb)hl+Y z{o(KHJl}=ERdqxy9|p#{mAiV<2z5!zQn}Wj1j~}$q3zI5x4!iVh%rNA=pU1iU3Tk1 zZimL)U9*;*9f`EROi`&cdDwIH7xFedwufTiayun*v}A=hW?0C@l@8r>RsIRH1##U zVA87@lbai2;K{DU9-KFhn|r}}Q@<^Xxc)hs9$~kuXa8cpfr+XUN%CF!6I1n9k9wn6giaK5dEF7MVKQF0|7nPPQyg*E^%?pk?8%Yi_lwx? zBTFZ`SrWoMOFfr_YuXyYaP@l2#q;xz#@;{XSe6;JKh5atGQp@LOF(2lwE`P8+Jmwp z*m2m8y=FR%IT6vCDfII#VH|{o3oX4!gEH3O7mh|(%06gTX|45^kJ;ltK=rTrn9<@iz-J< z8vk9>2gJ;omqt~6_d)sm=cO=UJspbrPRgq{&J(AdTJ&@)o%ytVRHB@bVeDCcb;s^v z-TtS4<(>#2l@Zi|C$aac;d64@kudf#ZS2V**0$h|sz_{#St zPvBk?w)l+nQW$~f%dL$I1kgH(Cg?U)R5hR=1SJDqp*Mp zD;P_B>%!{5B3R8Y>IXm;>(1)$(%MzWN#9rq>E#eOi_Kxv#FpX}@Datb(>8-}5gvj_ zo)#{WZgKaLZ*GQri`CHV*wYVSR*7T%e^@TuU*P?J{ch@>Va)}8U@gd8IYR;a|5QDn zQNraQ6fFBe=74=NSR+)xsUiCUn9|nb7{XMKJ!dS_qcNK53G9v#$K5TX!=pqmgT;KzseJ}{fpPg18%qRpm(Wi%E|l3zv-rbW}T63XcL`IBhV?Zd-bsPmqa_X77| ze2vD%VYV=E*+30GBb!k;TVBqHyL&dNjR7hJYN!EfKDy-MD=s+(wP)p{572wBP$`;r z6U=7mu%@$YSV6+AtUauwtU+U84y%X-XL{v+b!g08%Y1e_GZ$|&o<4z1WA|pM5vvel z*;+REzbfyz$UFF7mG@N~AMrmN@ZwN$NiwI8SHf}q(8T%10e?77QbV2v4`28Ed5@&v zuo_WvUe!-7=D{>FZ=dwvWfxa>_u~8MolS~7%1`8n{5_kLKZ%FjGuUhXk{mQhp7)0w z(w_)rD8|}^XA71ISWuoiR6r=4tw<5Pnc;&J2~tUK1ps#)))pEGt%SJiu$~wk6rL7d z5*7$AO5X^rX@f$b2@6~1iJ4*-aUThOgv6-YXqhkGJ(E}=ZW2T3>5{(N5wFb<@R~kF zGFO61oFzVzaLEY?NSBPs7qv=yC92YiQZS#fM4BmQOUvZPq=u}kQgC1TLh8?wOaJ@C z0QiaNe9hR`Zp}`Ti&(|*0Ks}Em&yOiNf;fQkA=nnAH)gs#_ad{AaU3Q?6v}G+WX*^ zQcc)5>#uIAiX4gCMifv0!@!*M*B)zN83&-;?Pv0 zXtt-*F4I)_)w&^kDUGSm$2}TmFcvY^&kp>(^6!%5V!YkeTXbwPb2ookj3qPkSjs$V z(<@8W@HOu$Eyr1*y#7=S*HeP!b6a`%n)_oa z^Ef7B+MejC_U?xo84vEsCO(Cpa#}|c!!tFHB*JwxFMADvxFURl6Vj2mNwtfc+4JqU zW=`F(-FRGm7MrQUWR}9&NjCI1*vLU0K#dHzQuN}=oz2o|cwgPqoZ#+zc@?kf?yJK^ zwIh*v_Tc=y>{H2vS*y!slR7(SAyV?sGNthk!1)vEKV{)cWu7dKWtJy` zhV_%xc}ZY+mE!d2htq+ zuyW@Nbz|3tu^dAmOfrnuFyYY638d-p_%r|wKxt6ReQK-M4;n7@rMa^&-K_r2Tn5T;hMnW!-_~))V}^wB z#HZ5)WXDRphfK0#HPNZ)JXGx+{8u@l-l#=pr)3<9I}B?;i($0es_z@Rv@I;C}S3T32d;v@qZ`vama+j@rr>%^;=r<+Bdaa zj%xhH*5FL$;F{UV1U13vJh_b{)KJ7tH?XNn;1KeXI>zmMNd!Bq#_Jueo~mafnaWe; z-IRb?ygG>^kIm!qj`5nO3d#!dc@KCmc~e~tH1x{e0vYcwkHn|*=kr(bH}U`BgG2lT z{^6&2$JiYS})l_^m)#F5ETFwlf$?WTyY^~{7`#*<>)l2E1Eo660}R%Q`1LXFQE{8l-|##&LK`UJ5jN8 z26*q=M|&@MDhXh8O3pCGOTjcL18)HTxPv~H02`U=IxrgV{Q#~>|JRZLmjVQfM$QCJVT^_6|9&8n8}F3NAiFuD8?pu(}zx8%~$3jwgRuXE-VAiREN{vuUb!OOWy7 z%eA37mg{nzNu{-33z*w>SG#-NM#uTSpzOk&$27-&Bj`EUtbf6W?(A)6@2s5PvQ<^p zRh5OJi-`AU{J|Q&hdqaWJE>w~;*B$n;@t}=Ay>WY57=JyDMOv+`9*(N9W+tzIqM^< zo3+l?%|fa4w)3_-7e#457s=pOO{P#f&P6WeR@qTH4bDZb<(4QZ-_AvPaFxnql;Fu~ zpE>v01fH3bp_7{HWQs9wLHPAK8f(>DSDxa0<`K_D4%5#?PM)aqH+(YL)0+UG=b@WY z@21nt7%_zyWdDM@Rh9Afu#TU6AL0NC=@QA-StCRA!Uhx5VoB2N!yfJ_%1YEI1vlG0j#**Kge2b?Cuo{yR&O zSMjKemwk6i_XN#(x>ECcMC`kE64 zEC;N?aiM%bB=q)sAzVg!>HA9vkDE2;2yN(2X^ggJRFly&oi`iBj?!YOvL9@eemdE# zT077b{RzsYPo{NGIO5KH;>7@Omq;&LK*-+`yCt^FcO3GyMP_mMv$+)> z6o^))gBu5ry)r#sIB4?fiv z?CvZ9nlaf%b@idrL8F}9<7Lqmmu9@M9G_KT?@k^%WB7|uGuN@r=wkLtDDVi(=4-R98fD~DN| zQU7_oQx$`Xb8wZI$_!+#+~uNtz3MB;dpHcH8#te-=)2j+!{vChv zE#+SE_K&?UEE5yfshc_iN^n9`xn>s9a|Hao3+}g001;#`JJ7c2saYup40>e21Jamj_L;VFt`voU2&W_3u z+!kOzt@ld7|EBP)g-{t^r~)&gw+VbBJ!EhRDDKgvG}`cU2litMFH zhIW0Hc-?%%>?;3kHCWbu5kvj}RY|s_P_jfa1!GINl4BCEhjf&5U-Clo zNg|gZQeCN$sdUBbwy39Gt3Ik0TrzY9!P3K0&3$Q~@I%FX_Iv5@8q&y{v9CWi8ajrN z7VO`k>!7s*E^m25$ z_!;~D@}C|SgF!_Nn+hKr;fIhF@@B)mS@r4kyY&km?~7bvml%J)ea@ER_G3F%&I%oQ zx?tv*(*-;w;Hl%(bswfN?Kn)^72eh2hfHSB9k@=1LACgATtc{kk!QGnq-QfchJ>|@ zsK81Whsa>h@cW6n;dOSIlj6HChPX2|#RPZ;!N!79Q<+0dho_#SN`2VaDP$Vc5vd9x z658!{+7mb-ZeQ&W>?ejt5IG@8>b~Q%R6~N}?Pht!GmG~jOF-oPL>Tm&$Q6cI5@F*i zuc9Hit7X4NY)&5!&qJT7v&((AdDF(H^Wix}J$Ogqh=G$G;Tba`s$k_Mhje58iu$Ws zVH>sJEf3!FWF8+mA3Z)Z+A`|Ou{yhqH!8bjjb&Z#i9|vb${SOcub$R25k>&}A|>CC zw|e#+nRO^o7q@~&>?RNJaA4&SA z=8CBX@ISoWZkJL++mbRpcdO8I{WI~}r&ez1bnP|#+*#hM>i-I8yOk;>hTv<`JmDvr zoQ5!T8K#W6Hh{_aSLC!Sjd7h3a2q^5_R-y4yi0sQ+*7n8!~Z)dYeg;}ZqpHYUMp)Y zYd^#WLOCC{A=;5#NzLp#Bufmum(UzOpavUH7OSy7N>nOfFnP!4xuoyICL~RgNOJ2B zSjhUS`pt_&Syfl2>4{bRQm;Dtfgg%=-oBv6{+rSk3-o(S_$5QZjDR>HgUik6fgW)Dm z=UW7r1ftU_w#`HEW#7D!JMzYZq_LZHkQBQ$UH{u;<(+|M0Lpd-PLGRPIdQ#dx9PUo zoxfm#_Yu?HO|gvJfo=0@)Cl2o#jhBWfo-N*TK8ul3xOWWSO3l^nth0|N(~P(LE$-g z;<)kAr9a8M5y`a-xn8?;gRJMbNgn!HjwNB1+~jQceq-H22i32b>q-j*qjS$;@wl1= z%fb`0aJN{AYe<0MhDFN%(Yx-F9ix}Q(qMU<{KAib4PVn)dN)|E+f!XPA0kX#FBo(f zPoICyrI)fvXY)$EaUNiBZ40}8aiHmq?9ObY^~O!DE4>aZ40H2ZwAYgHM;M8{-b$es zjdbB^@n#gKMR(nf^$DDfYv#U-d-hL*|7A_E2|4;aUHB_ku^@jgR&RKPodw z`+|f>9jR9dM_L|xZiOirnDGfwwF|$HMLxg@?aaOwqQVc&vW;->p(lN^o}1=>uGL>- zxd5t>UnrgZ96!A{amX96omiL3zTch}q@Q_eArzo>Kps3L6fr)qA<8Ob&UkMnR})x; zAbVmj-C^eZHjBDj|Hj{fuf0z(DIB<;dG`0*nNNPW_^jUfzQ4?K$F?6gnD2ge8`OpHn_rH|ZbJgQ6NM4#vEA zjd}FxhvfNv-Vg9))pJi7d6imOVz5p~7SQu*zZ;S_P-HA3RO@+vN&$MDkgOrWc%dVQ z&2b=_*MkXmkBY3gu3OCOUAD9yNS*LqJ0$CFJ-_f4Q|FmLHfR1q^MIMi>&YXJ2b{jl z{H2nY_PATu0w8h3SrkGu3^={d3NK6aRN+BE4XCFvVM+bo@ysS-BtmA6?6%*cw)X9! zw~;#Kl!=~a-O&0)4aAl8YEiF|jSXOJL-Lyj;a8#gq06GB2ilqflp&e>2MxbfWTfl2 zuK&F>|7v`8-qY&Is`kIb?$&d&jc^eSF|MMaI77Ijz(M4mCn{?wd}Um<^p+nJ7C@McIobX(4}l1l$W;*IX9lTJh=VDWvd>0 zF4WI}=`mP(A5KBu|autKo+w(!BGF%8W(8TC!R)rd!G%-Evsq z>EyV}cWyJOgwLtEM<=~&%~8{BICMD#jCpzfSJ`@73QDCjj~K%z6Ja(aJv{l!HQ-9J z?e_V(Ssow{NIM}J8=1oMTkr6nK4lL8R#U;8k(QxB zbab)D@-&#k4Nr;~C%Wj&&wqQA{F2`R&JCj5a4zI`Jp7*t1%NN zsH*3xw+w|N9sRqb)CK^UE>jSIn}NMdp(P!Di@b$DKt2)Pf9p;DGWb%dY zn3%(s(E!N|jERm`2QM9Zg4*hf9W;;I(_pnrF1n6-hxEOt-Kk|rv5nR;gkVH5P+1DH z)MCK|Ep^IU1R;*66zLj~3-#PJMAUI2s-}oKUZj5u{G<}KMO3ngs-q*K>UB{K&0vCA zp=)JUNThaA9n6T6MbxR+MN~r(l_sJZi>Na$i1d-uX2h8ZW?5#$^jQgJMP@|v1hX15 z;y;Wo>PIu=qZ!e%i+bUY8S=-BXw^kEutBaE*breqhK&tkV?+FBVHefS263|?E)r4Q z7mKJ%MAW4s>M{}4Zn=nh48G3;NRjR;5jABm#ML6|nl5UK4bgqQi0UY!vP4wpE~>wd z1JR|6YUV(6?V@@tb|7vNQMZVw+eFmV?IJ2$MDiey#?3tta}Q!z7j=yX;<3hq7$KtW z6H)iW_j*7?J=lyQiyaU%hg*n_19C`2jTBL%%th2__|8Stm;|#Pj~m1jB5J&ddP+o1 zc$r`}-Jf_S!OYg5$iJCjw!xox7QROj^*ns0X(H-H5%sc&nhS4`C!$^vQLiSLJ@CIl z6pE;KMARY?wPZtr*-wAs^)4!iKtRN6;tlv;6oD8<5N|H%qArabU_N7qw&?Kat zdyc3dFG!s_Bk5ajoR{}_{iG>pt<-8V73llS(~`8%Nr+^e$#@-g3i3(Cflh#$OJq+Y z2dHB-qG>!tn3$tFEr+NY{ua!*_Cu-VJTXV6F!H6hs8o#8y&@gX|1!8|#bx)uJ&GII zA|j$rMy??@vWYswKgqhE2%eZqp~Wi;p@sN;LF5QjZA1PjN2cxkglKw>TcPh1G{D^F z2Yj5JI3T1Wd*%;iirsjMM5fsA7PP2DEf^XniqREe6W$`>h${So-ynkuN-gCrrH%5F zlH7?*kSPG2BvWY8DNLC{kNz^-klw9ypih)3biN>yWQwiyDgL=XvV-Wk`{^^Y=`uw$ z-Q=B$X|zmXCR3cIXVHu3HT2nf@N#6XOfgTU_((5^n)!!rU}=nZny{kKL*rGR01rBEs&E(o3dL^_D4oWQs_; z6uW%8M|S3Q$UibgfJ_l6Q`Fg!YoogDw4BYIxo{2>y^V@o|E#d)azz@S2=d zmZVGZ^omb`e~;HWnIg>Vs8{-Rnc~8olnj|7Q>M5^hEJGl$X&|4B~#RTopE-*BvS}v ziY%ET8_u=xlaTC{;dRBU!0UlmTK3x8@QHIpGR0f3Lil*vyozOtpI-a9r@8lK3eyKN z#Y6a;T=DpnC)~Vpnc}HTQNyj2DXQRutd=PnxC*Xz)C>3=Udj}YWs2+EAIfje9sPth zU3Ya#i)C=9PHObm@f46C8?PVz^(~Sh8&Zw_8je7s0uEe62{ISa(Qh6iNO-_O1qJ?q za`am*{wuX`@D>tpAwnsE1X&v#{Dj0$O3h#=eveLgj}Ul|5K+w_phE)CYX%QO;vgh6 zaY7Rk(U6FS1oZSvkm*6Wp>S=Ax;=V!it_Cvx4Y=6Ao~20shJb_$$HLkO+pC z=0G9`5?k>rw!$l}L*hCld~w1T5{#p)+a!6F+ z|Jo`zcn*o@5NmOw77iL9(EzatCz{~kJtW>k{EQQy;h+r?Z4f&|pm<3K9Q+U!FZltn z8z;Kqpa&8?5P#vsFF5!Ei9Zkvq99QaRWnE^D_%k*%lE@Ct88_~Tdj!$ANf0w4zAL=YT=Kq3TU1WrW2!9hqIggBA}i4pidq9G9tiCFxK zSU5NdiIWh|;KUg?NQOi*#B(@t4h}9r;sV4=IB^LMav+fd@d{2{frIOixDGKl8xpzM zHG_8`aR(A5_!T8^@Bk7IAhzRIJb{C9NR&gY!mp@;gXfTV4zU&|YT=*(5)BZWaH0tg z-b3O&#LqbK84lVY(FU;tCpzHZ2PA$#?8b?1IOu^y55!+M@e29|6#C<2b#Sr$xmn{$voa{zg;WLIW zjUgU7*}Ve7VffM);*lHO#~~bzd)a*jBCo5v8bV~8_Q*GgQH+ssO89k+bQ&>-_~ZcV z%Tb6iamgclARaFqNq`U=_h#g_@=*SX{t*d;xHzh|0%H6^Z3=QI|76@|Z7YbU4rseV zI30IEI}BpNL+w-uXW~9;mq6tI)ozB67-wiW2r&sYoJ2X4pB(3DxESKuD8p?KQsQz9 z4?|3SYM2S(T-;Z~ClJr8&XYn&i!+-C=!f#tSI?tExDdB{o;}2i@$-BjWW-&c7XvZ# z#k@QSm*RfTtAZ$)u)GsOR@}Vh8kUFhvsue$LCA>O z8{XIiQ8;bq0EB|LM^@EfDU-IRqJb9m>DIE65JQgSfaLZ-@`C1s#L%DDHVsF2u*Oph^h;kFEEBYGT_P zxA$ZKsfK`v4MUgMLO>Af1f=SbP{kfV!GanPDb^%X>}Gsyuq5|Wu@vS;sKd7fwc4R^`wPLxjBH7suXxw5_fyBy%Q zoVUvlZYuWTyVk?)ec7%9a8tRrcGo4it-8GHDcn5RdwJJaxUIgtiz?iH?jiiv5pEx` z4hO=`+lh{dFqgPxFcfwxjL$`k8g*gFagc{mg#ks0squ_-FP zq7igMbFG-MOcx&zo1x+r@Cot?MxtV=MldSR92H-M&t;c43Kh#Vf@^TsMx){)jo`XQ zFa|zgu|{x1BN&T{Z)yZtw={xrsJKKUh|aUPfQoNx1pjCR<5BS)_y~eLIx4=a5!{21 zV2O(58bPT>UZ^D_>CT%!>vHG)ZSA8Iv%I*nj5Dt-=c zsn-ampyCFN;063ji zip?$Hslayl>l)Q~W|=!GCf*Afc!38h9z7l2Fb@?YnG8Il%o7!lTM2*Q1@|_Yf^RSL zM#U5cera!6qmZ_aYP`NUm3DrVE}mcJhln0{F~Y3|yOm|AmTm z7oV}xGJm-5dJJ5jfpbuCnkNPSQx*VE)8={2fjYIB6x>`1pRki^Y^w~0 zUl=fOmNEnt@1o!r<|;!`u^|IDV&IG5gA8ZjR0bY~iuwB~xPXE$M#aI%7Gw$hEn^1G zS1v`x->Ak}eN^LRsF=pUk1LlyLd7Nw+?0Xql+i|9W8h|RKgwwE*AE0yaISHNMleSs z2uHt`gINr=#Uw(#xpKOkuQcJ-NDR>+_P9q9FoPuvg#TNS+_;>~$KO$cjS2k~% zh>Gb9+>(JOOocxvD4^hpS@5?^D0mXQ$%=tnGw@{d7F|5FN*CXXiftJ916^EiTU`bP zzcfnO1UECf?RKDIr7rH>z0>ZRE}m7Vi|<0km|dAhz~38Edrk~LV!rtld|S6rHxzF7 zbnlLYo6PPz-4|)L4BU=^r=nu}5C(pwI}H_2VBq&CctJWUc3|Mu-Fr~+QYVdInMTmn zO=FybAD${2LR$gP(rzb&#vN4)e-ez)CNgk6_{OcGO=939kt~Gvgn}QmL2e+lrxe@~ zd4bSalNtCN=RGVo5sJG@3I!)e&Izm^O`pyD)GoE1D}j52iD44=b7*1D^q(Xq6SM znS!@a@KkuWRtnw*kI0Ia2oEF)9)J~Xt4085Rqw56+cg3snl6jB!$c$4xk!wP{Xdj3 z@cFD&G)^DPr?G+= zcn$O+)8;Yox3r_90%-vhJP^LKfwU<2u7oo1rGd0z3&oRl@$G@MMevo@#d88z(ZW_J z8Tj2m+G4neldRqa(v~oAH!C8L<}@HA{46aakfo{c9#!rUv^lys*D57~hQSkrt&5+D zpt<6jf zdpAY=Q20|Ez;-EnxO<~_S9OXOLKR2);jl|zlstPlJCW0oF7~&?hEg*QWxG8ALmbI* zE`7>z^NQvq&z#fjMiIM;S@8KnrsVw;gX9^ot<}qxQ=Rf0d6kw}HZU?UW3W1o0+WfZ zutl$^vB-{H!O8X;Sueq`S@0Ifg>}#B8 zTJ%*9gQg$VQh;2zpT#a5Ebn7 zu-l=NM?sTdQODmAFt3x-mBJo)D7?|F^1723!2WM#hwi4lExuGSWp(+(-PfAo>qWN4 zui)~Q-i8MfCCl;ww*$tk^xwjYn6PGQ!b-2X+s8ceE?Jn+CC~GX;qUX(oxAJeqQyJq zSNZLG<|e5B0y#+wlfLuc`aIzu+rEltd6(71}DXK%@w`uz>aem#&waln}&H+#4(-ivL7xJlGGCguY{yUMoH#BCjI)Mi} zxi=gSvSv?I=o8o5oGQ!ja~rrHxWBmI|1IR-&jUF;64_bHYvY|&khy&@nZGn`Yy*eC zQxwlH=wwwPhI~_Nv9g7^F$Kw#Zhxrde;F9n%y%!~pRq?o- zhi5oaNkVY4WSZ1ldPOp#R8pH2y27NmS<)-fmI8C>P@Oew$dIN;v!sC3rY&T?m8wr4 zEBs7&glsjvNU+mfOPJpKvPHco}xV)?S=6nz2 z9OpJ?riXj%MOr@c%3b6Ao`e44Y%pAT*9xToZG_?-WKHxVYn(1B*SO5Ne(PSX?`-F1 zbqEto^vkM6&eX+X%9P^hGL8yn(l05^&|}5O(HqDLr_VtPfhoZCRuAEw%_-mI9Oiv)OB$)0J_Q1F9u2G_@qGg*}oFH6MR@8>U8Hq#arn zv`m&$JFWBKRGJsZ#&cI=<`DApb-0&K!~P2upNnluzW$=CB7EGhh+M zlyJx!Vf%VTE!6i0zqfKA7;CUeXiOIS6;O8ANI0)J6&yonn2zJz2O#aD&SG4`gZ` zFBj%THwB9Gd7Tdz)4XEF&OA8+ZbqZ6o}-BHcme` zq=|cM^!=IW`qu@?C3}$W%U%yP0%$E2|!X;2AdTPzzN3#k?;xkvA!A<(Z z6T92kJ8mD5v)6XFxHmI6|CTCUbag5q2FuRaHf*i&Qjar~c=RwO>WbhmvIWLysG+tyseBdgEJ;&TwE8c@)Z=6$qRxv4N0 ztQjm)tyOJPkzVUNwR|L?8{B;pXTwMM$SY;NOB?23=K$JKyUS^-m;4wPIbHY5{eYlN zvrlbubLl?R95jLQIO6>MJ?#D@4*NHw??xQZah}!l>&2MX8wn{c!R^BKUxJ@8hcj!* zcDtC7o%ZK$Pjza+qC6py#VDlKER>`mcz%TKns$(apcB3#oc#?Z?>kVGkCe{!nAb9i zCTyQR!r$ayREwqG)>7YvbS^#4%xc@n%V}{3>DI!QaJ_3f(Th5e{FZFiJjCFF{7w;A zb(fA9nizvfRo5TW7wuCXFA=ud+W=c8Xk~vJ)m)Ek>BgHK+JFvg(~K?MPwf_{=d`Z= z!&U!&vScT$7xaR4Nx=m{$1OL_I(Ytr#o^4~!eOuh$&jgWy6rO) zfO(?%q7eSP_I>Tq-sYhWNg%~+W`ek50e?kequIW%d_F+!W+p`Y(?oGqRQ{%!kAf}7 zf1K6BRJ*H#zZ~D>)=x9uoMgYqB0&7P>!IbwHQi}I*p8eMf3?Xv88B6HsU69(1fsYo zdUAr~Mf-IgKmUYQ#rxaGJyvc0z`b*ey4IG5BB&A6|Cvh}(pl2{R(6V5w;hp$AC8fX zX^p+{9MmHbSl@+9?XV!<^(*Zwtzk+x?SfV^^SCp+>g=i9vh;HOV(*Z96fmXhPIf5k zi}nX;JZ30Ah8bUI(_y8U9bFZYV)muvSeO3ffS=P`u=ki*1s^%5+}vnpvcKqJ@n*pD zDMhx#cimO4?Yo0DjHt)b6=2A*bzDyJ6lKzV9D$|k1m`kG&QWq&IfuS2F*qNRDfokO z&A1b|Gq^PiRyNYYxle>aNsD!eyTIF+ETTOaLK#>tA0)zStaj=x&V;kB_d76aHCag; z-V7&QdMOm`drN{JbB9xm^52JvDLsqc2hCnZ-BtKc2MYdap3U>;k-hn;yraBxJn%~N zg!hiu#iQ_Xkv-py4|GM#`J4Cxeg^*x{|3LB4_-l_aF)cEYAqtK;RI}oglymQM6T$X z=)Pzn@j(RsmXd5=M@a@fL?V|aON_5oJ)jmyZsv>`ezEYw3TqH@w(vvMNqf6SqDvAq z6^h^!?A|d&(rkK>6lK1U?w13N^osmH&52~~6o|r3%J*Sq@;bS{DYLRyUaGCY7c$Ex z!Le>u^%h{UZb9h=5Vi3BmhQ!HkKiUjfpUksy+&{h2dgnhZTB!#WpEu;O&+Qc)ldyU zOi|;D4X!8hYhH~Df7*fATzZ)je77+rRHU$t%C9so>9zRJmBoS8d zQ|Vv~=Dg+_-GE8jOQ&NVQZSx5@+2hjP94MVvTKrxnBjR-uU{@_E}7uQN01~N$}%}( z<6(@Az2c0eNy9Lp&)JSmaw>PvMu3#N*>T`%%kBVyF1%xbg9N zI%ss9Q@q|(P2mI`bOPcOzlgt<5B^`1;SYYQzGy~H&^gIm(do&Qj#jWvv|Z#o_Jqhk zZOq7`jxaiCJVfazYX2oNJmpVkN`BKpuw?pJ%GVLhqo>BuOC*ma;H~5y6_Fm3UwhA# z?v(~hL6r2moQ0i`YEQW(G6>TCW5JXC-dc&1} zI*GBUkQ9x`ebY(wl)9zIKQQY6yhP;7nl!kR+<9?V}MmGC2WFc+H;y1U@EF?|^X7FE4 zYSSKSgN5RnH{ilOJ9Qm@2#o?I2w(riTuJpFECk^VW3ykLXnNXlwuwIkD(<+mH!>on zVam;?pP9AV37;+RhNo+hRbvK1IFe=|;>|Cuo76pOva`jPY;7rC6ugKCi}cvkLy5Wp z|8g=g^ljkQqD@B;u4BoLYuJ6a011M&I*(L=xnY@E87>E<6FB$g zZjv;+02mvc?zEy~u*c)lm^V+I#M`%tI8L@Ho}2gc zjri3%>-RCUJHyuv41~jB2R1=_{sXwfW7mPX1NgcC+cTT_sr<3OGspf|?0oFbreZw- zN$>pHQ|wuOG^W^UQ{@8ISPiY9A7Z%1{-DMk5ZmNYcWf#G2gGBAzHwvA<`LffcR!yU z10&03$`-KNGVgtvDVte5K>;itI7_{xTjc95UCL8dGVLO+yMD8!ORxBh%(k0Y0#?!r z`j}I<)2VmI(bW+A*<~uKp-va!Hq+typBMx}z;4-LLU!&-!RGPaBgV1|O$EC}nWDn< z1LC4R_Tq+i7h7jZLyPT&-4`1u7aNq;VC|8ES;|VX!n{=SPfBLi?2FB}EXf{fa=}*h zLxkAE;aGDfxY^~0w| z{-O3!3IPW!cz1GKmtv<%^zyYs!JF3(K(0E;X;nFM++AgADYss&3!&#<3;JePI3LIu zPe4ljpF1 zQRhsDeKG8@k&T#UhsumHA#Ym6^qmp9>ud_zXV43NbkDJ8d@BkiyZ#9%On^P3jT@LS z%F^Ly=}SMrZ#s7+h2Qi$A>hh(^9mLu1v^3q)*D#D2i+>iUC|rq-6=0wC!3Q0d@@h{ z3-+9bOjILm_N&4)GyOC^T&}~K?U#kA=46AYQ|yGiK9)`HR}P6?I6zildtPDrWguh+ zb@T4nH)3OIo=}{B^sofYlN6oGv`(ehW=B#ot<7q`AL*JBcG#R;lC=ty6=PWxw^7)= zu)QRRA>A@fY_Ki6fg~9PTJD^Hl6sn*WOX#J?rj&0LHPYp}26Doz)q zDK8bsYYs%3y0P{~%>lJrMzFq~{@^_0w7sjnt8$-CN)TfA(&?PlBW-)uEv67ehaa_a zY%qHPJL;aFeN?*E)I8UuHL0-fIhFhu{EvLL;{%Lrh@Dw;`zaF%bPn-G@-<^y+4tk3@4!e(m$Ibuq@icx&PJcpiTIr$-E;mkTt=3K zQ%f=S>f_Ic)CJ&`^ncX_$_Ze6m>YMO9G62M=s(-as-XH#o@%kJY(Q?TuvSb{cq_D4 zmwyV>i&R*3e+V{gPNjh{b`0ihze{C*Xf0*3z83d@-pZXk5wB>}siIMC=Ba4VgxKY* zX>h!BXs%G!gDHUvOsk#pA2e4?35;iqXm6`Dv;7!jo>t!cQ3tjO%&u#O5IXi=xZWid zgV+VzE!Wt=&J9al;Hu>F!I?I!gO0%F;T{vsv zw+@kDj%)Q&ysOO`UCD{6lmx+8cs5ml9bb>M!fC3uJDjG9Q_i$MMr3`#FR7I#9;G4I zER`#YJiO_(Z)u2u?pxZ5qHu5IEp6$%^L_k!WQv_%rRnqDTB5h&nQdtq7}0FiU1U{r ze*vv%v{kpU4d_?#Ob`x7)g)^2SF&i>9xRn;gke^{o{mP-0%dr{!Rqp zoH1!BqG@~L?dI@vHl5{DhQ-Hjyg#D3kZ$(3tnVp(v1;VDGEpDx0(&v@o#_x#@>u?> zxjT*`luMWKb_Z2jVRp=QNNGA68ypsa=+5=>HYu0oWbAJA((Ru6;6mfjZDGv{&DoFbT&O` z^xJEz=m~Vt`TMQxZ@N@cCaIIO(7&00HL^c+s_h!t7-j}_E;E1$c@-AabY?bFDSF17 z48=}OJxncZB<6rMg!rCT63~PSbfComf4 zXr<-w@EoU;>6E=E)6ZEi^)Q48;@$`LsBLCHZO?xNuJ2t%cIe2Ip7|z z5o>|GPaXbFY$Cr@1fXP=PtIbF^4mqX`4E@&jt?V12d_CCga2F)saXPN&T>)mhDAL` zdLB<{XCm6@q8@}Sw7>DEU1?X#{~PYU5> zU|9Y7dY!v&l^r#DCM!mOx#J?s{bXwtInxtaquLKVOy1hG!ed4qyd0d)Eh{#=QtCMA zF56+!waNz=JN*9r=ZX#md%(5p8k&&T6`s&h(^I*b`c{8j?n?K#;-!P z#iI?S=JTIZVomY{^^sNJwkoi$w*Ej>l44t(Nb!#fL?~3M?%FbI%}eb!=d8Umz%c8A zRgAhHx9gqH*XyREA`hq?-y*x*2^xbq0L_eFdFI7t((pq1S|effJ&Y(kxTysH@&R zEoGzZO=|^p^mh99@lU!9nd6y`R)e;8H|Bii@~KZYS^GWN!VJn6ol#}?>^fs@?3y?% z$z^kywLzDxvd-CFhIGlM*m%I8bs#+Vx59IObVCEr9_3m6VFD^P#4!oO)?wk&Ls%EN zxXqN-gp;-lv>-^<1hr>#?8nt`K1;zt%$K8aiFA$O?Bs|zc^pv0spP!ioRn%fM%nee*)uP`^ZlP;J`SQH@3Kj@HClHWn8jZI<`S*SDdug`*Vf%>zHZ z4za!>6Pk=2_4dw^+}B@>InO{Wc+%Zmsej|4BD~^OrSlEC96|Ktp7IwDrptR3Kb3lo z;PTBwc0TnsY8SPSdQ-=f?%e1P%fATQv+Ts}{OtwvLF$O1OZYN3g@Hb)hq0`aOe z)iKo{`ag9n-UOS*I!mkQ52{}(!w=($kOfK?0{9U5Zx<*x62nE7A}3KX0qS}T1Fs01 z4_-+z40KTrhyY5p54(~!?c|p-%eZ#i$8W)xvM-em-0@+2i8ppyvVQjP`x4mfEPhU? zugMfGnZugc>8>xo8m$D1u2u=+OHSlH_` zzP&QCwce#)(OT;(M$zZd2<3TnI%UtKoi0Ne2wj0`mffwo&|H(h>96_s=!mV7KCbF5 z?X^XpyJO%V4xn;72xso-9W!*!aOd%bumNUlaQ_A#8uMsH`FKa2Xs*D8IlKSW$}v+k zT%$F6sIbRk(yHgo;rsyR*hww)js|c`MVec`sysz&Yuo!0o`c;M+e8ON&8*!tf8kLx zoxCfz_d-hSBf*9zf~oqC1RIZ9>YK7VD;&hAXTXQ34Rexb9HM33bz8iC*uC}d2YIpS z9>t#3RTtB&;_WQs?#`mMlS|XPZq33uw6W^TsdH$+O|8RSuKq8K#gc@vWD^4r#&U}! zyo1K&LSikkjW|e1xuh_m>p8KCOBxf{Yzq;UgwIFi>Th}%f>DhFsjFaL%nUDNv6EHZ z5*Cn9PF_7rgE#HZ0`x9ULS145(FeW>0qX(7}z<{LX3;WVWU#8EbJ^KNBoMD zV@fRd)a74s-)B6t8s@ukG<(x5kYHE?p2tOi)4MA zGWlpOn8YQ~qyHg~hVlT39wkvn4@73X2*nIIDdcTXkQD7BJWIt*-a{TXB$puFQ@A$Y zoX_CTN*sOZDA9lbLizs_UL}Wyp^+g{1;eXPB!@*^5;DBnAWD>gU!oZV8D1S~052fG z{!Bu3I_od$T}d_3ELjO>)Y73)_d+RGdVQKmCfFf8EL~zDl9BM`SGlBK;@_*P++OY` z2lM62<(uS{fBmpKc4v6+4=Zr1_?CR<1iu%q^&RpD=-jy7l>3G*;}%vJ6La8+kHkK! zTc#NO(g*4Zk+|AT>55QxlcKy4v!AW+RIj_J#tnP1vaMHVEeot=nf$aU`%0UlNP6Ac zY_23aNj2|TGbqKs`hV-vfJD)g#$#-TG;8x!hvx5o=l}zP5`@ zi29Fff~)1K=420a7v~_(!D?eo&ig98?{bjr8cvJ9pAx0ax2iCq)Qk)Av$hYm_!2e( zGL&c(6SiHeZ!^V9-8rndg_KR0vwyj7i?8aiGE5Kp)hr6u?#{VZ{V3|ALQ($NF~DIO zywVcTsri6RV_y8`_clOL8>)OADmNx(#ntt6EpM=IQ91A&N_G7jqMC>I&G}=yHgM@G zv)=Hv!NDED9l(#%g4oqG?6s%_%61iK$YsaPw?oqX>=C3g+A3%%C9d}Dr_NEPBkCYX zinJPHwc*Hs>|M*;x|j>|t=2m3`o?4b^CDTeM7n6dGz}VSX!=P?rDwdOes5G~>Tz*+}{aH548s(&5hyZ&OBXM+3Tr#;NEGzTXbb0%9%3J4$WmyB5F~^!SjpIFkSCsdl1}!;9 z2|^YodjEncjnf{auJ4J5adGn{uPcRrOOeY`1Fl67NQ|>zLY$q=_2-6jH*=4NIk`WlAl#jXQ)gN`u#6Kwg8l@X~qNybHWL(NZ%bq&g9@rK$$<-}8R* z!VUNqyLR%~{NFH~kQfKn^YvAS`MLaS{F=?t+Dd5Xdj5(3QZ;lP@f0l*fwdxX{4_Rt z`47DG?meLX-6@i`|ErrIixHYT|AVVbllUey-~m;$EM^wiL-GxKM0@k&W4U=f|G-7R zq(9g7VGo+{zBD}H7+aIoGwQNFyJ_-;e|-~}G!Sx)5+HPiL$!RycBWnOI;69eiX5bV zkOo);6)NqQyfZ}K>7e6+5M*H35a)=*90|idlp{jXBLxkJk;&UtAkY4x;M<{~+3n|9lbTPqulAVnVO;R^pKtAhxU)}j-KN=hTZ;u3 zdd_2K(pmjrEr<1cOyAYA?>38_I$um|ExlUyv(d9X&L#8s?ND_eLCyn7<3xQ)?$rf1 z@vFJeIMJ}kvjiLPtkr?}&AdRDkLy~jt>avR93AKcOtb*ff%f!?mo3G6iwk#AfP;L> zpmE|%YSS;CSVi1W-2qz$+k3d?CGlNMTlp0;64@-491uq zHk)#B35au^XX;L$-OBo=*X-GRhXu|EN4I^q;?B6ky5l@k{U)Il_I7vwa0yXg4c!Ej zn?Al1v##McjJdN8{{5lbVtX6$*9tbNoEWB^c4(39eRUgek!@`R_*wrh>Yr%cML&4c z+PAfbc>~?hCu_Fby^AVHSM!iWr5)Jz)rRlY_bw{TznK5swTLI+&dfbR{kYg^(46w+ zIGgMC)oNst`J&+gyFYhz7z5gxth6|ng2TJNK1f?+Su5HL{GRid`*fABqpc}mp+Fg? zT)aNxb#Ea2B^i5v))$Dh4pSu*UP^4Kt!Hx(=6B&_`&R7g0oM+z z4y!aF?ZUaW%(?qvJ`<)hFL$l