From 43792b9eeda5ba6d5fc57b0779537681a022cfeb Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Fri, 12 Jan 2007 22:27:48 +0000 Subject: [PATCH] propagate required settings for the remote disk from boot loader to kernel (client-ip, server-ip, server-port) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19780 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/boot/disk_identifier.h | 6 + headers/private/kernel/boot/kernel_args.h | 1 + headers/private/kernel/boot/net/RemoteDisk.h | 3 + src/system/boot/loader/net/RemoteDisk.cpp | 12 + .../boot/platform/bios_ia32/devices.cpp | 1 + src/system/boot/platform/pxe_ia32/devices.cpp | 27 +- src/system/boot/platform/pxe_ia32/network.cpp | 32 +- src/system/boot/platform/pxe_ia32/network.h | 319 +----------------- src/system/kernel/fs/vfs_boot.cpp | 7 + 9 files changed, 61 insertions(+), 347 deletions(-) diff --git a/headers/private/kernel/boot/disk_identifier.h b/headers/private/kernel/boot/disk_identifier.h index 52f2cebf37..7c8a5651e0 100644 --- a/headers/private/kernel/boot/disk_identifier.h +++ b/headers/private/kernel/boot/disk_identifier.h @@ -23,6 +23,7 @@ enum device_types { USB_DEVICE, FIREWIRE_DEVICE, FIBRE_DEVICE, + NETWORK_DEVICE, }; #define NUM_DISK_CHECK_SUMS 5 @@ -61,6 +62,11 @@ typedef struct disk_identifier { struct { uint64 wwd; } fibre; + struct { + uint32 client_ip; + uint32 server_ip; + uint16 server_port; + } network; struct { off_t size; struct { diff --git a/headers/private/kernel/boot/kernel_args.h b/headers/private/kernel/boot/kernel_args.h index 24aa866772..bd52047d5f 100644 --- a/headers/private/kernel/boot/kernel_args.h +++ b/headers/private/kernel/boot/kernel_args.h @@ -46,6 +46,7 @@ typedef struct kernel_args { off_t partition_offset; bool user_selected; bool booted_from_image; + bool booted_from_network; bool cd; } boot_disk; diff --git a/headers/private/kernel/boot/net/RemoteDisk.h b/headers/private/kernel/boot/net/RemoteDisk.h index f862e4e97c..cddd5842f4 100644 --- a/headers/private/kernel/boot/net/RemoteDisk.h +++ b/headers/private/kernel/boot/net/RemoteDisk.h @@ -28,6 +28,9 @@ public: virtual status_t GetName(char *nameBuffer, size_t bufferSize) const; virtual off_t Size() const; + ip_addr_t ServerIPAddress() const; + uint16 ServerPort() const; + static RemoteDisk *FindAnyRemoteDisk(); private: diff --git a/src/system/boot/loader/net/RemoteDisk.cpp b/src/system/boot/loader/net/RemoteDisk.cpp index 5bef3c6414..838363d69b 100644 --- a/src/system/boot/loader/net/RemoteDisk.cpp +++ b/src/system/boot/loader/net/RemoteDisk.cpp @@ -179,6 +179,18 @@ RemoteDisk::Size() const return fImageSize; } +ip_addr_t +RemoteDisk::ServerIPAddress() const +{ + return fServerAddress; +} + +uint16 +RemoteDisk::ServerPort() const +{ + return fServerPort; +} + // FindAnyRemoteDisk RemoteDisk * RemoteDisk::FindAnyRemoteDisk() diff --git a/src/system/boot/platform/bios_ia32/devices.cpp b/src/system/boot/platform/bios_ia32/devices.cpp index b0de718942..a9f9878f2a 100644 --- a/src/system/boot/platform/bios_ia32/devices.cpp +++ b/src/system/boot/platform/bios_ia32/devices.cpp @@ -757,6 +757,7 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) TRACE(("boot drive size: %Ld bytes\n", drive->Size())); gKernelArgs.boot_disk.booted_from_image = gBootedFromImage; + gKernelArgs.boot_disk.booted_from_network = false; return B_OK; } diff --git a/src/system/boot/platform/pxe_ia32/devices.cpp b/src/system/boot/platform/pxe_ia32/devices.cpp index 7301cd668c..8961529bca 100644 --- a/src/system/boot/platform/pxe_ia32/devices.cpp +++ b/src/system/boot/platform/pxe_ia32/devices.cpp @@ -6,6 +6,7 @@ #include "bios.h" #include "pxe_undi.h" +#include "network.h" #include #include @@ -37,8 +38,12 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) // init a remote disk, if possible RemoteDisk *remoteDisk = RemoteDisk::FindAnyRemoteDisk(); - if (!remoteDisk) + if (!remoteDisk) { + unsigned ip = NetStack::Default()->GetEthernetInterface()->IPAddress(); + panic("PXE boot: can't find remote disk on server %u.%u.%u.%u\n", + (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); return B_ENTRY_NOT_FOUND; + } devicesList->Add(remoteDisk); return B_OK; @@ -74,11 +79,23 @@ status_t platform_register_boot_device(Node *device) { TRACE("platform_register_boot_device\n"); - disk_identifier &disk = gKernelArgs.boot_disk.identifier; - disk.bus_type = UNKNOWN_BUS; - disk.device_type = UNKNOWN_DEVICE; - disk.device.unknown.size = device->Size(); + gKernelArgs.platform_args.boot_drive_number = 0xffff; + gKernelArgs.platform_args.drives = NULL; + + RemoteDisk *rd = static_cast(device); + UNDI *undi = static_cast(NetStack::Default()->GetEthernetInterface()); + + gKernelArgs.boot_disk.identifier.bus_type = UNKNOWN_BUS; + gKernelArgs.boot_disk.identifier.device_type = NETWORK_DEVICE; + gKernelArgs.boot_disk.identifier.device.network.client_ip = undi->IPAddress(); + gKernelArgs.boot_disk.identifier.device.network.server_ip = rd->ServerIPAddress(); + gKernelArgs.boot_disk.identifier.device.network.server_port = rd->ServerPort(); + gKernelArgs.boot_disk.partition_offset = 0; + gKernelArgs.boot_disk.user_selected = false; + gKernelArgs.boot_disk.booted_from_image = false; + gKernelArgs.boot_disk.booted_from_network = true; + gKernelArgs.boot_disk.cd = false; return B_OK; } diff --git a/src/system/boot/platform/pxe_ia32/network.cpp b/src/system/boot/platform/pxe_ia32/network.cpp index 6c3ddc7158..f522b94794 100644 --- a/src/system/boot/platform/pxe_ia32/network.cpp +++ b/src/system/boot/platform/pxe_ia32/network.cpp @@ -9,12 +9,9 @@ #include #include -#include #include -#include -#include - +#include "network.h" #include "pxe_undi.h" //#define TRACE_NETWORK @@ -52,29 +49,6 @@ hex_dump(const void *_data, int length) #endif // !TRACE_NETWORK -class UNDI : public EthernetInterface -{ -public: - UNDI(); - virtual ~UNDI(); - - status_t Init(); - - virtual mac_addr_t MACAddress() const; - - virtual void * AllocateSendReceiveBuffer(size_t size); - virtual void FreeSendReceiveBuffer(void *buffer); - - virtual ssize_t Send(const void *buffer, size_t size); - virtual ssize_t Receive(void *buffer, size_t size); - -private: - mac_addr_t fMACAddress; - bool fRxFinished; - PXE_STRUCT * fPxeData; -}; - - UNDI::UNDI() : fMACAddress() , fRxFinished(true) @@ -123,7 +97,9 @@ UNDI::Init() ip_addr_t ipClient = ntohl(*(ip_addr_t *)(buf + 16)); ip_addr_t ipServer = ntohl(*(ip_addr_t *)(buf + 20)); - dprintf("client-ip: %08x, server-ip: %08x\n", (int)ipClient, (int)ipServer); + dprintf("client-ip: %lu.%lu.%lu.%lu, server-ip: %lu.%lu.%lu.%lu\n", + (ipClient >> 24) & 0xff, (ipClient >> 16) & 0xff, (ipClient >> 8) & 0xff, ipClient & 0xff, + (ipServer >> 24) & 0xff, (ipServer >> 16) & 0xff, (ipServer >> 8) & 0xff, ipServer & 0xff); SetIPAddress(ipClient); diff --git a/src/system/boot/platform/pxe_ia32/network.h b/src/system/boot/platform/pxe_ia32/network.h index 6c3ddc7158..15a34999f8 100644 --- a/src/system/boot/platform/pxe_ia32/network.h +++ b/src/system/boot/platform/pxe_ia32/network.h @@ -1,56 +1,16 @@ +#ifndef _PXE_NETWORK_H +#define _PXE_NETWORK_H /* * Copyright 2006, Marcus Overhagen . * Distributed under the terms of the MIT License. */ -#include -#include -#include -#include - #include -#include - #include #include -#include "pxe_undi.h" - -//#define TRACE_NETWORK -#ifdef TRACE_NETWORK -# define TRACE(x...) dprintf(x) -#else -# define TRACE(x...) -#endif - -#ifdef TRACE_NETWORK - -static void -hex_dump(const void *_data, int length) -{ - uint8 *data = (uint8*)_data; - for (int i = 0; i < length; i++) { - if (i % 4 == 0) { - if (i % 32 == 0) { - if (i != 0) - TRACE("\n"); - TRACE("%03x: ", i); - } else - TRACE(" "); - } - - TRACE("%02x", data[i]); - } - TRACE("\n"); -} - -#else // !TRACE_NETWORK - -#define hex_dump(data, length) - -#endif // !TRACE_NETWORK - +struct PXE_STRUCT; class UNDI : public EthernetInterface { @@ -60,6 +20,7 @@ public: status_t Init(); + ip_addr_t ServerIPAddress() const; virtual mac_addr_t MACAddress() const; virtual void * AllocateSendReceiveBuffer(size_t size); @@ -74,274 +35,4 @@ private: PXE_STRUCT * fPxeData; }; - -UNDI::UNDI() - : fMACAddress() - , fRxFinished(true) - , fPxeData(NULL) -{ - TRACE("UNDI::UNDI\n"); - - fPxeData = pxe_undi_find_data(); - if (!fPxeData) - panic("can't find !PXE structure"); - - dprintf("PXE API entrypoint at %04x:%04x\n", fPxeData->EntryPointSP.seg, fPxeData->EntryPointSP.ofs); -} - - -UNDI::~UNDI() -{ - TRACE("UNDI::~UNDI\n"); -} - - -status_t -UNDI::Init() -{ - TRACE("UNDI::Init\n"); - - PXENV_GET_CACHED_INFO cached_info; - PXENV_UNDI_GET_INFORMATION get_info; - PXENV_UNDI_GET_STATE get_state; - PXENV_UNDI_OPEN undi_open; - uint16 res; - - cached_info.PacketType = PXENV_PACKET_TYPE_CACHED_REPLY; - cached_info.BufferSize = 0; - cached_info.BufferLimit = 0; - cached_info.Buffer.seg = 0; - cached_info.Buffer.ofs = 0; - res = call_pxe_bios(fPxeData, GET_CACHED_INFO, &cached_info); - if (res != 0 || cached_info.Status != 0) { - char s[100]; - snprintf(s, sizeof(s), "Can't determine IP address! PXENV_GET_CACHED_INFO res %x, status %x\n", res, cached_info.Status); - panic(s); - } - - char *buf = (char *)(cached_info.Buffer.seg * 16 + cached_info.Buffer.ofs); - ip_addr_t ipClient = ntohl(*(ip_addr_t *)(buf + 16)); - ip_addr_t ipServer = ntohl(*(ip_addr_t *)(buf + 20)); - - dprintf("client-ip: %08x, server-ip: %08x\n", (int)ipClient, (int)ipServer); - - SetIPAddress(ipClient); - - undi_open.OpenFlag = 0; - undi_open.PktFilter = FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS; - undi_open.R_Mcast_Buf.MCastAddrCount = 0; - - res = call_pxe_bios(fPxeData, UNDI_OPEN, &undi_open); - if (res != 0 || undi_open.Status != 0) { - dprintf("PXENV_UNDI_OPEN failed, res %x, status %x, ignoring\n", res, undi_open.Status); - } - - res = call_pxe_bios(fPxeData, UNDI_GET_STATE, &get_state); - if (res != 0 || get_state.Status != 0) { - dprintf("PXENV_UNDI_GET_STATE failed, res %x, status %x, ignoring\n", res, get_state.Status); - } else { - switch (get_state.UNDIstate) { - case PXE_UNDI_GET_STATE_STARTED: - TRACE("PXE_UNDI_GET_STATE_STARTED\n"); - break; - case PXE_UNDI_GET_STATE_INITIALIZED: - TRACE("PXE_UNDI_GET_STATE_INITIALIZED\n"); - break; - case PXE_UNDI_GET_STATE_OPENED: - TRACE("PXE_UNDI_GET_STATE_OPENED\n"); - break; - default: - TRACE("unknown undi state 0x%02x\n", get_state.UNDIstate); - break; - } - } - - res = call_pxe_bios(fPxeData, UNDI_GET_INFORMATION, &get_info); - if (res != 0 || get_info.Status != 0) { - dprintf("PXENV_UNDI_GET_INFORMATION failed, res %x, status %x\n", res, get_info.Status); - return B_ERROR; - } - - TRACE("Status = %x\n", get_info.Status); - TRACE("BaseIo = %x\n", get_info.BaseIo); - TRACE("IntNumber = %x\n", get_info.IntNumber); - TRACE("MaxTranUnit = %x\n", get_info.MaxTranUnit); - TRACE("HwType = %x\n", get_info.HwType); - TRACE("HwAddrLen = %x\n", get_info.HwAddrLen); - TRACE("RxBufCt = %x\n", get_info.RxBufCt); - TRACE("TxBufCt = %x\n", get_info.TxBufCt); - - fMACAddress = get_info.CurrentNodeAddress; - - TRACE("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", fMACAddress[0], fMACAddress[1], fMACAddress[2], fMACAddress[3], fMACAddress[4], fMACAddress[5]); - - return B_OK; -} - - -mac_addr_t -UNDI::MACAddress() const -{ - return fMACAddress; -} - - -void * -UNDI::AllocateSendReceiveBuffer(size_t size) -{ - TRACE("UNDI::AllocateSendReceiveBuffer, size %ld\n", size); - if (size > 0x3000) - return NULL; - - return (void *)0x500; -} - - -void -UNDI::FreeSendReceiveBuffer(void *buffer) -{ - TRACE("UNDI::FreeSendReceiveBuffer\n"); -} - - -ssize_t -UNDI::Send(const void *buffer, size_t size) -{ - TRACE("UNDI::Send, buffer %p, size %ld\n", buffer, size); - -// hex_dump(buffer, size); - - PXENV_UNDI_TRANSMIT undi_tx; - PXENV_UNDI_TBD undi_tbd; - - undi_tx.Protocol = P_UNKNOWN; - undi_tx.XmitFlag = XMT_DESTADDR; - undi_tx.DestAddr.seg = SEG((char *)buffer + 16); - undi_tx.DestAddr.ofs = OFS((char *)buffer + 16); - undi_tx.TBD.seg = SEG(&undi_tbd); - undi_tx.TBD.ofs = OFS(&undi_tbd); - - undi_tbd.ImmedLength = size; - undi_tbd.Xmit.seg = SEG(buffer); - undi_tbd.Xmit.ofs = OFS(buffer); - undi_tbd.DataBlkCount = 0; - - uint16 res = call_pxe_bios(fPxeData, UNDI_TRANSMIT, &undi_tx); - if (res != 0 || undi_tx.Status != 0) { - dprintf("UNDI_TRANSMIT failed, res %x, status %x\n", res, undi_tx.Status); - return 0; - } - - TRACE("UNDI_TRANSMIT success\n"); - - return size; -} - - -ssize_t -UNDI::Receive(void *buffer, size_t size) -{ - //TRACE("UNDI::Receive, buffer %p, size %ld\n", buffer, size); - - PXENV_UNDI_ISR undi_isr; - uint16 res; - - if (!fRxFinished) { - TRACE("continue receive...\n"); - - undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; - res = call_pxe_bios(fPxeData, UNDI_ISR, &undi_isr); - if (res != 0 || undi_isr.Status != 0) { - dprintf("PXENV_UNDI_ISR_IN_GET_NEXT failed, res %x, status %x\n", res, undi_isr.Status); - fRxFinished = true; - return 0; - } - - } else { - - undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_START; - - res = call_pxe_bios(fPxeData, UNDI_ISR, &undi_isr); - if (res != 0 || undi_isr.Status != 0) { - dprintf("PXENV_UNDI_ISR_IN_START failed, res %x, status %x\n", res, undi_isr.Status); - return -1; - } - - if (undi_isr.FuncFlag != PXENV_UNDI_ISR_OUT_OURS) { -// TRACE("not ours\n"); - return -1; - } - - // send EOI to pic ? - -// TRACE("PXENV_UNDI_ISR_OUT_OURS\n"); - - undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS; - res = call_pxe_bios(fPxeData, UNDI_ISR, &undi_isr); - if (res != 0 || undi_isr.Status != 0) { - dprintf("PXENV_UNDI_ISR_IN_PROCESS failed, res %x, status %x\n", res, undi_isr.Status); - return -1; - } - } - - switch (undi_isr.FuncFlag) { - case PXENV_UNDI_ISR_OUT_TRANSMIT: - TRACE("PXENV_UNDI_ISR_OUT_TRANSMIT\n"); - fRxFinished = false; - return 0; - - case PXENV_UNDI_ISR_OUT_RECEIVE: - TRACE("PXENV_UNDI_ISR_OUT_RECEIVE\n"); -// TRACE("BufferLength %d\n", undi_isr.BufferLength); -// TRACE("FrameLength %d\n", undi_isr.FrameLength); -// TRACE("FrameHeaderLength %d\n", undi_isr.FrameHeaderLength); - if (undi_isr.FrameLength > undi_isr.BufferLength) - panic("UNDI::Receive: multi buffer frames not supported"); - if (size > undi_isr.BufferLength) - size = undi_isr.BufferLength; - memcpy(buffer, (const void *)(undi_isr.Frame.seg * 16 + undi_isr.Frame.ofs), size); -// hex_dump(buffer, size); - fRxFinished = false; - return size; - - case PXENV_UNDI_ISR_OUT_BUSY: - TRACE("PXENV_UNDI_ISR_OUT_BUSY\n"); - fRxFinished = true; - return -1; - - case PXENV_UNDI_ISR_OUT_DONE: - TRACE("PXENV_UNDI_ISR_OUT_DONE\n"); - fRxFinished = true; - return -1; - - default: - TRACE("default!!!\n"); - return -1; - } -} - - -status_t -platform_net_stack_init() -{ - TRACE("platform_net_stack_init\n"); - - UNDI *interface = new(nothrow) UNDI; - if (!interface) - return B_NO_MEMORY; - - status_t error = interface->Init(); - if (error != B_OK) { - TRACE("platform_net_stack_init: interface init failed\n"); - delete interface; - return error; - } - - error = NetStack::Default()->AddEthernetInterface(interface); - if (error != B_OK) { - delete interface; - return error; - } - - return B_OK; -} +#endif diff --git a/src/system/kernel/fs/vfs_boot.cpp b/src/system/kernel/fs/vfs_boot.cpp index 2bba442338..574d85ce01 100644 --- a/src/system/kernel/fs/vfs_boot.cpp +++ b/src/system/kernel/fs/vfs_boot.cpp @@ -184,6 +184,7 @@ is_boot_device(kernel_args *args, KDiskDevice *device, bool strict) case USB_DEVICE: case FIREWIRE_DEVICE: case FIBRE_DEVICE: + case NETWORK_DEVICE: // TODO: implement me! break; } @@ -211,6 +212,12 @@ get_boot_partitions(kernel_args *args, PartitionStack &partitions) return status; } + if (args->boot_disk.booted_from_network) { + panic("get_boot_partitions: boot from network, server %08lx, client %08lx\n", + args->boot_disk.identifier.device.network.server_ip, + args->boot_disk.identifier.device.network.client_ip); + } + struct BootPartitionVisitor : KPartitionVisitor { BootPartitionVisitor(kernel_args &args, PartitionStack &stack) : fArgs(args), fPartitions(stack) {}