mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 16:53:55 -06:00
This commit was generated by cvs2svn to compensate for changes in r2,
which included commits to RCS files with non-trunk default branches. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
e63c3dc74b
commit
31e31b8a24
16 changed files with 5791 additions and 0 deletions
973
linux-user/elfload.c
Normal file
973
linux-user/elfload.c
Normal file
|
@ -0,0 +1,973 @@
|
|||
/* This is the Linux kernel elf-loading code, ported into user space */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gemu.h"
|
||||
|
||||
#include "linux_bin.h"
|
||||
#include "elf.h"
|
||||
#include "segment.h"
|
||||
|
||||
/* Necessary parameters */
|
||||
#define ALPHA_PAGE_SIZE 4096
|
||||
#define X86_PAGE_SIZE 4096
|
||||
|
||||
#define ALPHA_PAGE_MASK (~(ALPHA_PAGE_SIZE-1))
|
||||
#define X86_PAGE_MASK (~(X86_PAGE_SIZE-1))
|
||||
|
||||
#define ALPHA_PAGE_ALIGN(addr) ((((addr)+ALPHA_PAGE_SIZE)-1)&ALPHA_PAGE_MASK)
|
||||
#define X86_PAGE_ALIGN(addr) ((((addr)+X86_PAGE_SIZE)-1)&X86_PAGE_MASK)
|
||||
|
||||
#define NGROUPS 32
|
||||
|
||||
#define X86_ELF_EXEC_PAGESIZE X86_PAGE_SIZE
|
||||
#define X86_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(X86_ELF_EXEC_PAGESIZE-1))
|
||||
#define X86_ELF_PAGEOFFSET(_v) ((_v) & (X86_ELF_EXEC_PAGESIZE-1))
|
||||
|
||||
#define ALPHA_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ALPHA_PAGE_SIZE-1))
|
||||
#define ALPHA_ELF_PAGEOFFSET(_v) ((_v) & (ALPHA_PAGE_SIZE-1))
|
||||
|
||||
#define INTERPRETER_NONE 0
|
||||
#define INTERPRETER_AOUT 1
|
||||
#define INTERPRETER_ELF 2
|
||||
|
||||
#define DLINFO_ITEMS 12
|
||||
|
||||
/* Where we find X86 libraries... */
|
||||
//#define X86_DEFAULT_LIB_DIR "/usr/x86/"
|
||||
#define X86_DEFAULT_LIB_DIR "/"
|
||||
|
||||
//extern void * mmap4k();
|
||||
#define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f)
|
||||
|
||||
extern unsigned long x86_stack_size;
|
||||
|
||||
static int load_aout_interp(void * exptr, int interp_fd);
|
||||
|
||||
#ifdef BSWAP_NEEDED
|
||||
static void bswap_ehdr(Elf32_Ehdr *ehdr)
|
||||
{
|
||||
bswap16s(&ehdr->e_type); /* Object file type */
|
||||
bswap16s(&ehdr->e_machine); /* Architecture */
|
||||
bswap32s(&ehdr->e_version); /* Object file version */
|
||||
bswap32s(&ehdr->e_entry); /* Entry point virtual address */
|
||||
bswap32s(&ehdr->e_phoff); /* Program header table file offset */
|
||||
bswap32s(&ehdr->e_shoff); /* Section header table file offset */
|
||||
bswap32s(&ehdr->e_flags); /* Processor-specific flags */
|
||||
bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
|
||||
bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
|
||||
bswap16s(&ehdr->e_phnum); /* Program header table entry count */
|
||||
bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
|
||||
bswap16s(&ehdr->e_shnum); /* Section header table entry count */
|
||||
bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
|
||||
}
|
||||
|
||||
static void bswap_phdr(Elf32_Phdr *phdr)
|
||||
{
|
||||
bswap32s(&phdr->p_type); /* Segment type */
|
||||
bswap32s(&phdr->p_offset); /* Segment file offset */
|
||||
bswap32s(&phdr->p_vaddr); /* Segment virtual address */
|
||||
bswap32s(&phdr->p_paddr); /* Segment physical address */
|
||||
bswap32s(&phdr->p_filesz); /* Segment size in file */
|
||||
bswap32s(&phdr->p_memsz); /* Segment size in memory */
|
||||
bswap32s(&phdr->p_flags); /* Segment flags */
|
||||
bswap32s(&phdr->p_align); /* Segment alignment */
|
||||
}
|
||||
#endif
|
||||
|
||||
static void * get_free_page(void)
|
||||
{
|
||||
void * retval;
|
||||
|
||||
/* User-space version of kernel get_free_page. Returns a page-aligned
|
||||
* page-sized chunk of memory.
|
||||
*/
|
||||
retval = mmap4k(0, ALPHA_PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
if((long)retval == -1) {
|
||||
perror("get_free_page");
|
||||
exit(-1);
|
||||
}
|
||||
else {
|
||||
return(retval);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_page(void * pageaddr)
|
||||
{
|
||||
(void)munmap(pageaddr, ALPHA_PAGE_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* 'copy_string()' copies argument/envelope strings from user
|
||||
* memory to free pages in kernel mem. These are in a format ready
|
||||
* to be put directly into the top of new user memory.
|
||||
*
|
||||
*/
|
||||
static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
|
||||
unsigned long p)
|
||||
{
|
||||
char *tmp, *tmp1, *pag = NULL;
|
||||
int len, offset = 0;
|
||||
|
||||
if (!p) {
|
||||
return 0; /* bullet-proofing */
|
||||
}
|
||||
while (argc-- > 0) {
|
||||
if (!(tmp1 = tmp = get_user(argv+argc))) {
|
||||
fprintf(stderr, "VFS: argc is wrong");
|
||||
exit(-1);
|
||||
}
|
||||
while (get_user(tmp++));
|
||||
len = tmp - tmp1;
|
||||
if (p < len) { /* this shouldn't happen - 128kB */
|
||||
return 0;
|
||||
}
|
||||
while (len) {
|
||||
--p; --tmp; --len;
|
||||
if (--offset < 0) {
|
||||
offset = p % X86_PAGE_SIZE;
|
||||
if (!(pag = (char *) page[p/X86_PAGE_SIZE]) &&
|
||||
!(pag = (char *) page[p/X86_PAGE_SIZE] =
|
||||
(unsigned long *) get_free_page())) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (len == 0 || offset == 0) {
|
||||
*(pag + offset) = get_user(tmp);
|
||||
}
|
||||
else {
|
||||
int bytes_to_copy = (len > offset) ? offset : len;
|
||||
tmp -= bytes_to_copy;
|
||||
p -= bytes_to_copy;
|
||||
offset -= bytes_to_copy;
|
||||
len -= bytes_to_copy;
|
||||
memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static int in_group_p(gid_t g)
|
||||
{
|
||||
/* return TRUE if we're in the specified group, FALSE otherwise */
|
||||
int ngroup;
|
||||
int i;
|
||||
gid_t grouplist[NGROUPS];
|
||||
|
||||
ngroup = getgroups(NGROUPS, grouplist);
|
||||
for(i = 0; i < ngroup; i++) {
|
||||
if(grouplist[i] == g) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int count(char ** vec)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; *vec; i++) {
|
||||
vec++;
|
||||
}
|
||||
|
||||
return(i);
|
||||
}
|
||||
|
||||
static int prepare_binprm(struct linux_binprm *bprm)
|
||||
{
|
||||
struct stat st;
|
||||
int mode;
|
||||
int retval, id_change;
|
||||
|
||||
if(fstat(bprm->fd, &st) < 0) {
|
||||
return(-errno);
|
||||
}
|
||||
|
||||
mode = st.st_mode;
|
||||
if(!S_ISREG(mode)) { /* Must be regular file */
|
||||
return(-EACCES);
|
||||
}
|
||||
if(!(mode & 0111)) { /* Must have at least one execute bit set */
|
||||
return(-EACCES);
|
||||
}
|
||||
|
||||
bprm->e_uid = geteuid();
|
||||
bprm->e_gid = getegid();
|
||||
id_change = 0;
|
||||
|
||||
/* Set-uid? */
|
||||
if(mode & S_ISUID) {
|
||||
bprm->e_uid = st.st_uid;
|
||||
if(bprm->e_uid != geteuid()) {
|
||||
id_change = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set-gid? */
|
||||
/*
|
||||
* If setgid is set but no group execute bit then this
|
||||
* is a candidate for mandatory locking, not a setgid
|
||||
* executable.
|
||||
*/
|
||||
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
|
||||
bprm->e_gid = st.st_gid;
|
||||
if (!in_group_p(bprm->e_gid)) {
|
||||
id_change = 1;
|
||||
}
|
||||
}
|
||||
|
||||
memset(bprm->buf, 0, sizeof(bprm->buf));
|
||||
retval = lseek(bprm->fd, 0L, SEEK_SET);
|
||||
if(retval >= 0) {
|
||||
retval = read(bprm->fd, bprm->buf, 128);
|
||||
}
|
||||
if(retval < 0) {
|
||||
perror("prepare_binprm");
|
||||
exit(-1);
|
||||
/* return(-errno); */
|
||||
}
|
||||
else {
|
||||
return(retval);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
|
||||
struct image_info * info)
|
||||
{
|
||||
unsigned long stack_base;
|
||||
int i;
|
||||
extern unsigned long stktop;
|
||||
|
||||
stack_base = X86_STACK_TOP - MAX_ARG_PAGES*X86_PAGE_SIZE;
|
||||
|
||||
p += stack_base;
|
||||
if (bprm->loader) {
|
||||
bprm->loader += stack_base;
|
||||
}
|
||||
bprm->exec += stack_base;
|
||||
|
||||
/* Create enough stack to hold everything. If we don't use
|
||||
* it for args, we'll use it for something else...
|
||||
*/
|
||||
if(x86_stack_size > MAX_ARG_PAGES*X86_PAGE_SIZE) {
|
||||
if((long)mmap4k((void *)(X86_STACK_TOP-x86_stack_size), x86_stack_size + X86_PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_GROWSDOWN | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
|
||||
perror("stk mmap");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if((long)mmap4k((void *)stack_base, (MAX_ARG_PAGES+1)*X86_PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_GROWSDOWN | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
|
||||
perror("stk mmap");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
stktop = stack_base;
|
||||
|
||||
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
|
||||
if (bprm->page[i]) {
|
||||
info->rss++;
|
||||
|
||||
memcpy((void *)stack_base, (void *)bprm->page[i], X86_PAGE_SIZE);
|
||||
free_page((void *)bprm->page[i]);
|
||||
}
|
||||
stack_base += X86_PAGE_SIZE;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static void set_brk(unsigned long start, unsigned long end)
|
||||
{
|
||||
/* page-align the start and end addresses... */
|
||||
start = ALPHA_PAGE_ALIGN(start);
|
||||
end = ALPHA_PAGE_ALIGN(end);
|
||||
if (end <= start)
|
||||
return;
|
||||
if((long)mmap4k(start, end - start,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
|
||||
perror("cannot mmap brk");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* We need to explicitly zero any fractional pages
|
||||
after the data section (i.e. bss). This would
|
||||
contain the junk from the file that should not
|
||||
be in memory */
|
||||
|
||||
|
||||
static void padzero(unsigned long elf_bss)
|
||||
{
|
||||
unsigned long nbyte;
|
||||
char * fpnt;
|
||||
|
||||
nbyte = elf_bss & (ALPHA_PAGE_SIZE-1); /* was X86_PAGE_SIZE - JRP */
|
||||
if (nbyte) {
|
||||
nbyte = ALPHA_PAGE_SIZE - nbyte;
|
||||
fpnt = (char *) elf_bss;
|
||||
do {
|
||||
*fpnt++ = 0;
|
||||
} while (--nbyte);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int * create_elf_tables(char *p, int argc, int envc,
|
||||
struct elfhdr * exec,
|
||||
unsigned long load_addr,
|
||||
unsigned long interp_load_addr, int ibcs,
|
||||
struct image_info *info)
|
||||
{
|
||||
unsigned int *argv, *envp, *dlinfo;
|
||||
unsigned int *sp;
|
||||
char **alpha_envp;
|
||||
|
||||
/*
|
||||
* Force 16 byte alignment here for generality.
|
||||
*/
|
||||
sp = (unsigned int *) (~15UL & (unsigned long) p);
|
||||
sp -= exec ? DLINFO_ITEMS*2 : 2;
|
||||
dlinfo = sp;
|
||||
sp -= envc+1;
|
||||
envp = sp;
|
||||
sp -= argc+1;
|
||||
argv = sp;
|
||||
if (!ibcs) {
|
||||
put_user(envp,--sp);
|
||||
put_user(argv,--sp);
|
||||
}
|
||||
alpha_envp = (char **)malloc((envc+1) * sizeof(char *));
|
||||
|
||||
#define NEW_AUX_ENT(id, val) \
|
||||
put_user ((id), dlinfo++); \
|
||||
put_user ((val), dlinfo++)
|
||||
|
||||
if (exec) { /* Put this here for an ELF program interpreter */
|
||||
struct elf_phdr * eppnt;
|
||||
eppnt = (struct elf_phdr *)((unsigned long)exec->e_phoff);
|
||||
|
||||
NEW_AUX_ENT (AT_PHDR, (unsigned int)(load_addr + exec->e_phoff));
|
||||
NEW_AUX_ENT (AT_PHENT, (unsigned int)(sizeof (struct elf_phdr)));
|
||||
NEW_AUX_ENT (AT_PHNUM, (unsigned int)(exec->e_phnum));
|
||||
NEW_AUX_ENT (AT_PAGESZ, (unsigned int)(ALPHA_PAGE_SIZE));
|
||||
NEW_AUX_ENT (AT_BASE, (unsigned int)(interp_load_addr));
|
||||
NEW_AUX_ENT (AT_FLAGS, (unsigned int)0);
|
||||
NEW_AUX_ENT (AT_ENTRY, (unsigned int) exec->e_entry);
|
||||
NEW_AUX_ENT (AT_UID, (unsigned int) getuid());
|
||||
NEW_AUX_ENT (AT_EUID, (unsigned int) geteuid());
|
||||
NEW_AUX_ENT (AT_GID, (unsigned int) getgid());
|
||||
NEW_AUX_ENT (AT_EGID, (unsigned int) getegid());
|
||||
}
|
||||
NEW_AUX_ENT (AT_NULL, 0);
|
||||
#undef NEW_AUX_ENT
|
||||
put_user((unsigned int)argc,--sp);
|
||||
info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff);
|
||||
while (argc-->0) {
|
||||
put_user(p,argv++);
|
||||
while (get_user(p++)) /* nothing */ ;
|
||||
}
|
||||
put_user(0,argv);
|
||||
info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);
|
||||
__environ = alpha_envp;
|
||||
while (envc-->0) {
|
||||
*alpha_envp++ = (char *)p;
|
||||
put_user(p,envp++);
|
||||
while (get_user(p++)) /* nothing */ ;
|
||||
}
|
||||
put_user(0,envp);
|
||||
*alpha_envp = 0;
|
||||
info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);
|
||||
return sp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
|
||||
int interpreter_fd,
|
||||
unsigned long *interp_load_addr)
|
||||
{
|
||||
struct elf_phdr *elf_phdata = NULL;
|
||||
struct elf_phdr *eppnt;
|
||||
unsigned long load_addr;
|
||||
int load_addr_set = 0;
|
||||
int retval;
|
||||
unsigned long last_bss, elf_bss;
|
||||
unsigned long error;
|
||||
int i;
|
||||
|
||||
elf_bss = 0;
|
||||
last_bss = 0;
|
||||
error = 0;
|
||||
|
||||
/* We put this here so that mmap will search for the *first*
|
||||
* available memory...
|
||||
*/
|
||||
load_addr = INTERP_LOADADDR;
|
||||
|
||||
/* First of all, some simple consistency checks */
|
||||
if ((interp_elf_ex->e_type != ET_EXEC &&
|
||||
interp_elf_ex->e_type != ET_DYN) ||
|
||||
!elf_check_arch(interp_elf_ex->e_machine)) {
|
||||
return ~0UL;
|
||||
}
|
||||
|
||||
/* Now read in all of the header information */
|
||||
|
||||
if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > X86_PAGE_SIZE)
|
||||
return ~0UL;
|
||||
|
||||
elf_phdata = (struct elf_phdr *)
|
||||
malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
|
||||
|
||||
if (!elf_phdata)
|
||||
return ~0UL;
|
||||
|
||||
/*
|
||||
* If the size of this structure has changed, then punt, since
|
||||
* we will be doing the wrong thing.
|
||||
*/
|
||||
if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
|
||||
{
|
||||
free(elf_phdata);
|
||||
return ~0UL;
|
||||
}
|
||||
|
||||
retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
|
||||
if(retval >= 0) {
|
||||
retval = read(interpreter_fd,
|
||||
(char *) elf_phdata,
|
||||
sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
|
||||
}
|
||||
|
||||
if (retval < 0) {
|
||||
perror("load_elf_interp");
|
||||
exit(-1);
|
||||
free (elf_phdata);
|
||||
return retval;
|
||||
}
|
||||
#ifdef BSWAP_NEEDED
|
||||
eppnt = elf_phdata;
|
||||
for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
|
||||
bswap_phdr(eppnt);
|
||||
}
|
||||
#endif
|
||||
eppnt = elf_phdata;
|
||||
for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
|
||||
if (eppnt->p_type == PT_LOAD) {
|
||||
int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
|
||||
int elf_prot = 0;
|
||||
unsigned long vaddr = 0;
|
||||
unsigned long k;
|
||||
|
||||
if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
|
||||
if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
|
||||
if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
|
||||
if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
|
||||
elf_type |= MAP_FIXED;
|
||||
vaddr = eppnt->p_vaddr;
|
||||
}
|
||||
error = (unsigned long)mmap4k(load_addr+X86_ELF_PAGESTART(vaddr),
|
||||
eppnt->p_filesz + X86_ELF_PAGEOFFSET(eppnt->p_vaddr),
|
||||
elf_prot,
|
||||
elf_type,
|
||||
interpreter_fd,
|
||||
eppnt->p_offset - X86_ELF_PAGEOFFSET(eppnt->p_vaddr));
|
||||
|
||||
if (error > -1024UL) {
|
||||
/* Real error */
|
||||
close(interpreter_fd);
|
||||
free(elf_phdata);
|
||||
return ~0UL;
|
||||
}
|
||||
|
||||
if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
|
||||
load_addr = error;
|
||||
load_addr_set = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the end of the file mapping for this phdr, and keep
|
||||
* track of the largest address we see for this.
|
||||
*/
|
||||
k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
|
||||
if (k > elf_bss) elf_bss = k;
|
||||
|
||||
/*
|
||||
* Do the same thing for the memory mapping - between
|
||||
* elf_bss and last_bss is the bss section.
|
||||
*/
|
||||
k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
|
||||
if (k > last_bss) last_bss = k;
|
||||
}
|
||||
|
||||
/* Now use mmap to map the library into memory. */
|
||||
|
||||
close(interpreter_fd);
|
||||
|
||||
/*
|
||||
* Now fill out the bss section. First pad the last page up
|
||||
* to the page boundary, and then perform a mmap to make sure
|
||||
* that there are zeromapped pages up to and including the last
|
||||
* bss page.
|
||||
*/
|
||||
padzero(elf_bss);
|
||||
elf_bss = X86_ELF_PAGESTART(elf_bss + ALPHA_PAGE_SIZE - 1); /* What we have mapped so far */
|
||||
|
||||
/* Map the last of the bss segment */
|
||||
if (last_bss > elf_bss) {
|
||||
mmap4k(elf_bss, last_bss-elf_bss,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
}
|
||||
free(elf_phdata);
|
||||
|
||||
*interp_load_addr = load_addr;
|
||||
return ((unsigned long) interp_elf_ex->e_entry) + load_addr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs,
|
||||
struct image_info * info)
|
||||
{
|
||||
struct elfhdr elf_ex;
|
||||
struct elfhdr interp_elf_ex;
|
||||
struct exec interp_ex;
|
||||
int interpreter_fd = -1; /* avoid warning */
|
||||
unsigned long load_addr;
|
||||
int load_addr_set = 0;
|
||||
unsigned int interpreter_type = INTERPRETER_NONE;
|
||||
unsigned char ibcs2_interpreter;
|
||||
int i;
|
||||
void * mapped_addr;
|
||||
struct elf_phdr * elf_ppnt;
|
||||
struct elf_phdr *elf_phdata;
|
||||
unsigned long elf_bss, k, elf_brk;
|
||||
int retval;
|
||||
char * elf_interpreter;
|
||||
unsigned long elf_entry, interp_load_addr = 0;
|
||||
int status;
|
||||
unsigned long start_code, end_code, end_data;
|
||||
unsigned long elf_stack;
|
||||
char passed_fileno[6];
|
||||
|
||||
ibcs2_interpreter = 0;
|
||||
status = 0;
|
||||
load_addr = 0;
|
||||
elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
|
||||
#ifdef BSWAP_NEEDED
|
||||
bswap_ehdr(&elf_ex);
|
||||
#endif
|
||||
|
||||
if (elf_ex.e_ident[0] != 0x7f ||
|
||||
strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
|
||||
/* First of all, some simple consistency checks */
|
||||
if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
|
||||
(! elf_check_arch(elf_ex.e_machine))) {
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
/* Now read in all of the header information */
|
||||
|
||||
elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
|
||||
if (elf_phdata == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
|
||||
if(retval > 0) {
|
||||
retval = read(bprm->fd, (char *) elf_phdata,
|
||||
elf_ex.e_phentsize * elf_ex.e_phnum);
|
||||
}
|
||||
|
||||
if (retval < 0) {
|
||||
perror("load_elf_binary");
|
||||
exit(-1);
|
||||
free (elf_phdata);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
elf_ppnt = elf_phdata;
|
||||
|
||||
elf_bss = 0;
|
||||
elf_brk = 0;
|
||||
|
||||
|
||||
elf_stack = ~0UL;
|
||||
elf_interpreter = NULL;
|
||||
start_code = ~0UL;
|
||||
end_code = 0;
|
||||
end_data = 0;
|
||||
|
||||
for(i=0;i < elf_ex.e_phnum; i++) {
|
||||
if (elf_ppnt->p_type == PT_INTERP) {
|
||||
if ( elf_interpreter != NULL )
|
||||
{
|
||||
free (elf_phdata);
|
||||
free(elf_interpreter);
|
||||
close(bprm->fd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* This is the program interpreter used for
|
||||
* shared libraries - for now assume that this
|
||||
* is an a.out format binary
|
||||
*/
|
||||
|
||||
elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+strlen(X86_DEFAULT_LIB_DIR));
|
||||
|
||||
if (elf_interpreter == NULL) {
|
||||
free (elf_phdata);
|
||||
close(bprm->fd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
strcpy(elf_interpreter, X86_DEFAULT_LIB_DIR);
|
||||
retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
|
||||
if(retval >= 0) {
|
||||
retval = read(bprm->fd,
|
||||
elf_interpreter+strlen(X86_DEFAULT_LIB_DIR),
|
||||
elf_ppnt->p_filesz);
|
||||
}
|
||||
if(retval < 0) {
|
||||
perror("load_elf_binary2");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* If the program interpreter is one of these two,
|
||||
then assume an iBCS2 image. Otherwise assume
|
||||
a native linux image. */
|
||||
|
||||
/* JRP - Need to add X86 lib dir stuff here... */
|
||||
|
||||
if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
|
||||
strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
|
||||
ibcs2_interpreter = 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("Using ELF interpreter %s\n", elf_interpreter);
|
||||
#endif
|
||||
if (retval >= 0) {
|
||||
retval = open(elf_interpreter, O_RDONLY);
|
||||
if(retval >= 0) {
|
||||
interpreter_fd = retval;
|
||||
}
|
||||
else {
|
||||
perror(elf_interpreter);
|
||||
exit(-1);
|
||||
/* retval = -errno; */
|
||||
}
|
||||
}
|
||||
|
||||
if (retval >= 0) {
|
||||
retval = lseek(interpreter_fd, 0, SEEK_SET);
|
||||
if(retval >= 0) {
|
||||
retval = read(interpreter_fd,bprm->buf,128);
|
||||
}
|
||||
}
|
||||
if (retval >= 0) {
|
||||
interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
|
||||
interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */
|
||||
}
|
||||
if (retval < 0) {
|
||||
perror("load_elf_binary3");
|
||||
exit(-1);
|
||||
free (elf_phdata);
|
||||
free(elf_interpreter);
|
||||
close(bprm->fd);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
elf_ppnt++;
|
||||
}
|
||||
|
||||
/* Some simple consistency checks for the interpreter */
|
||||
if (elf_interpreter){
|
||||
interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
|
||||
|
||||
/* Now figure out which format our binary is */
|
||||
if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
|
||||
(N_MAGIC(interp_ex) != QMAGIC)) {
|
||||
interpreter_type = INTERPRETER_ELF;
|
||||
}
|
||||
|
||||
if (interp_elf_ex.e_ident[0] != 0x7f ||
|
||||
strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
|
||||
interpreter_type &= ~INTERPRETER_ELF;
|
||||
}
|
||||
|
||||
if (!interpreter_type) {
|
||||
free(elf_interpreter);
|
||||
free(elf_phdata);
|
||||
close(bprm->fd);
|
||||
return -ELIBBAD;
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, we are done with that, now set up the arg stuff,
|
||||
and then start this sucker up */
|
||||
|
||||
if (!bprm->sh_bang) {
|
||||
char * passed_p;
|
||||
|
||||
if (interpreter_type == INTERPRETER_AOUT) {
|
||||
sprintf(passed_fileno, "%d", bprm->fd);
|
||||
passed_p = passed_fileno;
|
||||
|
||||
if (elf_interpreter) {
|
||||
bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p);
|
||||
bprm->argc++;
|
||||
}
|
||||
}
|
||||
if (!bprm->p) {
|
||||
if (elf_interpreter) {
|
||||
free(elf_interpreter);
|
||||
}
|
||||
free (elf_phdata);
|
||||
close(bprm->fd);
|
||||
return -E2BIG;
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, This is the point of no return */
|
||||
info->end_data = 0;
|
||||
info->end_code = 0;
|
||||
info->start_mmap = (unsigned long)ELF_START_MMAP;
|
||||
info->mmap = 0;
|
||||
elf_entry = (unsigned long) elf_ex.e_entry;
|
||||
|
||||
/* Do this so that we can load the interpreter, if need be. We will
|
||||
change some of these later */
|
||||
info->rss = 0;
|
||||
bprm->p = setup_arg_pages(bprm->p, bprm, info);
|
||||
info->start_stack = bprm->p;
|
||||
|
||||
/* Now we do a little grungy work by mmaping the ELF image into
|
||||
* the correct location in memory. At this point, we assume that
|
||||
* the image should be loaded at fixed address, not at a variable
|
||||
* address.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
|
||||
if (elf_ppnt->p_type == PT_LOAD) {
|
||||
int elf_prot = 0;
|
||||
if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
|
||||
if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
|
||||
if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
|
||||
|
||||
mapped_addr = mmap4k(X86_ELF_PAGESTART(elf_ppnt->p_vaddr),
|
||||
(elf_ppnt->p_filesz +
|
||||
X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
|
||||
elf_prot,
|
||||
(MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
|
||||
bprm->fd,
|
||||
(elf_ppnt->p_offset -
|
||||
X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
|
||||
|
||||
if((unsigned long)mapped_addr == 0xffffffffffffffff) {
|
||||
perror("mmap");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef LOW_ELF_STACK
|
||||
if (X86_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
|
||||
elf_stack = X86_ELF_PAGESTART(elf_ppnt->p_vaddr);
|
||||
#endif
|
||||
|
||||
if (!load_addr_set) {
|
||||
load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
|
||||
load_addr_set = 1;
|
||||
}
|
||||
k = elf_ppnt->p_vaddr;
|
||||
if (k < start_code) start_code = k;
|
||||
k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
|
||||
if (k > elf_bss) elf_bss = k;
|
||||
#if 1
|
||||
if ((elf_ppnt->p_flags & PF_X) && end_code < k)
|
||||
#else
|
||||
if ( !(elf_ppnt->p_flags & PF_W) && end_code < k)
|
||||
#endif
|
||||
end_code = k;
|
||||
if (end_data < k) end_data = k;
|
||||
k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
|
||||
if (k > elf_brk) elf_brk = k;
|
||||
}
|
||||
}
|
||||
|
||||
if (elf_interpreter) {
|
||||
if (interpreter_type & 1) {
|
||||
elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
|
||||
}
|
||||
else if (interpreter_type & 2) {
|
||||
elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
|
||||
&interp_load_addr);
|
||||
}
|
||||
|
||||
close(interpreter_fd);
|
||||
free(elf_interpreter);
|
||||
|
||||
if (elf_entry == ~0UL) {
|
||||
printf("Unable to load interpreter\n");
|
||||
free(elf_phdata);
|
||||
exit(-1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
free(elf_phdata);
|
||||
|
||||
if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
|
||||
info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
|
||||
|
||||
#ifdef LOW_ELF_STACK
|
||||
info->start_stack = bprm->p = elf_stack - 4;
|
||||
#endif
|
||||
bprm->p = (unsigned long)
|
||||
create_elf_tables((char *)bprm->p,
|
||||
bprm->argc,
|
||||
bprm->envc,
|
||||
(interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
|
||||
load_addr,
|
||||
interp_load_addr,
|
||||
(interpreter_type == INTERPRETER_AOUT ? 0 : 1),
|
||||
info);
|
||||
if (interpreter_type == INTERPRETER_AOUT)
|
||||
info->arg_start += strlen(passed_fileno) + 1;
|
||||
info->start_brk = info->brk = elf_brk;
|
||||
info->end_code = end_code;
|
||||
info->start_code = start_code;
|
||||
info->end_data = end_data;
|
||||
info->start_stack = bprm->p;
|
||||
|
||||
/* Calling set_brk effectively mmaps the pages that we need for the bss and break
|
||||
sections */
|
||||
set_brk(elf_bss, elf_brk);
|
||||
|
||||
padzero(elf_bss);
|
||||
|
||||
#if 0
|
||||
printf("(start_brk) %x\n" , info->start_brk);
|
||||
printf("(end_code) %x\n" , info->end_code);
|
||||
printf("(start_code) %x\n" , info->start_code);
|
||||
printf("(end_data) %x\n" , info->end_data);
|
||||
printf("(start_stack) %x\n" , info->start_stack);
|
||||
printf("(brk) %x\n" , info->brk);
|
||||
#endif
|
||||
|
||||
if ( info->personality == PER_SVR4 )
|
||||
{
|
||||
/* Why this, you ask??? Well SVr4 maps page 0 as read-only,
|
||||
and some applications "depend" upon this behavior.
|
||||
Since we do not have the power to recompile these, we
|
||||
emulate the SVr4 behavior. Sigh. */
|
||||
mapped_addr = mmap4k(NULL, ALPHA_PAGE_SIZE, PROT_READ | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE, -1, 0);
|
||||
}
|
||||
|
||||
#ifdef ELF_PLAT_INIT
|
||||
/*
|
||||
* The ABI may specify that certain registers be set up in special
|
||||
* ways (on i386 %edx is the address of a DT_FINI function, for
|
||||
* example. This macro performs whatever initialization to
|
||||
* the regs structure is required.
|
||||
*/
|
||||
ELF_PLAT_INIT(regs);
|
||||
#endif
|
||||
|
||||
|
||||
info->entry = elf_entry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int elf_exec(const char * filename, char ** argv, char ** envp,
|
||||
struct pt_regs * regs, struct image_info *infop)
|
||||
{
|
||||
struct linux_binprm bprm;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
bprm.p = X86_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
|
||||
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
|
||||
bprm.page[i] = 0;
|
||||
retval = open(filename, O_RDONLY);
|
||||
if (retval == -1) {
|
||||
perror(filename);
|
||||
exit(-1);
|
||||
/* return retval; */
|
||||
}
|
||||
else {
|
||||
bprm.fd = retval;
|
||||
}
|
||||
bprm.filename = (char *)filename;
|
||||
bprm.sh_bang = 0;
|
||||
bprm.loader = 0;
|
||||
bprm.exec = 0;
|
||||
bprm.dont_iput = 0;
|
||||
bprm.argc = count(argv);
|
||||
bprm.envc = count(envp);
|
||||
|
||||
retval = prepare_binprm(&bprm);
|
||||
|
||||
if(retval>=0) {
|
||||
bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p);
|
||||
bprm.exec = bprm.p;
|
||||
bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p);
|
||||
bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p);
|
||||
if (!bprm.p) {
|
||||
retval = -E2BIG;
|
||||
}
|
||||
}
|
||||
|
||||
if(retval>=0) {
|
||||
retval = load_elf_binary(&bprm,regs,infop);
|
||||
}
|
||||
if(retval>=0) {
|
||||
/* success. Initialize important registers */
|
||||
regs->esp = infop->start_stack;
|
||||
regs->eip = infop->entry;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Something went wrong, return the inode and free the argument pages*/
|
||||
for (i=0 ; i<MAX_ARG_PAGES ; i++) {
|
||||
free_page((void *)bprm.page[i]);
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
||||
static int load_aout_interp(void * exptr, int interp_fd)
|
||||
{
|
||||
printf("a.out interpreter not yet supported\n");
|
||||
return(0);
|
||||
}
|
||||
|
282
linux-user/ioctls.h
Normal file
282
linux-user/ioctls.h
Normal file
|
@ -0,0 +1,282 @@
|
|||
/* emulated ioctl list */
|
||||
|
||||
IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
||||
IOCTL(TCGETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
||||
IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
||||
IOCTL(TCSETSW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
||||
IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
|
||||
IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize)))
|
||||
IOCTL(FIONREAD, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TCGETA, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TCSETA, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TCSETAW, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TCSETAF, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TCSBRK, 0, TYPE_INT)
|
||||
IOCTL(TCSBRKP, 0, TYPE_INT)
|
||||
IOCTL(TCXONC, 0, TYPE_INT)
|
||||
IOCTL(TCFLSH, 0, TYPE_INT)
|
||||
IOCTL(TIOCEXCL, 0, TYPE_NULL)
|
||||
IOCTL(TIOCNXCL, 0, TYPE_NULL)
|
||||
IOCTL(TIOCSCTTY, 0, TYPE_INT)
|
||||
IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCGSOFTCAR, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCSSOFTCAR, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCLINUX, IOC_R | IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCCONS, 0, TYPE_NULL)
|
||||
IOCTL(TIOCGSERIAL, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCSSERIAL, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCPKT, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(FIONBIO, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCNOTTY, 0, TYPE_NULL)
|
||||
IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(FIOCLEX, 0, TYPE_NULL)
|
||||
IOCTL(FIONCLEX, 0, TYPE_NULL)
|
||||
IOCTL(FIOASYNC, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCGLCKTRMIOS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
||||
IOCTL(TIOCSLCKTRMIOS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
|
||||
IOCTL(TIOCSERCONFIG, 0, TYPE_NULL)
|
||||
IOCTL(TIOCSERGETLSR, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(TIOCSERGETMULTI, IOC_R, MK_PTR(MK_STRUCT(STRUCT_serial_multiport_struct)))
|
||||
IOCTL(TIOCSERSETMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_serial_multiport_struct)))
|
||||
IOCTL(TIOCMIWAIT, 0, TYPE_INT)
|
||||
IOCTL(TIOCGICOUNT, IOC_R, MK_PTR(MK_STRUCT(STRUCT_serial_icounter_struct)))
|
||||
|
||||
IOCTL(BLKROSET, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(BLKROGET, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(BLKRRPART, 0, TYPE_NULL)
|
||||
IOCTL(BLKGETSIZE, IOC_R, MK_PTR(TYPE_ULONG))
|
||||
#ifdef BLKGETSIZE64
|
||||
IOCTL(BLKGETSIZE64, IOC_R, MK_PTR(TYPE_ULONGLONG))
|
||||
#endif
|
||||
IOCTL(BLKFLSBUF, 0, TYPE_NULL)
|
||||
IOCTL(BLKRASET, 0, TYPE_INT)
|
||||
IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG))
|
||||
#ifdef FIBMAP
|
||||
IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG))
|
||||
#endif
|
||||
#ifdef FIGETBSZ
|
||||
IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG))
|
||||
#endif
|
||||
|
||||
IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
|
||||
IOCTL(SIOCDELRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
|
||||
IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
|
||||
IOCTL(SIOCSIFFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
|
||||
IOCTL(SIOCGIFADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCSIFADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCGIFBRDADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCSIFBRDADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCGIFDSTADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCSIFDSTADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCGIFNETMASK, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCSIFNETMASK, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCGIFHWADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCSIFHWADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCGIFTXQLEN, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCSIFTXQLEN, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCGIFMETRIC, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
|
||||
IOCTL(SIOCSIFMETRIC, IOC_W, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
|
||||
IOCTL(SIOCGIFMTU, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
|
||||
IOCTL(SIOCSIFMTU, IOC_W, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
|
||||
IOCTL(SIOCGIFMAP, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_ifmap_ifreq)))
|
||||
IOCTL(SIOCSIFMAP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_ifmap_ifreq)))
|
||||
IOCTL(SIOCGIFSLAVE, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
|
||||
IOCTL(SIOCSIFSLAVE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
|
||||
IOCTL(SIOCGIFMEM, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_ptr_ifreq)))
|
||||
IOCTL(SIOCSIFMEM, IOC_W, MK_PTR(MK_STRUCT(STRUCT_ptr_ifreq)))
|
||||
IOCTL(SIOCADDMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCDELMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||
IOCTL(SIOCSIFLINK, 0, TYPE_NULL)
|
||||
IOCTL(SIOCGIFCONF, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_ifconf)))
|
||||
IOCTL(SIOCGIFENCAP, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SIOCSIFENCAP, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SIOCDARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
|
||||
IOCTL(SIOCSARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
|
||||
IOCTL(SIOCGARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
|
||||
IOCTL(SIOCDRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
|
||||
IOCTL(SIOCSRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
|
||||
IOCTL(SIOCGRARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
|
||||
|
||||
IOCTL(CDROMPAUSE, 0, TYPE_NULL)
|
||||
IOCTL(CDROMSTART, 0, TYPE_NULL)
|
||||
IOCTL(CDROMSTOP, 0, TYPE_NULL)
|
||||
IOCTL(CDROMRESUME, 0, TYPE_NULL)
|
||||
IOCTL(CDROMEJECT, 0, TYPE_NULL)
|
||||
IOCTL(CDROMEJECT_SW, 0, TYPE_INT)
|
||||
IOCTL(CDROMCLOSETRAY, 0, TYPE_NULL)
|
||||
IOCTL(CDROMRESET, 0, TYPE_NULL)
|
||||
IOCTL(CDROMPLAYMSF, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMPLAYTRKIND, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMREADTOCHDR, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMREADTOCENTRY, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMVOLCTRL, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMSUBCHNL, IOC_RW, MK_PTR(TYPE_INT))
|
||||
/* XXX: incorrect (need specific handling) */
|
||||
IOCTL(CDROMREADAUDIO, IOC_W, MK_PTR(MK_STRUCT(STRUCT_cdrom_read_audio)))
|
||||
IOCTL(CDROMREADCOOKED, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMREADRAW, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMREADMODE1, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMREADMODE2, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMREADALL, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMMULTISESSION, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROM_GET_UPC, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMVOLREAD, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMSEEK, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROMPLAYBLK, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(CDROM_MEDIA_CHANGED, 0, TYPE_NULL)
|
||||
IOCTL(CDROM_SET_OPTIONS, 0, TYPE_INT)
|
||||
IOCTL(CDROM_CLEAR_OPTIONS, 0, TYPE_INT)
|
||||
IOCTL(CDROM_SELECT_SPEED, 0, TYPE_INT)
|
||||
IOCTL(CDROM_SELECT_DISC, 0, TYPE_INT)
|
||||
IOCTL(CDROM_DRIVE_STATUS, 0, TYPE_NULL)
|
||||
IOCTL(CDROM_DISC_STATUS, 0, TYPE_NULL)
|
||||
IOCTL(CDROMAUDIOBUFSIZ, 0, TYPE_INT)
|
||||
|
||||
IOCTL(SNDCTL_COPR_HALT, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_COPR_LOAD, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_COPR_RCODE, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_COPR_RCVMSG, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_COPR_RDATA, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_COPR_RESET, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_COPR_RUN, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_COPR_SENDMSG, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_COPR_WCODE, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_COPR_WDATA, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_CHANNELS, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_GETBLKSIZE, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_GETCAPS, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_GETFMTS, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_GETIPTR, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_GETISPACE, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_GETOPTR, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_GETOSPACE, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_GETTRIGGER, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_MAPOUTBUF, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_NONBLOCK, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_DSP_POST, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_DSP_RESET, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_DSP_SETDUPLEX, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_DSP_SETFMT, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_SETFRAGMENT, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_SETSYNCRO, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_DSP_SETTRIGGER, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_SPEED, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_STEREO, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_SUBDIVIDE, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_DSP_SYNC, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_FM_4OP_ENABLE, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_FM_LOAD_INSTR, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_MIDI_INFO, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_MIDI_MPUCMD, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_MIDI_MPUMODE, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_MIDI_PRETIME, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SEQ_CTRLRATE, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SEQ_GETINCOUNT, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SEQ_GETOUTCOUNT, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SEQ_NRMIDIS, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SEQ_NRSYNTHS, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SEQ_OUTOFBAND, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SEQ_PANIC, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_SEQ_PERCMODE, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SEQ_RESET, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_SEQ_RESETSAMPLES, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SEQ_SYNC, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_SEQ_TESTMIDI, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SEQ_THRESHOLD, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SYNTH_INFO, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_SYNTH_MEMAVL, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_TMR_CONTINUE, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_TMR_METRONOME, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_TMR_SELECT, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_TMR_SOURCE, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_TMR_START, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_TMR_STOP, 0, TYPE_NULL)
|
||||
IOCTL(SNDCTL_TMR_TEMPO, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SNDCTL_TMR_TIMEBASE, IOC_RW, MK_PTR(TYPE_INT))
|
||||
|
||||
IOCTL(SOUND_PCM_WRITE_FILTER, IOC_W | IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_PCM_READ_RATE, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_PCM_READ_CHANNELS, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_PCM_READ_BITS, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_PCM_READ_FILTER, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_INFO, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_ACCESS, 0, TYPE_PTRVOID)
|
||||
IOCTL(SOUND_MIXER_PRIVATE1, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_PRIVATE2, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_PRIVATE3, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_PRIVATE4, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_PRIVATE5, IOC_RW, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_VOLUME, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_BASS, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_TREBLE, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_SYNTH, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_PCM, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_SPEAKER, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_LINE, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_MIC, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_CD, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_IMIX, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_ALTPCM, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_RECLEV, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_IGAIN, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_OGAIN, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_LINE1, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_LINE2, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_LINE3, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_MUTE, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_ENHANCE, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_LOUD, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_RECSRC, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_DEVMASK, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_RECMASK, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_STEREODEVS, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_READ_CAPS, IOC_R, MK_PTR(TYPE_INT))
|
||||
|
||||
IOCTL(SOUND_MIXER_WRITE_VOLUME, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_BASS, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_TREBLE, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_SYNTH, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_PCM, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_SPEAKER, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_LINE, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_MIC, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_CD, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_IMIX, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_ALTPCM, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_RECLEV, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_IGAIN, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_OGAIN, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_LINE1, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_LINE2, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_LINE3, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_MUTE, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_ENHANCE, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_LOUD, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SOUND_MIXER_WRITE_RECSRC, IOC_W, MK_PTR(TYPE_INT))
|
||||
|
||||
IOCTL(HDIO_GETGEO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_hd_geometry)))
|
||||
IOCTL(HDIO_GET_UNMASKINTR, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(HDIO_GET_MULTCOUNT, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(HDIO_GET_IDENTITY, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(HDIO_GET_KEEPSETTINGS, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(HDIO_GET_NOWERR, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(HDIO_GET_DMA, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(HDIO_GET_32BIT, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(HDIO_DRIVE_CMD, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(HDIO_SET_UNMASKINTR, 0, TYPE_INT)
|
||||
IOCTL(HDIO_SET_MULTCOUNT, 0, TYPE_INT)
|
||||
IOCTL(HDIO_SET_KEEPSETTINGS, 0, TYPE_INT)
|
||||
IOCTL(HDIO_SET_NOWERR, 0, TYPE_INT)
|
||||
IOCTL(HDIO_SET_DMA, 0, TYPE_INT)
|
||||
IOCTL(HDIO_SET_32BIT, 0, TYPE_INT)
|
||||
IOCTL(HDIO_SET_PIO_MODE, 0, TYPE_INT)
|
310
linux-user/main.c
Normal file
310
linux-user/main.c
Normal file
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* emu main
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <elf.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "gemu.h"
|
||||
|
||||
#include "i386/hsw_interp.h"
|
||||
|
||||
unsigned long x86_stack_size;
|
||||
unsigned long stktop;
|
||||
|
||||
void gemu_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* virtual x86 CPU stuff */
|
||||
|
||||
extern int invoke_code16(Interp_ENV *, int, int);
|
||||
extern int invoke_code32(Interp_ENV *, int);
|
||||
extern char *e_print_cpuemu_regs(ENVPARAMS, int is32);
|
||||
extern char *e_emu_disasm(ENVPARAMS, unsigned char *org, int is32);
|
||||
extern void init_npu(void);
|
||||
|
||||
Interp_ENV env_global;
|
||||
Interp_ENV *envp_global;
|
||||
|
||||
QWORD EMUtime = 0;
|
||||
|
||||
int CEmuStat = 0;
|
||||
|
||||
long instr_count;
|
||||
|
||||
/* who will initialize this? */
|
||||
unsigned long io_bitmap[IO_BITMAP_SIZE+1];
|
||||
|
||||
/* debug flag, 0=disable 1..9=level */
|
||||
int d_emu = 0;
|
||||
|
||||
unsigned long CRs[5] =
|
||||
{
|
||||
0x00000013, /* valid bits: 0xe005003f */
|
||||
0x00000000, /* invalid */
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
/*
|
||||
* DR0-3 = linear address of breakpoint 0-3
|
||||
* DR4=5 = reserved
|
||||
* DR6 b0-b3 = BP active
|
||||
* b13 = BD
|
||||
* b14 = BS
|
||||
* b15 = BT
|
||||
* DR7 b0-b1 = G:L bp#0
|
||||
* b2-b3 = G:L bp#1
|
||||
* b4-b5 = G:L bp#2
|
||||
* b6-b7 = G:L bp#3
|
||||
* b8-b9 = GE:LE
|
||||
* b13 = GD
|
||||
* b16-19= LLRW bp#0 LL=00(1),01(2),11(4)
|
||||
* b20-23= LLRW bp#1 RW=00(x),01(w),11(rw)
|
||||
* b24-27= LLRW bp#2
|
||||
* b28-31= LLRW bp#3
|
||||
*/
|
||||
unsigned long DRs[8] =
|
||||
{
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0xffff1ff0,
|
||||
0x00000400,
|
||||
0xffff1ff0,
|
||||
0x00000400
|
||||
};
|
||||
|
||||
unsigned long TRs[2] =
|
||||
{
|
||||
0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
void FatalAppExit(UINT wAction, LPCSTR lpText)
|
||||
{
|
||||
fprintf(stderr, "Fatal error '%s' in CPU\n", lpText);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int e_debug_check(unsigned char *PC)
|
||||
{
|
||||
register unsigned long d7 = DRs[7];
|
||||
|
||||
if (d7&0x03) {
|
||||
if (d7&0x30000) return 0; /* only execute(00) bkp */
|
||||
if ((long)PC==DRs[0]) {
|
||||
e_printf("DBRK: DR0 hit at %p\n",PC);
|
||||
DRs[6] |= 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (d7&0x0c) {
|
||||
if (d7&0x300000) return 0;
|
||||
if ((long)PC==DRs[1]) {
|
||||
e_printf("DBRK: DR1 hit at %p\n",PC);
|
||||
DRs[6] |= 2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (d7&0x30) {
|
||||
if (d7&0x3000000) return 0;
|
||||
if ((long)PC==DRs[2]) {
|
||||
e_printf("DBRK: DR2 hit at %p\n",PC);
|
||||
DRs[6] |= 4;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (d7&0xc0) {
|
||||
if (d7&0x30000000) return 0;
|
||||
if ((long)PC==DRs[3]) {
|
||||
e_printf("DBRK: DR3 hit at %p\n",PC);
|
||||
DRs[6] |= 8;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Debug stuff */
|
||||
void logstr(unsigned long mask, const char *fmt,...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* unconditional message into debug log and stderr */
|
||||
#undef error
|
||||
void error(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int PortIO(DWORD port, DWORD value, UINT size, BOOL is_write)
|
||||
{
|
||||
fprintf(stderr, "IO: %s port=0x%lx value=0x%lx size=%d",
|
||||
is_write ? "write" : "read", port, value, size);
|
||||
return value;
|
||||
}
|
||||
|
||||
void LogProcName(WORD wSel, WORD wOff, WORD wAction)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void INT_handler(int num, void *env)
|
||||
{
|
||||
fprintf(stderr, "EM86: int %d\n", num);
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
|
||||
/* XXX: currently we use LDT entries */
|
||||
#define __USER_CS (0x23|4)
|
||||
#define __USER_DS (0x2B|4)
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n"
|
||||
"usage: gemu program [arguments...]\n"
|
||||
"Linux x86 emulator\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *filename;
|
||||
struct pt_regs regs1, *regs = ®s1;
|
||||
struct image_info info1, *info = &info1;
|
||||
Interp_ENV *env;
|
||||
|
||||
if (argc <= 1)
|
||||
usage();
|
||||
|
||||
filename = argv[1];
|
||||
|
||||
/* Zero out regs */
|
||||
memset(regs, 0, sizeof(struct pt_regs));
|
||||
|
||||
/* Zero out image_info */
|
||||
memset(info, 0, sizeof(struct image_info));
|
||||
|
||||
if(elf_exec(filename, argv+1, __environ, regs, info) != 0) {
|
||||
printf("Error loading %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("start_brk 0x%08lx\n" , info->start_brk);
|
||||
printf("end_code 0x%08lx\n" , info->end_code);
|
||||
printf("start_code 0x%08lx\n" , info->start_code);
|
||||
printf("end_data 0x%08lx\n" , info->end_data);
|
||||
printf("start_stack 0x%08lx\n" , info->start_stack);
|
||||
printf("brk 0x%08lx\n" , info->brk);
|
||||
printf("esp 0x%08lx\n" , regs->esp);
|
||||
printf("eip 0x%08lx\n" , regs->eip);
|
||||
#endif
|
||||
|
||||
target_set_brk((char *)info->brk);
|
||||
syscall_init();
|
||||
|
||||
env = &env_global;
|
||||
envp_global = env;
|
||||
memset(env, 0, sizeof(Interp_ENV));
|
||||
|
||||
env->rax.e = regs->eax;
|
||||
env->rbx.e = regs->ebx;
|
||||
env->rcx.e = regs->ecx;
|
||||
env->rdx.e = regs->edx;
|
||||
env->rsi.esi = regs->esi;
|
||||
env->rdi.edi = regs->edi;
|
||||
env->rbp.ebp = regs->ebp;
|
||||
env->rsp.esp = regs->esp;
|
||||
env->cs.cs = __USER_CS;
|
||||
env->ds.ds = __USER_DS;
|
||||
env->es.es = __USER_DS;
|
||||
env->ss.ss = __USER_DS;
|
||||
env->fs.fs = __USER_DS;
|
||||
env->gs.gs = __USER_DS;
|
||||
env->trans_addr = regs->eip;
|
||||
|
||||
LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
|
||||
LDT[__USER_CS >> 3].dwSelLimit = 0xfffff;
|
||||
LDT[__USER_CS >> 3].lpSelBase = NULL;
|
||||
|
||||
LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
|
||||
LDT[__USER_DS >> 3].dwSelLimit = 0xfffff;
|
||||
LDT[__USER_DS >> 3].lpSelBase = NULL;
|
||||
init_npu();
|
||||
|
||||
for(;;) {
|
||||
int err;
|
||||
uint8_t *pc;
|
||||
|
||||
err = invoke_code32(env, -1);
|
||||
env->trans_addr = env->return_addr;
|
||||
pc = env->seg_regs[0] + env->trans_addr;
|
||||
switch(err) {
|
||||
case EXCP0D_GPF:
|
||||
if (pc[0] == 0xcd && pc[1] == 0x80) {
|
||||
/* syscall */
|
||||
env->trans_addr += 2;
|
||||
env->rax.e = do_syscall(env->rax.e,
|
||||
env->rbx.e,
|
||||
env->rcx.e,
|
||||
env->rdx.e,
|
||||
env->rsi.esi,
|
||||
env->rdi.edi,
|
||||
env->rbp.ebp);
|
||||
} else {
|
||||
goto trap_error;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
trap_error:
|
||||
fprintf(stderr, "GEMU: Unknown error %d, aborting\n", err);
|
||||
d_emu = 9;
|
||||
fprintf(stderr, "%s\n%s\n",
|
||||
e_print_cpuemu_regs(env, 1),
|
||||
e_emu_disasm(env,pc,1));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
57
linux-user/qemu.h
Normal file
57
linux-user/qemu.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
#ifndef GEMU_H
|
||||
#define GEMU_H
|
||||
|
||||
#include "thunk.h"
|
||||
|
||||
struct pt_regs {
|
||||
long ebx;
|
||||
long ecx;
|
||||
long edx;
|
||||
long esi;
|
||||
long edi;
|
||||
long ebp;
|
||||
long eax;
|
||||
int xds;
|
||||
int xes;
|
||||
long orig_eax;
|
||||
long eip;
|
||||
int xcs;
|
||||
long eflags;
|
||||
long esp;
|
||||
int xss;
|
||||
};
|
||||
|
||||
/* This struct is used to hold certain information about the image.
|
||||
* Basically, it replicates in user space what would be certain
|
||||
* task_struct fields in the kernel
|
||||
*/
|
||||
struct image_info {
|
||||
unsigned long start_code;
|
||||
unsigned long end_code;
|
||||
unsigned long end_data;
|
||||
unsigned long start_brk;
|
||||
unsigned long brk;
|
||||
unsigned long start_mmap;
|
||||
unsigned long mmap;
|
||||
unsigned long rss;
|
||||
unsigned long start_stack;
|
||||
unsigned long arg_start;
|
||||
unsigned long arg_end;
|
||||
unsigned long env_start;
|
||||
unsigned long env_end;
|
||||
unsigned long entry;
|
||||
int personality;
|
||||
};
|
||||
|
||||
int elf_exec(const char * filename, char ** argv, char ** envp,
|
||||
struct pt_regs * regs, struct image_info *infop);
|
||||
|
||||
void target_set_brk(char *new_brk);
|
||||
void syscall_init(void);
|
||||
long do_syscall(int num, long arg1, long arg2, long arg3,
|
||||
long arg4, long arg5, long arg6);
|
||||
void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
|
||||
|
||||
|
||||
|
||||
#endif
|
105
linux-user/signal.c
Normal file
105
linux-user/signal.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Emulation of Linux signal handling
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
/* Algorithm strongly inspired from em86 : we queue the signals so
|
||||
that we can handle them at precise points in the emulated code. */
|
||||
|
||||
struct emulated_sigaction {
|
||||
struct target_sigaction sa;
|
||||
int nb_pending;
|
||||
struct target_siginfo info;
|
||||
};
|
||||
|
||||
struct emulated_sigaction sigact_table[NSIG];
|
||||
int signal_pending;
|
||||
|
||||
static inline int host_to_target_signal(int sig)
|
||||
{
|
||||
return sig;
|
||||
}
|
||||
|
||||
static inline int target_to_host_signal(int sig)
|
||||
{
|
||||
return sig;
|
||||
}
|
||||
|
||||
void signal_init(void)
|
||||
{
|
||||
struct sigaction act;
|
||||
int i;
|
||||
|
||||
/* set all host signal handlers */
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
act.sa_sigaction = host_signal_handler;
|
||||
for(i = 1; i < NSIG; i++) {
|
||||
sigaction(i, &sa, NULL);
|
||||
}
|
||||
|
||||
memset(sigact_table, 0, sizeof(sigact_table));
|
||||
}
|
||||
|
||||
static void host_signal_handler(int host_signum, siginfo_t *info,
|
||||
void *puc)
|
||||
{
|
||||
struct ucontext *uc = puc;
|
||||
int signum;
|
||||
/* get target signal number */
|
||||
signum = host_to_target(host_signum);
|
||||
if (signum >= TARGET_NSIG)
|
||||
return;
|
||||
/* we save the old mask */
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void process_pending_signals(void)
|
||||
{
|
||||
int signum;
|
||||
target_ulong _sa_handler;
|
||||
|
||||
struct emulated_sigaction *esig;
|
||||
|
||||
if (!signal_pending)
|
||||
return;
|
||||
|
||||
esig = sigact_table;
|
||||
for(signum = 1; signum < TARGET_NSIG; signum++) {
|
||||
if (esig->nb_pending != 0)
|
||||
goto handle_signal;
|
||||
esig++;
|
||||
}
|
||||
/* if no signal is pending, just return */
|
||||
signal_pending = 0;
|
||||
return;
|
||||
handle_signal:
|
||||
_sa_handler = esig->sa._sa_handler;
|
||||
if (_sa_handler == TARGET_SIG_DFL) {
|
||||
/* default handling
|
||||
}
|
||||
|
||||
|
||||
}
|
1349
linux-user/syscall.c
Normal file
1349
linux-user/syscall.c
Normal file
File diff suppressed because it is too large
Load diff
283
linux-user/syscall_defs.h
Normal file
283
linux-user/syscall_defs.h
Normal file
|
@ -0,0 +1,283 @@
|
|||
|
||||
/* common syscall defines for all architectures */
|
||||
|
||||
#define SOCKOP_socket 1
|
||||
#define SOCKOP_bind 2
|
||||
#define SOCKOP_connect 3
|
||||
#define SOCKOP_listen 4
|
||||
#define SOCKOP_accept 5
|
||||
#define SOCKOP_getsockname 6
|
||||
#define SOCKOP_getpeername 7
|
||||
#define SOCKOP_socketpair 8
|
||||
#define SOCKOP_send 9
|
||||
#define SOCKOP_recv 10
|
||||
#define SOCKOP_sendto 11
|
||||
#define SOCKOP_recvfrom 12
|
||||
#define SOCKOP_shutdown 13
|
||||
#define SOCKOP_setsockopt 14
|
||||
#define SOCKOP_getsockopt 15
|
||||
#define SOCKOP_sendmsg 16
|
||||
#define SOCKOP_recvmsg 17
|
||||
|
||||
struct target_timeval {
|
||||
target_long tv_sec;
|
||||
target_long tv_usec;
|
||||
};
|
||||
|
||||
struct target_iovec {
|
||||
target_long iov_base; /* Starting address */
|
||||
target_long iov_len; /* Number of bytes */
|
||||
};
|
||||
|
||||
struct target_rusage {
|
||||
struct target_timeval ru_utime; /* user time used */
|
||||
struct target_timeval ru_stime; /* system time used */
|
||||
target_long ru_maxrss; /* maximum resident set size */
|
||||
target_long ru_ixrss; /* integral shared memory size */
|
||||
target_long ru_idrss; /* integral unshared data size */
|
||||
target_long ru_isrss; /* integral unshared stack size */
|
||||
target_long ru_minflt; /* page reclaims */
|
||||
target_long ru_majflt; /* page faults */
|
||||
target_long ru_nswap; /* swaps */
|
||||
target_long ru_inblock; /* block input operations */
|
||||
target_long ru_oublock; /* block output operations */
|
||||
target_long ru_msgsnd; /* messages sent */
|
||||
target_long ru_msgrcv; /* messages received */
|
||||
target_long ru_nsignals; /* signals received */
|
||||
target_long ru_nvcsw; /* voluntary context switches */
|
||||
target_long ru_nivcsw; /* involuntary " */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int val[2];
|
||||
} kernel_fsid_t;
|
||||
|
||||
struct statfs {
|
||||
int f_type;
|
||||
int f_bsize;
|
||||
int f_blocks;
|
||||
int f_bfree;
|
||||
int f_bavail;
|
||||
int f_files;
|
||||
int f_ffree;
|
||||
kernel_fsid_t f_fsid;
|
||||
int f_namelen;
|
||||
int f_spare[6];
|
||||
};
|
||||
|
||||
/* mostly generic signal stuff */
|
||||
#define TARGET_SIG_DFL ((target_long)0) /* default signal handling */
|
||||
#define TARGET_SIG_IGN ((target_long)1) /* ignore signal */
|
||||
#define TARGET_SIG_ERR ((target_long)-1) /* error return from signal */
|
||||
|
||||
#ifdef TARGET_MIPS
|
||||
#define TARGET_NSIG 128
|
||||
#else
|
||||
#define TARGET_NSIG 64
|
||||
#endif
|
||||
#define TARGET_NSIG_BPW TARGET_LONG_BITS
|
||||
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
|
||||
|
||||
typedef struct {
|
||||
target_ulong sig[TARGET_NSIG_WORDS];
|
||||
} target_sigset_t;
|
||||
|
||||
/* Networking ioctls */
|
||||
#define TARGET_SIOCADDRT 0x890B /* add routing table entry */
|
||||
#define TARGET_SIOCDELRT 0x890C /* delete routing table entry */
|
||||
#define TARGET_SIOCGIFNAME 0x8910 /* get iface name */
|
||||
#define TARGET_SIOCSIFLINK 0x8911 /* set iface channel */
|
||||
#define TARGET_SIOCGIFCONF 0x8912 /* get iface list */
|
||||
#define TARGET_SIOCGIFFLAGS 0x8913 /* get flags */
|
||||
#define TARGET_SIOCSIFFLAGS 0x8914 /* set flags */
|
||||
#define TARGET_SIOCGIFADDR 0x8915 /* get PA address */
|
||||
#define TARGET_SIOCSIFADDR 0x8916 /* set PA address */
|
||||
#define TARGET_SIOCGIFDSTADDR 0x8917 /* get remote PA address */
|
||||
#define TARGET_SIOCSIFDSTADDR 0x8918 /* set remote PA address */
|
||||
#define TARGET_SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */
|
||||
#define TARGET_SIOCSIFBRDADDR 0x891a /* set broadcast PA address */
|
||||
#define TARGET_SIOCGIFNETMASK 0x891b /* get network PA mask */
|
||||
#define TARGET_SIOCSIFNETMASK 0x891c /* set network PA mask */
|
||||
#define TARGET_SIOCGIFMETRIC 0x891d /* get metric */
|
||||
#define TARGET_SIOCSIFMETRIC 0x891e /* set metric */
|
||||
#define TARGET_SIOCGIFMEM 0x891f /* get memory address (BSD) */
|
||||
#define TARGET_SIOCSIFMEM 0x8920 /* set memory address (BSD) */
|
||||
#define TARGET_SIOCGIFMTU 0x8921 /* get MTU size */
|
||||
#define TARGET_SIOCSIFMTU 0x8922 /* set MTU size */
|
||||
#define TARGET_SIOCSIFHWADDR 0x8924 /* set hardware address (NI) */
|
||||
#define TARGET_SIOCGIFENCAP 0x8925 /* get/set slip encapsulation */
|
||||
#define TARGET_SIOCSIFENCAP 0x8926
|
||||
#define TARGET_SIOCGIFHWADDR 0x8927 /* Get hardware address */
|
||||
#define TARGET_SIOCGIFSLAVE 0x8929 /* Driver slaving support */
|
||||
#define TARGET_SIOCSIFSLAVE 0x8930
|
||||
#define TARGET_SIOCADDMULTI 0x8931 /* Multicast address lists */
|
||||
#define TARGET_SIOCDELMULTI 0x8932
|
||||
|
||||
/* Bridging control calls */
|
||||
#define TARGET_SIOCGIFBR 0x8940 /* Bridging support */
|
||||
#define TARGET_SIOCSIFBR 0x8941 /* Set bridging options */
|
||||
|
||||
#define TARGET_SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */
|
||||
#define TARGET_SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */
|
||||
|
||||
/* ARP cache control calls. */
|
||||
#define TARGET_OLD_SIOCDARP 0x8950 /* old delete ARP table entry */
|
||||
#define TARGET_OLD_SIOCGARP 0x8951 /* old get ARP table entry */
|
||||
#define TARGET_OLD_SIOCSARP 0x8952 /* old set ARP table entry */
|
||||
#define TARGET_SIOCDARP 0x8953 /* delete ARP table entry */
|
||||
#define TARGET_SIOCGARP 0x8954 /* get ARP table entry */
|
||||
#define TARGET_SIOCSARP 0x8955 /* set ARP table entry */
|
||||
|
||||
/* RARP cache control calls. */
|
||||
#define TARGET_SIOCDRARP 0x8960 /* delete RARP table entry */
|
||||
#define TARGET_SIOCGRARP 0x8961 /* get RARP table entry */
|
||||
#define TARGET_SIOCSRARP 0x8962 /* set RARP table entry */
|
||||
|
||||
/* Driver configuration calls */
|
||||
#define TARGET_SIOCGIFMAP 0x8970 /* Get device parameters */
|
||||
#define TARGET_SIOCSIFMAP 0x8971 /* Set device parameters */
|
||||
|
||||
/* DLCI configuration calls */
|
||||
#define TARGET_SIOCADDDLCI 0x8980 /* Create new DLCI device */
|
||||
#define TARGET_SIOCDELDLCI 0x8981 /* Delete DLCI device */
|
||||
|
||||
|
||||
/* From <linux/fs.h> */
|
||||
|
||||
#define TARGET_BLKROSET TARGET_IO(0x12,93) /* set device read-only (0 = read-write) */
|
||||
#define TARGET_BLKROGET TARGET_IO(0x12,94) /* get read-only status (0 = read_write) */
|
||||
#define TARGET_BLKRRPART TARGET_IO(0x12,95) /* re-read partition table */
|
||||
#define TARGET_BLKGETSIZE TARGET_IO(0x12,96) /* return device size /512 (long *arg) */
|
||||
#define TARGET_BLKFLSBUF TARGET_IO(0x12,97) /* flush buffer cache */
|
||||
#define TARGET_BLKRASET TARGET_IO(0x12,98) /* Set read ahead for block device */
|
||||
#define TARGET_BLKRAGET TARGET_IO(0x12,99) /* get current read ahead setting */
|
||||
#define TARGET_BLKFRASET TARGET_IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */
|
||||
#define TARGET_BLKFRAGET TARGET_IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */
|
||||
#define TARGET_BLKSECTSET TARGET_IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */
|
||||
#define TARGET_BLKSECTGET TARGET_IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
|
||||
#define TARGET_BLKSSZGET TARGET_IO(0x12,104)/* get block device sector size */
|
||||
/* A jump here: 108-111 have been used for various private purposes. */
|
||||
#define TARGET_BLKBSZGET TARGET_IOR(0x12,112,sizeof(int))
|
||||
#define TARGET_BLKBSZSET TARGET_IOW(0x12,113,sizeof(int))
|
||||
#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
|
||||
#define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */
|
||||
#define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */
|
||||
|
||||
/* cdrom commands */
|
||||
#define TARGET_CDROMPAUSE 0x5301 /* Pause Audio Operation */
|
||||
#define TARGET_CDROMRESUME 0x5302 /* Resume paused Audio Operation */
|
||||
#define TARGET_CDROMPLAYMSF 0x5303 /* Play Audio MSF (struct cdrom_msf) */
|
||||
#define TARGET_CDROMPLAYTRKIND 0x5304 /* Play Audio Track/index
|
||||
(struct cdrom_ti) */
|
||||
#define TARGET_CDROMREADTOCHDR 0x5305 /* Read TOC header
|
||||
(struct cdrom_tochdr) */
|
||||
#define TARGET_CDROMREADTOCENTRY 0x5306 /* Read TOC entry
|
||||
(struct cdrom_tocentry) */
|
||||
#define TARGET_CDROMSTOP 0x5307 /* Stop the cdrom drive */
|
||||
#define TARGET_CDROMSTART 0x5308 /* Start the cdrom drive */
|
||||
#define TARGET_CDROMEJECT 0x5309 /* Ejects the cdrom media */
|
||||
#define TARGET_CDROMVOLCTRL 0x530a /* Control output volume
|
||||
(struct cdrom_volctrl) */
|
||||
#define TARGET_CDROMSUBCHNL 0x530b /* Read subchannel data
|
||||
(struct cdrom_subchnl) */
|
||||
#define TARGET_CDROMREADMODE2 0x530c /* Read TARGET_CDROM mode 2 data (2336 Bytes)
|
||||
(struct cdrom_read) */
|
||||
#define TARGET_CDROMREADMODE1 0x530d /* Read TARGET_CDROM mode 1 data (2048 Bytes)
|
||||
(struct cdrom_read) */
|
||||
#define TARGET_CDROMREADAUDIO 0x530e /* (struct cdrom_read_audio) */
|
||||
#define TARGET_CDROMEJECT_SW 0x530f /* enable(1)/disable(0) auto-ejecting */
|
||||
#define TARGET_CDROMMULTISESSION 0x5310 /* Obtain the start-of-last-session
|
||||
address of multi session disks
|
||||
(struct cdrom_multisession) */
|
||||
#define TARGET_CDROM_GET_MCN 0x5311 /* Obtain the "Universal Product Code"
|
||||
if available (struct cdrom_mcn) */
|
||||
#define TARGET_CDROM_GET_UPC TARGET_CDROM_GET_MCN /* This one is depricated,
|
||||
but here anyway for compatability */
|
||||
#define TARGET_CDROMRESET 0x5312 /* hard-reset the drive */
|
||||
#define TARGET_CDROMVOLREAD 0x5313 /* Get the drive's volume setting
|
||||
(struct cdrom_volctrl) */
|
||||
#define TARGET_CDROMREADRAW 0x5314 /* read data in raw mode (2352 Bytes)
|
||||
(struct cdrom_read) */
|
||||
/*
|
||||
* These ioctls are used only used in aztcd.c and optcd.c
|
||||
*/
|
||||
#define TARGET_CDROMREADCOOKED 0x5315 /* read data in cooked mode */
|
||||
#define TARGET_CDROMSEEK 0x5316 /* seek msf address */
|
||||
|
||||
/*
|
||||
* This ioctl is only used by the scsi-cd driver.
|
||||
It is for playing audio in logical block addressing mode.
|
||||
*/
|
||||
#define TARGET_CDROMPLAYBLK 0x5317 /* (struct cdrom_blk) */
|
||||
|
||||
/*
|
||||
* These ioctls are only used in optcd.c
|
||||
*/
|
||||
#define TARGET_CDROMREADALL 0x5318 /* read all 2646 bytes */
|
||||
|
||||
/*
|
||||
* These ioctls are (now) only in ide-cd.c for controlling
|
||||
* drive spindown time. They should be implemented in the
|
||||
* Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10,
|
||||
* GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE...
|
||||
* -Erik
|
||||
*/
|
||||
#define TARGET_CDROMGETSPINDOWN 0x531d
|
||||
#define TARGET_CDROMSETSPINDOWN 0x531e
|
||||
|
||||
/*
|
||||
* These ioctls are implemented through the uniform CD-ROM driver
|
||||
* They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM
|
||||
* drivers are eventually ported to the uniform CD-ROM driver interface.
|
||||
*/
|
||||
#define TARGET_CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */
|
||||
#define TARGET_CDROM_SET_OPTIONS 0x5320 /* Set behavior options */
|
||||
#define TARGET_CDROM_CLEAR_OPTIONS 0x5321 /* Clear behavior options */
|
||||
#define TARGET_CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */
|
||||
#define TARGET_CDROM_SELECT_DISC 0x5323 /* Select disc (for juke-boxes) */
|
||||
#define TARGET_CDROM_MEDIA_CHANGED 0x5325 /* Check is media changed */
|
||||
#define TARGET_CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
|
||||
#define TARGET_CDROM_DISC_STATUS 0x5327 /* Get disc type, etc. */
|
||||
#define TARGET_CDROM_CHANGER_NSLOTS 0x5328 /* Get number of slots */
|
||||
#define TARGET_CDROM_LOCKDOOR 0x5329 /* lock or unlock door */
|
||||
#define TARGET_CDROM_DEBUG 0x5330 /* Turn debug messages on/off */
|
||||
#define TARGET_CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
|
||||
|
||||
/* Note that scsi/scsi_ioctl.h also uses 0x5382 - 0x5386.
|
||||
* Future CDROM ioctls should be kept below 0x537F
|
||||
*/
|
||||
|
||||
/* This ioctl is only used by sbpcd at the moment */
|
||||
#define TARGET_CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */
|
||||
/* conflict with SCSI_IOCTL_GET_IDLUN */
|
||||
|
||||
/* DVD-ROM Specific ioctls */
|
||||
#define TARGET_DVD_READ_STRUCT 0x5390 /* Read structure */
|
||||
#define TARGET_DVD_WRITE_STRUCT 0x5391 /* Write structure */
|
||||
#define TARGET_DVD_AUTH 0x5392 /* Authentication */
|
||||
|
||||
#define TARGET_CDROM_SEND_PACKET 0x5393 /* send a packet to the drive */
|
||||
#define TARGET_CDROM_NEXT_WRITABLE 0x5394 /* get next writable block */
|
||||
#define TARGET_CDROM_LAST_WRITTEN 0x5395 /* get last block written on disc */
|
||||
|
||||
/* HD commands */
|
||||
|
||||
/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */
|
||||
#define TARGET_HDIO_GETGEO 0x0301 /* get device geometry */
|
||||
#define TARGET_HDIO_GET_UNMASKINTR 0x0302 /* get current unmask setting */
|
||||
#define TARGET_HDIO_GET_MULTCOUNT 0x0304 /* get current IDE blockmode setting */
|
||||
#define TARGET_HDIO_GET_IDENTITY 0x0307 /* get IDE identification info */
|
||||
#define TARGET_HDIO_GET_KEEPSETTINGS 0x0308 /* get keep-settings-on-reset flag */
|
||||
#define TARGET_HDIO_GET_32BIT 0x0309 /* get current io_32bit setting */
|
||||
#define TARGET_HDIO_GET_NOWERR 0x030a /* get ignore-write-error flag */
|
||||
#define TARGET_HDIO_GET_DMA 0x030b /* get use-dma flag */
|
||||
#define TARGET_HDIO_DRIVE_CMD 0x031f /* execute a special drive command */
|
||||
|
||||
/* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */
|
||||
#define TARGET_HDIO_SET_MULTCOUNT 0x0321 /* change IDE blockmode */
|
||||
#define TARGET_HDIO_SET_UNMASKINTR 0x0322 /* permit other irqs during I/O */
|
||||
#define TARGET_HDIO_SET_KEEPSETTINGS 0x0323 /* keep ioctl settings on reset */
|
||||
#define TARGET_HDIO_SET_32BIT 0x0324 /* change io_32bit flags */
|
||||
#define TARGET_HDIO_SET_NOWERR 0x0325 /* change ignore-write-error flag */
|
||||
#define TARGET_HDIO_SET_DMA 0x0326 /* change use-dma flag */
|
||||
#define TARGET_HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */
|
64
linux-user/syscall_types.h
Normal file
64
linux-user/syscall_types.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
STRUCT_SPECIAL(termios)
|
||||
|
||||
STRUCT(winsize,
|
||||
TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
|
||||
|
||||
STRUCT(serial_multiport_struct,
|
||||
TYPE_INT, TYPE_INT, TYPE_CHAR, TYPE_CHAR, TYPE_INT, TYPE_CHAR, TYPE_CHAR,
|
||||
TYPE_INT, TYPE_CHAR, TYPE_CHAR, TYPE_INT, TYPE_CHAR, TYPE_CHAR, TYPE_INT,
|
||||
MK_ARRAY(TYPE_INT, 32))
|
||||
|
||||
STRUCT(serial_icounter_struct,
|
||||
TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_INT, 16))
|
||||
|
||||
STRUCT(sockaddr,
|
||||
TYPE_SHORT, MK_ARRAY(TYPE_CHAR, 14))
|
||||
|
||||
STRUCT(rtentry,
|
||||
TYPE_ULONG, MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr),
|
||||
TYPE_SHORT, TYPE_SHORT, TYPE_ULONG, TYPE_PTRVOID, TYPE_SHORT, TYPE_PTRVOID,
|
||||
TYPE_ULONG, TYPE_ULONG, TYPE_SHORT)
|
||||
|
||||
STRUCT(ifmap,
|
||||
TYPE_ULONG, TYPE_ULONG, TYPE_SHORT, TYPE_CHAR, TYPE_CHAR, TYPE_CHAR,
|
||||
/* Spare 3 bytes */
|
||||
TYPE_CHAR, TYPE_CHAR, TYPE_CHAR)
|
||||
|
||||
/* The *_ifreq_list arrays deal with the fact that struct ifreq has unions */
|
||||
|
||||
STRUCT(sockaddr_ifreq,
|
||||
MK_ARRAY(TYPE_CHAR, IFNAMSIZ), MK_STRUCT(STRUCT_sockaddr))
|
||||
|
||||
STRUCT(short_ifreq,
|
||||
MK_ARRAY(TYPE_CHAR, IFNAMSIZ), TYPE_SHORT)
|
||||
|
||||
STRUCT(int_ifreq,
|
||||
MK_ARRAY(TYPE_CHAR, IFNAMSIZ), TYPE_INT)
|
||||
|
||||
STRUCT(ifmap_ifreq,
|
||||
MK_ARRAY(TYPE_CHAR, IFNAMSIZ), MK_STRUCT(STRUCT_ifmap))
|
||||
|
||||
STRUCT(char_ifreq,
|
||||
MK_ARRAY(TYPE_CHAR, IFNAMSIZ),
|
||||
MK_ARRAY(TYPE_CHAR, IFNAMSIZ))
|
||||
|
||||
STRUCT(ptr_ifreq,
|
||||
MK_ARRAY(TYPE_CHAR, IFNAMSIZ), TYPE_PTRVOID)
|
||||
|
||||
STRUCT(ifconf,
|
||||
TYPE_INT, TYPE_PTRVOID)
|
||||
|
||||
STRUCT(arpreq,
|
||||
MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), TYPE_INT, MK_STRUCT(STRUCT_sockaddr),
|
||||
MK_ARRAY(TYPE_CHAR, 16))
|
||||
|
||||
STRUCT(arpreq_old,
|
||||
MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), TYPE_INT, MK_STRUCT(STRUCT_sockaddr))
|
||||
|
||||
STRUCT(cdrom_read_audio,
|
||||
TYPE_CHAR, TYPE_CHAR, TYPE_CHAR, TYPE_CHAR, TYPE_CHAR, TYPE_INT, TYPE_PTRVOID,
|
||||
TYPE_NULL)
|
||||
|
||||
STRUCT(hd_geometry,
|
||||
TYPE_CHAR, TYPE_CHAR, TYPE_SHORT, TYPE_ULONG)
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue