Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

T60/T61 series specific matters only
Message
Author
axiom
Freshman Member
Posts: 100
Joined: Sat Mar 24, 2007 9:34 am
Location: Toronto, Canada

@

#31 Post by axiom » Fri Jun 22, 2007 7:18 pm

I guess a remapping will tell if the trouble really comes from the low TOLM value

Found in /usr/src/linux/arch/i386/kernel/setup.c

/*
* "mem=nopentium" disables the 4MB page tables.
* "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
* to <mem>, overriding the bios size.
* "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
* <start> to <start>+<mem>, overriding the bios size.
*
* HPA tells me bootloaders need to parse mem=, so no new
* option should be mem= [also see Documentation/i386/boot.txt]
*/

In the case that you want to use the [00000000c0000000 - 00000000f0000000] block, maybe you can try
memmap=3072M@256M (or some variants)
If it does nothing, then there is a stronger reason to believe in the TOLM issue.

But do try mem=3400MB before trying this one.

liyifan
Posts: 30
Joined: Wed Jun 20, 2007 10:40 pm
Location: Edmonton, Alberta, Canada

#32 Post by liyifan » Fri Jun 22, 2007 7:38 pm

OK, I now have a better understanding of this issue and I have some bad news.

http://download.intel.com/design/mobile ... 921904.pdf
Page 325, Figure 13. You have to specify ONE address (TOLUD) above which all memory is dedicated to PCI. From how the figure looks, plus the fact that we have 256MB display memory which is too big to put above F000_0000, the highest possible value for TOLUD would be D000_0000, which basically says no matter what we cannot go over 3.25GB.

Now, I'm still not sure why can't the bios give me 3.25GB. Anyone?

Axiom:
I'm running a livecd right now, but I will look into this when I get a chance. Thanks!
T60P, T7200, 4GB, FireGL 5250, 3945ABG, nice little baby.

axiom
Freshman Member
Posts: 100
Joined: Sat Mar 24, 2007 9:34 am
Location: Toronto, Canada

#33 Post by axiom » Fri Jun 22, 2007 7:58 pm

liyifan wrote:OK, I now have a better understanding of this issue and I have some bad news.

http://download.intel.com/design/mobile ... 921904.pdf
Page 325, Figure 13. You have to specify ONE address (TOLUD) above which all memory is dedicated to PCI. From how the figure looks, plus the fact that we have 256MB display memory which is too big to put above F000_0000, the highest possible value for TOLUD would be D000_0000, which basically says no matter what we cannot go over 3.25GB.
I am confused.
If that 256MB display memory can't go above F0000000, then you just take away the tail chunk of the C0000000-F0000000 block, which would still leave you C0000000-E0000000, so wouldn't the TOLUD thingy that you are talking about be E0000000 at max? So you still get 2/3 of that address block that you are eying on.
But regardless if it's the case, we should try to reclaim the first 256MB first, and get greedy if we actually get anywhere.
liyifan wrote: Axiom:
I'm running a livecd right now, but I will look into this when I get a chance. Thanks!
just pass in something like "mem=3200MB" as a boot parameter when you boot.
I forgot how's the format of a live cd, basically you just append that parameter to the string to use to call the kernel.

liyifan
Posts: 30
Joined: Wed Jun 20, 2007 10:40 pm
Location: Edmonton, Alberta, Canada

#34 Post by liyifan » Fri Jun 22, 2007 8:06 pm

axiom wrote: I am confused.
If that 256MB display memory can't go above F0000000, then you just take away the tail chunk of the C0000000-F0000000 block, which would still leave you C0000000-E0000000, so wouldn't the TOLUD thingy that you are talking about be E0000000 at max? So you still get 2/3 of that address block that you are eying on.
You have to look at the Figure, E000_0000 through F000_0000 is reserved for PCI-E configuration space... I know this sucks but now I'm setting 3.25 as my target. I really wish somebody from Lenovo could give a definitive answer - Yes it can be done or No don't bother.
T60P, T7200, 4GB, FireGL 5250, 3945ABG, nice little baby.

axiom
Freshman Member
Posts: 100
Joined: Sat Mar 24, 2007 9:34 am
Location: Toronto, Canada

#35 Post by axiom » Fri Jun 22, 2007 8:20 pm

I am starting to seeing it now
d0000000-dfffffff the 256mb block got used by the framebuffer.
so 00000000-ffffffff is the entire 4GByte block of i945, someone should have calculated it for me so I wouldn't be thinking that to be a 512mb block :P
and with that TOLUD thingy, the few tens of MB addresses at the end aren't usable either...

Now I think I understand it better than before
Thanks!

liyifan wrote: You have to look at the Figure, E000_0000 through F000_0000 is reserved for PCI-E configuration space... I know this sucks but now I'm setting 3.25 as my target. I really wish somebody from Lenovo could give a definitive answer - Yes it can be done or No don't bother.

liyifan
Posts: 30
Joined: Wed Jun 20, 2007 10:40 pm
Location: Edmonton, Alberta, Canada

#36 Post by liyifan » Fri Jun 22, 2007 9:30 pm

News:

http://blogs.conchango.com/jameshayes/default.aspx

A bios update from dell allowed 3.25GB instead of 3.0 sharp. Exactly what I wanted with my T60P.
T60P, T7200, 4GB, FireGL 5250, 3945ABG, nice little baby.

axiom
Freshman Member
Posts: 100
Joined: Sat Mar 24, 2007 9:34 am
Location: Toronto, Canada

#37 Post by axiom » Fri Jun 22, 2007 10:13 pm

I think now I see a point why people want open source BIOS so much.
If we get the source of the T60 bios, we can completely rearrange the memory mapping to squeeze the IO space real tight at the very end and raise that TOLUD thingy highest possible.

liyifan
Posts: 30
Joined: Wed Jun 20, 2007 10:40 pm
Location: Edmonton, Alberta, Canada

#38 Post by liyifan » Fri Jun 22, 2007 10:36 pm

axiom wrote:I think now I see a point why people want open source BIOS so much.
If we get the source of the T60 bios, we can completely rearrange the memory mapping to squeeze the IO space real tight at the very end and raise that TOLUD thingy highest possible.
Well, you can always disassemble your bios code, and maybe patch it. I'm looking at it right now to see if TOLUD is set as we thought. But... As I said I believe the best one can get (at least on T60P with 256MB Video Ram) is 3.25GB.
T60P, T7200, 4GB, FireGL 5250, 3945ABG, nice little baby.

axiom
Freshman Member
Posts: 100
Joined: Sat Mar 24, 2007 9:34 am
Location: Toronto, Canada

#39 Post by axiom » Fri Jun 22, 2007 11:01 pm

why don't you test out the mem boot parameters? I guess they give a good indication whether there is some lower level constraint exists(tolud) or not, especially the memmap one

mem=3200M

memmap=3072M@256M (or some variants, say 3100M@50M .. etc)

liyifan
Posts: 30
Joined: Wed Jun 20, 2007 10:40 pm
Location: Edmonton, Alberta, Canada

#40 Post by liyifan » Sun Jun 24, 2007 1:47 am

OK, I can now confirm that the TOLUD register is set to C0, which pretty much explains the 3GB sharp limit. C0==>C000-0000==>3.0GB, to put it in a simple way.

Since the thinkpad BIOS has a lot of customizations I it would take a lot of time to figure out whether this value is simply put there statically, I don't have the time to figure out and seems not too many people are interested in that 250MB... Anyway here's my thoughts if any one wants to go further: before the kernel starts, unlock and set the TOLUD register to D0, and fake a E820 memory map.

But again, as I noted before Dell had released a BIOS update for D820 which allowed it users to gain that additional 250MB so if anybody from Lenovo is reading this please let us know whether we can expect the same.

Axiom, big thanks for following through thus far.
T60P, T7200, 4GB, FireGL 5250, 3945ABG, nice little baby.

barrywohl
Junior Member
Junior Member
Posts: 445
Joined: Tue Mar 06, 2007 8:01 am
Location: Sheridan, WY
Contact:

#41 Post by barrywohl » Sun Jun 24, 2007 8:39 am

liyifan wrote:OK, I can now confirm that the TOLUD register is set to C0, which pretty much explains the 3GB sharp limit. C0==>C000-0000==>3.0GB, to put it in a simple way.
So the hard limit is 3 gb until the BIOS changes, even for Vista 64?

Why does Lenovo Direct sell 4 gb without a disclaimer?
First Thinkpad 755CX in 1995. First IBM: PC 1982 8088 w 64K RAM, dual floppy. Currently in use:
X230T with Win8Pro x64, i7, 500gb ssd; W700 WUXGA RAID 1 Blu-Ray W7Pro x64, occasionally a T61p with Win7Pro x64

axiom
Freshman Member
Posts: 100
Joined: Sat Mar 24, 2007 9:34 am
Location: Toronto, Canada

#42 Post by axiom » Sun Jun 24, 2007 12:14 pm

I am really interested to know the result of the memmap boot parameter, its job is exactly to fill in the gaps the e820 memory map leaves out.
(the e820 map fetching code is located @ /usr/src/linux/arch/i386/kernel/e820.c )

btw, how did you find out the TOLUD is at C0000000?


liyifan wrote:OK, I can now confirm that the TOLUD register is set to C0, which pretty much explains the 3GB sharp limit. C0==>C000-0000==>3.0GB, to put it in a simple way.

Since the thinkpad BIOS has a lot of customizations I it would take a lot of time to figure out whether this value is simply put there statically, I don't have the time to figure out and seems not too many people are interested in that 250MB... Anyway here's my thoughts if any one wants to go further: before the kernel starts, unlock and set the TOLUD register to D0, and fake a E820 memory map.

But again, as I noted before Dell had released a BIOS update for D820 which allowed it users to gain that additional 250MB so if anybody from Lenovo is reading this please let us know whether we can expect the same.

Axiom, big thanks for following through thus far.

liyifan
Posts: 30
Joined: Wed Jun 20, 2007 10:40 pm
Location: Edmonton, Alberta, Canada

#43 Post by liyifan » Sun Jun 24, 2007 1:16 pm

barrywohl wrote: So the hard limit is 3 gb until the BIOS changes, even for Vista 64?

Why does Lenovo Direct sell 4 gb without a disclaimer?
This only applies to T60 and T60p, the new T61s can use 4GB with 64-bit OSes. Besides, AFIK MS 32-bit consumer OSes have hard-coded 4GB address space limit, generating a similar effect to having a 945 chipset.

If you have a T60 and they didn't warn you (I think they do it to a certain extent), complain and let them at least give you 3.25GB :-) To be honest from what I've seen customer support is a bit clueless about this.
T60P, T7200, 4GB, FireGL 5250, 3945ABG, nice little baby.

liyifan
Posts: 30
Joined: Wed Jun 20, 2007 10:40 pm
Location: Edmonton, Alberta, Canada

#44 Post by liyifan » Sun Jun 24, 2007 1:27 pm

axiom wrote: btw, how did you find out the TOLUD is at C0000000?
Send 0x8000009C to I/O port 0xCF8, and then read a byte from port CFC, see the 945 specification link I posted earlier.
axiom wrote:I am really interested to know the result of the memmap boot parameter, its job is exactly to fill in the gaps the e820 memory map leaves out.
(the e820 map fetching code is located @ /usr/src/linux/arch/i386/kernel/e820.c )

btw, how did you find out the TOLUD is at C0000000?
OK, I see that you are really one persistent guy, may be more than I am :-) I believe it will not work but if you can PM me the exact modification that is needed to the ubuntu 7.10 live CD http://cdimage.ubuntu.com/daily-live/current/ I promise I'll PM you back the results once I have the time to try it.
T60P, T7200, 4GB, FireGL 5250, 3945ABG, nice little baby.

adidasprince
Posts: 34
Joined: Wed Mar 07, 2007 1:54 am
Location: Tokyo, Japan
Contact:

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#45 Post by adidasprince » Wed Jan 28, 2009 1:20 am

I found some explanation of 3.0GB issue.

Here is it. (from README for BIOS Update Utility 2.23)
BIOS INFORMATION

Memory Map Information
----------------------

Reserved Area:
The following conventional memory addresses are reserved by the BIOS
and others.

ATI Mobility Radeon X1300/X1400/FireGL V5200 models

C0000-CFFFF : Reserved for Video BIOS
D0000-D1FFF : Reserved for Option ROM of Ethernet (*1)
DC000-DFFFF : Reserved for USB BIOS (*2)
E0000-FFFFF : Reserved for System BIOS

Intel Graphics Media Accelerator 950 model

C0000-CE7FF : Reserved for Video BIOS
CE800-D07FF : Reserved for Option ROM of Ethernet (*1)
DC000-DFFFF : Reserved for USB BIOS (*2)
E0000-FFFFF : Reserved for System BIOS

Notes:
*1: This area becomes free by disabling the Internal Network Option
ROM option under Config and Network in the BIOS Setup Utility.
This choice will disable PXE and WOL features.
*2: This area becomes free by disabling the USB BIOS Support option
under Config and USB in the BIOS Setup Utility.
This choice does not affect using USB devices in Windows
operating systems.

Usable Area:
The following memory address can be used by the memory manager such as
EMM386.

ATI Mobility Radeon X1300/X1400/FireGL V5200 models

D2000-DBFFF

Intel Graphics Media Accelerator 950 model

D0800-DBFFF

Note: Certain addresses in this area will be reserved for CardBus
Controllers or others by Operating Systems.
The addresses vary and depend on the design of each Operating
System.
So ... , my answer is We can choose 3.0GB or 3.25 or 3.5 by ourselves.
IBM ThinkPad T60p 2007-93J

Uncle Joe
Posts: 26
Joined: Thu Aug 13, 2009 1:58 am
Location: Vienna, VA

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#46 Post by Uncle Joe » Thu Aug 13, 2009 3:39 am

Good news. I have a Lenovo 3000 N100 and I managed to mod it to recognize 3.5Gb RAM.
I'm pretty sure Lenovo isn't going to bother to release an updated BIOS, so I decided to do it myself.

Here's how I did it.

1. NOP some instruction in ROMEXEC0.ROM (BIOS code) that sets D_LCK bit in i945 memory controller. This allows
TOLUD to be changed. I used Phoenix BIOS Editor to unpack then repack. Then I reflashed the BIOS.

2. Remap PCI devices that use memory in [c0000000, e0000000). Namely, the Geforce's 256Mb framebuffer
was remapped from c0000000 to e0000000. Specifically, change PCI_BASE_ADDRESS_* for each device
and PCI_IO_BASE, PCI_IO_LIMIT for bridges.

3. Change the memory mapped IO base of the PCIX extended configuration space from e0000000 to f8000000.
This involves setting i945's PCIEXBAR and patching the MCFG ACPI table accordingly.

4. Change i945's TOLUD from c0 to e0

5. Update MTRR registers accordingly

6. Install a hook to override the int 0x15, e820 memory map

Steps 2 to 6 were performed by writing a GRUB2 module.

Things work great with both Vista and Debian. I'm running/testing some pretty large graph centrality algorithms + other simulations, so every piece of RAM helps. I also won't have to close Team Fortress 2 when I switch tasks. The only problem so far is suspend/resume is broken, but I always have the option of disabling the 3.5Gb mod from the boot loader.

If anyone wants detailed instructions, I'll be happy to share them.

Yale

yak
ThinkPadder
ThinkPadder
Posts: 1256
Joined: Thu Dec 06, 2007 3:17 pm
Location: NRW, Germany

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#47 Post by yak » Thu Aug 13, 2009 5:02 am

Uncle Joe, good job and welcome on-board!

Could this be released in a form usable for less savvy users? A BIOS binary possibly?
ThinkPad™ X201 / AFFS-120
i5-560M 2.67Ghz, 8GB RAM, Samsung 840 Pro 256GB SSD, Win 8 Pro 64-bit, UltraBase X200, ThinkPad Compact USB Keyboard,
Dell U2713HM (2560x1440, IPS), ExpressCard USB 3.0 (2 ports, flush), Nexus 7+10

Uncle Joe
Posts: 26
Joined: Thu Aug 13, 2009 1:58 am
Location: Vienna, VA

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#48 Post by Uncle Joe » Thu Aug 13, 2009 6:05 am

Great, looks like I have customers.

Doing all those fixups I described in the BIOS is the ideal solution, but is not possible currently because:
1. My fix-up code has hard coded values that assume certain PCI addresses, TOLUD, etc. Dynamic detection anyone?
2. ACPI sleep/resume is broken, so until it's fixed, you probably don't want the mod permanently in the BIOS.
3. I don't know how to inject custom code into the BIOS. So far I only NOPed 3 instructions. BIOS code seems pretty
tightly packed, so I probably can't overwrite existing code and call it.

Right now, the only practical way I know of to do this mod is to write a grub2 module (grub2 has ability to hook int 0x15, e820 and override the physical memory map). This is going to be a hassle for most people who don't have GNU/Linux installed because you'll have to install grub2, which I don't know how to except from Linux (maybe systemrescuecd can let you do this without needing to install Linux). I did write a hello world boot loader for testing purposes during this project, so maybe the fix-ups can be installed into the master boot record.

For those of you who like using bleeding edge software and have grub2, I've posted my grub2 code & how to do the BIOS mod at the bottom (why don't I see attach file option?).

My module should also work for the Thinkpad T60, since they both use the i945. Can someone add a post to the 4Gb sticky thread and tell them > 3Gb is possible? I originally expected to be able to use 3.7Gb RAM, but unfortunately, the GeForce framebuffer had to be mapped on an aligned address, resulting in ~250Mb waste. If your laptop graphics board
doesn't have such a large memory window, then you should be able to get > 3.5Gb.

Then there's the question of how to mod the T60 BIOS. I took a look at Thinkpad BIOS 2.23 and it looks like almost the exact
code as in the Lenovo BIOS is used to set the D_LCK bit of the SMRAM register (ndisasm -a $01A3000.FL1):

Code: Select all

0011AB29  B09D              mov al,0x9d              SMRAM register
0011AB2B  BB4B46            mov bx,0x464b         return address
0011AB2E  FF                db 0xff
0011AB2F  E994FE            jmp word 0xa9c6       read SMRAM
0011AB32  80CC10            or ah,0x10               set D_LCK
0011AB35  BB547F            mov bx,0x7f54
0011AB38  46                inc si
0011AB39  E991FE            jmp word 0xa9cd       write SMRAM
I don't know if just replacing the or with nops will work because there's probably a checksum somewhere that will be wrong, resulting in complaints during boot. I used Phoenix BIOS Editor to repack the Lenovo BIOS, and I assume it fixes the checksum.

--------------------------------------------------------------------------------------------Attachments-----------------------------------------------------------------------------------------------------

Code: Select all

-----------------------------------4gb.c---------------------------------
#include <grub/types.h>
#include <grub/dl.h>
#include <grub/pci.h>
#include <stdint.h>
#include <grub/misc.h>

// grub_pci_make_address uses dword instead of byte addressing for register
#define PCI_ADDRESS(bus, dev, fun, reg)  (1U << 31) | (bus << 16) | (dev << 11) | (fun << 8) | reg

#define PCI_MEMORY_BASE         0x20
#define PCI_MEMORY_LIMIT        0x22

#define PCI_PREF_MEMORY_BASE    0x24
#define PCI_PREF_MEMORY_LIMIT   0x26

#define PCI_CB_MEMORY_BASE_0   0x1c
#define PCI_CB_MEMORY_LIMIT_0  0x20

#define PCI_CB_MEMORY_BASE_1   0x24
#define PCI_CB_MEMORY_LIMIT_1  0x28

#define true 1
#define false 0

typedef uint8_t bool;
extern uint8_t g_is_4gb;



// set bits [index + n - 1 : index] of x to v
uint32_t SetBits(uint32_t x, uint32_t index, uint32_t n, uint32_t v)
{
  uint32_t mask = (1 << n) - 1;
  mask <<= index;
  x &= ~mask;
  x |= (v << index);
  return x;
}


#define PCIX_CONF_BAR 0x48
#define PCI_BASE_ADDRESS_0 0x10
#define PCI_BASE_ADDRESS_1 0x14
#define PCI_BASE_ADDRESS_2 0x18
#define PCI_BASE_ADDRESS_3 0x1c
#define PCI_BASE_ADDRESS_4 0x20
#define PCI_BASE_ADDRESS_5 0x24


inline void wrmsr(unsigned reg, uint32_t low, uint32_t high)
{
  asm(
    "wrmsr"
    : : "c"(reg), "a"(low), "d"(high));
}

#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
#define PAGE_SHIFT 12

// base, size are in pages; size *must* be power of 2 - I didn't realize this and notice memory bandwidth crawl to a halt
// base must be aligned on size
void SetMTRR(unsigned index, uint32_t base, uint32_t size, unsigned type)
{
  if (size == 0) {
    /* The invalid bit is kept in the mask, so we simply clear the
       relevant mask register to disable a range. */
    wrmsr(MTRRphysMask_MSR(index), 0, 0);
  } else  {
    wrmsr(MTRRphysBase_MSR(index), base << PAGE_SHIFT | type, (base & 0xf00000) >> (32 - PAGE_SHIFT));
    wrmsr(MTRRphysMask_MSR(index), -size << PAGE_SHIFT | 0x800, (-size & 0xf00000) >> (32 - PAGE_SHIFT));
  }
}

void SetBridgeMemoryRange(uint32_t pci_base, bool prefetchable, uint32_t base, uint32_t size)
{
  // note: bits[15:4] are bits 31:20 of full address - lower 4 bits unused
  uint32_t r = pci_base | (prefetchable ? PCI_PREF_MEMORY_BASE : PCI_MEMORY_BASE);
  uint16_t v = grub_pci_read_word(r);
  v |= (base & 0xfff00000) >> 16;
  grub_pci_write_word(r, v);
  r = pci_base | (prefetchable ? PCI_PREF_MEMORY_LIMIT : PCI_MEMORY_LIMIT);
  v = grub_pci_read_word(r);
  v |= ((base + size - 1) & 0xfff00000) >> 16;
  grub_pci_write_word(r, v);
}

void SetCardBridgeMemoryRange(uint32_t pci_base, bool prefetchable, uint32_t base, uint32_t size)
{
  grub_pci_write(pci_base | (prefetchable ? PCI_CB_MEMORY_BASE_0 : PCI_CB_MEMORY_BASE_1), base);
  grub_pci_write(pci_base | (prefetchable ? PCI_CB_MEMORY_LIMIT_0 : PCI_CB_MEMORY_LIMIT_1), (base + size - 1) & 0xfffff000);
}

// PCI spec states base must be aligned on region size to make address decoding easier (no subtracting addresses)
void SetDeviceMemoryBase(uint32_t pci_base, uint32_t reg, uint32_t base)
{
  uint32_t v = grub_pci_read(pci_base | reg);
  v &= 0xf;
  v |= (base & ~0xf);
  grub_pci_write(pci_base | reg, v);
}


uint8_t CacheOn(void)
{
  uint32_t cr0;
  asm("mov %%cr0, %0" : "=r"(cr0));
  return ((cr0 >> 30) & 0x1) == 0;
}

void wbinvd(void)
{
  asm volatile ("wbinvd");
}

void enable_cache(void)
{
  uint32_t cr0;
  asm("mov %%cr0, %0" : "=r"(cr0));
  cr0 &= 0x9fffffff;
  asm("mov %0, %%cr0" : : "r"(cr0));
}

void disable_cache(void)
{
  /* Disable and write back the cache */
  uint32_t cr0;
  asm("mov %%cr0, %0" : "=r"(cr0));
  cr0 |= 0x40000000;
  wbinvd();
  asm("mov %0, %%cr0" : : "r"(cr0));
  wbinvd();
}

#define MTRR_TYPE_UNCACHABLE 0
#define MTRR_TYPE_WRCOMB     1
#define MTRR_TYPE_WRTHROUGH  4
#define MTRR_TYPE_WRPROT     5
#define MTRR_TYPE_WRBACK     6

#define TOLUD 0x9c

GRUB_MOD_INIT (4gb)
{
  uint32_t mch_base = PCI_ADDRESS(0, 0, 0, 0),
    pcix_bridge0_base = PCI_ADDRESS(0, 1, 0, 0),  // root port
    pcix_bridge2_base = PCI_ADDRESS(0, 0x1c, 1, 0),
    geforce_base = PCI_ADDRESS(1, 0, 0, 0),
    audio_base = PCI_ADDRESS(0, 0x1b, 0, 0),
    usb_ehci_base = PCI_ADDRESS(0, 0x1d, 7, 0),
    south_bridge_base = PCI_ADDRESS(0, 0x1e, 0, 0),
    broadcom_base = PCI_ADDRESS(3, 0, 0, 0),
    realtek_8139_base = PCI_ADDRESS(5, 1, 0, 0),
    cardbus_bridge_base = PCI_ADDRESS(5, 4, 0, 0),
    firewire_base = PCI_ADDRESS(5, 6, 0, 0),
    sd_controller_base = PCI_ADDRESS(5, 6, 1, 0),
    mmc_controller_base = PCI_ADDRESS(5, 6, 2, 0),
    memory_stick_base = PCI_ADDRESS(5, 6, 3, 0),
    picture_card_base = PCI_ADDRESS(5, 6, 4, 0);

  g_is_4gb = true;   // tell grub_mmap_iterate to report more RAM

  disable_cache();     // do we really need to disable?
  grub_pci_write_byte(mch_base | TOLUD, 0xe0);

  // todo: this doesn't set MTRR on other core - apparently, issuing IPIs to do this seems pretty complicated
  SetMTRR(0, 0, 0x80000, MTRR_TYPE_WRBACK);
  SetMTRR(1, 0x80000, 0x40000, MTRR_TYPE_WRBACK);
  SetMTRR(2, 0xc0000, 0x20000, MTRR_TYPE_WRBACK);
  SetMTRR(3, 0xc0000 - 0x100, 0x100, MTRR_TYPE_UNCACHABLE);
  SetMTRR(4, 0xe0000 - 0x100, 0x100, MTRR_TYPE_UNCACHABLE);
  enable_cache();

  uint32_t pcix_conf_bar = grub_pci_read(mch_base | PCIX_CONF_BAR);
  pcix_conf_bar = SetBits(pcix_conf_bar, 26, 6, 0x3e);
  pcix_conf_bar = SetBits(pcix_conf_bar, 1, 2, 0x2);

  // need to write 2x because bits[2:1] need to be set before bits 27:26
  // can be written
  grub_pci_write(mch_base | PCIX_CONF_BAR, pcix_conf_bar);
  grub_pci_write(mch_base | PCIX_CONF_BAR, pcix_conf_bar);

  // root bus devices
  SetDeviceMemoryBase(audio_base, PCI_BASE_ADDRESS_0, 0xf0500000);
  SetDeviceMemoryBase(usb_ehci_base, PCI_BASE_ADDRESS_0, 0xf0504000);

  // PCIX root bridge
  SetBridgeMemoryRange(pcix_bridge0_base, true, 0xe0000000, 0x10000000);
  SetBridgeMemoryRange(pcix_bridge0_base, false, 0xf1000000, 0x2000000);

  SetDeviceMemoryBase(geforce_base, PCI_BASE_ADDRESS_0, 0xf2000000);
  SetDeviceMemoryBase(geforce_base, PCI_BASE_ADDRESS_1, 0xe0000000);
  SetDeviceMemoryBase(geforce_base, PCI_BASE_ADDRESS_3, 0xf1000000);

  // PCIX bridge 2
  SetBridgeMemoryRange(pcix_bridge2_base, false, 0xf0200000, 0x100000);
  SetBridgeMemoryRange(pcix_bridge2_base, true, 0xf0000000, 0x100000);
  
  SetDeviceMemoryBase(broadcom_base, PCI_BASE_ADDRESS_0, 0xf0200000);
  SetDeviceMemoryBase(broadcom_base, PCI_BASE_ADDRESS_2, 0xf0000000);

  // southbridge
  SetBridgeMemoryRange(south_bridge_base, false, 0xf0100000, 0x100000);
  SetBridgeMemoryRange(south_bridge_base, true, 0xf4000000, 0x4000000);
  
  SetDeviceMemoryBase(realtek_8139_base, PCI_BASE_ADDRESS_1, 0xf0100000);
  SetDeviceMemoryBase(sd_controller_base, PCI_BASE_ADDRESS_0, 0xf0100400);
  SetDeviceMemoryBase(firewire_base, PCI_BASE_ADDRESS_0, 0xf0100800);
  SetDeviceMemoryBase(mmc_controller_base, PCI_BASE_ADDRESS_0, 0xf0101000);
  SetDeviceMemoryBase(memory_stick_base, PCI_BASE_ADDRESS_0, 0xf0101400);
  SetDeviceMemoryBase(picture_card_base, PCI_BASE_ADDRESS_0, 0xf0101800);

  // cardbus is attached to southbridge
  SetCardBridgeMemoryRange(cardbus_bridge_base, true, 0xf4000000, 0x2000000);
  SetCardBridgeMemoryRange(cardbus_bridge_base, false, 0xf6000000, 0x2000000);

  volatile uint8_t *p;

  // DSDT
  p = (uint8_t *)0xbfee85b5;
  p[9] = 0x3b;    // checksum
  *(uint32_t *)&p[0x18f5] = 0xf8000000;  // pcix ext conf base
  *(uint32_t *)&p[0x18f9] = 0x04000000;  // pcix ext conf size
  *(uint32_t *)&p[0x1961] = 0xf8000000;
  *(uint32_t *)&p[0x1965] = 0x04000000;

  // ACPI MCFG table
  p = (uint8_t *)0xbfeecd58;
  p[9] = 0x48;   // checksum
  *(uint32_t *)&p[0x2c] = 0xf8000000;   // pcix ext conf base
  p[0x37] = 63;      // pcix ext conf last bus
  
  p = (uint8_t *)0xbfeecf3c;    // DBGP table
  p[9] = 0x99;
  *(uint32_t *)&p[0x2c] = 0xf0100800;    // 1394 MMIO  
}

GRUB_MOD_FINI (4gb)
{
}
--------------------------------------------kern/i386/pc/mmap.c------------------------------------------
#include <grub/machine/init.h>
#include <grub/machine/memory.h>
#include <grub/err.h>
#include <grub/types.h>
#include <grub/i386/pc/memory.h>
#include <stdint.h>

struct Region
{
  uint32_t base, size, type;
};

struct Region g_regions[] =
{
  {0,0x9f800, GRUB_MACHINE_MEMORY_AVAILABLE},
  {0x9f800, 0x800, GRUB_MACHINE_MEMORY_RESERVED},
  {0xdc000, 0x8000, GRUB_MACHINE_MEMORY_RESERVED},
  {0xe8000, 0x18000, GRUB_MACHINE_MEMORY_RESERVED},
  {0x100000, 0xbfde0000, GRUB_MACHINE_MEMORY_AVAILABLE},
  {0xbfee0000, 0xd000, GRUB_MACHINE_MEMORY_NVS},
  {0xbfeed000, 0x13000, GRUB_MACHINE_MEMORY_NVS}, 
  {0xbff00000, 0x100000, GRUB_MACHINE_MEMORY_RESERVED},
  {0xe0000000, 0x10000000, GRUB_MACHINE_MEMORY_RESERVED},
  {0xfec00000, 0x10000, GRUB_MACHINE_MEMORY_RESERVED},
  {0xfed00000, 0x400, GRUB_MACHINE_MEMORY_RESERVED},
  {0xfed14000, 0x4000, GRUB_MACHINE_MEMORY_RESERVED},
  {0xfed18000, 0x1000, GRUB_MACHINE_MEMORY_RESERVED},
  {0xfed19000, 0x1000, GRUB_MACHINE_MEMORY_RESERVED},
  {0xfed1c000, 0x4000, GRUB_MACHINE_MEMORY_RESERVED},
  {0xfed20000, 0x70000, GRUB_MACHINE_MEMORY_RESERVED},
  {0xfee00000, 0x1000, GRUB_MACHINE_MEMORY_RESERVED},
  {0xff000000, 0x1000000, GRUB_MACHINE_MEMORY_RESERVED}
};

uint8_t g_is_4gb = 0;

grub_err_t
grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
{
  int i;
  if (g_is_4gb)
  {
    g_regions[8].base = 0xf8000000;
    g_regions[8].size = 0x4000000;
  }

  for (i = 0; i < 8; ++i)
    hook(g_regions[i].base, g_regions[i].size, g_regions[i].type);

  if (g_is_4gb)
  {
    hook(0xc0000000, 0x20000000 - 0x100000, GRUB_MACHINE_MEMORY_AVAILABLE);
    hook(0xdff00000, 0x100000, GRUB_MACHINE_MEMORY_RESERVED);
  }
  for (i = 8; i < 18; ++i)
    hook(g_regions[i].base, g_regions[i].size, g_regions[i].type);
  return 0;
}
---------------------------------------------loader/i386/pc/chainloader.c-----------------------------------------------
(insert code into grub_chainloader_cmd() )

static void *preb_handle = 0;   // yale: can't duplicate or else preboot_hook gets called twice
                                   // causing unload_uneeded_dl to unload endlessly
  if (!preb_handle)
  {
    grub_err_t err = malloc_hook();    // register's int15 hook automatically
    if (err)
      grub_printf("can't allocate hook\n");
  }
---------------------------------------------how to mod BIOS (Lenovo 3000 N100)-----------------------------------------------
1. Open the Phoenix WPH file in a hex editor and find the following code.
(note: dissassembly below is of ROMEXEC0.ROM, so offsets will be different)

Code: Select all

000043DE  B09D              mov al,0x9d
000043E0  BB7950            mov bx,0x5079
000043E3  E9D8FE            jmp word 0x42be       read SMM
000043E6  80CC10            or ah,0x10             replace with NOP
000043E9  BB8250            mov bx,0x5082
000043EC  E9D5FE            jmp word 0x42c4
2. replace the or with nops
3. Unpack the modified WPH with Phoenix BIOS editor. Then Repack again (you need to make a trivial change and undo before the repack button becomes available).
4. Flash with the repacked WPH.
Last edited by Uncle Joe on Thu Aug 13, 2009 12:21 pm, edited 1 time in total.

yak
ThinkPadder
ThinkPadder
Posts: 1256
Joined: Thu Dec 06, 2007 3:17 pm
Location: NRW, Germany

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#49 Post by yak » Thu Aug 13, 2009 7:47 am

Unfortunately there's no attachment option on this forum.

Could you please enclose the code in

Code: Select all

 tags? This way the indentation will be preserved.

A fellow member of this forum, Zender, has a lot of experience modifying ThinkPad BIOSes. He uses this to add otherwise unsupported wireless cards to the whitelist. More about this in [url=http://forum.thinkpads.com/viewtopic.php?f=29&t=55837]this thread[/url].
ThinkPad™ X201 / AFFS-120
i5-560M 2.67Ghz, 8GB RAM, Samsung 840 Pro 256GB SSD, Win 8 Pro 64-bit, UltraBase X200, ThinkPad Compact USB Keyboard,
Dell U2713HM (2560x1440, IPS), ExpressCard USB 3.0 (2 ports, flush), Nexus 7+10

Uncle Joe
Posts: 26
Joined: Thu Aug 13, 2009 1:58 am
Location: Vienna, VA

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#50 Post by Uncle Joe » Thu Aug 13, 2009 1:35 pm

"Unfortunately there's no attachment option on this forum."

I'll post the complete code on my website later.

I still don't know how many people out there are willing to go this far for an extra 512Mb RAM (more or less, depending on memory used by peripherals). To build a usable solution for end users, I
need help with the following:

1. Method for running fixup code. I see the following possibilities:
a. grub2 - like I said earlier, the problem with this is that you need to install from GNU/Linux. I could create a bootable CD for this purpose. I don't know if
Windows only users will need to create a partition for grub2 files. Maybe the grub modules can be placed on NTFS.

b. boot loader - this probably will work best for people who don't have Linux, but the main problem is I highly doubt this code can fit into a 512 byte sector.
1 solution would be to create a small partition to hold the entire code. Another would be to find a static place to put the overflow code on an NTFS partition.
The most complicated would be to try and read from NTFS.
c. BIOS code injection - help from Zender and anyone else who knows how to do this will be appreciated.

Supporting multiple methods shouldn't be a problem because the same core code will be used.

2. Hardware configuration for each computer to be supported (probably any machine with i945 chipset)
PCI memory ranges from msinfo32 on Windows or lspci -v on Linux.
Existing e820 memory map - just save dmesg from Linux
MTRR values - /proc/mtrr

Meanwhile, for those of you with a Lenovo 3000 N100, you can use my mod by doing the following.
I only tested it on my type 0768, model E2U and I just realized the 3000 N100 has many variants, so I'm not sure if my
patch will work on them all. The BIOS patch should because all 3000 N100s use the same BIOS (but do they all use i945?).
At worst, the PCI remapping will be wrong, but the OS probably will fix it up anyways.


1. Flash your bios with this http://www.cc.gatech.edu/~yzhang67/NEW.WPH. I used WinPhlash.
I didn't have any problems on my 1st try, but you should prepare for the worst and make a bios recovery disk in case
you brick the BIOS. You have been warned :!:

2. Burn the grub2 boot disk I made: http://www.cc.gatech.edu/~yzhang67/grub.iso.
3. Boot from it. You should see a grub2 menu. The Vista option only works if Windows is installed on the 1st partition of 1st hard disk.
Most users probably still have the recovery partition as the 1st (I deleted mine), so you'll have to edit the boot command line by pressing e

and changing the line "root (hd0,1)" to "root (hd0,2)". Then press ctrl-x to boot.
If you're using GNU/Linux, then I assume you know what to do. See the grub2 wiki for help.
4. Enjoy

dozer
Sophomore Member
Posts: 209
Joined: Thu Jan 25, 2007 9:28 pm
Location: Grants Pass, Oregon

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#51 Post by dozer » Tue Aug 18, 2009 3:47 am

Uncle Joe, thanks VERY much for digging into this, and posting your results. 8)

Because the same BIOS file works on many variants of T60 with different option-loadings, I have to assume that the BIOS and/or the OS can 'insert' the various option-cards where they'll work fine.

So in theory a single modded ROM binary -should- work for many people.

Running counter to the above is your mention of losing ACPI/sleep functionality. That shouldn't have happened.

I think the first thing to do is figure out why that happened, and fix that problem.

That would allow the simplest of all possible methods to use this fix.....we all just flash our bios with UJ's binary. 8)

Otherwise, if we have to start applying patches at boot-time, then things get messier; as you've already discusses a little bit.

ps; I too urge you to contact Zender. He's been digging in the lenovo bios for several years now; and with some success.

Again....thanks! :)

Richard

PS on edit; I'm real curious how this works with an integrated-graphics mainboard. Presumably such a board can be set to use only 32mb or perhaps even less of "graphics RAM". If so, could we then get nother 200mb over the ATI-mainboard fix? That'd be a pretty significant gain, so worth checking on in regards to the intel-gpu mainboards.
WANTED! - Battery Diags/Reset Software; please PM me!
WTB: Good 9-cell T60 batt
WTB: Frankenpad T60 15" UXGA w/T61-Intel & internal modem
T60p, 2623-ddu, uxga, Intel-GPU || T61, 6465-01U 15.4" sxga || R60 9457-W37 14"xga

jack_b_uta
Posts: 19
Joined: Wed Aug 19, 2009 1:05 pm
Location: Enter your correct location ASAP

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#52 Post by jack_b_uta » Fri Aug 21, 2009 2:00 pm

Any luck with this. I would desperately like to try this out. Have a 3000 N100, 0689-A7U that has 2*2GB sticks in it. Vista 64 sees 4GB but can use only 3.

Uncle Joe
Posts: 26
Joined: Thu Aug 13, 2009 1:58 am
Location: Vienna, VA

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#53 Post by Uncle Joe » Fri Aug 21, 2009 5:25 pm

You're in luck and I'm glad to see people still interested. It's unfortunate I didn't see this in 2007 when more people were using T60s and 3000 N100s. When I got my 3000 N100 in spring 2007, I thought its 1Gb was plenty.

According to http://www.buy.com/prod/lenovo-3000-n10 ... 98920.html, your model uses a GMA 950, which unlike the Geforce 7300, doesn't need 256Mb memory mapped IO space. I'm guessing you'll be able to use ~3840Mb RAM.

As I said before, suspend/resume gets broken when my patch is applied, so I have a grub2 boot loader menu for choosing whether to apply the patch or not. I think supporting your model should be simple. The only hurdle is installing the grub2 boot loader. I've decided the best way to install grub2 without requiring GNU/Linux to be installed is to make a modified systemrescuecd http://www.sysresccd.org/Sysresccd-manu ... emRescueCd with grub2. However, the main risk is I don't know if the grub2 files can be installed onto NTFS or if it has to be on Ext2. If it has to be on Ext2, then you'll have to create a new partition (>= 2Mb) and format it as Ext2.

The other concern is flashing your BIOS. Although I'm confident my patched BIOS works for all 3000 N100 models (support page says all N100s use same BIOS and I only deleted 1 instruction in BIOS), I cannot guarantee it won't make your computer unbootable. In the past few days, I've been experimenting with injecting my fixup code into the BIOS and I've bricked my laptop >= 5 times. Luckily I am able to recover the old BIOS it by booting to crisis recovery mode. You can find how to make a crisis recovery disk elsewhere. Just know the quirks for the 3000 N100:

1. press fn + b to activate crisis recovery
2. floppy drive needs to be only USB device connected (not really necessary - I guess the recovery code thinks floppy is always device 0)
3. After unzipping crisis-recovery-disk-creator.zip, replace phlash16.exe with phlash1b.exe (others might work, but I haven't tried).

I'll probably get this done in a few days. Meanwhile, you can help by giving me your hardware info:
1. burn systemrescuecd
2. boot it and at menu, type rescue64 <enter>
3. "startx" (starts GUI)
4. open a console and "dmesg > /tmp/e820_map" (reports e820 memory map)
5. "/sbin/lspci -v > /tmp/pci" (reports PCI configuration)
6. send /tmp/e820_map and /tmp/pci to me

Uncle Joe
Posts: 26
Joined: Thu Aug 13, 2009 1:58 am
Location: Vienna, VA

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#54 Post by Uncle Joe » Sun Aug 23, 2009 12:43 am

Well, I guess I had more time than I expected. I've built a CD for testing and installing my mod. Get it here: http://www.cc.gatech.edu/~yzhang67/sysrescue_grub2.iso (will be uploaded in a few hours after this post). First, make sure you've flashed your BIOS with my modified one: http://www.cc.gatech.edu/~yzhang67/NEW.WPH. Then burn the CD and boot it.

The CD will automatically load my fixups. At the menu you should see these choices:

Windows
Windows 2
Debian
rescue
rescue64

You should test if my fixes work by choosing Windows or Windows 2, depending on which partition Windows is installed. Then open calculator -> about calculator and check if physical memory is > 3Gb. If it didn't increase, then most likely there's a problem with my fixups.

If it works, then you can choose to install my mod onto your hard disk. Reboot to the CD, and this time choose rescue or rescue64. When you get to the command line, execute "/mnt/cdrom/grub_install/install" (this installs grub2 to /grub on your Windows disk). Then, execute "reboot" and take out the CD.

After rebooting, you should see this grub2 menu:
Windows
Windows 2
Enable 4gb (click to enable my fixes)

To customize this menu, edit c:\grub\grub.cfg (see grub2 wiki).

Notes:

*Installing grub2 will overwrite your disk's master boot record. To uninstall, see here: http://support.microsoft.com/kb/927392 (I just use the Vista Upgrade Any Time DVD that came with my N100).

*I've inserted a check in my fixup code to see if there's a Geforce 7300. With a Geforce 7300, ~3584Mb RAM is set up. Without it, ~3840Mb is set up. This is a crude check, but should work for models using GMA 950. If you have a peripheral that needs a huge MMIO range, then there could be a conflict. That's why I said I needed hardware information for the different N100s.

*My mod is only intended for 3000 N100s. It should be able to be trivially extended to T60s by just using a different BIOS patch, but I need someone with a T60 who's willing to try the BIOS.

Enjoy your extra RAM :D

Uncle Joe
Posts: 26
Joined: Thu Aug 13, 2009 1:58 am
Location: Vienna, VA

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#55 Post by Uncle Joe » Sun Aug 23, 2009 6:12 pm

Well, I wasn't able to upload my original CD image because 250Mb exceeds my limit. After stripping it of everything except the kernel and initrd, it's down to 14Mb. The directions remain the same, except you won't see the rescue64 option and instead of executing "reboot" you need to hold down the power button.

jack_b_uta
Posts: 19
Joined: Wed Aug 19, 2009 1:05 pm
Location: Enter your correct location ASAP

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#56 Post by jack_b_uta » Mon Aug 24, 2009 4:14 pm

I am sorry I was not able to answer before. Was out of town over the weekend and just got back in.

I will give it a shot and post the results here. The steps as I understand them are

1) Flash BIOS using current OS (XP Pro.)
2) Reboot using systemrescuecd. Boot to the CD.
3) I have Windows XP installed on Disk(0) Partition(0) so the first GRUB option should work.
4) Boot to Windows.
5) Check available RAM to see if the MOD worked.

Question

When you say Suspend / resume will break, is it the same as the Standby / Resume option? Or is it the hibernate feature?


I will also post my System Specs here tonight.

Uncle Joe
Posts: 26
Joined: Thu Aug 13, 2009 1:58 am
Location: Vienna, VA

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#57 Post by Uncle Joe » Mon Aug 24, 2009 5:32 pm

Reboot using systemrescuecd. Boot to the CD.
- to clarify, use my sysrescue_grub2.iso, not the original, which is 250Mb. However, use the original to save dmesg and lspci when you get the chance.

Other than that, you're good to go. I never tested this on Windows XP, but I don't think this is a problem. The only problem I foresee is Windows not booting because the PCI peripherals aren't configured properly (e.g. overlap with RAM space) since I don't know which peripherals you have. I think Windows should reconfigure them. If this happens, don't worry, it's not permanent. Just reboot without the CD and report any error messages you saw.

When I say suspend/resume breaks, I mean suspend to RAM or sleep on Vista (wakes up in a few seconds). Hibernate (suspend to disk) still works. I guess hibernate is less dependent on ACPI / SMM code than sleep.

jack_b_uta
Posts: 19
Joined: Wed Aug 19, 2009 1:05 pm
Location: Enter your correct location ASAP

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#58 Post by jack_b_uta » Tue Aug 25, 2009 10:15 am

Does not look good. XP keeps blue screening when I try to flash NEW.WPH. I am using the Windows XP pro and WinPhlash. I tried using the WinPHlash from all the Lenovo 3000 N100 BIOS released, but each bluescreened.I also tried using WinPHlash from Y410, but that failed with a Checksum error. Any suggestions?

Another thing

I tried to boot off of your system rescue disk, but nothing shows up, the screen flashes and system restarts

Uncle Joe
Posts: 26
Joined: Thu Aug 13, 2009 1:58 am
Location: Vienna, VA

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#59 Post by Uncle Joe » Tue Aug 25, 2009 1:25 pm

Are you using 64bit XP? 2 years ago, someone claimed WinPhlash doesn't work on 64 bit Windows http://www.eyt.ca/blog/item/135/. Maybe you can try WinPhlash64. If that doesn't work, I can add a DOS boot option to the CD with phlash16.

I don't know what's causing the CD to reboot, but I've seen it before when I tried it on an older desktop. I think it's a grub2 issue because it also happens when I try to boot the CD from a virtual machine. I'll look into it.

jack_b_uta
Posts: 19
Joined: Wed Aug 19, 2009 1:05 pm
Location: Enter your correct location ASAP

Re: Why 3.0GB, not 3.25 or even 3.5? [Updated with Answer]

#60 Post by jack_b_uta » Tue Aug 25, 2009 1:47 pm

Nope its XP 32 Bit. I have an eval of 64 Bit Vista running on a different partiton but I doubt that is the problem. I will try to create a DOS bootable USB and use WinPhlash16.

Post Reply
  • Similar Topics
    Replies
    Views
    Last post

Return to “ThinkPad T6x Series”

Who is online

Users browsing this forum: No registered users and 3 guests