openfunix 0.1 released

This forums is for OS project announcements including project openings, new releases, update notices, test requests, and job openings (both paying and volunteer).
User avatar
Shaun
Member
Member
Posts: 43
Joined: Mon Sep 17, 2012 3:14 am
Contact:

openfunix 0.1 released

Post 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.
Kevin
Member
Member
Posts: 1071
Joined: Sun Feb 01, 2009 6:11 am
Location: Germany
Contact:

Re: openfunix 0.1 released

Post 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.
Developer of tyndur - community OS of Lowlevel (German)
User avatar
Shaun
Member
Member
Posts: 43
Joined: Mon Sep 17, 2012 3:14 am
Contact:

Re: openfunix 0.1 released

Post 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;
}


Kevin
Member
Member
Posts: 1071
Joined: Sun Feb 01, 2009 6:11 am
Location: Germany
Contact:

Re: openfunix 0.1 released

Post by Kevin »

Does your execve() include an implicit fork()?
Developer of tyndur - community OS of Lowlevel (German)
no92
Member
Member
Posts: 307
Joined: Wed Oct 30, 2013 1:57 pm
Libera.chat IRC: no92
Location: Germany
Contact:

Re: openfunix 0.1 released

Post 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.
seuti
Member
Member
Posts: 74
Joined: Tue Aug 19, 2014 1:20 pm

Re: openfunix 0.1 released

Post 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.
User avatar
Shaun
Member
Member
Posts: 43
Joined: Mon Sep 17, 2012 3:14 am
Contact:

Re: openfunix 0.1 released

Post 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.
Kevin
Member
Member
Posts: 1071
Joined: Sun Feb 01, 2009 6:11 am
Location: Germany
Contact:

Re: openfunix 0.1 released

Post 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.
Developer of tyndur - community OS of Lowlevel (German)
User avatar
Shaun
Member
Member
Posts: 43
Joined: Mon Sep 17, 2012 3:14 am
Contact:

Re: openfunix 0.1 released

Post 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.
User avatar
Roman
Member
Member
Posts: 568
Joined: Thu Mar 27, 2014 3:57 am
Location: Moscow, Russia
Contact:

Re: openfunix 0.1 released

Post 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!
Attachments
Снимок экрана 2014-11-27 в 23.31.55.png
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
- Alan Kay
no92
Member
Member
Posts: 307
Joined: Wed Oct 30, 2013 1:57 pm
Libera.chat IRC: no92
Location: Germany
Contact:

Re: openfunix 0.1 released

Post by no92 »

@Shaun: You should really put Roman's screenshot into the "When your OS goes crazy ..." topic :D
User avatar
Roman
Member
Member
Posts: 568
Joined: Thu Mar 27, 2014 3:57 am
Location: Moscow, Russia
Contact:

Re: openfunix 0.1 released

Post 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.
Attachments
Снимок экрана 2014-12-03 в 21.28.50.png
Снимок экрана 2014-12-03 в 21.26.29.png
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
- Alan Kay
User avatar
Shaun
Member
Member
Posts: 43
Joined: Mon Sep 17, 2012 3:14 am
Contact:

Re: openfunix 0.1 released

Post 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 11271 times

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

thanks again.
User avatar
Arto
Member
Member
Posts: 44
Joined: Wed May 15, 2013 5:49 pm
Location: Berlin
Contact:

Re: openfunix 0.1 released

Post 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.
Developer of libc11
User avatar
Shaun
Member
Member
Posts: 43
Joined: Mon Sep 17, 2012 3:14 am
Contact:

Re: openfunix 0.1 released

Post 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.
Post Reply