[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
/*
|
|
|
|
* Copyright 2007, Ingo Weinhold, bonefish@cs.tu-berlin.de.
|
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "vfs_net_boot.h"
|
|
|
|
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_dl.h>
|
|
|
|
#include <net/if_types.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/sockio.h>
|
|
|
|
|
|
|
|
#include <DiskDeviceTypes.h>
|
|
|
|
|
|
|
|
#include <disk_device_manager/KDiskDevice.h>
|
|
|
|
|
|
|
|
#include <KPath.h>
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
string_starts_with(const char* string, const char* prefix)
|
|
|
|
{
|
|
|
|
size_t stringLen = strlen(string);
|
|
|
|
size_t prefixLen = strlen(prefix);
|
|
|
|
return (stringLen >= prefixLen && strncmp(string, prefix, prefixLen) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
is_net_device(KDiskDevice* device)
|
|
|
|
{
|
|
|
|
const char* path = device->Path();
|
|
|
|
return (string_starts_with(path, "/dev/disk/virtual/nbd/")
|
|
|
|
|| string_starts_with(path, "/dev/disk/virtual/remote_disk/"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
compare_partitions_net_devices(const void *_a, const void *_b)
|
|
|
|
{
|
|
|
|
KPartition* a = *(KPartition**)_a;
|
|
|
|
KPartition* b = *(KPartition**)_b;
|
|
|
|
|
2007-07-16 03:51:21 +04:00
|
|
|
bool aIsNetDevice = is_net_device(a->Device());
|
|
|
|
bool bIsNetDevice = is_net_device(b->Device());
|
[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
|
2007-07-16 03:51:21 +04:00
|
|
|
int compare = (int)aIsNetDevice - (int)bIsNetDevice;
|
[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
if (compare != 0)
|
|
|
|
return compare;
|
|
|
|
|
|
|
|
return compare_image_boot(_a, _b);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class NetStackInitializer {
|
|
|
|
public:
|
|
|
|
NetStackInitializer(uint64 clientMAC, uint32 clientIP, uint32 netMask)
|
2008-04-19 23:28:34 +04:00
|
|
|
:
|
|
|
|
fSocket(-1),
|
|
|
|
fLinkSocket(-1),
|
|
|
|
fClientMAC(clientMAC),
|
|
|
|
fClientIP(clientIP),
|
|
|
|
fNetMask(netMask),
|
|
|
|
fFoundInterface(false),
|
|
|
|
fConfiguredInterface(false)
|
[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~NetStackInitializer()
|
|
|
|
{
|
|
|
|
// close control sockets
|
|
|
|
if (fSocket >= 0)
|
|
|
|
close(fSocket);
|
|
|
|
|
|
|
|
if (fLinkSocket >= 0)
|
|
|
|
close(fLinkSocket);
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t Init()
|
|
|
|
{
|
|
|
|
// open a control socket for playing with the stack
|
2008-04-19 23:28:34 +04:00
|
|
|
fSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
if (fSocket < 0) {
|
|
|
|
dprintf("NetStackInitializer: Failed to open socket: %s\n",
|
|
|
|
strerror(errno));
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ... and a link level socket
|
2008-04-19 23:28:34 +04:00
|
|
|
fLinkSocket = socket(AF_LINK, SOCK_DGRAM, 0);
|
[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
if (fLinkSocket < 0) {
|
|
|
|
dprintf("NetStackInitializer: Failed to open link level socket:"
|
|
|
|
" %s\n", strerror(errno));
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// now iterate through the existing network devices
|
|
|
|
KPath path;
|
2008-04-19 23:28:34 +04:00
|
|
|
status_t error = path.SetTo("/dev/net");
|
[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
if (error != B_OK)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
_ScanDevices(path);
|
|
|
|
|
2008-04-19 23:28:34 +04:00
|
|
|
return fConfiguredInterface ? B_OK : B_ERROR;
|
[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void _ScanDevices(KPath& path)
|
|
|
|
{
|
|
|
|
DIR* dir = opendir(path.Path());
|
|
|
|
if (!dir) {
|
|
|
|
dprintf("NetStackInitializer: Failed to opendir() \"%s\": %s\n",
|
|
|
|
path.Path(), strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t error = B_OK;
|
|
|
|
|
|
|
|
while (dirent* entry = readdir(dir)) {
|
|
|
|
// skip "." and ".."
|
|
|
|
if (strcmp(entry->d_name, ".") == 0
|
|
|
|
|| strcmp(entry->d_name, "..") == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
path.Append(entry->d_name);
|
|
|
|
|
|
|
|
struct stat st;
|
|
|
|
if (stat(path.Path(), &st) == 0) {
|
|
|
|
if (S_ISDIR(st.st_mode))
|
|
|
|
_ScanDevices(path);
|
|
|
|
else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
|
|
|
|
_ScanDevice(path.Path());
|
|
|
|
}
|
|
|
|
|
|
|
|
path.RemoveLeaf();
|
|
|
|
|
|
|
|
if (fFoundInterface)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
void _ScanDevice(const char* path)
|
|
|
|
{
|
|
|
|
dprintf("NetStackInitializer: scanning device %s\n", path);
|
|
|
|
|
|
|
|
// check if this interface is already known
|
|
|
|
ifreq request;
|
|
|
|
if (strlen(path) >= IF_NAMESIZE)
|
|
|
|
return;
|
|
|
|
strcpy(request.ifr_name, path);
|
|
|
|
|
|
|
|
if (ioctl(fSocket, SIOCGIFINDEX, &request, sizeof(request)) < 0) {
|
|
|
|
// not known yet -- add it
|
|
|
|
request.ifr_parameter.base_name[0] = '\0';
|
|
|
|
request.ifr_parameter.device[0] = '\0';
|
|
|
|
request.ifr_parameter.sub_type = 0;
|
|
|
|
|
|
|
|
if (ioctl(fSocket, SIOCAIFADDR, &request, sizeof(request)) < 0) {
|
|
|
|
dprintf("NetStackInitializer: adding interface failed for "
|
|
|
|
"device %s: %s\n", path, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// bring the interface up (get flags, add IFF_UP)
|
|
|
|
if (ioctl(fSocket, SIOCGIFFLAGS, &request, sizeof(request)) < 0) {
|
|
|
|
dprintf("NetStackInitializer: getting flags failed for interface "
|
|
|
|
"%s: %s\n", path, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int interfaceFlags = request.ifr_flags;
|
|
|
|
if (!(interfaceFlags & IFF_UP)) {
|
|
|
|
interfaceFlags |= IFF_UP;
|
|
|
|
request.ifr_flags = interfaceFlags;
|
|
|
|
if (ioctl(fSocket, SIOCSIFFLAGS, &request, sizeof(request)) < 0) {
|
|
|
|
dprintf("NetStackInitializer: failed to bring interface up "
|
|
|
|
"%s: %s\n", path, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the MAC address
|
|
|
|
if (ioctl(fLinkSocket, SIOCGIFADDR, &request, sizeof(request)) < 0) {
|
|
|
|
dprintf("NetStackInitializer: Getting MAC addresss failed for "
|
|
|
|
"interface %s: %s\n", path, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sockaddr_dl& link = *(sockaddr_dl*)&request.ifr_addr;
|
|
|
|
if (link.sdl_type != IFT_ETHER)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (link.sdl_alen == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
uint8* macBytes = (uint8 *)LLADDR(&link);
|
|
|
|
uint64 macAddress = ((uint64)macBytes[0] << 40)
|
|
|
|
| ((uint64)macBytes[1] << 32)
|
|
|
|
| ((uint64)macBytes[2] << 24)
|
|
|
|
| ((uint64)macBytes[3] << 16)
|
|
|
|
| ((uint64)macBytes[4] << 8)
|
|
|
|
| (uint64)macBytes[5];
|
|
|
|
|
|
|
|
dprintf("NetStackInitializer: found ethernet interface with MAC "
|
|
|
|
"address %02x:%02x:%02x:%02x:%02x:%02x; which is%s the one we're "
|
|
|
|
"looking for\n", macBytes[0], macBytes[1], macBytes[2], macBytes[3],
|
|
|
|
macBytes[4], macBytes[5], (macAddress == fClientMAC ? "" : "n't"));
|
|
|
|
|
|
|
|
if (macAddress != fClientMAC)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fFoundInterface = true;
|
|
|
|
|
|
|
|
// configure the interface
|
|
|
|
|
|
|
|
// set IP address
|
|
|
|
sockaddr_in& address = *(sockaddr_in*)&request.ifr_addr;
|
|
|
|
address.sin_family = AF_INET;
|
|
|
|
address.sin_len = sizeof(sockaddr_in);
|
|
|
|
address.sin_port = 0;
|
|
|
|
address.sin_addr.s_addr = htonl(fClientIP);
|
|
|
|
memset(&address.sin_zero[0], 0, sizeof(address.sin_zero));
|
|
|
|
if (ioctl(fSocket, SIOCSIFADDR, &request, sizeof(request)) < 0) {
|
|
|
|
dprintf("NetStackInitializer: Setting IP addresss failed for "
|
|
|
|
"interface %s: %s\n", path, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set net mask
|
|
|
|
address.sin_addr.s_addr = htonl(fNetMask);
|
|
|
|
if (ioctl(fSocket, SIOCSIFNETMASK, &request, sizeof(request)) < 0) {
|
|
|
|
dprintf("NetStackInitializer: Setting net mask failed for "
|
|
|
|
"interface %s: %s\n", path, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set broadcast address
|
|
|
|
address.sin_addr.s_addr = htonl(fClientIP | ~fNetMask);
|
|
|
|
if (ioctl(fSocket, SIOCSIFBRDADDR, &request, sizeof(request)) < 0) {
|
|
|
|
dprintf("NetStackInitializer: Setting broadcast address failed for "
|
|
|
|
"interface %s: %s\n", path, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set IFF_BROADCAST
|
|
|
|
if (!(interfaceFlags & IFF_BROADCAST)) {
|
|
|
|
interfaceFlags |= IFF_BROADCAST;
|
|
|
|
request.ifr_flags = interfaceFlags;
|
|
|
|
if (ioctl(fSocket, SIOCSIFFLAGS, &request, sizeof(request)) < 0) {
|
|
|
|
dprintf("NetStackInitializer: failed to set IFF_BROADCAST flag "
|
|
|
|
"for interface %s: %s\n", path, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// set default route; remove previous one, if any
|
|
|
|
route_entry route;
|
|
|
|
memset(&route, 0, sizeof(route_entry));
|
|
|
|
route.flags = RTF_STATIC | RTF_DEFAULT;
|
|
|
|
|
|
|
|
request.ifr_route = route;
|
|
|
|
ioctl(fSocket, SIOCDELRT, &request, sizeof(request));
|
|
|
|
if (ioctl(fSocket, SIOCADDRT, &request, sizeof(request)) < 0) {
|
|
|
|
dprintf("NetStackInitializer: Failed to set default route: %s\n",
|
|
|
|
strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fConfiguredInterface = true;
|
|
|
|
|
|
|
|
dprintf("NetStackInitializer: successfully configured boot network "
|
|
|
|
"interface\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
int fSocket;
|
|
|
|
int fLinkSocket;
|
|
|
|
uint64 fClientMAC;
|
|
|
|
uint32 fClientIP;
|
|
|
|
uint32 fNetMask;
|
|
|
|
bool fFoundInterface;
|
|
|
|
bool fConfiguredInterface;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark - NetBootMethod
|
|
|
|
|
|
|
|
|
|
|
|
NetBootMethod::NetBootMethod(const KMessage& bootVolume, int32 method)
|
|
|
|
: BootMethod(bootVolume, method)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NetBootMethod::~NetBootMethod()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
NetBootMethod::Init()
|
|
|
|
{
|
|
|
|
// We need to bring up the net stack.
|
|
|
|
status_t status;
|
|
|
|
|
|
|
|
uint64 clientMAC;
|
|
|
|
uint32 clientIP;
|
|
|
|
uint32 netMask;
|
|
|
|
if (fBootVolume.FindInt64("client MAC", (int64*)&clientMAC) != B_OK
|
|
|
|
|| fBootVolume.FindInt32("client IP", (int32*)&clientIP) != B_OK) {
|
|
|
|
panic("no client MAC or IP address or net mask\n");
|
|
|
|
return B_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fBootVolume.FindInt32("net mask", (int32*)&netMask) != B_OK) {
|
|
|
|
// choose default netmask depending on the class of the address
|
|
|
|
in_addr_t net = htonl(clientIP);
|
|
|
|
if (IN_CLASSA(net)
|
|
|
|
|| (ntohl(net) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
|
|
|
|
// class A, or loopback
|
2007-07-19 17:58:17 +04:00
|
|
|
netMask = ntohl(IN_CLASSA_NET);
|
[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
} else if (IN_CLASSB(net)) {
|
|
|
|
// class B
|
2007-07-19 17:58:17 +04:00
|
|
|
netMask = ntohl(IN_CLASSB_NET);
|
[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
} else {
|
|
|
|
// class C and rest
|
2007-07-19 17:58:17 +04:00
|
|
|
netMask = ntohl(IN_CLASSC_NET);
|
[Sorry, couldn't split this one up any further.]
* Images preloaded by the boot loader had to be modules to be of any use
to the kernel. Extended the mechanism so that any images not accepted
by the module code would later be tried to be added as drivers by the
devfs. This is a little hacky ATM, since the devfs manages the drivers
using a hash map keyed by the drivers inode ID, which those drivers
obviously don't have.
* The devfs emulates read_pages() using read(), if the device driver
doesn't implement the former (all old-style drivers), thus making it
possible to BFS, which uses the file cache which in turn requires
read_pages(), on the device. write_pages() emulation is still missing.
* Replaced the kernel_args::boot_disk structure by a KMessage, which can
more flexibly be extended and deals more gracefully with
arbitrarily-size data. The disk_identifier structure still exists,
though. It is added as message field in cases where needed (non net
boot). Moved the boot_drive_number field of the bios_ia32 platform
specific args into the message.
* Made the stage 1 PXE boot loader superfluous. Moved the relevant
initialization code into the stage 2 loader, which can now be loaded
directly via PXE.
* The PXE boot loader does now download a boot tgz archive via TFTP. It
does no longer use the RemoteDisk protocol (it could actually be
removed from the boot loader). It also parses the DHCP options in the
DHCPACK packet provided by PXE and extracts the root path to be
mounted by the kernel.
* Reorganized the boot volume search in the kernel (vfs_boot.cpp) and
added support for network boot. In this case the net stack is
initialized and the network interface the boot loader used is brought
up and configured. Since NBD and RemoteDisk are our only options for
net boot (and those aren't really configurable dynamically) ATM, the
the boot device is found automatically by the disk device manager.
Booting via PXE does work to some degree now. The most grievous problem
is that loading certain drivers or kernel modules (or related activity)
causes a reboot (likely a triple fault, though one wonders where our
double fault handler is on vacation). Namely the keyboard and mouse input
server add-ons need to be deactivated as well as the media server.
A smaller problem is the net server, which apparently tries to
(re-)configure the network interface we're using to boot, which
obviously doesn't work out that well. So, if all this stuff is disabled
Haiku does fully boot, when using the RemoteDisk protocol (not being
able to use keyboard or mouse doesn't make this a particular fascinating
experience, though ;-)). I had no luck with NBD -- it seemed to have
protocol problems with the servers I tried.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21611 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-15 06:10:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NetStackInitializer initializer(clientMAC, clientIP, netMask);
|
|
|
|
status = initializer.Init();
|
|
|
|
if (status != B_OK)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
// TODO: "net root path" should be used for finding the boot device/FS,
|
|
|
|
// but ATM neither the remote_disk nor the nbd driver are configurable
|
|
|
|
// at this point.
|
|
|
|
const char* rootPath = fBootVolume.GetString("net root path", NULL);
|
|
|
|
dprintf("NetBootMethod::Init(): net stack initialized; root path is: %s\n",
|
|
|
|
rootPath);
|
|
|
|
|
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
NetBootMethod::IsBootDevice(KDiskDevice* device, bool strict)
|
|
|
|
{
|
|
|
|
// We support only NBD and RemoteDisk at the moment, so we accept any
|
|
|
|
// device under /dev/disk/virtual/{nbd,remote_disk}/.
|
|
|
|
return is_net_device(device);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
NetBootMethod::IsBootPartition(KPartition* partition, bool& foundForSure)
|
|
|
|
{
|
|
|
|
// as long as it's BFS, we're fine
|
|
|
|
return (partition->ContentType()
|
|
|
|
&& strcmp(partition->ContentType(), kPartitionTypeBFS) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
NetBootMethod::SortPartitions(KPartition** partitions, int32 count)
|
|
|
|
{
|
|
|
|
qsort(partitions, count, sizeof(KPartition*),
|
|
|
|
compare_partitions_net_devices);
|
|
|
|
}
|