netfs.c
来自「EFI(Extensible Firmware Interface)是下一代BI」· C语言 代码 · 共 791 行 · 第 1/2 页
C
791 行
VERB_PRT(2, Print(L"Done\n")); } else { netfs_fd_free(nfs, f); VERB_PRT(2, Print(L"Failed: %r\n", status)); } DBG_PRT((L"File %s netbuf_size=%d: %r", name, f->netbuf_size, status));#if 0 Print(L"\n---\n"); { INTN i; for(i=0; i < netbuf_size; i++) { Print(L"%c", (CHAR16)netbuf[i]); } } Print(L"\n---\n");#endif return status;}static EFI_STATUSnetfs_read(netfs_interface_t *this, UINTN fd, VOID *buf, UINTN *size){ netfs_priv_state_t *nfs; netfs_fd_t *f; UINTN count; if (this == NULL || fd >= NETFS_FD_MAX || buf == NULL || size == NULL) return EFI_INVALID_PARAMETER; nfs = FS_PRIVATE(this); f = NETFS_FD2F(nfs, fd); if (NETFS_F_INVALID(f)) return EFI_INVALID_PARAMETER; count = MIN(*size, f->netbuf_size - f->netbuf_pos); if (count) Memcpy(buf, f->netbuf+f->netbuf_pos, count); *size = count; f->netbuf_pos += count; return EFI_SUCCESS;}static EFI_STATUSnetfs_close(netfs_interface_t *this, UINTN fd){ netfs_priv_state_t *nfs; netfs_fd_t *f; if (this == NULL || fd >= NETFS_FD_MAX) return EFI_INVALID_PARAMETER; nfs = FS_PRIVATE(this); f = NETFS_FD2F(nfs, fd); if (NETFS_F_INVALID(f)) return EFI_INVALID_PARAMETER; netfs_fd_free(nfs, f); return EFI_SUCCESS;}static EFI_STATUSnetfs_seek(netfs_interface_t *this, UINTN fd, UINT64 newpos){ netfs_priv_state_t *nfs; netfs_fd_t *f; if (this == NULL || fd >= NETFS_FD_MAX) return EFI_INVALID_PARAMETER; nfs = FS_PRIVATE(this); f = NETFS_FD2F(nfs, fd); if (NETFS_F_INVALID(f)) return EFI_INVALID_PARAMETER; if (newpos > f->netbuf_size) return EFI_INVALID_PARAMETER; f->netbuf_pos = newpos; return EFI_SUCCESS;}static EFI_STATUSnetfs_infosize(netfs_interface_t *this, UINTN fd, UINT64 *sz){ netfs_priv_state_t *nfs; netfs_fd_t *f; if (this == NULL || fd >= NETFS_FD_MAX || sz == NULL) return EFI_INVALID_PARAMETER; nfs = FS_PRIVATE(this); f = NETFS_FD2F(nfs, fd); if (NETFS_F_INVALID(f)) return EFI_INVALID_PARAMETER; *sz = f->netbuf_size; return EFI_SUCCESS;}static INTNfind_dhcp_option(EFI_PXE_BASE_CODE_PACKET *packet, UINT8 use_ipv6, UINT8 option, CHAR8 *str, INTN *len){ INTN i = 0; UINT8 tag, length; UINT8 *opts = packet->Dhcpv4.DhcpOptions; *len = 0; for(;;) { if (i >= 56) { DBG_PRT((L"reach end of options (no marker)\n")); break; } tag = opts[i++]; if (tag == 0) continue; if (tag == 255) break; length = opts[i++];#if 0 { UINT8 l = length, k = 0; Print(L"found option %d len=%d: ", tag, length); while (l--) { Print(L"%c(%d)\n", (CHAR16)opts[k], opts[k]); k++; } Print(L"\n"); }#endif if (tag == option) { *len = length; while (length--) { *str++ = opts[i++]; } return 0; } i += length; } return -1;}static EFI_STATUSnetfs_getinfo(netfs_interface_t *this, netfs_info_t *info){ netfs_priv_state_t *nfs; CHAR8 str[256]; INTN len, r; if (this == NULL || info == NULL) return EFI_INVALID_PARAMETER; nfs = FS_PRIVATE(this); Memcpy(&info->cln_ipaddr, &nfs->cln_ip, sizeof(EFI_IP_ADDRESS)); Memcpy(&info->srv_ipaddr, &nfs->srv_ip, sizeof(EFI_IP_ADDRESS)); Memcpy(&info->netmask, &nfs->netmask, sizeof(EFI_IP_ADDRESS)); Memcpy(&info->gw_ipaddr, &nfs->gw_ip, sizeof(EFI_IP_ADDRESS)); Memcpy(&info->hw_addr, &nfs->hw_addr, sizeof(info->hw_addr)); info->using_pxe = nfs->using_pxe; info->started = nfs->pxe->Mode->Started; info->using_ipv6 = nfs->pxe->Mode->UsingIpv6; if (nfs->pxe->Mode->UsingIpv6) goto skip_options; r = find_dhcp_option(&nfs->pxe->Mode->DhcpAck,nfs->pxe->Mode->UsingIpv6, 15, str, &len); str[len] = '\0'; ascii2U(str, info->domainame, 255); VERB_PRT(3, Print(L"domain(15): %a\n", str)); r = find_dhcp_option(&nfs->pxe->Mode->DhcpAck,nfs->pxe->Mode->UsingIpv6, 12, str, &len); str[len] = '\0'; ascii2U(str, info->hostname, 255); VERB_PRT(3, Print(L"hostname(12): %a\n", str)); /* * extract bootfile name from DHCP exchanges */ if (nfs->using_pxe == 0) { ascii2U(nfs->pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, info->bootfile, NETFS_BOOTFILE_MAXLEN); VERB_PRT(3, Print(L"bootfile: %s\n", info->bootfile)); }skip_options: return EFI_SUCCESS;}static UINT16find_pxe_server_type(EFI_PXE_BASE_CODE *pxe){ INTN i = 0, max; UINT8 tag, length; UINT8 *opts = pxe->Mode->PxeReply.Dhcpv4.DhcpOptions; UINT16 server_type; while(i < 55) { tag = opts[i]; length = opts[i+1]; DBG_PRT((L"Tag #%d Length %d\n",tag, length)); if (tag == 43) goto found; i += 2 + length; } return NETFS_DEFAULT_SERVER_TYPE;found: max = i+2+length; i += 2; while (i < max) { tag = opts[i]; length = opts[i+1]; if (tag == 71) { server_type =(opts[i+2]<<8) | opts[i+3]; DBG_PRT((L"ServerType: %d\n", server_type)); return server_type; } i+= 2 + length; } return NETFS_DEFAULT_SERVER_TYPE;}static EFI_STATUSnetfs_query_layer(netfs_interface_t *this, UINT16 server_type, UINT16 layer, UINTN maxlen, CHAR16 *str){ netfs_priv_state_t *nfs; EFI_STATUS status; if (this == NULL || str == NULL) return EFI_INVALID_PARAMETER; nfs = FS_PRIVATE(this); if (nfs->using_pxe == FALSE) return EFI_UNSUPPORTED; if (server_type == 0) server_type = find_pxe_server_type(nfs->pxe); status = nfs->pxe->Discover(nfs->pxe, server_type, &layer, FALSE, 0); if(status == EFI_SUCCESS) { ascii2U(nfs->pxe->Mode->PxeReply.Dhcpv4.BootpBootFile, str, maxlen); } return status;}static VOIDnetfs_init_state(netfs_t *netfs, EFI_HANDLE dev, EFI_PXE_BASE_CODE *pxe){ netfs_priv_state_t *nfs = FS_PRIVATE(netfs); UINTN i; /* need to do some init here on netfs_intf */ Memset(netfs, 0, sizeof(*netfs)); netfs->pub_intf.netfs_name = netfs_name; netfs->pub_intf.netfs_open = netfs_open; netfs->pub_intf.netfs_read = netfs_read; netfs->pub_intf.netfs_close = netfs_close; netfs->pub_intf.netfs_infosize = netfs_infosize; netfs->pub_intf.netfs_seek = netfs_seek; netfs->pub_intf.netfs_query_layer = netfs_query_layer; netfs->pub_intf.netfs_getinfo = netfs_getinfo; nfs->dev = dev; nfs->pxe = pxe; /* * we defer DHCP request until it is really necessary (netfs_open) */ if (pxe->Mode->Started == TRUE) netfs_extract_ip(nfs); Memset(nfs->fd_tab, 0, sizeof(nfs->fd_tab)); for (i=0; i < NETFS_FD_MAX-1; i++) { nfs->fd_tab[i].next = &nfs->fd_tab[i+1]; } /* null on last element is done by memset */ nfs->free_fd = nfs->fd_tab; nfs->free_fd_count = NETFS_FD_MAX;}static EFI_STATUSnetfs_install_one(EFI_HANDLE dev, VOID **intf){ EFI_STATUS status; netfs_t *netfs; EFI_PXE_BASE_CODE *pxe; status = BS->HandleProtocol (dev, &NetFsProtocol, (VOID **)&netfs); if (status == EFI_SUCCESS) { ERR_PRT((L"Warning: found existing %s protocol on device", FS_NAME)); goto found; } status = BS->HandleProtocol (dev, &PxeBaseCodeProtocol, (VOID **)&pxe); if (EFI_ERROR(status)) return EFI_INVALID_PARAMETER; netfs = (netfs_t *)alloc(sizeof(*netfs), EfiLoaderData); if (netfs == NULL) { ERR_PRT((L"failed to allocate %s", FS_NAME)); return EFI_OUT_OF_RESOURCES; } netfs_init_state(netfs, dev, pxe); status = LibInstallProtocolInterfaces(&dev, &NetFsProtocol, netfs, NULL); if (EFI_ERROR(status)) { ERR_PRT((L"Cannot install %s protocol: %r", FS_NAME, status)); free(netfs); return status; }found: if (intf) *intf = (VOID *)netfs; VERB_PRT(3, { EFI_DEVICE_PATH *dp; CHAR16 *str; dp = DevicePathFromHandle(dev); str = DevicePathToStr(dp); Print(L"attached %s to %s\n", FS_NAME, str); FreePool(str); }); return EFI_SUCCESS;} EFI_STATUSnetfs_install(VOID){ UINTN size = 0; UINTN i; EFI_STATUS status; VOID *intf; BS->LocateHandle(ByProtocol, &PxeBaseCodeProtocol, NULL, &size, NULL); if (size == 0) return EFI_UNSUPPORTED; /* no device found, oh well */ DBG_PRT((L"size=%d", size)); dev_tab = (dev_tab_t *)alloc(size, EfiLoaderData); if (dev_tab == NULL) { ERR_PRT((L"failed to allocate handle table")); return EFI_OUT_OF_RESOURCES; } status = BS->LocateHandle(ByProtocol, &PxeBaseCodeProtocol, NULL, &size, (VOID **)dev_tab); if (status != EFI_SUCCESS) { ERR_PRT((L"failed to get handles: %r", status)); free(dev_tab); return status; } ndev = size / sizeof(EFI_HANDLE); for(i=0; i < ndev; i++) { intf = NULL; netfs_install_one(dev_tab[i].dev, &intf); /* override device handle with interface pointer */ dev_tab[i].intf = intf; } return EFI_SUCCESS;} EFI_STATUSnetfs_uninstall(VOID){ netfs_priv_state_t *nfs; EFI_STATUS status; UINTN i; for(i=0; i < ndev; i++) { if (dev_tab[i].intf == NULL) continue; nfs = FS_PRIVATE(dev_tab[i].intf); status = BS->UninstallProtocolInterface(nfs->dev, &NetFsProtocol, dev_tab[i].intf); if (EFI_ERROR(status)) { ERR_PRT((L"Uninstall %s error: %r", FS_NAME, status)); continue; } VERB_PRT(3, { EFI_DEVICE_PATH *dp; CHAR16 *str; dp = DevicePathFromHandle(nfs->dev); str = DevicePathToStr(dp); Print(L"uninstalled %s on %s\n", FS_NAME, str); FreePool(str); }); if (nfs->pxe->Mode->Started == TRUE) nfs->pxe->Stop(nfs->pxe); free(dev_tab[i].intf); } if (dev_tab) free(dev_tab); return EFI_SUCCESS;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?