176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef LIBRM_H
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LIBRM_H
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
476d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER );
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Segment selectors as used in our protected-mode GDTs.
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Don't change these unless you really know what you're doing.
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define VIRTUAL_CS 0x08
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define VIRTUAL_DS 0x10
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PHYSICAL_CS 0x18
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PHYSICAL_DS 0x20
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define REAL_CS 0x28
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define REAL_DS 0x30
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LONG_CS 0x38
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LONG_DS 0x40
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef ASSEMBLY
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef UACCESS_LIBRM
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define UACCESS_PREFIX_librm
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define UACCESS_PREFIX_librm __librm_
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Variables in librm.S */
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern unsigned long virt_offset;
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Convert physical address to user pointer
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v phys_addr		Physical address
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret userptr		User pointer
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline userptr_t
4076d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanUACCESS_INLINE ( librm, phys_to_user ) ( unsigned long phys_addr ) {
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ( phys_addr - virt_offset );
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Convert user buffer to physical address
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v userptr		User pointer
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v offset		Offset from user pointer
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret phys_addr	Physical address
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline unsigned long
5276d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanUACCESS_INLINE ( librm, user_to_phys ) ( userptr_t userptr, off_t offset ) {
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ( userptr + offset + virt_offset );
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline userptr_t
5776d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanUACCESS_INLINE ( librm, virt_to_user ) ( volatile const void *addr ) {
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return trivial_virt_to_user ( addr );
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline void *
6276d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanUACCESS_INLINE ( librm, user_to_virt ) ( userptr_t userptr, off_t offset ) {
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return trivial_user_to_virt ( userptr, offset );
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline userptr_t
6776d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanUACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) {
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return trivial_userptr_add ( userptr, offset );
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline void
7276d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanUACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off,
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					userptr_t src, off_t src_off,
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					size_t len ) {
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	trivial_memcpy_user ( dest, dest_off, src, src_off, len );
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline void
7976d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanUACCESS_INLINE ( librm, memmove_user ) ( userptr_t dest, off_t dest_off,
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					 userptr_t src, off_t src_off,
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					 size_t len ) {
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	trivial_memmove_user ( dest, dest_off, src, src_off, len );
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline void
8676d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanUACCESS_INLINE ( librm, memset_user ) ( userptr_t buffer, off_t offset,
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					int c, size_t len ) {
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	trivial_memset_user ( buffer, offset, c, len );
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline size_t
9276d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanUACCESS_INLINE ( librm, strlen_user ) ( userptr_t buffer, off_t offset ) {
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return trivial_strlen_user ( buffer, offset );
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline off_t
9776d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanUACCESS_INLINE ( librm, memchr_user ) ( userptr_t buffer, off_t offset,
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					int c, size_t len ) {
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return trivial_memchr_user ( buffer, offset, c, len );
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/******************************************************************************
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Access to variables in .data16 and .text16
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern char *data16;
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern char *text16;
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __data16( variable )						\
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	__attribute__ (( section ( ".data16" ) ))			\
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	_data16_ ## variable __asm__ ( #variable )
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __data16_array( variable, array )				\
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	__attribute__ (( section ( ".data16" ) ))			\
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	_data16_ ## variable array __asm__ ( #variable )
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __bss16( variable )						\
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	__attribute__ (( section ( ".bss16" ) ))			\
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	_data16_ ## variable __asm__ ( #variable )
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __bss16_array( variable, array )				\
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	__attribute__ (( section ( ".bss16" ) ))			\
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	_data16_ ## variable array __asm__ ( #variable )
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __text16( variable )						\
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	__attribute__ (( section ( ".text16.data" ) ))			\
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	_text16_ ## variable __asm__ ( #variable )
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __text16_array( variable, array )				\
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	__attribute__ (( section ( ".text16.data" ) ))			\
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	_text16_ ## variable array __asm__ ( #variable )
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __use_data16( variable )					\
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	( * ( ( typeof ( _data16_ ## variable ) * )			\
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	      & ( data16 [ ( size_t ) & ( _data16_ ## variable ) ] ) ) )
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __use_text16( variable )					\
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	( * ( ( typeof ( _text16_ ## variable ) * )			\
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	      & ( text16 [ ( size_t ) & ( _text16_ ## variable ) ] ) ) )
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __from_data16( pointer )					\
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	( ( unsigned int )						\
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	  ( ( ( void * ) (pointer) ) - ( ( void * ) data16 ) ) )
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define __from_text16( pointer )					\
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	( ( unsigned int )						\
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	  ( ( ( void * ) (pointer) ) - ( ( void * ) text16 ) ) )
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Variables in librm.S, present in the normal data segment */
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern uint16_t rm_sp;
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern uint16_t rm_ss;
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern uint16_t __data16 ( rm_cs );
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define rm_cs __use_data16 ( rm_cs )
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern uint16_t __text16 ( rm_ds );
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define rm_ds __use_text16 ( rm_ds )
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Functions that librm expects to be able to link to.  Included here
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * so that the compiler will catch prototype mismatches.
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern void gateA20_set ( void );
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Convert segment:offset address to user buffer
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v segment		Real-mode segment
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v offset		Real-mode offset
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret buffer		User buffer
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline userptr_t
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanreal_to_user ( unsigned int segment, unsigned int offset ) {
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ( phys_to_user ( ( segment << 4 ) + offset ) );
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size );
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern void remove_user_from_rm_stack ( userptr_t data, size_t size );
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* TEXT16_CODE: declare a fragment of code that resides in .text16 */
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TEXT16_CODE( asm_code_str )			\
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	".section \".text16\", \"ax\", @progbits\n\t"	\
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	".code16\n\t"					\
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	asm_code_str "\n\t"				\
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	".code32\n\t"					\
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	".previous\n\t"
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* REAL_CODE: declare a fragment of code that executes in real mode */
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define REAL_CODE( asm_code_str )			\
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	"pushl $1f\n\t"					\
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	"call real_call\n\t"				\
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	"addl $4, %%esp\n\t"				\
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	TEXT16_CODE ( "\n1:\n\t"			\
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		      asm_code_str			\
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		      "\n\t"				\
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		      "ret\n\t" )
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PHYS_CODE( asm_code_str )			\
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	"call _virt_to_phys\n\t"			\
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	asm_code_str					\
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	"call _phys_to_virt\n\t"
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* ASSEMBLY */
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* LIBRM_H */
207