Discussion:
[PATCH 2/3] rtc-efi: add timezone to rtc_time that will used by rtc-efi
Lee, Chun-Yi
2012-12-28 16:26:40 UTC
Permalink
Per UEFI 2.3.1 spec, we can use SetTime() to store the timezone value to BIOS and
get it back by GetTime(). It's good for installation system to gain the default
timezone setting from BIOS that was set by manufacturer.

This patch adds new field tm_timezone to rtc_time struct for expose the timezone
to userspace. And, patch also adds the check logic to rtc-efi when convert timezone.
The check logic of timezone only affect on x86 architecture and keep the original
EFI_UNSPECIFIED_TIMEZONE value on IA64.

Cc: Matt Fleming <matt.fleming-***@public.gmane.org>
Cc: H. Peter Anvin <hpa-***@public.gmane.org>
Cc: Matthew Garrett <matthew.garrett-05XSO3Yj/JvQT0dZR+***@public.gmane.org>
Cc: Thomas Gleixner <tglx-***@public.gmane.org>
Cc: Ingo Molnar <mingo-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
Cc: Jan Beulich <JBeulich-IBi9RG/***@public.gmane.org>
Signed-off-by: Lee, Chun-Yi <jlee-IBi9RG/***@public.gmane.org>
---
drivers/rtc/rtc-efi.c | 20 +++++++++++++++++---
include/uapi/linux/rtc.h | 1 +
2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c
index c9f890b..4e74ec0 100644
--- a/drivers/rtc/rtc-efi.c
+++ b/drivers/rtc/rtc-efi.c
@@ -62,7 +62,7 @@ compute_wday(efi_time_t *eft)
return (ndays + 4) % 7;
}

-static void
+static int
convert_to_efi_time(struct rtc_time *wtime, efi_time_t *eft)
{
eft->year = wtime->tm_year + 1900;
@@ -73,7 +73,16 @@ convert_to_efi_time(struct rtc_time *wtime, efi_time_t *eft)
eft->second = wtime->tm_sec;
eft->nanosecond = 0;
eft->daylight = wtime->tm_isdst ? EFI_ISDST : 0;
+#ifdef CONFIG_X86
+ if (abs(wtime->tm_timezone) > 1440 &&
+ wtime->tm_timezone != EFI_UNSPECIFIED_TIMEZONE)
+ return -EINVAL;
+ eft->timezone = wtime->tm_timezone;
+#else
eft->timezone = EFI_UNSPECIFIED_TIMEZONE;
+#endif /* CONFIG_X86 */
+
+ return 0;
}

static void
@@ -86,6 +95,9 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime)
wtime->tm_mday = eft->day;
wtime->tm_mon = eft->month - 1;
wtime->tm_year = eft->year - 1900;
+#ifdef CONFIG_X86
+ wtime->tm_timezone = eft->timezone;
+#endif /* CONFIG_X86 */

/* day of the week [0-6], Sunday=0 */
wtime->tm_wday = compute_wday(eft);
@@ -130,7 +142,8 @@ static int efi_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
efi_time_t eft;
efi_status_t status;

- convert_to_efi_time(&wkalrm->time, &eft);
+ if (convert_to_efi_time(&wkalrm->time, &eft))
+ return -EINVAL;

/*
* XXX Fixme:
@@ -171,7 +184,8 @@ static int efi_set_time(struct device *dev, struct rtc_time *tm)
efi_status_t status;
efi_time_t eft;

- convert_to_efi_time(tm, &eft);
+ if (convert_to_efi_time(tm, &eft))
+ return -EINVAL;

status = efi.set_time(&eft);

diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h
index f8c82e6..841725f 100644
--- a/include/uapi/linux/rtc.h
+++ b/include/uapi/linux/rtc.h
@@ -27,6 +27,7 @@ struct rtc_time {
int tm_wday;
int tm_yday;
int tm_isdst;
+ int tm_timezone;
};

/*
--
1.6.4.2
Lee, Chun-Yi
2012-12-28 16:26:41 UTC
Permalink
This patch set uie_unsupported flag when driver probed because current rtc-efi
driver doesn't support UIE mode. Otherwise RTC_UIE_ON ioctl doesn't return EINVAL
and it causes userspace think the RTC_UIE supported by rtc-efi.

Set uie_unsupported then We can enable CONFIG_RTC_INTF_DEV_UIE_EMUL to emulate
RTC_UIE on rtc-efi.

Cc: Matt Fleming <matt.fleming-***@public.gmane.org>
Cc: H. Peter Anvin <hpa-***@public.gmane.org>
Cc: Matthew Garrett <matthew.garrett-05XSO3Yj/JvQT0dZR+***@public.gmane.org>
Cc: Thomas Gleixner <tglx-***@public.gmane.org>
Cc: Ingo Molnar <mingo-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
Cc: Jan Beulich <JBeulich-IBi9RG/***@public.gmane.org>
Signed-off-by: Lee, Chun-Yi <jlee-IBi9RG/***@public.gmane.org>
---
drivers/rtc/rtc-efi.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c
index 4e74ec0..dad1687 100644
--- a/drivers/rtc/rtc-efi.c
+++ b/drivers/rtc/rtc-efi.c
@@ -208,6 +208,8 @@ static int __init efi_rtc_probe(struct platform_device *dev)
if (IS_ERR(rtc))
return PTR_ERR(rtc);

+ rtc->uie_unsupported = 1;
+
platform_set_drvdata(dev, rtc);

return 0;
--
1.6.4.2
Matthew Garrett
2012-12-28 17:43:50 UTC
Permalink
UEFI time services, GetTime(), SetTime(), GetWakeupTime(), SetWakeupTime() are also
supported by other non-IA64 architecutre with UEFI BIOS, e.g. x86.
This patch changed RTC_DRV_EFI configuration to depend on EFI but not just IA64. It
checks efi_enabled flag and efi-rtc driver should enabled.
In theory, certainly - but do we still have machines that explode if the
get_time call is made? We may also want to think about disabling the
l
H. Peter Anvin
2012-12-28 19:07:11 UTC
Permalink
We do have such machines, which is why this change has been reverted twice already. I believe we should stick to the priority scheme I proposed a few weeks ago.
UEFI time services, GetTime(), SetTime(), GetWakeupTime(),
SetWakeupTime() are also
supported by other non-IA64 architecutre with UEFI BIOS, e.g. x86.
This patch changed RTC_DRV_EFI configuration to depend on EFI but not
just IA64. It
checks efi_enabled flag and efi-rtc driver should enabled.
In theory, certainly - but do we still have machines that explode if the
get_time call is made? We may also want to think about disabling the
legacy access to the RTC if the EFI calls are present.
--
Sent from my mobile phone. Please excuse brevity and lack of formatting.
Matthew Garrett
2012-12-28 19:17:43 UTC
Permalink
Post by H. Peter Anvin
We do have such machines, which is why this change has been reverted twice already. I believe we should stick to the priority scheme I proposed a few weeks ago.
I seem to have missed that discussion, and couldn't find it
H. Peter Anvin
2012-12-28 20:40:56 UTC
Permalink
Post by H. Peter Anvin
We do have such machines, which is why this change has been reverted twice already. I believe we should stick to the priority scheme I proposed a few weeks ago.
I seem to have missed that discussion, and couldn't find it after a
brief search. Got a pointer?
1. If ACPI exports a Time and Alarm Device (ACPI000E) the use it;
2. If ACPI exports an PC/AT device (PNP0B00/1/2) then use it(*);
3. If we have an EFI RTC use it;
4. Probe for a PC/AT RTC device.
I'm unsure what the ordering of 1 & 2 should be. The ACPI device has
the advantage that it contains time zone information, which is important
for Windows interoperability, and at least optionally supports
millisecond resolution; there is no way to even export "this is where
you find time zone information" (since we're dealing with an RTC with
embedded CMOS, there is storage available, it is just a matter of
telling the OS how to find it) for the PNP0B0x devices.
The TAD is also guaranteed to map 1:1 to the EFI RTC.
-hpa
--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.
Matthew Garrett
2012-12-28 20:49:42 UTC
Permalink
1. If ACPI exports a Time and Alarm Device (ACPI000E) the use it;
2. If ACPI exports an PC/AT device (PNP0B00/1/2) then use it(*);
3. If we have an EFI RTC use it;
4. Probe for a PC/AT RTC device.
In terms of ordering, 3 should probably come before 2 - but that depends
on us actually fixing the issues that are preventing some of these calls
from working. As far as wallclock time goes, EFI is going to be
available to us before we've parsed the DSDT to determine whether
there's any ACPI devices, so we'll almost certainly end up having to use
it at at least some point during boot. Otherwise, a
Matthew Garrett
2012-12-28 23:39:41 UTC
Permalink
No, that is explicitly the ordering that is excludable.
Windows uses the UEFI time functions. The fact that they fail for us on
a bunch of systems is just another symptom of our general failure to
accurately mimic Windows when making runtime calls, and we should just
make sure that that gets fixed rather than layering more workarounds on
top. It's an embarrassment that we're still unable to deal with
platforms that work fine with another OS.
H. Peter Anvin
2012-12-29 00:42:55 UTC
Permalink
Post by Matthew Garrett
No, that is explicitly the ordering that is excludable.
Windows uses the UEFI time functions. The fact that they fail for us on
a bunch of systems is just another symptom of our general failure to
accurately mimic Windows when making runtime calls, and we should just
make sure that that gets fixed rather than layering more workarounds on
top. It's an embarrassment that we're still unable to deal with
platforms that work fine with another OS.
Are they using them in preference to ACPI? This seems a bit odd, since
one can presume that the ACPI functions were added at Microsoft's request...

-hpa
Matthew Garrett
2012-12-29 04:37:29 UTC
Permalink
Post by H. Peter Anvin
Post by Matthew Garrett
No, that is explicitly the ordering that is excludable.
Windows uses the UEFI time functions. The fact that they fail for us on
a bunch of systems is just another symptom of our general failure to
accurately mimic Windows when making runtime calls, and we should just
make sure that that gets fixed rather than layering more workarounds on
top. It's an embarrassment that we're still unable to deal with
platforms that work fine with another OS.
Are they using them in preference to ACPI? This seems a bit odd, since
one can presume that the ACPI functions were added at Microsoft's request...
In preference to the ACPI RTC, I haven't yet had an ACPI 5.0 TAD device
to test in co
H. Peter Anvin
2012-12-29 05:19:21 UTC
Permalink
Again, we could hack a simulator and try it.
Post by Matthew Garrett
Post by H. Peter Anvin
Post by Matthew Garrett
No, that is explicitly the ordering that is excludable.
Windows uses the UEFI time functions. The fact that they fail for
us on
Post by H. Peter Anvin
Post by Matthew Garrett
a bunch of systems is just another symptom of our general failure
to
Post by H. Peter Anvin
Post by Matthew Garrett
accurately mimic Windows when making runtime calls, and we should
just
Post by H. Peter Anvin
Post by Matthew Garrett
make sure that that gets fixed rather than layering more
workarounds on
Post by H. Peter Anvin
Post by Matthew Garrett
top. It's an embarrassment that we're still unable to deal with
platforms that work fine with another OS.
Are they using them in preference to ACPI? This seems a bit odd,
since
Post by H. Peter Anvin
one can presume that the ACPI functions were added at Microsoft's
request...
In preference to the ACPI RTC, I haven't yet had an ACPI 5.0 TAD device
to test in comparison.
--
Sent from my mobile phone. Please excuse brevity and lack of formatting.
Matthew Garrett
2012-12-29 06:17:50 UTC
Permalink
Post by H. Peter Anvin
Again, we could hack a simulator and try it.
Yeah,
H. Peter Anvin
2012-12-28 23:44:45 UTC
Permalink
Post by Matthew Garrett
1. If ACPI exports a Time and Alarm Device (ACPI000E) the use it;
2. If ACPI exports an PC/AT device (PNP0B00/1/2) then use it(*);
3. If we have an EFI RTC use it;
4. Probe for a PC/AT RTC device.
In terms of ordering, 3 should probably come before 2 - but that depends
on us actually fixing the issues that are preventing some of these calls
from working. As far as wallclock time goes, EFI is going to be
available to us before we've parsed the DSDT to determine whether
there's any ACPI devices, so we'll almost certainly end up having to use
it at at least some point during boot. Otherwise, agreed.
[Resending due to misconfigured tablet]

3 before 2 is exactly what is known to break on existing hardware (ASUS).

If anything, we should move to using the EFI RTC as a very last resort,
i.e. 3 after 4. Ideally we should match Win8 behavior, but that would
require someone mocking up different ACPI and EFI functions in a
simulator and see how Win8 prioritizes things.

-hpa
joeyli
2013-01-02 02:45:51 UTC
Permalink
Hi hpa, =20

=E6=96=BC =E4=BA=94=EF=BC=8C2012-12-28 =E6=96=BC 15:44 -0800=EF=BC=8CH.=
Peter Anvin =E6=8F=90=E5=88=B0=EF=BC=9A
Post by H. Peter Anvin
=20
1. If ACPI exports a Time and Alarm Device (ACPI000E) the use it;
2. If ACPI exports an PC/AT device (PNP0B00/1/2) then use it(*);
3. If we have an EFI RTC use it;
4. Probe for a PC/AT RTC device.
=20
In terms of ordering, 3 should probably come before 2 - but that de=
pends
Post by H. Peter Anvin
on us actually fixing the issues that are preventing some of these =
calls
Post by H. Peter Anvin
from working. As far as wallclock time goes, EFI is going to be
available to us before we've parsed the DSDT to determine whether
there's any ACPI devices, so we'll almost certainly end up having t=
o use
Post by H. Peter Anvin
it at at least some point during boot. Otherwise, agreed.
=20
=20
[Resending due to misconfigured tablet]
=20
3 before 2 is exactly what is known to break on existing hardware (AS=
US).

I didn't find the EFI RTC problem on Asus from google.=20
Could you please share what's the situation on ASUS hardware?


Thanks a lot!
Joey Lee
Post by H. Peter Anvin
=20
If anything, we should move to using the EFI RTC as a very last resor=
t,
Post by H. Peter Anvin
i.e. 3 after 4. Ideally we should match Win8 behavior, but that woul=
d
Post by H. Peter Anvin
require someone mocking up different ACPI and EFI functions in a
simulator and see how Win8 prioritizes things.
=20
-hpa
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" =
in
Post by H. Peter Anvin
More majordomo info at http://vger.kernel.org/majordomo-info.html
=20
Matt Fleming
2013-01-02 07:26:32 UTC
Permalink
Post by joeyli
I didn't find the EFI RTC problem on Asus from google.
Could you please share what's the situation on ASUS hardware?
It's mentioned in the following commit (which has since been reverted in
Linus' tree),

commit 185034e72d591f9465e5e18f937ed642e7ea0070
Author: Matt Fleming <matt.fleming-***@public.gmane.org>
Date: Fri Sep 7 18:28:04 2012 +0100

x86, efi: 1:1 pagetable mapping for virtual EFI calls

Some firmware still needs a 1:1 (virt->phys) mapping even after we've
called SetVirtualAddressMap(). So install the mapping alongside our
existing kernel mapping whenever we make EFI calls in virtual mode.

This bug was discovered on ASUS machines where the firmware
implementation of GetTime() accesses the RTC device via physical
addresses, even though that's bogus per the UEFI spec since we've
informed the firmware via SetVirtualAddressMap() that the boottime
memory map is no longer valid.

This bug seems to be present in a lot of consumer devices, so there's
not a lot we can do about this spec violation apart from workaround
it.


The bug was originally mentioned here,

https://lkml.org/lkml/2012/3/12/214
joeyli
2012-12-29 01:00:03 UTC
Permalink
=E6=96=BC =E4=BA=94=EF=BC=8C2012-12-28 =E6=96=BC 17:43 +0000=EF=BC=8CMa=
tthew Garrett =E6=8F=90=E5=88=B0=EF=BC=9A
UEFI time services, GetTime(), SetTime(), GetWakeupTime(), SetWakeu=
pTime() are also
supported by other non-IA64 architecutre with UEFI BIOS, e.g. x86.
=20
This patch changed RTC_DRV_EFI configuration to depend on EFI but n=
ot just IA64. It
checks efi_enabled flag and efi-rtc driver should enabled.
=20
In theory, certainly - but do we still have machines that explode if =
the
get_time call is made? We may also want to think about disabling the
legacy access to the RTC if the EFI calls are present.
The legacy get_time access on my test machine is work fine, not thing
explode. :-)
Just we have a function want to expose the timezone information to
userspace and also store it.


Thanks a lot!
Joey Lee
H. Peter Anvin
2012-12-29 01:07:37 UTC
Permalink
=E6=96=BC =E4=BA=94=EF=BC=8C2012-12-28 =E6=96=BC 17:43 +0000=EF=BC=8C=
Matthew Garrett =E6=8F=90=E5=88=B0=EF=BC=9A
UEFI time services, GetTime(), SetTime(), GetWakeupTime(), SetWakeu=
pTime() are also
supported by other non-IA64 architecutre with UEFI BIOS, e.g. x86.
This patch changed RTC_DRV_EFI configuration to depend on EFI but n=
ot just IA64. It
checks efi_enabled flag and efi-rtc driver should enabled.
In theory, certainly - but do we still have machines that explode if=
the
get_time call is made? We may also want to think about disabling the
legacy access to the RTC if the EFI calls are present.
=20
The legacy get_time access on my test machine is work fine, not thing
explode. :-)
Just we have a function want to expose the timezone information to
userspace and also store it.
=20
We should indeed save the timezone information if it is available --
either from the ACPI TAD or from the EFI RTC, or even via some
platform-dependent mechanism. It is important, though, that that is
separate from the order of priority.

-hpa
joeyli
2013-01-09 06:23:11 UTC
Permalink
=E6=96=BC =E4=BA=94=EF=BC=8C2012-12-28 =E6=96=BC 17:07 -0800=EF=BC=8CH.=
Peter Anvin =E6=8F=90=E5=88=B0=EF=BC=9A
Post by H. Peter Anvin
=E6=96=BC =E4=BA=94=EF=BC=8C2012-12-28 =E6=96=BC 17:43 +0000=EF=BC=8C=
Matthew Garrett =E6=8F=90=E5=88=B0=EF=BC=9A
Post by H. Peter Anvin
UEFI time services, GetTime(), SetTime(), GetWakeupTime(), SetWak=
eupTime() are also
Post by H. Peter Anvin
supported by other non-IA64 architecutre with UEFI BIOS, e.g. x86=
=2E
Post by H. Peter Anvin
This patch changed RTC_DRV_EFI configuration to depend on EFI but=
not just IA64. It
Post by H. Peter Anvin
checks efi_enabled flag and efi-rtc driver should enabled.
In theory, certainly - but do we still have machines that explode =
if the
Post by H. Peter Anvin
get_time call is made? We may also want to think about disabling t=
he
Post by H. Peter Anvin
legacy access to the RTC if the EFI calls are present.
=20
The legacy get_time access on my test machine is work fine, not thi=
ng
Post by H. Peter Anvin
explode. :-)
Just we have a function want to expose the timezone information to
userspace and also store it.
=20
=20
We should indeed save the timezone information if it is available --
either from the ACPI TAD or from the EFI RTC, or even via some
platform-dependent mechanism. It is important, though, that that is
separate from the order of priority.
=20
-hpa
=20
I found Windows 8 doesn't aware/maintain the Timezone and Daylight
fields in EFI_TIME struct.

I got a Acer UEFI notebook and I keep the Windows 8 hard drive
(/dev/sda) but install Linux to another hard drive (/dev/sdb).=20

On Linux, I applied my rtc-efi patches for allow user space feed
Timezone and store it to BIOS through SetTime(). I wrote a simple user
space program to set Timezone and Daylight fields, after set those
fields I reboot to Windows 8 and use DateTime setting GUI to look at th=
e
change. Looks Windows doesn't aware the change, it just assume the time
in DateTime filed is local time, but didn't show the Timezone that was
set by me on Linux to GUI.

Then, I select another Timezone(country) through Windows 8 GUI, and
reboot to Linux. I read the Timezone and Daylight by program but didn't
see the Timezone and Daylight changed by Windows 8, the value is still
the same with my latest time setting by Linux program. Windows 8 change=
d
DayTime fields but didn't maintain Timezone and Daylight.

I only have this machine with preloaded Windows 8 for verify the
behavior, not sure it's normally or not. If Windows 8 ignores Timezone
and Daylight fields in UEFI BIOS, then I think it's lower down the
necessary for we maintain Timezone and Daylight in UEFI BIOS.=20

We still can store Timezone and Daylight value to UEFI, but will have n=
o
any interactive with Windows 8.

Appreciate for any suggestions.


Thanks a lot!
Joey Lee
H. Peter Anvin
2013-01-09 06:27:36 UTC
Permalink
That makes it even less compelling...
=E6=96=BC =E4=BA=94=EF=BC=8C2012-12-28 =E6=96=BC 17:07 -0800=EF=BC=8CH=
=2E Peter Anvin =E6=8F=90=E5=88=B0=EF=BC=9A
Post by H. Peter Anvin
Post by joeyli
=E6=96=BC =E4=BA=94=EF=BC=8C2012-12-28 =E6=96=BC 17:43 +0000=EF=BC=
=8CMatthew Garrett =E6=8F=90=E5=88=B0=EF=BC=9A
Post by H. Peter Anvin
Post by joeyli
Post by Matthew Garrett
UEFI time services, GetTime(), SetTime(), GetWakeupTime(),
SetWakeupTime() are also
Post by H. Peter Anvin
Post by joeyli
Post by Matthew Garrett
supported by other non-IA64 architecutre with UEFI BIOS, e.g.
x86.
Post by H. Peter Anvin
Post by joeyli
Post by Matthew Garrett
This patch changed RTC_DRV_EFI configuration to depend on EFI bu=
t
not just IA64. It
Post by H. Peter Anvin
Post by joeyli
Post by Matthew Garrett
checks efi_enabled flag and efi-rtc driver should enabled.
In theory, certainly - but do we still have machines that explode
if the
Post by H. Peter Anvin
Post by joeyli
Post by Matthew Garrett
get_time call is made? We may also want to think about disabling
the
Post by H. Peter Anvin
Post by joeyli
Post by Matthew Garrett
legacy access to the RTC if the EFI calls are present.
=20
The legacy get_time access on my test machine is work fine, not
thing
Post by H. Peter Anvin
Post by joeyli
explode. :-)
Just we have a function want to expose the timezone information to
userspace and also store it.
=20
=20
We should indeed save the timezone information if it is available --
either from the ACPI TAD or from the EFI RTC, or even via some
platform-dependent mechanism. It is important, though, that that is
separate from the order of priority.
=20
-hpa
=20
I found Windows 8 doesn't aware/maintain the Timezone and Daylight
fields in EFI_TIME struct.
I got a Acer UEFI notebook and I keep the Windows 8 hard drive
(/dev/sda) but install Linux to another hard drive (/dev/sdb).=20
On Linux, I applied my rtc-efi patches for allow user space feed
Timezone and store it to BIOS through SetTime(). I wrote a simple user
space program to set Timezone and Daylight fields, after set those
fields I reboot to Windows 8 and use DateTime setting GUI to look at
the
change. Looks Windows doesn't aware the change, it just assume the tim=
e
in DateTime filed is local time, but didn't show the Timezone that was
set by me on Linux to GUI.
Then, I select another Timezone(country) through Windows 8 GUI, and
reboot to Linux. I read the Timezone and Daylight by program but didn'=
t
see the Timezone and Daylight changed by Windows 8, the value is still
the same with my latest time setting by Linux program. Windows 8
changed
DayTime fields but didn't maintain Timezone and Daylight.
I only have this machine with preloaded Windows 8 for verify the
behavior, not sure it's normally or not. If Windows 8 ignores Timezone
and Daylight fields in UEFI BIOS, then I think it's lower down the
necessary for we maintain Timezone and Daylight in UEFI BIOS.=20
We still can store Timezone and Daylight value to UEFI, but will have
no
any interactive with Windows 8.
Appreciate for any suggestions.
Thanks a lot!
Joey Lee
--=20
Sent from my mobile phone. Please excuse brevity and lack of formatting=
=2E

Loading...