Index: trunk/kernel/libk/elf.c
===================================================================
--- trunk/kernel/libk/elf.c	(revision 690)
+++ trunk/kernel/libk/elf.c	(revision 1)
@@ -2,5 +2,5 @@
  * elf.c - elf parser: find and map process CODE and DATA segments
  *
- * Authors   Alain Greiner    (2016,2017,2018,2019,2020)
+ * Authors   Alain Greiner    (2016)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -22,17 +22,14 @@
  */
 
-#include <kernel_config.h>
-#include <hal_kernel_types.h>
-#include <hal_special.h>
+#include <almos_config.h>
+#include <hal_types.h>
 #include <hal_uspace.h>
 #include <printk.h>
 #include <process.h>
-#include <thread.h>
-#include <mapper.h>
 #include <vseg.h>
 #include <kmem.h>
 #include <vfs.h>
 #include <elf.h>
-#include <syscalls.h>
+
 
 ///////////////////////////////////////////////////////////////////
@@ -41,31 +38,34 @@
 // - return false with an error message if illegal header.
 ///////////////////////////////////////////////////////////////////
-static bool_t elf_isValidHeader(Elf_Ehdr *header)
+static bool_t elf_isValidHeader(Elf32_Ehdr *header)
 {
-	if( (header->e_ident[EI_CLASS]   == ELFCLASS)    &&
-	    (header->e_ident[EI_DATA]    == ELFDATA2LSB) &&
-	    (header->e_ident[EI_VERSION] == EV_CURRENT)  && 
-        ( (header->e_machine == EM_MIPS)        ||
-	      (header->e_machine == EM_MIPS_RS3_LE) ||
-	      (header->e_machine == EM_X86_64) )         &&
-	    (header->e_type == ET_EXEC) )
-		return true;
-
-	if( header->e_ident[EI_CLASS] != ELFCLASS )
-		printk("\n[ERROR] in %s : Elf is not 32/64-Binary\n", __FUNCTION__ );
+	if((header->e_ident[EI_CLASS] == ELFCLASS32) 
+	   && (header->e_ident[EI_DATA] == ELFDATA2LSB) 
+	   && (header->e_ident[EI_VERSION] == EV_CURRENT)
+	   && (header->e_ident[EI_OSABI] == ELFOSABI_NONE)
+	   && ((header->e_machine == EM_MIPS) || 
+	       (header->e_machine == EM_MIPS_RS3_LE) ||
+	       (header->e_machine == EM_386))
+	   && (header->e_type == ET_EXEC))          return true;
+   
+	if( header->e_ident[EI_CLASS] != ELFCLASS32 )
+    printk("\n[ERROR] in %s : Elf is not 32-Binary\n", __FUNCTION__ );
 
 	if( header->e_ident[EI_DATA] != ELFDATA2LSB )
-		printk("\n[ERROR] in %s : Elf is not 2's complement, little endian\n", __FUNCTION__ );
-
-	if( header->e_ident[EI_VERSION] != EV_CURRENT )
-		printk("\n[ERROR] in %s : Elf is not in Current Version\n", __FUNCTION__);
-
-	if( (header->e_machine != EM_MIPS) &&
-	    (header->e_machine != EM_MIPS_RS3_LE) &&
-	    (header->e_machine != EM_X86_64) )
-		printk("\n[ERROR] in %s : unexpected core / accept only MIPS or x86_64\n", __FUNCTION__ );
-
-	if( header->e_type != ET_EXEC )
-		printk("\n[ERROR] in %s : Elf is not executable binary\n", __FUNCTION__ );
+    printk("\n[ERROR] in %s : Elf is not 2's complement, little endian\n", __FUNCTION__ );
+
+	if( header->e_ident[EI_VERSION] != EV_CURRENT ) 
+    printk("\n[ERROR] in %s : Elf is not in Current Version\n", __FUNCTION__);
+
+	if( header->e_ident[EI_OSABI] != ELFOSABI_NONE )
+    printk("\n[ERROR] in %s : Unexpected Elf ABI, need UNIX System V ABI\n", __FUNCTION__ );
+
+	if( (header->e_machine == EM_MIPS) || 
+		(header->e_machine == EM_MIPS_RS3_LE) || 
+        (header->e_machine == EM_386) ) 
+	printk("\n[ERROR] in %s : unexpected core / accept only MIPS or 80386\n", __FUNCTION__ );
+
+	if( header->e_type == ET_EXEC )
+	printk("\n[ERROR] in %s : Elf is not executable binary\n", __FUNCTION__ );
 
 	return false;
@@ -73,34 +73,26 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////
-// This static function loads the .elf header in the buffer allocated by the caller.
-///////////////////////////////////////////////////////////////////////////////////////
+// This function load the .elf header in the buffer allocated by the caller.
 // @ file   : extended pointer on the remote file descriptor.
 // @ buffer : pointer on buffer allocated by the caller.
 // @ size   : number of bytes to read.
 ///////////////////////////////////////////////////////////////////////////////////////
-static error_t elf_header_load( xptr_t   file_xp,
+static error_t elf_header_read( xptr_t   file_xp,
                                 void   * buffer,
                                 uint32_t size )
-{
-	error_t   error;
-	xptr_t    buf_xp;
-
-	buf_xp = XPTR( local_cxy , buffer );
-
-	// load .elf header
-	error = vfs_kernel_move( true,     // to_buffer
-	                         file_xp,
-	                         buf_xp,
-	                         size );
-
-	if( error )
-	{
-		printk("\n[ERROR] in %s : cannot read ELF header size : %d\n",
-               __FUNCTION__ , size );
-		return -1;
-	}
-
-	Elf_Ehdr * header = (Elf_Ehdr *)buffer;
-
+{ 
+    uint32_t  count;
+
+    // load .elf header 
+	count = vfs_read( file_xp , buffer , size );
+
+	if( count != size )
+	{
+		printk("\n[ERROR] in %s : failed to read ELF header\n", __FUNCTION__ );
+		return -1;
+	}
+
+    Elf32_Ehdr * header = (Elf32_Ehdr *)buffer;
+    
 	if( (header->e_ident[EI_MAG0] != ELFMAG0) ||
 	    (header->e_ident[EI_MAG1] != ELFMAG1) ||
@@ -108,5 +100,5 @@
 	    (header->e_ident[EI_MAG3] != ELFMAG3) )
 	{
-		printk("\n[ERROR] in %s : file not in ELF format\n", __FUNCTION__ );
+		printk("\n[ERROR] in %s : file %s not in ELF format\n", __FUNCTION__ );
 		return -1;
 	}
@@ -118,10 +110,8 @@
 	}
 	return 0;
-
-} // end elf_header_load()
+}  // end elf_header_read()
 
 ///////////////////////////////////////////////////////////////////////////////////////
 // This function registers in the process VMM the CODE and DATA segments.
-///////////////////////////////////////////////////////////////////////////////////////
 // @ file      : extended pointer on the remote file descriptor.
 // @ segs_base : local pointer on buffer containing the segments descriptors array
@@ -129,223 +119,221 @@
 // @ process   : local pointer on process descriptor.
 ///////////////////////////////////////////////////////////////////////////////////////
-static error_t elf_segments_register( xptr_t       file_xp,
-                                      void       * segs_base,
-                                      uint32_t     nb_segs,
-                                      process_t  * process )
+static error_t elf_segments_load( xptr_t       file_xp,
+				                  void       * segs_base,
+                                  uint32_t     nb_segs,
+				                  process_t  * process )
 {
+	error_t      error;
 	uint32_t     index;
-	intptr_t     file_size;
-	intptr_t     mem_size;
-	intptr_t     file_offset;
-	intptr_t     vbase;
+	uint32_t     file_size;
+    uint32_t     mem_size;
+	intptr_t     start;
 	uint32_t     type;
 	uint32_t     flags;
-	vseg_t     * vseg;
-
-	Elf_Phdr * seg_ptr = (Elf_Phdr *)segs_base;
-
-	// loop on segments
-	for( index = 0 ; index < nb_segs ; index++ , seg_ptr++ )
-	{
-		if( seg_ptr->p_type != PT_LOAD)
-			continue;
-
-		// get segment attributes
-		vbase       = seg_ptr->p_vaddr;     // vseg base vaddr
-		mem_size    = seg_ptr->p_memsz;     // actual vseg size
-		file_offset = seg_ptr->p_offset;    // vseg offset in .elf file
-		file_size   = seg_ptr->p_filesz;    // vseg size in .elf file
-		flags       = seg_ptr->p_flags;
+	uint32_t     offset;
+    vseg_t     * vseg;
+
+    Elf32_Phdr * seg_ptr = (Elf32_Phdr *)segs_base;
+
+    // loop on segments
+	for( index = 0 ; index < nb_segs ; index++ , seg_ptr++ ) 
+	{   
+		if( seg_ptr->p_type != PT_LOAD) continue;
+    
+        // get segment attributes
+		start     = seg_ptr->p_vaddr;
+        offset    = seg_ptr->p_offset;
+        file_size = seg_ptr->p_filesz;
+        mem_size  = seg_ptr->p_memsz;
+        flags     = seg_ptr->p_flags;
+
+        // check alignment
+		if( start & CONFIG_PPM_PAGE_MASK )
+		{
+			printk("\n[WARNING] in %s : segment base not aligned = %x\n",
+			       __FUNCTION__, start );
+		}
+
+        // check size
+        if( file_size != mem_size )
+		{
+			printk("\n[WARNING] in %s : base = %x / mem_size = %x / file_size = %x\n",
+			       __FUNCTION__, start , mem_size , file_size);
+		}
+
+        // set seek on segment base in file
+		error = vfs_lseek( file_xp , offset , VFS_SEEK_SET , NULL );
+
+		if( error )
+		{
+			printk("\n[ERROR] in %s : failed to seek\n", __FUNCTION__ );
+			return -1;
+		}
 
 		if( flags & PF_X ) // found CODE segment
 		{
-			type                       = VSEG_TYPE_CODE;
-			process->vmm.code_vpn_base = vbase >> CONFIG_PPM_PAGE_ORDER;
-		}
-		else               // found DATA segment
-		{
-			type                       = VSEG_TYPE_DATA;
-			process->vmm.data_vpn_base = vbase >> CONFIG_PPM_PAGE_ORDER;
-		}
-
-        // get .elf file descriptor cluster and local pointer 
-        cxy_t        file_cxy = GET_CXY( file_xp );
-        vfs_file_t * file_ptr = GET_PTR( file_xp );
-
-        // get local pointer on .elf file mapper
-        mapper_t * mapper_ptr = (mapper_t *)hal_remote_lpt( XPTR( file_cxy , 
-                                                                  &file_ptr->mapper ) );
-		// register vseg in VMM
-		vseg = (vseg_t *)vmm_create_vseg( process,
-                                          type,
-		                                  vbase,
-		                                  mem_size,
-                                          file_offset,
-                                          file_size,
-                                          XPTR( file_cxy , mapper_ptr ),
-		                                  local_cxy );  
+            type                       = VSEG_TYPE_CODE;
+			process->vmm.code_vpn_base = start >> CONFIG_PPM_PAGE_SHIFT;
+
+			elf_dmsg("\n[INFO] %s found CODE vseg / base = %x / size = %x\n",
+                     __FUNCTION__ , start , mem_size );
+		}
+		else                   // found DATA segment
+		{
+            type                       = VSEG_TYPE_DATA;
+			process->vmm.data_vpn_base = start >> CONFIG_PPM_PAGE_SHIFT;
+
+			elf_dmsg("\n[INFO] %s found DATA vseg / base = %x / size = %x\n",
+                     __FUNCTION__, start , mem_size );
+		}
+
+        // register vseg in VMM
+		vseg = (vseg_t *)vmm_create_vseg( process, 
+					                      start,
+					                      mem_size, 
+					                      type );
 		if( vseg == NULL )
 		{
 			printk("\n[ERROR] in %s : cannot map segment / base = %x / size = %x\n",
-			       __FUNCTION__ , vbase , mem_size );
+			       __FUNCTION__ , start , mem_size );
 			return -1;
 		}
 
-#if DEBUG_ELF_LOAD
-uint32_t   cycle = (uint32_t)hal_get_cycles();
-thread_t * this  = CURRENT_THREAD;
-if( DEBUG_ELF_LOAD < cycle )
-printk("\n[%s] thread[%x,%x] found %s vseg / base %x / size %x\n"
-"  file_size %x / file_offset %x / mapper[%x,%x] / cycle %d\n",
-__FUNCTION__ , this->process->pid, this->trdid, 
-vseg_type_str(vseg->type) , vseg->min , vseg->max - vseg->min ,
-vseg->file_size , vseg->file_offset , 
-GET_CXY(vseg->mapper_xp), GET_PTR(vseg->mapper_xp), cycle );
-#endif
-
+		vfs_file_count_up( file_xp );
 	}
 
 	return 0;
-
-} // end elf_segments_register()
-
-//////////////////////////////////////////////
-error_t elf_load_process( xptr_t      file_xp,
-                          process_t * process )
+} // end elf_load_segments()
+
+///////////////////////////////////////////////
+error_t elf_load_process( char      * pathname,
+                          process_t * process)
 {
-    uint32_t     new_offset;       // unused, required by vfs_lseek() 
-	Elf_Ehdr     header;           // local buffer for .elf header
+	kmem_req_t   req;              // kmem request for program header
+    char         path_copy[256];   // local copy of pathname
+	uint32_t     length;           // actual path length
+	Elf32_Ehdr   header;           // local buffer for .elf header
 	void       * segs_base;        // pointer on buffer for segment descriptors array
-	uint32_t     segs_size;        // size of buffer for segment descriptors array
-    char         name[CONFIG_VFS_MAX_NAME_LENGTH];
+    uint32_t     segs_size;        // size of buffer for segment descriptors array  
+	xptr_t       file_xp;          // extended pointer on created file descriptor
+    uint32_t     count;            // bytes counter
 	error_t      error;
 
-    // get file cluster and local pointer
-    cxy_t        file_cxy = GET_CXY( file_xp );
-    vfs_file_t * file_ptr = GET_PTR( file_xp );
-
-    // get inode pointer
-    vfs_inode_t * inode_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
- 
-    // get file name for error reporting and debug
-    vfs_inode_get_name( XPTR( file_cxy , inode_ptr ) , name );
-    
-#if DEBUG_ELF_LOAD
-uint32_t   cycle = (uint32_t)hal_get_cycles();
-thread_t * this  = CURRENT_THREAD;
-if( DEBUG_ELF_LOAD < cycle )
-printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, name, cycle );
-#endif
-
-	// load header in local buffer
-	error = elf_header_load( file_xp ,
-	                         &header,
-	                         sizeof(Elf_Ehdr) );
+    // get path length from user space
+	length = hal_strlen_from_uspace( pathname );
+
+    if( length > 255 )
+    {
+        printk("\n[ERROR] in %s : pathname length too long\n", __FUNCTION__ );
+        return -1;
+    }
+
+    // make a local copy for pathname
+    hal_copy_from_uspace( path_copy , pathname , length+1 );
+
+    // open file
+    file_xp = XPTR_NULL;  // avoid GCC warning
+
+	error = vfs_open( process->vfs_cwd_xp, 
+                      path_copy,
+                      VFS_O_RDONLY,
+                      &file_xp );
 	if( error )
 	{
-		printk("\n[ERROR] in %s : cannot get header for <%s>\n", __FUNCTION__ , name );
-		return -1;
-	}
-
-#if (DEBUG_ELF_LOAD & 1)
-if( DEBUG_ELF_LOAD < cycle )
-printk("\n[%s] loaded elf header for <%s>\n"
-       "      - size    = %x\n"
-       "      - version = %x\n"
-       "      - entry   = %x\n"
-       "      - machine = %x\n"
-       "      - offset  = %x\n"
-       "      - segnum  = %x\n",
-       __FUNCTION__, name,
-       header.e_ehsize,
-       header.e_version,
-       header.e_entry,
-       header.e_machine,
-       header.e_phoff,
-       header.e_phnum );
-#endif
+		printk("\n[ERROR] in %s : failed to open executable file %s\n",
+               __FUNCTION__ , path_copy );
+		return -1;
+	}
+
+    // load header in local buffer
+	error = elf_header_read( file_xp , 
+                             &header,
+                             sizeof(Elf32_Ehdr) );
+	if( error ) 
+    {
+        vfs_close( file_xp , &count );
+        return -1;
+    }
+
+	elf_dmsg("\n[INFO] %s loaded elf header for %s\n", __FUNCTION__ , path_copy );
 
 	if( header.e_phnum == 0 )
 	{
 		printk("\n[ERROR] in %s : no segments found\n", __FUNCTION__ );
-		return -1;
-	}
-
-	// compute buffer size for segment descriptors array
-	segs_size = sizeof(Elf_Phdr) * header.e_phnum;
-
-	// allocate memory for segment descriptors array
-	segs_base = kmem_alloc( bits_log2(segs_size) , AF_NONE );
+        vfs_close( file_xp , &count );
+		return -1;
+	}
+
+    // compute buffer size for segment descriptors array
+	segs_size = sizeof(Elf32_Phdr) * header.e_phnum;
+  
+    // allocate memory for segment descriptors array
+	req.type  = KMEM_GENERIC;
+	req.size  = segs_size;
+	req.flags = AF_KERNEL;
+	segs_base = kmem_alloc( &req );
 
 	if( segs_base == NULL )
-	{
+    {
 		printk("\n[ERROR] in %s : no memory for segment descriptors\n", __FUNCTION__ );
-		return -1;
-	}
-
-	// set seek pointer in file descriptor to access segment descriptors array
-	error = vfs_lseek( file_xp , header.e_phoff, SEEK_SET , &new_offset );
+        vfs_close( file_xp , &count );
+        return -1;
+    }
+
+    // set seek pointer in file descriptor to access segment descriptors array
+	error = vfs_lseek( file_xp , header.e_phoff, VFS_SEEK_SET , NULL );
 
 	if( error )
 	{
 		printk("\n[ERROR] in %s : cannot seek for descriptors array\n", __FUNCTION__ );
-		kmem_free( segs_base , bits_log2(segs_size) );
-		return -1;
-	}
-
-#if (DEBUG_ELF_LOAD & 1)
-if( DEBUG_ELF_LOAD < cycle )
-printk("\n[%s] segments array allocated for <%s>\n", __FUNCTION__ , name );
-#endif
-
-	// load seg descriptors array to local buffer
-	error = vfs_kernel_move( true,                  // to_buffer
-	                         file_xp,
-	                         XPTR( local_cxy , segs_base ),
-	                         segs_size );
-
+        vfs_close( file_xp , &count );
+	    req.ptr = segs_base;
+	    kmem_free( &req );
+		return -1;
+	}
+
+    // load seg descriptors array to local buffer 
+	count = vfs_read( file_xp, 
+                      segs_base,
+                      segs_size );
+
+	if( count != segs_size )
+	{
+		printk("\n[ERROR] in %s : cannot read segments descriptors\n", __FUNCTION__ );
+        vfs_close( file_xp , &count );
+	    req.ptr = segs_base;
+	    kmem_free( &req );
+		return -1;
+	}
+
+	elf_dmsg("\n[INFO] %s loaded segments descriptors for %s \n", __FUNCTION__ , path_copy );
+
+    // register loadable segments in process VMM
+	error = elf_segments_load( file_xp, 
+                               segs_base,
+                               header.e_phnum,
+                               process );
 	if( error )
-	{
-		printk("\n[ERROR] in %s : cannot read segments descriptors\n", __FUNCTION__ );
-		kmem_free( segs_base , bits_log2(segs_size) );
-		return -1;
-	}
-
-#if (DEBUG_ELF_LOAD & 1)
-if( DEBUG_ELF_LOAD < cycle )
-printk("\n[%s] loaded segments descriptors for <%s>\n", __FUNCTION__ , name );
-#endif
-
-	// register loadable segments in process VMM
-	error = elf_segments_register( file_xp,
-	                               segs_base,
-	                               header.e_phnum,
-	                               process );
-	if( error )
-	{
-		printk("\n[ERROR] in %s : cannot register segments descriptors\n", __FUNCTION__ );
-		kmem_free( segs_base , bits_log2(segs_size) );
-		return -1;
-	}
-
-	// register process entry point in VMM
+    {
+        vfs_close( file_xp , &count );
+	    req.ptr = segs_base;
+	    kmem_free( &req );
+		return -1;
+    }
+
+    // register process entry point in VMM
 	process->vmm.entry_point = (intptr_t)header.e_entry;
 
-	// register extended pointer on .elf file descriptor
-	process->vfs_bin_xp = file_xp;
-
-	// release allocated memory for program header
-    kmem_free( segs_base , bits_log2(segs_size) );
-
-#if DEBUG_ELF_LOAD
-cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_ELF_LOAD < cycle )
-printk("\n[%s] thread[%x,%x] exit for <%s> / entry_point %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, name, header.e_entry, cycle );
-#endif
+    // register extended pointer on .elf file descriptor 
+    process->vfs_bin_xp = file_xp;
+
+    // release allocated memory for program header
+	req.ptr = segs_base;
+	kmem_free(&req);
+
+	elf_dmsg("\n[INFO] %s successfully completed / entry point = %x for %s]\n", 
+		 __FUNCTION__, (uint32_t) header.e_entry , path_copy );
 
 	return 0;
-
 }  // end elf_load_process()
 
