Index | Thread | Search

From:
"Theo de Raadt" <deraadt@openbsd.org>
Subject:
Re: Y2K40 fixes for macppc
To:
Miod Vallat <miod@online.fr>
Cc:
tech@openbsd.org
Date:
Fri, 09 Oct 2026 13:21:24 -0600

Download raw body.

Thread
Looks great to me.

Miod Vallat <miod@online.fr> wrote:

> Several macppc systems (the oldest ones with ADB, and the laptops) store
> the time as the unsigned number of seconds since 1904.
> 
> Instead of wrapping around in january 2038, they do so in february 2040.
> 
> I might not be around to see this, but the following diff tries to cope
> with this by acknowledging that this hardware was built in the late
> 1990s, if not later, and that timestamps in the 1904-1970 range should
> be handled as in the 2040-2106 range instead.
> 
> With this diff, a PowerMac1,1 (courtesy of otto@ 21 years ago) allows
> the system date to be set in 2041, and picks it correctly upon reboot.
> 
> Index: dev/adb.c
> ===================================================================
> RCS file: /OpenBSD/src/sys/arch/macppc/dev/adb.c,v
> diff -u -p -r1.52 adb.c
> --- dev/adb.c	14 Apr 2024 03:26:25 -0000	1.52
> +++ dev/adb.c	9 Oct 2026 19:00:27 -0000
> @@ -1417,6 +1417,9 @@ set_adb_info(ADBSetInfoBlock * info, int
>  
>  }
>  
> +/* Number of seconds between 19040101 and 19700101 */
> +#define DIFF19041970 2082844800
> +
>  /* caller should really use machine-independent version: getPramTime */
>  /* this version does pseudo-adb access only */
>  int
> @@ -1430,7 +1433,7 @@ adb_read_date_time(time_t *time)
>  
>  	switch (adbHardware) {
>  	case ADB_HW_PMU:
> -		pm_read_date_time(time);
> +		pm_read_date_time(&t);
>  		retcode = 0;
>  		break;
>  
> @@ -1450,7 +1453,6 @@ adb_read_date_time(time_t *time)
>  
>  		delay(20); /* completion occurs too soon? */
>  		memcpy(&t, output + 1, sizeof(t));
> -		*time = (time_t)t;
>  		retcode = 0;
>  		break;
>  
> @@ -1460,9 +1462,16 @@ adb_read_date_time(time_t *time)
>  		break;
>  	}
>  	if (retcode == 0) {
> -#define DIFF19041970 2082844800
> +		/*
> +		 * The value we've obtained is a 32-bit value of the number
> +		 * of seconds since 1904. It will wrap on 20400206.
> +		 * Since this hardware did not exist until the late 1990s,
> +		 * assume negative values are beyond 2040.
> +		 */
> +		*time = (time_t)t;
> +		if (t < DIFF19041970)
> +			*time += 1ULL << 32;
>  		*time -= DIFF19041970;
> -
>  	} else {
>  		*time = 0;
>  	}
> @@ -1483,7 +1492,7 @@ adb_set_date_time(time_t time)
>  	switch (adbHardware) {
>  
>  	case ADB_HW_CUDA:
> -		t = time;		/* XXX eventually truncates */
> +		t = time;		/* truncates */
>  
>  		output[0] = 0x06;	/* 6 byte message */
>  		output[1] = 0x01;	/* to pram/rtc device */
> Index: dev/pm_direct.c
> ===================================================================
> RCS file: /OpenBSD/src/sys/arch/macppc/dev/pm_direct.c,v
> diff -u -p -r1.35 pm_direct.c
> --- dev/pm_direct.c	22 Nov 2023 18:14:35 -0000	1.35
> +++ dev/pm_direct.c	9 Oct 2026 19:00:27 -0000
> @@ -738,10 +738,9 @@ pm_adb_poweroff(void)
>  }
>  
>  void
> -pm_read_date_time(time_t *time)
> +pm_read_date_time(uint32_t *time)
>  {
>  	PMData p;
> -	u_int32_t t;
>  
>  	p.command = PMU_READ_RTC;
>  	p.num_data = 0;
> @@ -749,20 +748,18 @@ pm_read_date_time(time_t *time)
>  	p.r_buf = p.data;
>  	pmgrop(&p);
>  
> -	bcopy(p.data, &t, sizeof(t));
> -	*time = (time_t)t;
> +	bcopy(p.data, time, sizeof(*time));
>  }
>  
>  void
> -pm_set_date_time(time_t time)
> +pm_set_date_time(uint32_t time)
>  {
>  	PMData p;
> -	u_int32_t t = time;		/* XXX eventually truncates */
>  
>  	p.command = PMU_SET_RTC;
> -	p.num_data = sizeof(t);
> +	p.num_data = sizeof(time);
>  	p.s_buf = p.r_buf = p.data;
> -	bcopy(&t, p.data, sizeof(t));
> +	bcopy(&time, p.data, sizeof(time));
>  	pmgrop(&p);
>  }
>  
> Index: dev/pm_direct.h
> ===================================================================
> RCS file: /OpenBSD/src/sys/arch/macppc/dev/pm_direct.h,v
> diff -u -p -r1.17 pm_direct.h
> --- dev/pm_direct.h	22 Oct 2024 21:50:02 -0000	1.17
> +++ dev/pm_direct.h	9 Oct 2026 19:00:27 -0000
> @@ -54,8 +54,8 @@ int	pm_adb_op(u_char *, void *, void *, 
>  void	pm_adb_restart(void);
>  void	pm_adb_poweroff(void);
>  void	pm_intr(void);
> -void	pm_read_date_time(time_t *);
> -void	pm_set_date_time(time_t);
> +void	pm_read_date_time(uint32_t *);
> +void	pm_set_date_time(uint32_t);
>  
>  struct pmu_battery_info {
>  	unsigned int flags;
>