aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-09-02 22:09:02 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-09-02 22:09:02 -0700
commit14b82edb040c794b0aee61c9a422a6f8266b4916 (patch)
tree709f205158d097a888902a753a4a5d802642a492
parent55a178a351c272f249c420ec7ac5b11270c9a766 (diff)
parentb5e5e33602d563cb792083e95b13cbd95136e7e5 (diff)
downloadbak.git-14b82edb040c794b0aee61c9a422a6f8266b4916.tar.gz
bak.git-14b82edb040c794b0aee61c9a422a6f8266b4916.tar.xz
bak.git-14b82edb040c794b0aee61c9a422a6f8266b4916.zip
Merge branch 'fsc' into elflink
-rw-r--r--core/bios.inc7
-rw-r--r--core/cleanup.inc2
-rw-r--r--core/common.inc1
-rw-r--r--core/cpuinit.inc52
-rw-r--r--core/diskstart.inc2
-rw-r--r--core/fs/pxe/dnsresolv.c6
-rw-r--r--core/fs/pxe/pxe.c94
-rw-r--r--core/fs/pxe/pxe.h1
-rw-r--r--core/idle.inc18
-rw-r--r--core/include/core.h8
-rw-r--r--core/init.inc43
-rw-r--r--core/isolinux.asm1
-rw-r--r--core/pxelinux.asm7
-rw-r--r--core/timer.inc45
-rw-r--r--core/ui.inc4
15 files changed, 181 insertions, 110 deletions
diff --git a/core/bios.inc b/core/bios.inc
index 4c6c5b59..33a3cd4c 100644
--- a/core/bios.inc
+++ b/core/bios.inc
@@ -20,10 +20,15 @@
%define _BIOS_INC
global BIOS_fbm, BIOS_timer
- absolute 4*1Eh ; In the interrupt table
+ ; Interrupt vectors
+ absolute 4*1Ch
+BIOS_timer_hook resd 1
+
+ absolute 4*1Eh
fdctab equ $
fdctab1 resw 1
fdctab2 resw 1
+
absolute 0400h
serial_base resw 4 ; Base addresses for 4 serial ports
absolute 0413h
diff --git a/core/cleanup.inc b/core/cleanup.inc
index 35967f68..300584c7 100644
--- a/core/cleanup.inc
+++ b/core/cleanup.inc
@@ -52,6 +52,8 @@ cleanup_hardware:
call comboot_cleanup_api
+ call timer_cleanup
+
popad
; If we enabled serial port interrupts, clean them up now
diff --git a/core/common.inc b/core/common.inc
index 80dbb4f9..7078011e 100644
--- a/core/common.inc
+++ b/core/common.inc
@@ -18,6 +18,7 @@
%include "strcpy.inc" ; strcpy()
%include "idle.inc" ; Idle handling
%include "adv.inc" ; Auxillary Data Vector
+%include "timer.inc" ; Timer handling
; Note: the prefix section is included late, to avoid problems with some
; versions of NASM that had issues with forward references to EQU symbols.
diff --git a/core/cpuinit.inc b/core/cpuinit.inc
deleted file mode 100644
index fdd097ae..00000000
--- a/core/cpuinit.inc
+++ /dev/null
@@ -1,52 +0,0 @@
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; cpuinit.inc
-;;
-;; CPU-dependent initialization and related checks.
-;;
-
-check_escapes:
- mov ah,02h ; Check keyboard flags
- int 16h
- mov [KbdFlags],al ; Save for boot prompt check
- test al,04h ; Ctrl->skip 386 check
- jnz skip_checks
-
-;
-; Now check that there is sufficient low (DOS) memory
-;
-; NOTE: Linux doesn't use all of real_mode_seg, but we use the same
-; segment for COMBOOT images, which can use all 64K
-;
-dosram_k equ (real_mode_seg+0x1000) >> 6 ; Minimum DOS memory (K)
- int 12h
- cmp ax,dosram_k
- jae enough_ram
- mov si,err_noram
- call writestr_early
- jmp kaboom
-enough_ram:
-skip_checks:
-
- section .data16
-err_noram db 'It appears your computer has less than '
- asciidec dosram_k
- db 'K of low ("DOS")'
- db CR, LF
- db 'RAM. Syslinux needs at least this amount to boot. If you get'
- db CR, LF
- db 'this message in error, hold down the Ctrl key while'
- db CR, LF
- db 'booting, and I will take your word for it.', CR, LF, 0
- section .text16
diff --git a/core/diskstart.inc b/core/diskstart.inc
index 36d513ed..4c4e8ee9 100644
--- a/core/diskstart.inc
+++ b/core/diskstart.inc
@@ -718,8 +718,6 @@ expand_super:
; Common initialization code
;
%include "init.inc"
-%include "cpuinit.inc"
-
pushad
mov eax,ROOT_FS_OPS
diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c
index 98bc960e..15560447 100644
--- a/core/fs/pxe/dnsresolv.c
+++ b/core/fs/pxe/dnsresolv.c
@@ -181,7 +181,7 @@ uint32_t dns_resolv(const char *name)
int ques, reps; /* number of questions and replies */
uint8_t timeout;
const uint8_t *timeout_ptr = TimeoutTable;
- uint16_t oldtime;
+ uint32_t oldtime;
uint32_t srv;
uint32_t *srv_ptr = dns_server;
struct dnshdr *hd1 = (struct dnshdr *)DNSSendBuf;
@@ -232,7 +232,7 @@ uint32_t dns_resolv(const char *name)
if (err || udp_write.status != 0)
continue;
- oldtime = BIOS_timer;
+ oldtime = jiffies();
while (1) {
udp_read.status = 0;
udp_read.src_ip = srv;
@@ -249,7 +249,7 @@ uint32_t dns_resolv(const char *name)
if (hd2->id == hd1->id)
break;
- if ((uint16_t)(BIOS_timer-oldtime) >= timeout) {
+ if (jiffies()-oldtime >= timeout) {
/* time out */
timeout = *timeout_ptr++;
if (!timeout)
diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c
index f3c9bf30..4d081916 100644
--- a/core/fs/pxe/pxe.c
+++ b/core/fs/pxe/pxe.c
@@ -54,6 +54,9 @@ static const struct tftp_options tftp_options[] =
};
static const int tftp_nopts = sizeof tftp_options / sizeof tftp_options[0];
+static void tftp_error(struct open_file_t *file, uint16_t errnum,
+ const char *errstr);
+
/*
* Initialize the Files structure
*/
@@ -116,12 +119,12 @@ static void free_socket(struct open_file_t *file)
static void pxe_close_file(struct file *file)
{
- /*
- * XXX: we really should see if the connection is open as send
- * a courtesy ERROR packet so the server knows the connection is
- * dead.
- */
- free_socket(file->open_file);
+ struct open_file_t *open_file = file->open_file;
+
+ if (open_file->tftp_localport && !open_file->tftp_goteof)
+ tftp_error(open_file, 0, "No error, file close");
+
+ free_socket(open_file);
}
/**
@@ -270,6 +273,41 @@ int pxe_call(int opcode, void *data)
}
/**
+ * Send an ERROR packet. This is used to terminate a connection.
+ *
+ * @file: TFTP file pointer
+ * @errnum: Error number (network byte order)
+ * @errstr: Error string (included in packet)
+ */
+static void tftp_error(struct open_file_t *file, uint16_t errnum,
+ const char *errstr)
+{
+ static __lowmem struct {
+ uint16_t err_op;
+ uint16_t err_num;
+ char err_msg[64];
+ } __packed err_buf;
+ static __lowmem struct s_PXENV_UDP_WRITE udp_write;
+ int len = min(strlen(errstr), sizeof(err_buf.err_msg)-1);
+
+ err_buf.err_op = TFTP_ERROR;
+ err_buf.err_num = errnum;
+ memcpy(err_buf.err_msg, errstr, len);
+ err_buf.err_msg[len] = '\0';
+
+ udp_write.src_port = file->tftp_localport;
+ udp_write.dst_port = file->tftp_remoteport;
+ udp_write.ip = file->tftp_remoteip;
+ udp_write.gw = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+ udp_write.buffer = FAR_PTR(&err_buf);
+ udp_write.buffer_size = 4 + len + 1;
+
+ /* If something goes wrong, there is nothing we can do, anyway... */
+ pxe_call(PXENV_UDP_WRITE, &udp_write);
+}
+
+
+/**
* Send ACK packet. This is a common operation and so is worth canning.
*
* @param: file, TFTP block pointer
@@ -514,7 +552,7 @@ static void fill_buffer(struct open_file_t *file)
const uint8_t *timeout_ptr = TimeoutTable;
uint8_t timeout;
uint16_t buffersize;
- uint16_t old_time;
+ uint32_t oldtime;
void *data = NULL;
static __lowmem struct s_PXENV_UDP_READ udp_read;
@@ -538,7 +576,7 @@ static void fill_buffer(struct open_file_t *file)
timeout_ptr = TimeoutTable;
timeout = *timeout_ptr++;
- old_time = BIOS_timer;
+ oldtime = jiffies();
while (timeout) {
udp_read.buffer.offs = file->tftp_pktbuf;
udp_read.buffer.seg = PKTBUF_SEG;
@@ -549,13 +587,11 @@ static void fill_buffer(struct open_file_t *file)
udp_read.d_port = file->tftp_localport;
err = pxe_call(PXENV_UDP_READ, &udp_read);
if (err) {
- if (BIOS_timer == old_time)
- continue;
-
- BIOS_timer = old_time;
- timeout--; /* decrease one timer tick */
- if (!timeout) {
- timeout = *timeout_ptr++;
+ uint32_t now = jiffies();
+
+ if (now-oldtime >= timeout) {
+ oldtime = now;
+ timeout = *timeout_ptr++;
if (!timeout)
break;
}
@@ -688,7 +724,6 @@ static int fill_tail(char *dst)
*/
static void pxe_searchdir(char *filename, struct file *file)
{
- static __lowmem char tftp_proto_err[32];
char *buf = packet_buf;
char *p = filename;
char *options;
@@ -704,7 +739,7 @@ static void pxe_searchdir(char *filename, struct file *file)
int buffersize;
const uint8_t *timeout_ptr;
uint8_t timeout;
- uint16_t oldtime;
+ uint32_t oldtime;
uint16_t tid;
uint16_t opcode;
uint16_t blk_num;
@@ -786,8 +821,8 @@ static void pxe_searchdir(char *filename, struct file *file)
/* Packet transmitted OK, now we need to receive */
timeout = *timeout_ptr++;
- oldtime = BIOS_timer;
- while (timeout) {
+ oldtime = jiffies();
+ for (;;) {
buf = packet_buf;
udp_read.buffer.offs = OFFS_WRT(buf, 0);
udp_read.buffer.seg = 0;
@@ -796,11 +831,10 @@ static void pxe_searchdir(char *filename, struct file *file)
udp_read.d_port = tid;
err = pxe_call(PXENV_UDP_READ, &udp_read);
if (err) {
- if (oldtime == BIOS_timer)
- continue;
- timeout --; /* Decrease one timer tick */
- if (!timeout)
- goto failure;
+ uint32_t now = jiffies();
+ if (now-oldtime >= timeout)
+ goto failure;
+ continue;
}
/* Make sure the packet actually came from the server */
@@ -956,17 +990,7 @@ done:
err_reply:
/* Build the TFTP error packet */
- p = tftp_proto_err;
- *(uint16_t *)p = TFTP_ERROR;
- p += 2;
- *(uint16_t *)p = TFTP_EOPTNEG;
- p += 2;
- strcat(p, "TFTP_protocol error");
-
- udp_write.dst_port = open_file->tftp_remoteport;
- udp_write.buffer = FAR_PTR(tftp_proto_err);
- udp_write.buffer_size = 24;
- pxe_call(PXENV_UDP_WRITE, &udp_write);
+ tftp_error(open_file, TFTP_EOPTNEG, "TFTP protocol error");
printf("TFTP server sent an incomprehesible reply\n");
kaboom();
diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h
index 8a2b190c..f62fa7a7 100644
--- a/core/fs/pxe/pxe.h
+++ b/core/fs/pxe/pxe.h
@@ -197,7 +197,6 @@ extern int have_uuid;
extern uint8_t uuid_type;
extern char uuid[];
-extern volatile uint16_t BIOS_timer;
extern uint16_t BIOS_fbm;
extern const uint8_t TimeoutTable[];
diff --git a/core/idle.inc b/core/idle.inc
index 966b6e26..8d699733 100644
--- a/core/idle.inc
+++ b/core/idle.inc
@@ -15,10 +15,10 @@
TICKS_TO_IDLE equ 4
reset_idle:
- push ax
- mov ax,[cs:BIOS_timer]
- mov [cs:IdleTimer],ax
- pop ax
+ push eax
+ mov eax,[cs:__jiffies]
+ mov [cs:IdleTimer],eax
+ pop eax
sti ; Guard against BIOS/PXE brokenness...
ret
@@ -54,9 +54,9 @@ do_idle:
pop si
sti
.ok:
- mov ax,[BIOS_timer]
- sub ax,[IdleTimer]
- cmp ax,TICKS_TO_IDLE
+ mov eax,[__jiffies]
+ sub eax,[IdleTimer]
+ cmp eax,TICKS_TO_IDLE
jb .done
mov eax,[idle_hook_func]
@@ -74,6 +74,7 @@ do_idle:
.ret: ret
section .data16
+ alignz 4
global idle_hook_func
idle_hook_func dd 0
NoHalt dw 0
@@ -81,4 +82,5 @@ NoHalt dw 0
hlt_err db 'ERROR: idle with IF=0', CR, LF, 0
section .bss16
-IdleTimer resw 1
+ alignb 4
+IdleTimer resd 1
diff --git a/core/include/core.h b/core/include/core.h
index c13aa16f..dbcbff1c 100644
--- a/core/include/core.h
+++ b/core/include/core.h
@@ -43,5 +43,13 @@ void call16(void (*)(void), const com32sys_t *, com32sys_t *);
__noreturn _kaboom(void);
#define kaboom() _kaboom()
+/*
+ * Basic timer function...
+ */
+extern const volatile uint32_t __jiffies;
+static inline uint32_t jiffies(void)
+{
+ return __jiffies;
+}
#endif /* CORE_H */
diff --git a/core/init.inc b/core/init.inc
index 5617a697..a3fe3041 100644
--- a/core/init.inc
+++ b/core/init.inc
@@ -29,6 +29,11 @@ common_init:
jne kaboom
;
+; Initialize timer
+;
+ call timer_init
+
+;
; Initialize configuration information
;
call reset_config
@@ -44,6 +49,44 @@ common_init:
call adjust_screen
;
+; CPU-dependent initialization and related checks.
+;
+check_escapes:
+ mov ah,02h ; Check keyboard flags
+ int 16h
+ mov [KbdFlags],al ; Save for boot prompt check
+ test al,04h ; Ctrl->skip 386 check
+ jnz skip_checks
+
+;
+; Now check that there is sufficient low (DOS) memory
+;
+; NOTE: Linux doesn't use all of real_mode_seg, but we use the same
+; segment for COMBOOT images, which can use all 64K
+;
+dosram_k equ (real_mode_seg+0x1000) >> 6 ; Minimum DOS memory (K)
+ int 12h
+ cmp ax,dosram_k
+ jae enough_ram
+ mov si,err_noram
+ call writestr_early
+ jmp kaboom
+enough_ram:
+skip_checks:
+
+ section .data16
+err_noram db 'It appears your computer has less than '
+ asciidec dosram_k
+ db 'K of low ("DOS")'
+ db CR, LF
+ db 'RAM. Syslinux needs at least this amount to boot. If you get'
+ db CR, LF
+ db 'this message in error, hold down the Ctrl key while'
+ db CR, LF
+ db 'booting, and I will take your word for it.', CR, LF, 0
+ section .text16
+
+;
; The code to decompress the PM code and initialize other segments.
;
extern _lzo1x_decompress_asm_fast
diff --git a/core/isolinux.asm b/core/isolinux.asm
index b67bdc19..fc8adc66 100644
--- a/core/isolinux.asm
+++ b/core/isolinux.asm
@@ -1109,7 +1109,6 @@ all_read:
; Common initialization code
;
%include "init.inc"
-%include "cpuinit.inc"
; Patch the writechr routine to point to the full code
mov di,writechr
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index 5512e843..995de327 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -173,11 +173,6 @@ _start1:
pm_call fs_init
;
-; Common initialization code
-;
-%include "cpuinit.inc"
-
-;
; Initialize the idle mechanism
;
call reset_idle
@@ -248,6 +243,8 @@ local_boot:
; kaboom: write a message and bail out. Wait for quite a while,
; or a user keypress, then do a hard reboot.
;
+; Note: use BIOS_timer here; we may not have jiffies set up.
+;
global kaboom
kaboom:
RESET_STACK_AND_SEGS AX
diff --git a/core/timer.inc b/core/timer.inc
new file mode 100644
index 00000000..caae8265
--- /dev/null
+++ b/core/timer.inc
@@ -0,0 +1,45 @@
+;; -----------------------------------------------------------------------
+;;
+;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+;; Boston MA 02110-1301, USA; either version 2 of the License, or
+;; (at your option) any later version; incorporated herein by reference.
+;;
+;; -----------------------------------------------------------------------
+
+;;
+;; timer.inc
+;;
+;; Very simple counting timer
+;;
+;; This lets us have a simple incrementing variable without worrying
+;; about the BIOS_timer variable wrapping around at "midnight" and other
+;; weird things.
+;;
+
+ section .text16
+
+timer_init:
+ ; Hook INT 1Ch
+ mov eax,[BIOS_timer_hook]
+ mov [BIOS_timer_next],eax
+ mov dword [BIOS_timer_hook],timer_irq
+ ret
+
+timer_cleanup:
+ ; Unhook INT 1Ch
+ mov eax,[BIOS_timer_next]
+ mov [BIOS_timer_hook],eax
+ ret
+
+timer_irq:
+ inc dword [cs:__jiffies]
+ jmp 0:0
+BIOS_timer_next equ $-4
+
+ section .bss16
+ global __jiffies
+__jiffies resd 1 ; The actual timer variable
diff --git a/core/ui.inc b/core/ui.inc
index 87d0c647..9a653b1c 100644
--- a/core/ui.inc
+++ b/core/ui.inc
@@ -529,11 +529,11 @@ getchar_timeout:
call reset_idle
.loop:
- push word [BIOS_timer]
+ push word [__jiffies]
call pollchar
jnz .got_char
pop ax
- cmp ax,[BIOS_timer] ; Has the timer advanced?
+ cmp ax,[__jiffies] ; Has the timer advanced?
je .loop
dec dword [ThisKbdTo]