static DALResult _AllocBit(uint32 * pMask, uint32 uMaxBits, uint32 *uBitPos)
{
   uint32 i, j, bmsk,val;

   val=(ROUND_UP_32(uMaxBits))/32;

   for(i=0; i<val; i++)
   {
      bmsk = pMask[i];
      if(bmsk==0xFFFFFFFF)
      {
/*Skip loop if free bit positions are not available*/
         continue;
      }
      for(j=0; j<32; j++)
      {
         if(!(bmsk&1))
         {
            if(uMaxBits > (i*32 + j))
            {
               *uBitPos = i*32 + j;
               pMask[i] |= (1<<j);
               return DAL_SUCCESS;
            }
            return DAL_ERROR;
         }
         bmsk >>=1;
      }
   }

   return DAL_ERROR;
}
static DALResult _AllocateMemForBitMasks(uint32** pMask, uint32 uNumBits)
{

   uint32 uMemSize = sizeof(uint32) * (ROUND_UP_32(uNumBits)/32);

//LHT add size check because DALSYS_Malloc will assert after
//DALHeap_Malloc fails on request of size zero.
   if (0 < uMemSize)
   {
      if(DAL_SUCCESS != DALSYS_Malloc(uMemSize, (void **)pMask))
      {
         return DAL_ERROR;
      }

      memset(*pMask, 0, uMemSize);
   }
   return DAL_SUCCESS;
}
示例#3
0
CInputStream* CResLoader::LoadNewResourceSync(const SObjectTag& tag, void* extBuf)
{
    void* buf = extBuf;
    CPakFile* file = FindResourceForLoad(tag);
    size_t resSz = ROUND_UP_32(x50_cachedResInfo->x8_size);
    if (!buf)
    {
        CCallStack cs(AT_PRETTY_FUNCTION, "UnknownType");
        buf = CMemory::Alloc(resSz,
                             IAllocator::EHint::Large,
                             IAllocator::EScope::Default,
                             IAllocator::EType::Primitive,
                             cs);
    }
    file->SyncSeekRead(buf, resSz, ESeekOrigin::Begin, x50_cachedResInfo->x4_offset);
    CInputStream* newStrm = new CMemoryInStream((atUint8*)buf, resSz, !extBuf);
    if (x50_cachedResInfo->xb_compressed)
    {
        newStrm->readUint32Big();
        newStrm = new CZipInputStream(std::move(std::unique_ptr<CInputStream>(newStrm)));
    }
    return newStrm;
}
示例#4
0
std::shared_ptr<IDvdRequest> CResLoader::LoadResourceAsync(const SObjectTag& tag, void* buf)
{
    return FindResourceForLoad(tag.id)->AsyncSeekRead(buf, ROUND_UP_32(x50_cachedResInfo->x8_size),
                                                      ESeekOrigin::Begin, x50_cachedResInfo->x4_offset);
}
示例#5
0
文件: DiscWii.cpp 项目: AxioDL/nod
    uint64_t buildFromDirectory(const SystemChar* dirIn,
                                const SystemChar* dolIn,
                                const SystemChar* apploaderIn,
                                const SystemChar* partHeadIn)
    {
        /* Read head and validate key members */
        std::unique_ptr<IFileIO> ph = NewFileIO(partHeadIn);

        uint8_t tkey[16];
        {
            if (ph->beginReadStream(0x1BF)->read(tkey, 16) != 16)
                LogModule.report(logvisor::Fatal, _S("unable to read title key from %s"), partHeadIn);
        }

        uint8_t tkeyiv[16] = {};
        {
            if (ph->beginReadStream(0x1DC)->read(tkeyiv, 8) != 8)
                LogModule.report(logvisor::Fatal, _S("unable to read title key IV from %s"), partHeadIn);
        }

        uint8_t ccIdx;
        {
            if (ph->beginReadStream(0x1F1)->read(&ccIdx, 1) != 1)
                LogModule.report(logvisor::Fatal, _S("unable to read common key index from %s"), partHeadIn);
            if (ccIdx > 1)
                LogModule.report(logvisor::Fatal, _S("common key index may only be 0 or 1"));
        }

        uint32_t tmdSz;
        {
            if (ph->beginReadStream(0x2A4)->read(&tmdSz, 4) != 4)
                LogModule.report(logvisor::Fatal, _S("unable to read TMD size from %s"), partHeadIn);
            tmdSz = SBig(tmdSz);
        }

        uint64_t h3Off;
        {
            uint32_t h3Ptr;
            if (ph->beginReadStream(0x2B4)->read(&h3Ptr, 4) != 4)
                LogModule.report(logvisor::Fatal, _S("unable to read H3 pointer from %s"), partHeadIn);
            h3Off = uint64_t(SBig(h3Ptr)) << 2;
        }

        uint64_t dataOff;
        {
            uint32_t dataPtr;
            if (ph->beginReadStream(0x2B8)->read(&dataPtr, 4) != 4)
                LogModule.report(logvisor::Fatal, _S("unable to read data pointer from %s"), partHeadIn);
            dataOff = uint64_t(SBig(dataPtr)) << 2;
        }
        m_userOffset = dataOff;

        std::unique_ptr<uint8_t[]> tmdData(new uint8_t[tmdSz]);
        if (ph->beginReadStream(0x2C0)->read(tmdData.get(), tmdSz) != tmdSz)
            LogModule.report(logvisor::Fatal, _S("unable to read TMD from %s"), partHeadIn);

        /* Copy partition head up to H3 table */
        std::unique_ptr<IFileIO::IWriteStream> ws = m_parent.getFileIO().beginWriteStream(m_baseOffset);
        {
            uint64_t remCopy = h3Off;

            uint8_t copyBuf[8192];
            std::unique_ptr<IFileIO::IReadStream> rs = ph->beginReadStream();
            while (remCopy)
            {
                size_t rdBytes = rs->read(copyBuf, std::min(size_t(8192), size_t(remCopy)));
                if (rdBytes)
                {
                    ws->write(copyBuf, rdBytes);
                    remCopy -= rdBytes;
                    continue;
                }
                for (size_t i=0 ; i<remCopy ; ++i)
                    ws->write("", 1);
                break;
            }
        }

        /* Prepare crypto pass */
        m_aes->setKey(COMMON_KEYS[ccIdx]);
        m_aes->decrypt(tkeyiv, tkey, tkey, 16);
        m_aes->setKey(tkey);

        {
            /* Assemble partition data */
            std::unique_ptr<IPartWriteStream> cws = beginWriteStream(0x1F0000);
            bool result = DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(*cws, dirIn, dolIn, apploaderIn);
            if (!result)
                return 0;

            /* Pad out user area to nearest cleartext sector */
            m_curUser = cws->position();
            uint64_t curUserRem = m_curUser % 0x1F0000;
            if (curUserRem)
            {
                curUserRem = 0x1F0000 - curUserRem;
                for (size_t i=0 ; i<curUserRem ; ++i)
                    cws->write("\xff", 1);
                m_curUser += curUserRem;
            }

            /* Begin crypto write and add content header */
            cws = beginWriteStream(0);
            Header header(m_gameID, m_gameTitle.c_str(), true, 0, 0, 0);
            header.write(*cws);

            /* Get Apploader Size */
            Sstat theStat;
            if (Stat(apploaderIn, &theStat))
                LogModule.report(logvisor::Fatal, _S("unable to stat %s"), apploaderIn);

            /* Compute boot table members and write */
            size_t fstOff = 0x2440 + ROUND_UP_32(theStat.st_size);
            size_t fstSz = sizeof(FSTNode) * m_buildNodes.size();
            fstSz += m_buildNameOff;
            fstSz = ROUND_UP_32(fstSz);

            if (fstOff + fstSz >= 0x1F0000)
                LogModule.report(logvisor::Fatal,
                                 "FST flows into user area (one or the other is too big)");

            cws->write(nullptr, 0x420 - sizeof(Header));
            uint32_t vals[4];
            vals[0] = SBig(uint32_t(m_dolOffset >> uint64_t(2)));
            vals[1] = SBig(uint32_t(fstOff >> uint64_t(2)));
            vals[2] = SBig(uint32_t(fstSz));
            vals[3] = SBig(uint32_t(fstSz));
            cws->write(vals, 16);

            /* Write Apploader */
            cws->write(nullptr, 0x2440 - 0x430);
            std::unique_ptr<IFileIO::IReadStream> rs = NewFileIO(apploaderIn)->beginReadStream();
            char buf[8192];
            size_t xferSz = 0;
            SystemString apploaderName(apploaderIn);
            ++m_parent.m_progressIdx;
            while (true)
            {
                size_t rdSz = rs->read(buf, 8192);
                if (!rdSz)
                    break;
                cws->write(buf, rdSz);
                xferSz += rdSz;
                if (0x2440 + xferSz >= 0x1F0000)
                    LogModule.report(logvisor::Fatal,
                                     "apploader flows into user area (one or the other is too big)");
                m_parent.m_progressCB(m_parent.m_progressIdx, apploaderName, xferSz);
            }

            size_t fstOffRel = fstOff - 0x2440;
            if (xferSz > fstOffRel)
                LogModule.report(logvisor::Fatal, "apploader unexpectedly flows into FST");
            for (size_t i=0 ; i<fstOffRel-xferSz ; ++i)
                cws->write("\xff", 1);

            /* Write FST */
            cws->write(m_buildNodes.data(), m_buildNodes.size() * sizeof(FSTNode));
            for (const std::string& str : m_buildNames)
                cws->write(str.data(), str.size()+1);
        }

        /* Write new crypto content size */
        uint64_t groupCount = m_curUser / 0x1F0000;
        uint64_t cryptContentSize = (groupCount * 0x200000) >> uint64_t(2);
        uint32_t cryptContentSizeBig = SBig(uint32_t(cryptContentSize));
        ws = m_parent.getFileIO().beginWriteStream(m_baseOffset + 0x2BC);
        ws->write(&cryptContentSizeBig, 0x4);

        /* Write new H3 */
        ws = m_parent.getFileIO().beginWriteStream(m_baseOffset + h3Off);
        ws->write(m_h3, 0x18000);

        /* Compute content hash and replace in TMD */
        sha1nfo sha;
        sha1_init(&sha);
        sha1_write(&sha, (char*)m_h3, 0x18000);
        memcpy(tmdData.get() + 0x1F4, sha1_result(&sha), 20);

        /* Same for content size */
        uint64_t contentSize = groupCount * 0x1F0000;
        uint64_t contentSizeBig = SBig(contentSize);
        memcpy(tmdData.get() + 0x1EC, &contentSizeBig, 8);

        /* Zero-out TMD signature to simplify brute-force */
        memset(tmdData.get() + 0x4, 0, 0x100);

        /* Brute-force zero-starting hash */
        size_t tmdCheckSz = tmdSz - 0x140;
        struct BFWindow
        {
            uint64_t word[7];
        }* bfWindow = (BFWindow*)(tmdData.get() + 0x19A);
        bool good = false;
        uint64_t attempts = 0;
        SystemString bfName(_S("Brute force attempts"));
        ++m_parent.m_progressIdx;
        for (int w=0 ; w<7 ; ++w)
        {
            for (uint64_t i=0 ; i<UINT64_MAX ; ++i)
            {
                bfWindow->word[w] = i;
                sha1_init(&sha);
                sha1_write(&sha, (char*)(tmdData.get() + 0x140), tmdCheckSz);
                uint8_t* hash = sha1_result(&sha);
                ++attempts;
                if (hash[0] == 0)
                {
                    good = true;
                    break;
                }
                m_parent.m_progressCB(m_parent.m_progressIdx, bfName, attempts);
            }
            if (good)
                break;
        }
        m_parent.m_progressCB(m_parent.m_progressIdx, bfName, attempts);

        ws = m_parent.getFileIO().beginWriteStream(m_baseOffset + 0x2C0);
        ws->write(tmdData.get(), tmdSz);

        return m_baseOffset + dataOff + groupCount * 0x200000;
    }