intwrap grub_pxe_scan

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-04-04 15:49:06 +02:00
parent 65936631e4
commit 1b8cb8573b
3 changed files with 53 additions and 69 deletions

View file

@ -27,6 +27,7 @@
#include <grub/env.h> #include <grub/env.h>
#include <grub/machine/pxe.h> #include <grub/machine/pxe.h>
#include <grub/machine/int.h>
#include <grub/machine/memory.h> #include <grub/machine/memory.h>
#define SEGMENT(x) ((x) >> 4) #define SEGMENT(x) ((x) >> 4)
@ -55,6 +56,45 @@ struct grub_pxe_data
char filename[0]; char filename[0];
}; };
static grub_uint32_t pxe_rm_entry = 0;
static struct grub_pxenv *
grub_pxe_scan (void)
{
struct grub_bios_int_registers regs;
struct grub_pxenv *ret;
void *pxe;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
regs.ebx = 0;
regs.ecx = 0;
regs.eax = 0x5650;
grub_bios_interrupt (0x1a, &regs);
if ((regs.eax & 0xffff) != 0x564e)
return NULL;
ret = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff));
if (grub_memcmp (ret->signature, GRUB_PXE_SIGNATURE, sizeof (ret->signature))
!= 0)
return NULL;
if (ret->version < 0x201)
return NULL;
pxe = (void *) ((((ret->pxe_ptr & 0xffff0000) >> 16) << 4)
+ (ret->pxe_ptr & 0xffff));
if (!pxe)
return NULL;
/* !PXE */
if (*(grub_uint32_t *) pxe != 0x45585021)
return NULL;
pxe_rm_entry = ret->rm_entry;
return ret;
}
static int static int
grub_pxe_iterate (int (*hook) (const char *name)) grub_pxe_iterate (int (*hook) (const char *name))
{ {
@ -202,14 +242,14 @@ grub_pxefs_open (struct grub_file *file, const char *name)
if (curr_file != 0) if (curr_file != 0)
{ {
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2); grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2, pxe_rm_entry);
curr_file = 0; curr_file = 0;
} }
c.c1.server_ip = disk_data->server_ip; c.c1.server_ip = disk_data->server_ip;
c.c1.gateway_ip = disk_data->gateway_ip; c.c1.gateway_ip = disk_data->gateway_ip;
grub_strcpy ((char *)&c.c1.filename[0], name); grub_strcpy ((char *)&c.c1.filename[0], name);
grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1); grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry);
if (c.c1.status) if (c.c1.status)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
@ -217,7 +257,7 @@ grub_pxefs_open (struct grub_file *file, const char *name)
c.c2.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); c.c2.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
c.c2.packet_size = grub_pxe_blksize; c.c2.packet_size = grub_pxe_blksize;
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2); grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry);
if (c.c2.status) if (c.c2.status)
return grub_error (GRUB_ERR_BAD_FS, "open fails"); return grub_error (GRUB_ERR_BAD_FS, "open fails");
@ -275,14 +315,14 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len)
struct grub_pxenv_tftp_open o; struct grub_pxenv_tftp_open o;
if (curr_file != 0) if (curr_file != 0)
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o); grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry);
o.server_ip = disk_data->server_ip; o.server_ip = disk_data->server_ip;
o.gateway_ip = disk_data->gateway_ip; o.gateway_ip = disk_data->gateway_ip;
grub_strcpy ((char *)&o.filename[0], data->filename); grub_strcpy ((char *)&o.filename[0], data->filename);
o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
o.packet_size = grub_pxe_blksize; o.packet_size = grub_pxe_blksize;
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o); grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o, pxe_rm_entry);
if (o.status) if (o.status)
{ {
grub_error (GRUB_ERR_BAD_FS, "open fails"); grub_error (GRUB_ERR_BAD_FS, "open fails");
@ -297,7 +337,7 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len)
while (pn >= data->packet_number) while (pn >= data->packet_number)
{ {
c.buffer_size = data->block_size; c.buffer_size = data->block_size;
grub_pxe_call (GRUB_PXENV_TFTP_READ, &c); grub_pxe_call (GRUB_PXENV_TFTP_READ, &c, pxe_rm_entry);
if (c.status) if (c.status)
{ {
grub_error (GRUB_ERR_BAD_FS, "read fails"); grub_error (GRUB_ERR_BAD_FS, "read fails");
@ -318,7 +358,7 @@ grub_pxefs_close (grub_file_t file)
if (curr_file == file) if (curr_file == file)
{ {
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c); grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c, pxe_rm_entry);
curr_file = 0; curr_file = 0;
} }
@ -454,7 +494,7 @@ grub_pxe_detect (void)
ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK;
ci.buffer = 0; ci.buffer = 0;
ci.buffer_size = 0; ci.buffer_size = 0;
grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci); grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry);
if (ci.status) if (ci.status)
return; return;

View file

@ -168,6 +168,8 @@
#ifndef ASM_FILE #ifndef ASM_FILE
#define GRUB_PXE_SIGNATURE "PXENV+"
struct grub_pxenv struct grub_pxenv
{ {
grub_uint8_t signature[6]; /* 'PXENV+'. */ grub_uint8_t signature[6]; /* 'PXENV+'. */
@ -302,8 +304,7 @@ struct grub_pxenv_unload_stack
grub_uint8_t reserved[10]; grub_uint8_t reserved[10];
} __attribute__ ((packed)); } __attribute__ ((packed));
struct grub_pxenv * EXPORT_FUNC(grub_pxe_scan) (void); int EXPORT_FUNC(grub_pxe_call) (int func, void * data, grub_uint32_t pxe_rm_entry);
int EXPORT_FUNC(grub_pxe_call) (int func, void * data);
extern struct grub_pxenv *grub_pxe_pxenv; extern struct grub_pxenv *grub_pxe_pxenv;

View file

@ -1434,65 +1434,8 @@ FUNCTION(grub_get_rtc)
popl %ebp popl %ebp
ret ret
pxe_rm_entry:
.long 0
/* /*
* struct grub_pxenv *grub_pxe_scan (void); * int grub_pxe_call (int func, void* data, grub_uint32_t pxe_rm_entry);
*/
FUNCTION(grub_pxe_scan)
pushl %ebp
pushl %ebx
xorl %ebx, %ebx
xorl %ecx, %ecx
call prot_to_real
.code16
pushw %es
movw $0x5650, %ax
int $0x1A
cmpw $0x564E, %ax
jnz 1f
cmpl $0x4E455850, %es:(%bx) /* PXEN(V+) */
jnz 1f
cmpw $0x201, %es:6(%bx) /* API version */
jb 1f
lesw %es:0x28(%bx), %bx /* !PXE structure */
cmpl $0x45585021, %es:(%bx) /* !PXE */
jnz 1f
movw %es, %cx
jmp 2f
1:
xorw %bx, %bx
xorw %cx, %cx
2:
popw %es
DATA32 call real_to_prot
.code32
xorl %eax, %eax
leal (%eax, %ecx, 4), %ecx
leal (%ebx, %ecx, 4), %eax /* eax = ecx * 16 + ebx */
orl %eax, %eax
jz 1f
movl 0x10(%eax), %ecx
movl %ecx, pxe_rm_entry
1:
popl %ebx
popl %ebp
ret
/*
* int grub_pxe_call (int func, void* data);
*/ */
FUNCTION(grub_pxe_call) FUNCTION(grub_pxe_call)
pushl %ebp pushl %ebp
@ -1501,13 +1444,13 @@ FUNCTION(grub_pxe_call)
pushl %edi pushl %edi
pushl %ebx pushl %ebx
movl %ecx, %ebx
movl %eax, %ecx movl %eax, %ecx
movl %edx, %eax movl %edx, %eax
andl $0xF, %eax andl $0xF, %eax
shrl $4, %edx shrl $4, %edx
shll $16, %edx shll $16, %edx
addl %eax, %edx addl %eax, %edx
movl pxe_rm_entry, %ebx
call prot_to_real call prot_to_real
.code16 .code16