1*4882a593Smuzhiyun========================== 2*4882a593SmuzhiyunEFI Real Time Clock driver 3*4882a593Smuzhiyun========================== 4*4882a593Smuzhiyun 5*4882a593SmuzhiyunS. Eranian <eranian@hpl.hp.com> 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunMarch 2000 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun1. Introduction 10*4882a593Smuzhiyun=============== 11*4882a593Smuzhiyun 12*4882a593SmuzhiyunThis document describes the efirtc.c driver has provided for 13*4882a593Smuzhiyunthe IA-64 platform. 14*4882a593Smuzhiyun 15*4882a593SmuzhiyunThe purpose of this driver is to supply an API for kernel and user applications 16*4882a593Smuzhiyunto get access to the Time Service offered by EFI version 0.92. 17*4882a593Smuzhiyun 18*4882a593SmuzhiyunEFI provides 4 calls one can make once the OS is booted: GetTime(), 19*4882a593SmuzhiyunSetTime(), GetWakeupTime(), SetWakeupTime() which are all supported by this 20*4882a593Smuzhiyundriver. We describe those calls as well the design of the driver in the 21*4882a593Smuzhiyunfollowing sections. 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun2. Design Decisions 24*4882a593Smuzhiyun=================== 25*4882a593Smuzhiyun 26*4882a593SmuzhiyunThe original ideas was to provide a very simple driver to get access to, 27*4882a593Smuzhiyunat first, the time of day service. This is required in order to access, in a 28*4882a593Smuzhiyunportable way, the CMOS clock. A program like /sbin/hwclock uses such a clock 29*4882a593Smuzhiyunto initialize the system view of the time during boot. 30*4882a593Smuzhiyun 31*4882a593SmuzhiyunBecause we wanted to minimize the impact on existing user-level apps using 32*4882a593Smuzhiyunthe CMOS clock, we decided to expose an API that was very similar to the one 33*4882a593Smuzhiyunused today with the legacy RTC driver (driver/char/rtc.c). However, because 34*4882a593SmuzhiyunEFI provides a simpler services, not all ioctl() are available. Also 35*4882a593Smuzhiyunnew ioctl()s have been introduced for things that EFI provides but not the 36*4882a593Smuzhiyunlegacy. 37*4882a593Smuzhiyun 38*4882a593SmuzhiyunEFI uses a slightly different way of representing the time, noticeably 39*4882a593Smuzhiyunthe reference date is different. Year is the using the full 4-digit format. 40*4882a593SmuzhiyunThe Epoch is January 1st 1998. For backward compatibility reasons we don't 41*4882a593Smuzhiyunexpose this new way of representing time. Instead we use something very 42*4882a593Smuzhiyunsimilar to the struct tm, i.e. struct rtc_time, as used by hwclock. 43*4882a593SmuzhiyunOne of the reasons for doing it this way is to allow for EFI to still evolve 44*4882a593Smuzhiyunwithout necessarily impacting any of the user applications. The decoupling 45*4882a593Smuzhiyunenables flexibility and permits writing wrapper code is ncase things change. 46*4882a593Smuzhiyun 47*4882a593SmuzhiyunThe driver exposes two interfaces, one via the device file and a set of 48*4882a593Smuzhiyunioctl()s. The other is read-only via the /proc filesystem. 49*4882a593Smuzhiyun 50*4882a593SmuzhiyunAs of today we don't offer a /proc/sys interface. 51*4882a593Smuzhiyun 52*4882a593SmuzhiyunTo allow for a uniform interface between the legacy RTC and EFI time service, 53*4882a593Smuzhiyunwe have created the include/linux/rtc.h header file to contain only the 54*4882a593Smuzhiyun"public" API of the two drivers. The specifics of the legacy RTC are still 55*4882a593Smuzhiyunin include/linux/mc146818rtc.h. 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun3. Time of day service 59*4882a593Smuzhiyun====================== 60*4882a593Smuzhiyun 61*4882a593SmuzhiyunThe part of the driver gives access to the time of day service of EFI. 62*4882a593SmuzhiyunTwo ioctl()s, compatible with the legacy RTC calls: 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun Read the CMOS clock:: 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun ioctl(d, RTC_RD_TIME, &rtc); 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun Write the CMOS clock:: 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun ioctl(d, RTC_SET_TIME, &rtc); 71*4882a593Smuzhiyun 72*4882a593SmuzhiyunThe rtc is a pointer to a data structure defined in rtc.h which is close 73*4882a593Smuzhiyunto a struct tm:: 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun struct rtc_time { 76*4882a593Smuzhiyun int tm_sec; 77*4882a593Smuzhiyun int tm_min; 78*4882a593Smuzhiyun int tm_hour; 79*4882a593Smuzhiyun int tm_mday; 80*4882a593Smuzhiyun int tm_mon; 81*4882a593Smuzhiyun int tm_year; 82*4882a593Smuzhiyun int tm_wday; 83*4882a593Smuzhiyun int tm_yday; 84*4882a593Smuzhiyun int tm_isdst; 85*4882a593Smuzhiyun }; 86*4882a593Smuzhiyun 87*4882a593SmuzhiyunThe driver takes care of converting back an forth between the EFI time and 88*4882a593Smuzhiyunthis format. 89*4882a593Smuzhiyun 90*4882a593SmuzhiyunThose two ioctl()s can be exercised with the hwclock command: 91*4882a593Smuzhiyun 92*4882a593SmuzhiyunFor reading:: 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun # /sbin/hwclock --show 95*4882a593Smuzhiyun Mon Mar 6 15:32:32 2000 -0.910248 seconds 96*4882a593Smuzhiyun 97*4882a593SmuzhiyunFor setting:: 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun # /sbin/hwclock --systohc 100*4882a593Smuzhiyun 101*4882a593SmuzhiyunRoot privileges are required to be able to set the time of day. 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun4. Wakeup Alarm service 104*4882a593Smuzhiyun======================= 105*4882a593Smuzhiyun 106*4882a593SmuzhiyunEFI provides an API by which one can program when a machine should wakeup, 107*4882a593Smuzhiyuni.e. reboot. This is very different from the alarm provided by the legacy 108*4882a593SmuzhiyunRTC which is some kind of interval timer alarm. For this reason we don't use 109*4882a593Smuzhiyunthe same ioctl()s to get access to the service. Instead we have 110*4882a593Smuzhiyunintroduced 2 news ioctl()s to the interface of an RTC. 111*4882a593Smuzhiyun 112*4882a593SmuzhiyunWe have added 2 new ioctl()s that are specific to the EFI driver: 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun Read the current state of the alarm:: 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun ioctl(d, RTC_WKALM_RD, &wkt) 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun Set the alarm or change its status:: 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun ioctl(d, RTC_WKALM_SET, &wkt) 121*4882a593Smuzhiyun 122*4882a593SmuzhiyunThe wkt structure encapsulates a struct rtc_time + 2 extra fields to get 123*4882a593Smuzhiyunstatus information:: 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun struct rtc_wkalrm { 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun unsigned char enabled; /* =1 if alarm is enabled */ 128*4882a593Smuzhiyun unsigned char pending; /* =1 if alarm is pending */ 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun struct rtc_time time; 131*4882a593Smuzhiyun } 132*4882a593Smuzhiyun 133*4882a593SmuzhiyunAs of today, none of the existing user-level apps supports this feature. 134*4882a593SmuzhiyunHowever writing such a program should be hard by simply using those two 135*4882a593Smuzhiyunioctl(). 136*4882a593Smuzhiyun 137*4882a593SmuzhiyunRoot privileges are required to be able to set the alarm. 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun5. References 140*4882a593Smuzhiyun============= 141*4882a593Smuzhiyun 142*4882a593SmuzhiyunCheckout the following Web site for more information on EFI: 143*4882a593Smuzhiyun 144*4882a593Smuzhiyunhttp://developer.intel.com/technology/efi/ 145