Please read through the whole mail. The first part is about printf issues, while the second part points out much more important problems with 64bit resources and stuff. Thanks.
On 10.08.2007 18:31, ron minnich wrote:
Thanks very much for this.
I have another patch pending which changes %Lx (L is unspecified for integers, happens to work) to %llx ("official" long long for integers).
Quoting from the printf(3) man page:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
The length modifier Here, `integer conversion' stands for d, i, o, u, x, or X conversion.
hh A following integer conversion corresponds to a signed char or unsigned char argument, or a following n conversion corresponds to a pointer to a signed char argument.
h A following integer conversion corresponds to a short int or unsigned short int argument, or a following n conversion corresponds to a pointer to a short int argument.
l (ell) A following integer conversion corresponds to a long int or unsigned long int argument.
ll (ell-ell). A following integer conversion corresponds to a long long int or unsigned long long int argument.
L A following a, A, e, E, f, F, g, or G conversion corresponds to a long double argument.
z A following integer conversion corresponds to a size_t or ssize_t argument.
t A following integer conversion corresponds to a ptrdiff_t argument. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Conclusions: * "L" is for floats only. * "t" or "z" might be handy for resource sizes. * "h" and "hh" for u16 and u8 seem to be unknown to most coders (except in util/dtc) and gcc doesn't warn about them. Should investigate usefulness for us.
I have a suggestion. Nowadays, for things that are pointers, even if they are not typed as such, I've taken to this style:
On 8/9/07, Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net wrote:
./superio/winbond/w83627hf/superio.c:init_hwm() +printk(BIOS_SPEW, "base = 0x%04lx, reg = 0x%02x, value = 0x%02x\r\n", base, reg,value);
vv vvvvvvv
printk(BIOS_SPEW, "base = %p, reg = 0x%02x, value = 0x%02x\r\n", (void *) base, reg,value);
printk(BIOS_DEBUG, "ROM address for %s = %lx\n", dev_path(dev), rom_address);
vv vvvvvvvv
printk(BIOS_DEBUG, "ROM address for %s = %p\n", dev_path(dev), (void *) rom_address);
Do I understand this correctly? (void *) conversion and usage of %p for things that are essentially pointers.
Why do this? It's actually more portable, even across plan 9 and linux. It will probably work correctly in 64 bit mode. And, that rom_address really *is* an address.
I like it, but... in the first example it seems this was an error, the base is not an address, but some u16 value. Stefan? Can you tell us what the reason is?
The second example is more correct, but we still face a problem: resource_t is u64 and as long as we don't use long mode, %p will expect 32bit values. However, almost everything being a resource_t (base, size, limit) is essentially a pointer of a pointerdiff. Now how do we handle that?
And while we're at correct typing, shouldn't arch/x86/linuxbios_table.c use resource_t in most places where it uses u64?
I have a lot of open questions: * How do we handle accesses to resources above 4 GB when we confine ourselves to 32bit code? * How do 32bit operating systems handle resources above 4 GB? Should we just avoid locating resources up there? Only do it if unavoidable? Consider a machine with 4 GB of RAM and a graphics card with 512 MB. That combination can be bought today. Now what will happen if video RAM grows to 4 GB? Can we boot such a machine in 32bit mode at all? Should we show a warning? Refuse to boot any non-64bit OS? * Should we have some preference setting which controls 64bit resource allocation? * Is there any point trying to handle 64bit resources on 32bit machines? * Do we have to compile 64bit code for 64bit machines?
Regards, Carl-Daniel