[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Debian + Mac OS X and time problems ...



On Thu, 2003-05-15 at 19:13, Tim Weippert wrote:
> HI there, 
> 
> i have both Debian (SID) and Mac OS X on a Powerbook G4. I have read
> that Mac OS X use UTC to save/set the hardware clock.
> 
> I thought i have to say my Debian installation, that the clock will be
> set to GMT and then calc the right time depend on the timezone, but it
> is strange, the time isn't correct, it's about 20 hours in the future.
> 
> I can't figure out what i have to do to have the right time wihtin Mac
> OS X and Debian (CEST Timezone Europe/Berlin)?

What happens is a bit "weird".

For historical reasons, MacOS stores an offset to GMT (timezone) in
the nvram. MacOS used to store the current timezone there, and used to
store the RTC as local time.

MacOS X does not use this offset (nor, I think, recent versions of
MacOS 9). _However_, for compatibility, what MacOS X do is, on boot,
to add that offset to the time read from the RTC, and when writing
back to the RTC, to substract it.

So the time in the RTC isn't really "local time", it's just relative
to whatever offset is stored in the nvram, which can be quite junk
in fact.

On the other hand, the Linux kernel will apply that offset when
reading from the RTC initially at boot. BUT, it will not apply it
to whatever is done via /dev/rtc and thus will not apply it when
reading/writing to nvram. So the offset isn't "transparent" unlike
what MacOS X does.

I originally wrote it like OS X does (and before OS X was around) but
got so badly flamed about it that I reverted to the current mecanism,
and I fell that changing it now would piss off more people.

The solution to really have an UTC RTC is to write a 0 in that offset
field in nvram. I don't think OS X will ever change it back to anything
else (though I suspect MacOS 9 will, so be careful).

I started writing a tool to write that, but I never finished it.
Enclosed is what I have to read the MachineLocation structure from
nvram, feel free to hack the tool to write it back.

Note that the format of the structure is a bit weird, I'd suggest you
read some MacOS litterature on the subject, though all you really want
is probably just to set it all to 0

Ben


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>

/* Some offsets in XPRAM */
#define PMAC_XPRAM_MACHINE_LOC	0xe4
#define PMAC_XPRAM_SOUND_VOLUME	0x08

/* Machine location structure in XPRAM */
struct pmac_machine_location {
	unsigned int	latitude;	/* 2+30 bit Fractional number */
	unsigned int	longitude;	/* 2+30 bit Fractional number */
	unsigned int	delta;		/* mix of GMT delta and DLS */
};

/* /dev/nvram ioctls */
#define PMAC_NVRAM_GET_OFFSET	_IOWR('p', 0x40, int) /* Get NVRAM partition offset */

enum {
	pmac_nvram_OF,		/* Open Firmware partition */
	pmac_nvram_XPRAM,	/* MacOS XPRAM partition */
	pmac_nvram_NR		/* MacOS Name Registry partition */
};

int
main(int argc, char *argv[])
{
	int				fd, rc, offset;
	int				goff, dst;
	struct pmac_machine_location	loc;
	
	fd = open("/dev/nvram", O_RDWR);
	if (fd < 0) {
		perror("Can't open /dev/nvram");
		return ENODEV;
	}

	offset = pmac_nvram_XPRAM;
	rc = ioctl(fd, PMAC_NVRAM_GET_OFFSET, &offset); 
	if (rc != 0) {
		perror("Can't get XPRAM offset");
		close(fd);
		return ENXIO;
	}
	printf("XPRAM offset in nvram: %d\n", offset);

	lseek(fd, offset + PMAC_XPRAM_MACHINE_LOC, SEEK_SET);
	rc = read(fd, &loc, sizeof(loc));
	if (rc != sizeof(loc)) {
		perror("Can't read machine location record");
		close(fd);
		return EIO;
	}

	printf("Machine location:\n");
	printf("latitude  : %08lx\n", loc.latitude);
	printf("longitude : %08lx\n", loc.longitude);
	dst = loc.delta >> 24;
	loc.delta &= 0x00ffffff;
	if (loc.delta & 0x00800000)
		loc.delta |= 0xff000000;
	goff = *((int *)&loc.delta);
	printf("offset    : %d\n", goff);
	printf("dst       : %d\n", dst);

	close(fd);
	return 0;
}

Reply to: