Logo Search packages:      
Sourcecode: virtualbox-ose version File versions  Download package

static int kldrModLXDoIterData2Unpacking ( KU8 *  pbDst,
const KU8 *  pbSrc,
int  cbSrc 
) [static]

Unpacks iterdata (aka EXEPACK).

Returns:
0 on success, non-zero kLdr status code on failure.
Parameters:
pbDst Where to put the uncompressed data. (Assumes OBJPAGELEN size.)
pbSrc The compressed source data.
cbSrc The file size of the compressed data. The source buffer contains 4 additional zero bytes.

Definition at line 1578 of file kLdrModLX.c.

References KLDR_ERR_LX_BAD_ITERDATA2, kLdrModLXMemCopyW(), and OBJPAGELEN.

Referenced by kldrModLXDoLoadBits().

{
    int cbDst = OBJPAGELEN;

    while (cbSrc > 0)
    {
        /*
         * Bit 0 and 1 is the encoding type.
         */
        switch (*pbSrc & 0x03)
        {
            /*
             *
             *  0  1  2  3  4  5  6  7
             *  type  |              |
             *        ----------------
             *             cb         <cb bytes of data>
             *
             * Bits 2-7 is, if not zero, the length of an uncompressed run
             * starting at the following byte.
             *
             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
             *  type  |              |  |                    | |                     |
             *        ----------------  ---------------------- -----------------------
             *             zero                 cb                 char to multiply
             *
             * If the bits are zero, the following two bytes describes a 1 byte interation
             * run. First byte is count, second is the byte to copy. A count of zero is
             * means end of data, and we simply stops. In that case the rest of the data
             * should be zero.
             */
            case 0:
            {
                if (*pbSrc)
                {
                    const int cb = *pbSrc >> 2;
                    cbDst -= cb;
                    if (cbDst < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    cbSrc -= cb + 1;
                    if (cbSrc < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    kHlpMemCopy(pbDst, ++pbSrc, cb);
                    pbDst += cb;
                    pbSrc += cb;
                }
                else if (cbSrc < 2)
                    return KLDR_ERR_LX_BAD_ITERDATA2;
                else
                {
                    const int cb = pbSrc[1];
                    if (!cb)
                        goto l_endloop;
                    cbDst -= cb;
                    if (cbDst < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    cbSrc -= 3;
                    if (cbSrc < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    kHlpMemSet(pbDst, pbSrc[2], cb);
                    pbDst += cb;
                    pbSrc += 3;
                }
                break;
            }


            /*
             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
             *  type  |  |  |     |  |                       |
             *        ----  -------  -------------------------
             *        cb1   cb2 - 3          offset            <cb1 bytes of data>
             *
             * Two bytes layed out as described above, followed by cb1 bytes of data to be copied.
             * The cb2(+3) and offset describes an amount of data to be copied from the expanded
             * data relative to the current position. The data copied as you would expect it to be.
             */
            case 1:
            {
                cbSrc -= 2;
                if (cbSrc < 0)
                    return KLDR_ERR_LX_BAD_ITERDATA2;
                else
                {
                    const unsigned  off = ((unsigned)pbSrc[1] << 1) | (*pbSrc >> 7);
                    const int       cb1 = (*pbSrc >> 2) & 3;
                    const int       cb2 = ((*pbSrc >> 4) & 7) + 3;

                    pbSrc += 2;
                    cbSrc -= cb1;
                    if (cbSrc < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    cbDst -= cb1;
                    if (cbDst < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    kHlpMemCopy(pbDst, pbSrc, cb1);
                    pbDst += cb1;
                    pbSrc += cb1;

                    if (off > OBJPAGELEN - (unsigned)cbDst)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    cbDst -= cb2;
                    if (cbDst < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    kHlpMemMove(pbDst, pbDst - off, cb2);
                    pbDst += cb2;
                }
                break;
            }


            /*
             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
             *  type  |  |  |                                |
             *        ----  ----------------------------------
             *       cb-3               offset
             *
             * Two bytes layed out as described above.
             * The cb(+3) and offset describes an amount of data to be copied from the expanded
             * data relative to the current position.
             *
             * If offset == 1 the data is not copied as expected, but in the memcpyw manner.
             */
            case 2:
            {
                cbSrc -= 2;
                if (cbSrc < 0)
                    return KLDR_ERR_LX_BAD_ITERDATA2;
                else
                {
                    const unsigned  off = ((unsigned)pbSrc[1] << 4) | (*pbSrc >> 4);
                    const int       cb = ((*pbSrc >> 2) & 3) + 3;

                    pbSrc += 2;
                    if (off > OBJPAGELEN - (unsigned)cbDst)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    cbDst -= cb;
                    if (cbDst < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    kLdrModLXMemCopyW(pbDst, pbDst - off, cb);
                    pbDst += cb;
                }
                break;
            }


            /*
             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
             *  type  |        |  |              |  |                                |
             *        ----------  ----------------  ----------------------------------
             *           cb1            cb2                      offset                <cb1 bytes of data>
             *
             * Three bytes layed out as described above, followed by cb1 bytes of data to be copied.
             * The cb2 and offset describes an amount of data to be copied from the expanded
             * data relative to the current position.
             *
             * If offset == 1 the data is not copied as expected, but in the memcpyw manner.
             */
            case 3:
            {
                cbSrc -= 3;
                if (cbSrc < 0)
                    return KLDR_ERR_LX_BAD_ITERDATA2;
                else
                {
                    const int       cb1 = (*pbSrc >> 2) & 0xf;
                    const int       cb2 = ((pbSrc[1] & 0xf) << 2) | (*pbSrc >> 6);
                    const unsigned  off = ((unsigned)pbSrc[2] << 4) | (pbSrc[1] >> 4);

                    pbSrc += 3;
                    cbSrc -= cb1;
                    if (cbSrc < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    cbDst -= cb1;
                    if (cbDst < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    kHlpMemCopy(pbDst, pbSrc, cb1);
                    pbDst += cb1;
                    pbSrc += cb1;

                    if (off > OBJPAGELEN - (unsigned)cbDst)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    cbDst -= cb2;
                    if (cbDst < 0)
                        return KLDR_ERR_LX_BAD_ITERDATA2;
                    kLdrModLXMemCopyW(pbDst, pbDst - off, cb2);
                    pbDst += cb2;
                }
                break;
            }
        } /* type switch. */
    } /* unpack loop */

l_endloop:


    /*
     * Zero remainder of the page.
     */
    if (cbDst > 0)
        kHlpMemSet(pbDst, 0, cbDst);

    return 0;
}


Generated by  Doxygen 1.6.0   Back to index