Chameleon

Issue 339: Memory Bug Report

Reported by Wang Xi, Apr 29, 2013

Hello,

I found a bug that chameleon reported incorrect system memroy by 
BIOS, which is existing in all the version.

My notebook is Asus N56VZ, I think many Asus notebooks have the same 
problem. I installed 8GB, but chameleon reports only 3229MB. So 
today I got source code, finally I found (haven't tested, but I am 
sure),

The const kMemoryMapCountMax (only 40 loops) IS TOO SMALL to get the 
actual memory from bios in biosfn.c.

For my Asus N56, getMemoryMap() loops up to 40 times (I typed 
"?Memory" to get the number of ranges, which is 40).

Resolution:
1.extend kMemoryMapCountMax to at least 1000 or more.
or
2. don't use it. The best way is to in getMemoryMap() change while ( 
count < maxRangeCount ) to while (1).

I am the author of NetTransport (http://www.net-xfer.com/)

Hope you fix it soon.

Xi

Comment 1 by Wang Xi, Apr 29, 2013

unsigned long getMemoryMap( MemoryRange *   rangeArray,
                            unsigned long   maxRangeCount,
                            unsigned long * conMemSizePtr,
                            unsigned long * extMemSizePtr )
{
    #define kMemoryMapSignature  'SMAP'
    #define kDescriptorSizeMin   20

    MemoryRange *	range = (MemoryRange *)BIOS_ADDR;
    unsigned long	count = 0;
    //    unsigned long	rerangedCount;
    unsigned long long	conMemSize = 0;
    unsigned long long	extMemSize = 0;

    // Prepare for the INT15 E820h call. Each call returns a single
    // memory range. A continuation value is returned that must be
    // provided on a subsequent call to fetch the next range.
    //
    // Certain BIOSes (Award 6.00PG) expect the upper word in EAX
    // to be cleared on entry, otherwise only a single range will
    // be reported.
    //
    // Some BIOSes will simply ignore the value of ECX on entry.
    // Probably best to keep its value at 20 to avoid surprises.

    //printf("Get memory map 0x%x, %d\n", rangeArray); 
getchar();
    if (maxRangeCount > (BIOS_LEN / sizeof(MemoryRange))) {
        maxRangeCount = (BIOS_LEN / sizeof(MemoryRange));
    }
    bb.ebx.rx = 0;  // Initial continuation value must be zero.

// Xi   2013.4.29
// {
//    while ( count < maxRangeCount )
// }
    while (1)
    {
        bb.intno  = 0x15;
        bb.eax.rx = 0xe820;
        bb.ecx.rx = kDescriptorSizeMin;
        bb.edx.rx = kMemoryMapSignature;
        bb.edi.rr = NORMALIZED_OFFSET(  (unsigned long) range );
        bb.es     = NORMALIZED_SEGMENT( (unsigned long) range );
        bios(&bb);

        // Check for errors.

        if ( bb.flags.cf
        ||   bb.eax.rx != kMemoryMapSignature
        ||   bb.ecx.rx != kDescriptorSizeMin ) {
            //printf("Got an error %x %x %x\n", 
bb.flags.cf,
            //       bb.eax.rx, bb.ecx.rx);
            break;
        }

        // Tally up the conventional/extended memory sizes.

        if ( range->type == kMemoryRangeUsable ||
             range->type == kMemoryRangeACPI   ||
             range->type == kMemoryRangeNVS )
        {
            // Tally the conventional memory ranges.
            if ( range->base + range->length <= 0xa0000 ) {
                conMemSize += range->length;
            } 

            // Record the top of extended memory.
            if ( range->base >= EXTENDED_ADDR ) {
                extMemSize += range->length;
            }
        }

        range++;
        count++;

        // Is this the last address range?

        if ( bb.ebx.rx == 0 ) {
            //printf("last range\n");
            break;
        }
    }
    *conMemSizePtr = conMemSize / 1024;  // size in KB
    *extMemSizePtr = extMemSize  / 1024;  // size in KB

#if 0
    rerangedCount = rerangeMemoryMap(count);
    range += rerangedCount - count;
#endif

    // Copy out data
    bcopy((char *)BIOS_ADDR, rangeArray, ((char *)range - (char 
*)BIOS_ADDR));

#if DEBUG
    {
        int i;
        printf("%d total ranges\n", count); getchar();
        for (i=0, range = rangeArray; i<count; i++, range++) {
            printf("range: type %d, base 0x%x, length 
0x%x\n",
                   range->type, (unsigned int)range->base, 
(unsigned int)range->length); getchar();
        }
    }
#endif

    return count;
}

Comment 2 by Wang Xi, Apr 29, 2013

Hello,

How to compile chameleon? On Linux, or Mac OS, or Windows?

Xi

Comment 3 by Mark Langovoi, Apr 29, 2013

Only Mac OS, xCode.

Comment 4 by Wang Xi, Apr 29, 2013

or

#define kMemoryMapCountMax     1000

Comment 5 by Mark Langovoi, Apr 29, 2013

Now i don't have my n56vz. When i get it back, i test it.

Comment 6 by Wang Xi, Apr 29, 2013

If you can package to this ISO format like the attachment, I can 
test for you.

Xi

Comment 7 by Wang Xi, Apr 29, 2013

Mac OS 10.8.3 reports 8G, but its active monitor shows only 3.25G

Comment 8 by Wang Xi, Apr 29, 2013

Xocde version? 4.6 ?

Comment 9 by Wang Xi, Apr 29, 2013

can't be compiled by Xcode 3.2.6, I like 3.2.6.

Comment 10 by Mark Langovoi, Apr 29, 2013

I complile with lastest xCode, when set patch for HD4000.

Comment 11 by Mark Langovoi, Apr 29, 2013

Now i don't have any pcs with Mac OS...(

Comment 12 by Hector Gonzalez, May 1, 2013

Just one comment. Even though the "while (1)" fixes the 
memory detection problem while booting it causes sleep problems

Setting the value for kMemoryMapCountMax seems to be the correct 
approach.

Thanks again Xi for pointing out the bug!

H.

Comment 13 by Wang Xi, May 1, 2013

Please update it soon.
I used Xcode 4.6 to compile chameleon, but Xcode told me that I have 
no make execute.

Thanks

Xi

Comment 14 by Hector Gonzalez, May 1, 2013

Hi Xi,

I had the same issue and this is what I did (just in case you want 
to compile)

Install shell tools using Xcode preferences menu (downloads). Then I 
compiled using command line with latest code from chameleon SVN.

Comment 15 by John Madness, May 3, 2013

Hello all!

I have many problems to compile Chameleon on OSX 10.8.2 + XCode 
4.6.2 (different versions have a different compile mistakes, and i 
tired to find the solution for anything of it) :<

Can someone upload the worked compiled version (with updated 
kMemoryMapCountMax) here?... 
I'm apologise for this ... use.

Comment 16 by Hector Gonzalez, May 3, 2013

There you go.

https://dl.dropboxusercontent.com/u/289985/i386.zip

Comment 17 by ErmaC , May 3, 2013

Status: Accepted

Comment 18 by Wang Xi, May 4, 2013

Hello,

I tested, YES, it's GREAT, I saw 8.13G appeared in Active Monitor.

Thank you, Hector Gonzalez

Xi

Comment 19 by John Madness, May 4, 2013

It's working! (:

Thanks to all!

Comment 20 by John Madness, May 4, 2013

It's working! (:

Thanks to all!

Comment 21 by John Madness, May 4, 2013

It's working! (:

Thanks to all!

Comment 22 by jns 1936, May 5, 2013

hey guys, sorry for my lack of skills but how did you test it? did 
you rebuild chameleon from source?

thanks by the way

Comment 23 by ErmaC , May 5, 2013

Status: Fixed

Comment 24 by Wang Xi, May 6, 2013

Hello,

kMemoryMapCountMax = 100 is enough, I counted the number of memory 
blocks of Asus N56VZ was 52. So kMemoryMapCountMax = 100 is enough.

Xi

Comment 25 by jns 1936, May 7, 2013

checked, works great.
finally all 16Gb of RAM are recognized and used.

thanks once again

Comment 26 by Nicolás Petersen, May 28, 2013

Has this anything to do with the recognition of the Vram of a 670mx 
graphics card ?

Created: 10 years 11 months ago by Wang Xi

Updated: 10 years 10 months ago

Status: Fixed

Followed by: 6 persons

Labels:
Priority:Medium
Type:Defect