iPXE
bios_timer.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 /** @file
27  *
28  * BIOS timer
29  *
30  */
31 
32 #include <ipxe/timer.h>
33 #include <realmode.h>
34 #include <bios.h>
35 #include <ipxe/pit8254.h>
36 
37 /** Number of ticks per day
38  *
39  * This seems to be the normative value, as used by e.g. SeaBIOS to
40  * decide when to set the midnight rollover flag.
41  */
42 #define BIOS_TICKS_PER_DAY 0x1800b0
43 
44 /** Number of ticks per BIOS tick */
45 #define TICKS_PER_BIOS_TICK \
46  ( ( TICKS_PER_SEC * 60 * 60 * 24 ) / BIOS_TICKS_PER_DAY )
47 
48 /**
49  * Get current system time in ticks
50  *
51  * @ret ticks Current time, in ticks
52  *
53  * Use direct memory access to BIOS variables, longword 0040:006C
54  * (ticks today) and byte 0040:0070 (midnight crossover flag) instead
55  * of calling timeofday BIOS interrupt.
56  */
57 static unsigned long bios_currticks ( void ) {
58  static uint32_t offset;
59  uint32_t ticks;
60  uint8_t midnight;
61 
62  /* Re-enable interrupts so that the timer interrupt can occur */
63  __asm__ __volatile__ ( "sti\n\t"
64  "nop\n\t"
65  "nop\n\t"
66  "cli\n\t" );
67 
68  /* Read current BIOS time of day */
69  get_real ( ticks, BDA_SEG, BDA_TICKS );
70  get_real ( midnight, BDA_SEG, BDA_MIDNIGHT );
71 
72  /* Handle midnight rollover */
73  if ( midnight ) {
74  midnight = 0;
75  put_real ( midnight, BDA_SEG, BDA_MIDNIGHT );
77  }
78  ticks += offset;
79 
80  /* Convert to timer ticks */
81  return ( ticks * TICKS_PER_BIOS_TICK );
82 }
83 
84 /** BIOS timer */
85 struct timer bios_timer __timer ( TIMER_NORMAL ) = {
86  .name = "bios",
87  .currticks = bios_currticks,
88  .udelay = pit8254_udelay,
89 };
#define TICKS_PER_BIOS_TICK
Number of ticks per BIOS tick.
Definition: bios_timer.c:45
#define BIOS_TICKS_PER_DAY
Number of ticks per day.
Definition: bios_timer.c:42
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define get_real
Definition: libkir.h:151
#define BDA_TICKS
Definition: bios.h:15
iPXE timers
#define put_real
Definition: libkir.h:150
A timer.
Definition: timer.h:28
static unsigned long bios_currticks(void)
Get current system time in ticks.
Definition: bios_timer.c:57
8254 Programmable Interval Timer
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
unsigned char uint8_t
Definition: stdint.h:10
#define BDA_SEG
Definition: bios.h:6
unsigned int uint32_t
Definition: stdint.h:12
struct timer bios_timer __timer(TIMER_NORMAL)
BIOS timer.
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
const char * name
Name.
Definition: timer.h:30
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
#define BDA_MIDNIGHT
Definition: bios.h:16
#define TIMER_NORMAL
Normal timer.
Definition: timer.h:63