Skip to content

Instantly share code, notes, and snippets.

@BlockoS
Created December 9, 2009 20:57
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BlockoS/252808 to your computer and use it in GitHub Desktop.
Save BlockoS/252808 to your computer and use it in GitHub Desktop.
Smallest possible raw X11 init
//// TODO :: 3. Clean up
//// 4. Events
//// 5. Create a colormap
//// 6. glx ?
#ifdef DEBUG
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/un.h>
#include <sys/select.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <linux/net.h>
#include <errno.h>
#include <stdio.h>
#endif // DEBUG
#include <stdint.h>
#include <asm/unistd.h>
static int fd;
#ifdef DEBUG
static struct sockaddr_un addr =
#else
struct
{
uint16_t sun_family;
char sun_path[32];
} addr =
#endif
{
1, // AF_UNIX,
"/tmp/.X11-unix/X0"
};
struct
{
uint8_t byte_order;
uint8_t pad0;
uint16_t protocol_major_version;
uint16_t protocol_minor_version;
uint16_t authorization_protocol_name_len;
uint16_t authorization_protocol_data_len;
uint8_t pad1[2];
} setup_request =
{
0x6c, /* LSB */
0,
11, /* protocol major version */
0, /* protocol minor version */
0, 0,
{ 0, 0 }
};
static union
{
uint8_t buffer[4096];
struct
{
uint8_t status;
uint8_t pad0[5];
uint16_t length;
} generic_setup_response;
struct
{
uint8_t success;
uint8_t pad0;
uint16_t protocol_major_version;
uint16_t protocol_minor_version;
uint16_t length;
uint32_t release_number;
uint32_t resource_id_base;
uint32_t resource_id_mask;
uint32_t motion_buffer_size;
uint16_t vendor_len;
uint16_t maximum_request_length;
uint8_t roots_len;
uint8_t pixmap_formats_len;
uint8_t image_byte_order;
uint8_t bitmap_format_bit_order;
uint8_t bitmap_format_scanline_unit;
uint8_t bitmap_format_scanline_pad;
uint8_t min_keycode;
uint8_t max_keycode;
uint8_t pad1[4];
} setup_response;
} response;
struct pixmap_format_t
{
uint8_t depth;
uint8_t bits_per_pixel;
uint8_t scan_line_pad;
uint8_t pad0;
uint32_t pad2;
};
struct depth_t
{
uint8_t depth;
uint8_t pad1;
uint16_t visual_count;
uint32_t pad;
};
struct visual_type_t
{
uint32_t visual_id;
uint8_t _class;
uint8_t bits_per_rgb;
uint16_t colormap_entries;
uint32_t red_mask;
uint32_t green_mask;
uint32_t blue_mask;
uint32_t pad0;
};
struct screen_t
{
uint32_t root;
uint32_t default_colormap;
uint32_t white_pixel;
uint32_t black_pixel;
uint32_t current_input_masks;
uint16_t width_in_pixels;
uint16_t height_in_pixels;
uint16_t width_in_millimeters;
uint16_t height_in_millimeters;
uint16_t min_installed_maps;
uint16_t max_installed_maps;
uint32_t root_visual_id;
uint8_t backing_stores;
uint8_t save_unders;
uint8_t root_depth;
uint8_t allowed_depths_len;
};
#define CREATE_WINDOW_REQ 1
#define DESTROY_WINDOW_REQ 4
#define MAP_WINDOW_REQ 8
struct general_request_t
{
uint8_t request_type;
uint8_t pad0;
uint16_t length;
uint32_t id;
};
struct window_request_t
{
uint8_t request_type;
uint8_t depth;
uint16_t length;
uint32_t window_id;
uint32_t parent_id;
int16_t x;
int16_t y;
uint16_t width;
uint16_t height;
uint16_t border_width;
uint16_t _class;
uint32_t visual_id;
uint32_t value_mask;
};
struct error_t
{
uint8_t type;
uint8_t error_code;
uint16_t sequence_number;
uint32_t resource_id;
uint16_t minor_code;
uint8_t major_code;
uint8_t pad1;
uint32_t pad3;
uint32_t pad4;
uint32_t pad5;
uint32_t pad6;
uint32_t pad7;
};
unsigned long arg[] =
{
1, // AF_UNIX
1, // SOCK_STREAM,
0
};
#ifdef DEBUG
int main()
#else
int _start()
#endif // DEBUG
{
int ret;
__asm__ __volatile__
(
"movl $102,%%eax \n\t" // SYS_socketcall
"movl $1,%%ebx \n\t" // SYS_SOCKET
"int $0x80"
: "=a"(fd) : "c"(arg)
);
arg[0] = fd;
arg[1] = (unsigned long int)&addr;
arg[2] = 20 + sizeof(addr.sun_family);
__asm__ __volatile__
(
"movl $102,%%eax \n\t" // SYS_socketcall
"movl $3,%%ebx \n\t" // SYS_CONNECT
"int $0x80"
: "=a"(ret) : "c"(arg)
);
__asm__ __volatile__
(
"movl $55, %%eax \n\t" // SYS_fcntl
"movl $0x02, %%ecx \n\t" // F_SETFD
"movl $0x01, %%edx \n\t" // FD_CLOEXEC
"int $0x80"
: : "b"(fd)
);
// Set setup request
__asm__ __volatile__
(
"movl $4, %%eax \n\t" // SYS_write
"movl $%c[count], %%edx \n\t" // count
"int $0x80"
: "=a"(ret) : "b"(fd), "c"(&setup_request), [count] "i"(sizeof(setup_request))
);
// Read first part of the setup response
__asm__ __volatile__
(
"movl $3, %%eax \n\t" // SYS_read
"movl $%c[count], %%edx \n\t" // count
"int $0x80"
: "=a"(ret) : "b"(fd), "c"(response.buffer), [count] "i"(sizeof(response.generic_setup_response))
);
if( response.generic_setup_response.status != 1 )
{
goto end;
}
// Read the rest of the setup response
__asm__ __volatile__
(
"movl $3, %%eax \n\t" // SYS_read
"int $0x80"
: "=a"(ret) : "b"(fd), "c"(response.buffer+sizeof(response.generic_setup_response)), "d"(response.generic_setup_response.length*4)
);
struct screen_t *scr = (struct screen_t*)(response.buffer + sizeof( response.setup_response ) + response.setup_response.vendor_len + response.setup_response.pixmap_formats_len * sizeof(struct pixmap_format_t));
int shift = 0;
int mask = response.setup_response.resource_id_mask;
while(!(mask & 1))
{
++shift;
mask >>= 1;
}
// Send window request
struct window_request_t *win_req = (struct window_request_t*)(response.buffer + sizeof(response.generic_setup_response) + response.generic_setup_response.length*4);
win_req->request_type = CREATE_WINDOW_REQ;
win_req->depth = scr->root_depth;
win_req->window_id = response.setup_response.resource_id_base+(1<<shift);
win_req->parent_id = scr->root;
win_req->x = 0;
win_req->y = 0;
win_req->width = 320;
win_req->height = 240;
win_req->border_width = 0;
win_req->_class = 1; // InputOutput
win_req->visual_id = 0; // CopyFromParent
win_req->value_mask = 0; // None atm
win_req->length = sizeof(struct window_request_t) >> 2;
__asm__ __volatile__
(
"movl $4, %%eax \n\t" // SYS_write
"movl $%c[count], %%edx \n\t" // count
"int $0x80"
: "=a"(ret) : "b"(fd), "c"(win_req), [count] "i"(sizeof(struct window_request_t))
);
// Map window
struct general_request_t map_window_req;
map_window_req.request_type = MAP_WINDOW_REQ;
map_window_req.pad0 = 0;
map_window_req.length = sizeof(struct general_request_t)>>2;
map_window_req.id = win_req->window_id;
__asm__ __volatile__
(
"movl $4, %%eax \n\t" // SYS_write
"movl $%c[count], %%edx \n\t" // count
"int $0x80"
: "=a"(ret) : "b"(fd), "c"(&map_window_req), [count] "i"(sizeof(struct general_request_t ))
);
#ifdef DEBUG
// Sleep
sleep(5);
#endif // DEBUG
// Destroy window
struct general_request_t destroy_window_req;
destroy_window_req.request_type = DESTROY_WINDOW_REQ;
destroy_window_req.pad0 = 0;
destroy_window_req.length = sizeof(struct general_request_t)>>2;
map_window_req.id = win_req->window_id;
__asm__ __volatile__
(
"movl $4, %%eax \n\t" // SYS_write
"movl $%c[count], %%edx \n\t" // count
"int $0x80"
: "=a"(ret) : "b"(fd), "c"(&destroy_window_req), [count] "i"(sizeof(struct general_request_t ))
);
end:
//close(fd);
//syscall( SYS_close, fd );
__asm__ __volatile__
(
"movl $6, %%eax \n\t" // SYS_close
"int $0x80"
: : "b"(fd)
);
#ifdef DEBUG
return 0;
#else
__asm__ __volatile__
(
"movl $1, %eax \n\t" // SYS_exit
"xorl %ebx, %ebx \n\t"
"int $0x80"
);
#endif // DEBUG
}
//// TODO :: 1. Errors
//// 2. Destroy window
//// 3. Clean up
//// 4. Events
//// 5. Create a colormap
//// 6. glx ?
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/un.h>
#include <sys/select.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <linux/net.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <asm/unistd.h>
static int fd;
static struct sockaddr_un addr =
{
1, // AF_UNIX,
"/tmp/.X11-unix/X0"
};
struct
{
uint8_t byte_order;
uint8_t pad0;
uint16_t protocol_major_version;
uint16_t protocol_minor_version;
uint16_t authorization_protocol_name_len;
uint16_t authorization_protocol_data_len;
uint8_t pad1[2];
} setup_request =
{
0x6c, /* LSB */
0,
11, /* protocol major version */
0, /* protocol minor version */
0, 0,
{ 0, 0 }
};
static union
{
uint8_t buffer[4096];
struct
{
uint8_t status;
uint8_t pad0[5];
uint16_t length;
} generic_setup_response;
struct
{
uint8_t success;
uint8_t pad0;
uint16_t protocol_major_version;
uint16_t protocol_minor_version;
uint16_t length;
uint32_t release_number;
uint32_t resource_id_base;
uint32_t resource_id_mask;
uint32_t motion_buffer_size;
uint16_t vendor_len;
uint16_t maximum_request_length;
uint8_t roots_len;
uint8_t pixmap_formats_len;
uint8_t image_byte_order;
uint8_t bitmap_format_bit_order;
uint8_t bitmap_format_scanline_unit;
uint8_t bitmap_format_scanline_pad;
uint8_t min_keycode;
uint8_t max_keycode;
uint8_t pad1[4];
} setup_response;
} response;
struct setup_failed_t
{
uint8_t status;
uint8_t reason_length;
uint16_t protocol_major_version;
uint16_t protocol_minor_version;
uint16_t length;
};
struct setup_authenticate_t
{
uint8_t status;
uint8_t pad[5];
uint16_t length;
};
struct pixmap_format_t
{
uint8_t depth;
uint8_t bits_per_pixel;
uint8_t scan_line_pad;
uint8_t pad0;
uint32_t pad2;
};
struct depth_t
{
uint8_t depth;
uint8_t pad1;
uint16_t visual_count;
uint32_t pad;
};
struct visual_type_t
{
uint32_t visual_id;
uint8_t _class;
uint8_t bits_per_rgb;
uint16_t colormap_entries;
uint32_t red_mask;
uint32_t green_mask;
uint32_t blue_mask;
uint32_t pad0;
};
struct screen_t
{
uint32_t root;
uint32_t default_colormap;
uint32_t white_pixel;
uint32_t black_pixel;
uint32_t current_input_masks;
uint16_t width_in_pixels;
uint16_t height_in_pixels;
uint16_t width_in_millimeters;
uint16_t height_in_millimeters;
uint16_t min_installed_maps;
uint16_t max_installed_maps;
uint32_t root_visual_id;
uint8_t backing_stores;
uint8_t save_unders;
uint8_t root_depth;
uint8_t allowed_depths_len;
};
#define CREATE_WINDOW_REQ 1
#define DESTROY_WINDOW_REQ 4
#define MAP_WINDOW_REQ 8
struct general_request_t
{
uint8_t request_type;
uint8_t pad0;
uint16_t length;
uint32_t id;
};
struct window_request_t
{
uint8_t request_type;
uint8_t depth;
uint16_t length;
uint32_t window_id;
uint32_t parent_id;
int16_t x;
int16_t y;
uint16_t width;
uint16_t height;
uint16_t border_width;
uint16_t _class;
uint32_t visual_id;
uint32_t value_mask;
};
struct error_t
{
uint8_t type;
uint8_t error_code;
uint16_t sequence_number;
uint32_t resource_id;
uint16_t minor_code;
uint8_t major_code;
uint8_t pad1;
uint32_t pad3;
uint32_t pad4;
uint32_t pad5;
uint32_t pad6;
uint32_t pad7;
};
#define KeyPressMask 1
#define CWEventMask (1L<<11)
#define CWColormap (1L<<13)
unsigned long arg[] =
{
1, // AF_UNIX
1, // SOCK_STREAM,
0
};
void display_infos()
{
// version number
printf( "version number:\t%d.%d\n",
response.setup_response.protocol_major_version,
response.setup_response.protocol_minor_version );
// vendor string
uint8_t *ptr = response.buffer + sizeof( response.setup_response );
int i, j, k;
printf( "vendor string:\t" );
fflush(stdout);
write( 1, ptr, response.setup_response.vendor_len );
printf( "\n" );
ptr += response.setup_response.vendor_len;
// version release number
printf( "version release number:\t%d\n",
response.setup_response.release_number );
// pixmap format
struct pixmap_format_t *pfmt = (struct pixmap_format_t*)(ptr);
printf("supported pixmap formats\n");
for(i=0; i<response.setup_response.pixmap_formats_len; ++i, ++pfmt)
{
printf( "\tdepth %d, "
"\tbits_per_pixel %d, "
"\tscan_line_pad %d\n",
pfmt->depth,
pfmt->bits_per_pixel,
pfmt->scan_line_pad );
}
ptr += response.setup_response.pixmap_formats_len * sizeof(struct pixmap_format_t);
// screens
printf( "number of screens:\t%d\n",
response.setup_response.roots_len );
struct screen_t *scr = (struct screen_t*)(ptr);
printf( "screen #0\n"
"dimensions:\t%dx%d pixels (%dx%d millimeters)\n"
"root window id:\t0x%x\n"
"number of colormaps:\tminimum %d, maximum %d\n"
"default colormap:\t0x%x\n"
"preallocated pixels:\tblack %d, white %d\n"
"default visual id:\t0x%x\n"
"depth:\t%d\n",
scr->width_in_pixels, scr->height_in_pixels,
scr->width_in_millimeters, scr->height_in_millimeters,
scr->root,
scr->min_installed_maps, scr->max_installed_maps,
scr->default_colormap,
scr->black_pixel, scr->white_pixel,
scr->root_visual_id,
scr->root_depth );
ptr += sizeof(struct screen_t);
for(j=0; j<scr->allowed_depths_len; ++j)
{
struct depth_t *dp = (struct depth_t*)(ptr);
ptr += sizeof(struct depth_t);
printf( "\tdepth:\t%d\n"
"\tvisual count:\t%d\n",
dp->depth,
dp->visual_count );
for(k=0; k<dp->visual_count; ++k)
{
struct visual_type_t* vis = (struct visual_type_t*)(ptr);
ptr += sizeof(struct visual_type_t);
printf( "\t\tvisual id:\t0x%x\n"
"\t\tclass:\t%d\n"
"\t\tdepth:\t%d planes\n"
"\t\tavailable colormap entries:\t%d per subfield\n"
"\t\tred, green, blue masks:\t0x%x, 0x%x, 0x%x\n"
"\t\tsignificant bits in color specification:\t%d bits\n\n",
vis->visual_id,
vis->_class,
scr->root_depth,
vis->colormap_entries,
vis->red_mask, vis->green_mask, vis->blue_mask,
vis->bits_per_rgb );
}
}
}
int main()
{
int ret;
// fd = socket( addr.sun_family, SOCK_STREAM, 0 );
fd = syscall( SYS_socketcall, SYS_SOCKET, arg );
if( fd == -1 )
{
perror( "Cannot create socket" );
return 1;
}
arg[0] = fd;
arg[1] = (unsigned long int)&addr;
arg[2] = 20 + sizeof(addr.sun_family);
// ret = connect( fd, (struct sockaddr*)&addr, 20 + sizeof(addr.sun_family) );
ret = syscall( SYS_socketcall, SYS_CONNECT, arg );
if( ret < 0 )
{
perror( "Cannot connect to address" );
close( fd );
return 1;
}
//fcntl( fd, F_SETFD, FD_CLOEXEC);
ret = syscall( SYS_fcntl, fd, F_SETFD, FD_CLOEXEC );
//write( fd, &setup_request, sizeof(setup_request) );
ret = syscall( SYS_write, fd, &setup_request, sizeof(setup_request) );
if( ret < 0 )
{
perror( "Cannot write" );
close( fd );
return 1;
}
//ret = read( fd, &setup_response, sizeof( setup_response ) );
ret = syscall( SYS_read, fd, &response.generic_setup_response, sizeof( response.generic_setup_response ) );
if( ret != sizeof( response.generic_setup_response ) )
{
perror( "Cannot read generic setup response" );
close( fd );
return 1;
}
if( response.generic_setup_response.status != 1 )
{
switch( response.generic_setup_response.status )
{
case 0:
write(STDERR_FILENO, response.buffer+sizeof(struct setup_failed_t), ((struct setup_failed_t*)(response.buffer))->reason_length);
break;
case 2:
write(STDERR_FILENO, response.buffer+sizeof(struct setup_authenticate_t), ((struct setup_authenticate_t*)(response.buffer))->length*4);
break;
default:
break;
};
fprintf( stderr, "\n" );
goto end;
}
// Read the rest of the setup response
ret = syscall( SYS_read, fd, response.buffer+sizeof(response.generic_setup_response), response.generic_setup_response.length*4 );
if( ret != (response.generic_setup_response.length * 4) )
{
perror( "Cannot read the rest of the setup response" );
close(fd);
return 1;
}
display_infos();
struct screen_t *scr = (struct screen_t*)(response.buffer + sizeof( response.setup_response ) + response.setup_response.vendor_len + response.setup_response.pixmap_formats_len * sizeof(struct pixmap_format_t));
int shift = 0;
int mask = response.setup_response.resource_id_mask;
while(!(mask & 1))
{
++shift;
mask >>= 1;
}
struct window_request_t *win_req = (struct window_request_t*)(response.buffer + sizeof(response.generic_setup_response) + response.generic_setup_response.length*4);
win_req->request_type = CREATE_WINDOW_REQ;
win_req->depth = scr->root_depth;
win_req->window_id = response.setup_response.resource_id_base+(1<<shift);
win_req->parent_id = scr->root;
win_req->x = 0;
win_req->y = 0;
win_req->width = 320;
win_req->height = 240;
win_req->border_width = 0;
win_req->_class = 1; // InputOutput
win_req->visual_id = 0; // CopyFromParent
win_req->value_mask = CWEventMask;
win_req->length = (sizeof(struct window_request_t) >> 2) + 1;
uint32_t *value_ptr = (uint32_t*)( ((uint8_t*)win_req) + sizeof( struct window_request_t ) );
value_ptr[0] = KeyPressMask;
ret = write( fd, win_req, sizeof(struct window_request_t) + sizeof(uint32_t));
if( ret != (sizeof( struct window_request_t ) + sizeof(uint32_t)))
{
perror( "Window request failed!" );
goto end;
}
fd_set rfd;
struct timeval timeout = { 0, 10 };
do
{
FD_ZERO( &rfd );
FD_SET( fd, &rfd );
ret = select( fd+1, &rfd, 0, 0, &timeout );
} while( timeout.tv_sec || timeout.tv_usec );
printf( "%d %ld %ld\n", ret, timeout.tv_sec, timeout.tv_usec );
/*
uint8_t dummy[256];
ret = read(fd, dummy, 256);
struct error_t* err = (struct error_t*)(dummy);
printf( "type %d\n"
"code %d\n"
"seq num %d\n"
"resource id 0x%x\n"
"code %d %d\n"
"\nwindow id 0x%x\n"
"root id 0x%x\n",
err->type,
err->error_code,
err->sequence_number,
err->resource_id,
err->minor_code,
err->major_code,
win_req->window_id,
scr->root );
FILE* out=fopen("rep.bin", "wb");
fwrite(dummy, 1, ret, out);
fclose(out);
*/
// Map window
struct general_request_t map_window_req;
map_window_req.request_type = MAP_WINDOW_REQ;
map_window_req.pad0 = 0;
map_window_req.length = sizeof(struct general_request_t)>>2;
map_window_req.id = win_req->window_id;
ret = write( fd, &map_window_req, sizeof(map_window_req) );
if( ret != sizeof(map_window_req) )
{
perror( "Cannot send MapWindow request!" );
}
sleep(5);
// Destroy window
struct general_request_t destroy_window_req;
destroy_window_req.request_type = DESTROY_WINDOW_REQ;
destroy_window_req.pad0 = 0;
destroy_window_req.length = sizeof(struct general_request_t)>>2;
map_window_req.id = win_req->window_id;
ret = write( fd, &map_window_req, sizeof(map_window_req) );
if( ret != sizeof(map_window_req) )
{
perror( "Cannot send DestroyWindow request!" );
}
end:
//close(fd);
syscall( SYS_close, fd );
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment