Page 1 of 2

openfunix 0.1 released

Posted: Tue Nov 25, 2014 3:47 am
by Shaun
hi,buddies!

i am glad to announce that openfunix os 0.1.0 is available now.

What's OpenFunix?
openfunix is a new kernel written by shaun from scratch.It is a small, lightweight, and fast kernel designed for x86 arcs.

What's new in this release?

the main feature for this version up is Supporting for elf32 shared library loading.
as we all know, the elf shared library loading work in linux kernel is taken by interpreter(ld-linux.so.6) which is running in userspace. kernel load the interpreter first into memory and transport control to interpreter when kernel find out that an app is dynamic linked, the interpreter then resolve dependencies and load libraries that app needed into memory, do relocation stuff, after all of these things done, interpreter jumps to app's entry point.

that's sounds good,reasonable, but for me, why we wouldn't put that job in kernel space? what's the bad things if we put it in kernel space? Actually i have taken a try, and i did it.

the shared library loading and relocating things all are located in kernel space in openfunix. feel free to try it out. anybody who has different opinions about it, please let me know.

HOW TOS
1.download floppy img and disk file.
http://forum.openfunix.com/download/file.php?id=6
2.extract the zip file, you will get two files:floppy and hd.disk.tar.gz, unpack the hd.disk.tar.gz, you will get the disk file(hd.disk, 1G size, formatted with ext2 filesystem).
3.run qemu with command below in linux box(make sure the floppy file and hd.disk file are in the same directory):
qemu -fda floppy.img -boot a -monitor stdio -drive id=disk,file=hd.disk,if=none -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0
4,if everything is ok, you will get this pic:
Screenshot.png
when kernel starts over, it will ask you to input password, type this: op3nfunix
now you can run any app you like, the app "hello" in /root directory is compiled with libc.so(actually it's newlib :lol: ).
when you run hello with command:exec /root/hello, the kernel loads hello binary file first and then libc.so(in /lib/), handle relocation works for libc.so.

tips:you can close kernel logs by using command: loglevel 4

enjoy.

Re: openfunix 0.1 released

Posted: Tue Nov 25, 2014 4:31 am
by Kevin
I would suggest that you make "ls" work without an argument, it's rather confusing that it prints nothing (not even an error message).

When I try "exec root/hello" (as a relative path), I get "open file:oot/hello failed". Also if I write "execute", it still runs the exec command. I think you can improve your command line parser a bit. With "exec /lib/libc.so", I can crash the system; and I also managed to crash it with some funny paths like "exec /root/.././/lib/../root/hello". I suppose it's not intentional that I can use backspace to delete characters even if I haven't written anything yet.

But in general, my impression is that the surface looks like less than there really is. Support for AHCI, ext2 and shared libraries already tells a bit. I think you should just polish the user interface a bit and you can turn it into something nice quite quickly.

Re: openfunix 0.1 released

Posted: Tue Nov 25, 2014 9:44 pm
by Shaun
@Kevin

great thanks for your feedback.

the user-land command parser is very simple, even quite a little bit ugly. i will update it in next release.
also path related bugs is included.

i paste the source code of init program below, typing help can give you much more information.

the kernel also support BSD compatible tcp/ip stack. ifconfig command can be used to change interface's ip address.

and in virtualbox you can ping openfunix from your host os if it is configured properly.
a quick overview can be found here :http://www.openfunix.com/?page_id=126

thanks again.

Code: Select all

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/sockio.h>
#include <sys/endian.h>
#include <dirent.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <net/if.h>



#define perror(...)	\
	printf("%s", ##__VA_ARGS__); while (1);

#define PRINT_VER()	\
	do {	printf("Welcome to openfunix!\n");	\
		printf("Copyright by Shaun, 2012-2014.\nMail:openfunix at gmail dot com\n"); \
		printf("http://www.openfunix.com\n");	\
		fflush(NULL);	\
	} while (0)	

#define PRINT_PROMT()	\
	do {	printf("\nOPENFUNIX# ");	\
		fflush(NULL);	\
	} while (0)


void help();
void ifconfig();
void ping();
void ls();
void loglevel(char *buf);
void dash();
void makedir(char *buf);
void exec(char *buf);
struct cmd {
	char *c_name;
	void (*c_func)();
} cmds[] = {
		{"help",  help},
		{"ifconfig", ifconfig},
		{"ping", ping},
		{"ls", ls},
		{"loglevel", loglevel},
		{"dash", dash},
		{"mkdir", makedir},
		{"exec", exec},
		{0, 0},
};

struct	sockaddr_in netmask;

void loglevel(char *buf)
{
	int level = atoi((buf));
	printf("set log level to %d\n", level);
	setloglevel(level);
}

void help()
{
	struct cmd *p;
	PRINT_VER();
	printf("command supported:\n");
	for (p=cmds; p->c_name; p++)
		printf("%s ", p->c_name);
}

void dash()
{
	extern char **environ;
	char *const *envp = environ;
	char *argv[] = {NULL,0};
	execve("/root/dash",(char *const *)argv, envp);
	wait(NULL);
}
void makedir(char *buf)
{
	int ret;
	ret = mkdir(buf, S_IRWXU | S_IFDIR);
	if (ret < 0)
		printf("mkdir error:%s\n", strerror(errno));

}

void exec(char *buf)
{

	extern char **environ;
	char *const *envp = environ;
	if (strcmp(buf, "") == 0)
		return;
	char *argv = strchr(++buf, ' ');
	if (argv)
		*argv++ = 0;
	char *argvs[] = {argv, 0};// this should be in a while
	char *name = buf;
	if (execve(name, (char *const *)argvs, envp) < 0)
		return;
	wait(NULL);
}

void ping(char *buf)
{

}
void ls(char *buf)
{
	const char *path =(const char *)(buf);
	DIR *dirp;
	struct dirent *dp;
	struct stat st = {0};
	int ret;

	//should list current directory.
	if (strcmp(buf, "") == 0)
		return;

	ret = stat(buf, &st);
	if (ret < 0) {
		printf("stat error:%s\n", strerror(errno));
		return;
	}

	switch(st.st_mode & S_IFMT) {
	case S_IFDIR:
		goto ls_dir;
	case S_IFBLK:
		printf("b mode:%lo size:%d  %s\n", (unsigned long)st.st_mode, st.st_size, buf);
		break;
	case S_IFREG:
		printf("mode:%lo size:%d  %s\n", (unsigned long)st.st_mode, st.st_size, buf);
		break;
	case S_IFIFO:
		printf("f mode: %lo size:%d  %s\n", (unsigned long)st.st_mode, st.st_size, buf);
		break;
	case S_IFSOCK:
		printf("s mode:%lo size:%d  %s\n", (unsigned long)st.st_mode, st.st_size, buf);
		break;
	default:
		printf("mode:%lo size:%d  %s\n", (unsigned long)st.st_mode, st.st_size, buf);
		break;
	}

	return;
ls_dir:
	dirp = opendir(path);
	if (dirp == NULL){
		printf("open dir %s faild.errno:%d\n", path, errno);
		return;
	}
	dp = readdir(dirp);
	while (dp != NULL) 
	{
		dp->d_name[dp->d_namlen] = 0;
		printf("%s ", dp->d_name);
		dp = readdir(dirp);
	}
	printf("\n");
	fflush(NULL);
	closedir(dirp);
	
}
void in_status()
{
	struct sockaddr_in *sin;
	int s, flags;
	struct	ifreq		ifr;

	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s < 0) {
		perror("ifconfig: socket");
		exit(1);
	}

	memset(&ifr, 0, sizeof(ifr));

	memcpy(ifr.ifr_name, "eth0", 5);
	printf("name:%s", ifr.ifr_name);

	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
		perror("ioctl (SIOCGIFFLAGS)");
		exit(1);
	}

	flags = ifr.ifr_flags;


	fflush(NULL);
	if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
			bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
		} else
			perror("ioctl (SIOCGIFADDR)");
	}
	sin = (struct sockaddr_in *)&ifr.ifr_addr;
	printf("\tinet %s ", inet_ntoa(sin->sin_addr));
	//strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
	if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
		if (errno != EADDRNOTAVAIL)
			perror("ioctl (SIOCGIFNETMASK)");
		bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
	} else
		netmask.sin_addr =
		    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;

	printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr));
	if (flags & IFF_BROADCAST) {
		if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
			if (errno == EADDRNOTAVAIL)
			    bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
			else
			    perror("ioctl (SIOCGIFADDR)");
		}
		//strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
		sin = (struct sockaddr_in *)&ifr.ifr_addr;
		if (sin->sin_addr.s_addr != 0)
			printf("broadcast %s", inet_ntoa(sin->sin_addr));
	}
	putchar('\n');
	fflush(NULL);
	close(s);
}

void if_setaddr(in_addr_t addr)
{
	struct sockaddr_in *sin;
	int fd, ret;
	struct	ifreq	ifr;
	
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (fd < 0) {
		printf("socket error:%d\n", errno);
		return;
	}
	memset(&ifr, 0, sizeof(ifr));
	strcpy(ifr.ifr_name, "eth0");
	sin = (struct sockaddr_in *)&ifr.ifr_addr;
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = addr;
	//sin->sin_len = sizeof(struct sockaddr_in);
	
	ret = ioctl(fd, SIOCSIFADDR, (caddr_t)&ifr);
	if (ret < 0) {
		printf("ioctl error:%d\n", errno);
	}
	close(fd);
	return;
}


void ifconfig(char *buf)
{
	char *p = (char *)(buf);
	in_addr_t addr;
	if (*p != '\0') {
		addr = inet_addr(p);
		if (addr == INADDR_NONE) {
			printf("invalid addrress\n");
			return;
		}

		if_setaddr(addr);
		return ;
	}


	in_status();
}


int main(int argc, char **argv, char **env)
{
	int ret;
	char buf[32] = {0};
	struct cmd *p;
	int fd = open("/dev/tty", O_RDWR, 0);
	if (fd < 0){
		//printf("open tty error:%s\n",strerror(errno));
		return -1;
	}
	dup2(fd, 1);
	dup2(fd, 2);
	//fcntl(fd, F_SETFD, 1);
	do {
		printf("Password:");
		fflush(NULL);
		ret = read(fd, buf, 31);
		if (ret > 0){
			if (strncmp(buf, "op3nfunix", 9) != 0){
				printf("password error\n");
				fflush(NULL);
				continue;
			}
			//printf("Login OK!\n");
			break;
		}
	}while (1);

	PRINT_VER();

	PRINT_PROMT();
	memset(buf, 0, sizeof(buf));
	while ((ret = read(fd, buf, 31)) > 0) {
		buf[ret-1] = 0;
		for (p=cmds; p->c_name; p++) {
			if (strncmp(p->c_name, buf, strlen(p->c_name)) == 0)
				break;
		}

		if (p->c_func)
			(*p->c_func)(buf + strlen(p->c_name) + 1);

		 next:
		 memset(buf, 0, sizeof(buf));
		 printf("OPENFUNIX# ");	
		 fflush(NULL);
	}
	
	return 0;
}



Re: openfunix 0.1 released

Posted: Wed Nov 26, 2014 2:36 am
by Kevin
Does your execve() include an implicit fork()?

Re: openfunix 0.1 released

Posted: Wed Nov 26, 2014 3:04 am
by no92
Is it open source? The name implies that it is. If it's closed-source, you should really rename it, to avoid confusion.

Re: openfunix 0.1 released

Posted: Wed Nov 26, 2014 3:34 am
by seuti
no92 wrote:Is it open source? The name implies that it is. If it's closed-source, you should really rename it, to avoid confusion.
Under the download page of the website
OpenFunix kernel source is not available for now.
Maybe the source will be released in the future.

Re: openfunix 0.1 released

Posted: Wed Nov 26, 2014 10:00 pm
by Shaun
Kevin wrote:Does your execve() include an implicit fork()?
enh, it's hard to say, actually nope.

the behavior of execve() api in openfunix does not conform what in traditional unix-like system's. i haven't implemented the fork() system call yet. when you make a execve call, the calling path looks like this:execve()->sys_execve()->kexecve()->kcreate_process()->...

in fact, i don't like the traditional fork() system call. it may cause a weird action sometime specially for a freshman. From my project experience these years,i once saw some people coding like this:

Code: Select all

pid_t pid1=fork();
pid_t pid2=fork();
----do some work-------
printf("pid1:%d, pid2:%d", pid1, pid2);


mybe that guy just wants to create two processes,but taking a stupid way...

so, i export create_process() system call, which behaves much more like what in windows. i can fully control the process state(stop, running, sleeping) in creating phase.

also if you want to run a binary file, just make an execve() call, and it will create a process and run it.

but in another side, unimplemented the fork() system call may decrease the portability of various unix-like apps. Maybe in the near future i _have_ to add it for some reasons.

what's the opinions of you guys?

@seuti
Maybe the source will be released in the future.
yep, you get it.

Re: openfunix 0.1 released

Posted: Thu Nov 27, 2014 4:25 am
by Kevin
fork/exec is probably not as straightforward as a single create_process is, but it provides a little more flexibility, especially around file descriptor inheritance, and it is what helps you port POSIX programs. Which one you choose, is to a certain degree a matter of taste and a design decision that you need to make (it's your OS, not mine).

But, please, if you call it execve(), then implement what the name promises. If you don't, use a different name. Especially when you start porting programs, functions that look the same as on POSIX, but do something different, are bound to give you endless trouble.

Re: openfunix 0.1 released

Posted: Thu Nov 27, 2014 7:11 am
by Shaun
Kevin wrote:fork/exec is probably not as straightforward as a single create_process is, but it provides a little more flexibility, especially around file descriptor inheritance, and it is what helps you port POSIX programs. Which one you choose, is to a certain degree a matter of taste and a design decision that you need to make (it's your OS, not mine).

But, please, if you call it execve(), then implement what the name promises. If you don't, use a different name. Especially when you start porting programs, functions that look the same as on POSIX, but do something different, are bound to give you endless trouble.
that's make sense. Supporting for both(fork() and create_process()) is a win-win choice.

Re: openfunix 0.1 released

Posted: Thu Nov 27, 2014 2:33 pm
by Roman
There's a bug probably somewhere in the kernel (in the tty?). Strange behavior happens, when shift is pressed.

Edit: Anyway, that's a great work!

Re: openfunix 0.1 released

Posted: Fri Nov 28, 2014 4:40 pm
by no92
@Shaun: You should really put Roman's screenshot into the "When your OS goes crazy ..." topic :D

Re: openfunix 0.1 released

Posted: Wed Dec 03, 2014 12:30 pm
by Roman
The kernel is really buggy, I hope, you will fix it. Wish you good luck.
"ls /root/init/../init." crashes the entire system.

Re: openfunix 0.1 released

Posted: Thu Dec 04, 2014 7:57 am
by Shaun
Roman wrote:The kernel is really buggy, I hope, you will fix it. Wish you good luck.
"ls /root/init/../init." crashes the entire system.

Hi, Roman
first, thanks for your feedback and fully test.

i have fixed the path related bugs, and updated the disk file, the previous released disk file does not contain dash binary, since the init program is simple and buggy, i decided to port dash for my default shell.now you can download dash file from http://www.openfunix.com/apps.html or download the newly updated disk file on that page.

since the lack of fork() system call, we can not run app in dash through default command, but we can run app using exec command in dash shell.
Screenshot-5.png
Screenshot-5.png (11.1 KiB) Viewed 11285 times

i am porting "ls" app these days, i hope that could give us a better experience in next release.

thanks again.

Re: openfunix 0.1 released

Posted: Thu Dec 04, 2014 8:07 am
by Arto
Shaun wrote:i am porting "ls" app these days, i hope could give us a better experience.
Are you aware of the Toybox project, by the way? It's a permissively-licensed userland implementation whence you could get implementations of all basic utilities, such as indeed ls.

Re: openfunix 0.1 released

Posted: Thu Dec 04, 2014 8:21 am
by Shaun
Arto wrote:
Shaun wrote:i am porting "ls" app these days, i hope could give us a better experience.
Are you aware of the Toybox project, by the way? It's a permissively-licensed userland implementation whence you could get implementations of all basic utilities, such as indeed ls.
enh,i have no aware of that, it seems like that toybox has the same functionality with busybox, i will dig into it to find some useful information. thanks for the tips.