How to add DFU support to u-boot? - arm

I'm trying to add DFU support to the u-boot I'm using in my project because I figured out that DFU support is not enabled in it.
I'm using freescale u-boot (cloning from git://git.freescale.com/imx/uboot-imx.git) and I checked out the tag "rel_imx_4.1.15_1.1.0_ga" wich is the one I'm required to work on.
The thing is that going through the u-boot documentation I can see that DFU have to be enabled. I added the following to my .h file
#define CONFIG_USB_FUNCTION_DFU
#define CONFIG_CMD_DFU
#define CONFIG_DFU_MMC
#define CONFIG_SYS_DFU_DATA_BUF_SIZE SZ_16M
#define DFU_DEFAULT_POLL_TIMEOUT 300
But I'm getting the following errors:
common/built-in.o: In function `do_dfu':
/home/m4l490n/uboot-imx/common/cmd_dfu.c:29: undefined reference to `dfu_init_env_entities'
/home/m4l490n/uboot-imx/common/cmd_dfu.c:35: undefined reference to `dfu_show_entities'
/home/m4l490n/uboot-imx/common/cmd_dfu.c:41: undefined reference to `g_dnl_clear_detach'
/home/m4l490n/uboot-imx/common/cmd_dfu.c:42: undefined reference to `g_dnl_register'
/home/m4l490n/uboot-imx/common/cmd_dfu.c:44: undefined reference to `g_dnl_detach'
/home/m4l490n/uboot-imx/common/cmd_dfu.c:50: undefined reference to `dfu_usb_get_reset'
/home/m4l490n/uboot-imx/common/cmd_dfu.c:67: undefined reference to `usb_gadget_handle_interrupts'
/home/m4l490n/uboot-imx/common/cmd_dfu.c:70: undefined reference to `g_dnl_unregister'
/home/m4l490n/uboot-imx/common/cmd_dfu.c:72: undefined reference to `dfu_free_entities'
/home/m4l490n/uboot-imx/common/cmd_dfu.c:77: undefined reference to `g_dnl_clear_detach'
arm-linux-gnueabihf-ld.bfd: BFD (GNU Binutils for Ubuntu) 2.24 assertion fail ../../bfd/elf32-arm.c:7696
arm-linux-gnueabihf-ld.bfd: BFD (GNU Binutils for Ubuntu) 2.24 assertion fail ../../bfd/elf32-arm.c:7696
arm-linux-gnueabihf-ld.bfd: BFD (GNU Binutils for Ubuntu) 2.24 assertion fail ../../bfd/elf32-arm.c:7696
arm-linux-gnueabihf-ld.bfd: BFD (GNU Binutils for Ubuntu) 2.24 assertion fail ../../bfd/elf32-arm.c:7696
arm-linux-gnueabihf-ld.bfd: BFD (GNU Binutils for Ubuntu) 2.24 assertion fail ../../bfd/elf32-arm.c:7696
arm-linux-gnueabihf-ld.bfd: BFD (GNU Binutils for Ubuntu) 2.24 assertion fail ../../bfd/elf32-arm.c:7696
arm-linux-gnueabihf-ld.bfd: BFD (GNU Binutils for Ubuntu) 2.24 assertion fail ../../bfd/elf32-arm.c:7696
arm-linux-gnueabihf-ld.bfd: BFD (GNU Binutils for Ubuntu) 2.24 assertion fail ../../bfd/elf32-arm.c:7696
arm-linux-gnueabihf-ld.bfd: BFD (GNU Binutils for Ubuntu) 2.24 assertion fail ../../bfd/elf32-arm.c:7696
arm-linux-gnueabihf-ld.bfd: error: required section '.rel.plt' not found in the linker script
arm-linux-gnueabihf-ld.bfd: final link failed: Invalid operation
make: *** [u-boot] Error 1
I noticed that If I remove #define CONFIG_CMD_DFU from the .h file it compiles fine but if I enter => dfu in the u-boot shell it says:
Unknown command 'dfu' - try 'help'
So the question is *Do you know what else do I need to add to enable DFU in the u-boot I'm using?
Thanks!!

To fix these linking errors:
undefined reference to dfu_*
enable the USB portion of the DFU USB class:
#define CONFIG_DFU_FUNCTION
To fix this linking error:
undefined reference to usb_gadget_handle_interrupts
enable your UDC controller (I'm pretty sure your platform has ChipIdea UDC controller), and also enable USB gadget:
#define CONFIG_CI_UDC
#define CONFIG_USBD_HS
#define CONFIG_USB_GADGET
#define CONFIG_USB_GADGET_DUALSPEED
#define CONFIG_USB_GADGET_VBUS_DRAW 2
To fix these linking errors:
undefined reference to g_dnl_*
enable and configure USB download gadget:
#define CONFIG_USBDOWNLOAD_GADGET
#define CONFIG_G_DNL_VENDOR_NUM 0x18d1
#define CONFIG_G_DNL_PRODUCT_NUM 0x0d02
#define CONFIG_G_DNL_MANUFACTURER "FSL"
Now you should be able to build U-Boot successfully. Tested on configs/mx7dsabresd_defconfig (with changes to include/configs/mx7dsabresd.h). Configuration values for download gadget (G_DNL) were taken from include/configs/mx7dsabresdandroid.h.
Basically, linking problems can be solved next way. To find out what definition is missing, you can look where missing function is implemented, then look for Makefile where corresponding source file is enabled for build, and from that Makefile you can figure out which option to define, so that corresponding object-file is built and wanted function is in place at linking stage.

Related

Linking EFI application with LLVM on MacOS

I'm attempting to cross-compile and link a very simple EFI application that is using the EFI headers from the Zircon kernel. Despite my best efforts, I am unable to link a working PE executable under macOS Montery (with apple silicon), due to the LLD flag -subsystem:efi_application not being valid. The full error is:
FAILED: test.efi: && /opt/local/bin/clang -target x86_64-none-elf -ffreestanding -nostdlib -fuse-ld=lld -dll -WX -Wl,-subsystem:efi_application -Wl,entry:efi_main src/main.c.obj -o test.efi && :
ld.lld: error: unknown argument '-subsystem:efi_application'
Several guides indicate that lld-link is required to compile this correctly, however adding -fuse-ld=lld-link results in errors stating:
clang: error: invalid linker name in argument '-fuse-ld=lld-link'
This occurs despite the fact that I have lld-link in my $PATH. If I, instead, pass the full lld-link path to -fuse-ld=, I get the following error:
FAILED: test.efi: && /opt/local/bin/clang -target x86_64-none-elf -ffreestanding -target x86_64-none-elf -nostdlib -dll -WX -Wl,-subsystem:efi_application -Wl,-entry:efi_main -fuse-ld=/opt/local/bin/lld-link src/main.c.obj -o test.efi && :
lld-link: warning: ignoring unknown argument '--eh-frame-hdr'
lld-link: warning: ignoring unknown argument '-m'
lld-link: warning: ignoring unknown argument '-dynamic-linker'
lld-link: warning: ignoring unknown argument '-o'
lld-link: warning: ignoring unknown argument '-L/opt/local/libexec/llvm-13/bin/../lib'
lld-link: warning: ignoring unknown argument '-L/usr/lib'
lld-link: error: could not open 'elf_x86_64': No such file or directory
lld-link: error: could not open '/lib64/ld-linux-x86-64.so.2': No such file or directory
lld-link: error: could not open 'test.efi': No such file or directory
lld-link: error: src/main.c.obj: unknown file type
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I am using the MacPorts LLVM-13 package. The result of $ lld-link --version is LLD 13.0.0.
For reference, the code I'm attempting to compile and link is, simply:
#include "efi/protocol/graphics-output.h"
#include "efi/protocol/loaded-image.h"
#include "efi/system-table.h"
#include "efi/types.h"
#define ERR(x) if (EFI_ERROR((x))) { return (x); }
efi_status efi_main(efi_handle handle __attribute__((unused)), efi_system_table* st) {
efi_status status;
/* clear the screen */
status = st->ConOut->ClearScreen(st->ConOut);
ERR(status);
/* print 'Hello World' */
status = st->ConOut->OutputString(st->ConOut, u"Hello World");
ERR(status);
return EFI_SUCCESS;
}
What do I need to change above in order to build an EFI application using LLVM on macOS?
I'd also be curious to know any ideas as to why -fuse-ld=lld-link would fail when it exists in my PATH, and why using -fuse-ld=/opt/local/bin/lld-link would result in other implicit linker flags not succeeding.
System Details:
Compiler Suite: LLVM-13 (Macport Installation)
Host OS: macOS Monterey (Apple Silicon, M1 Pro)
Target Arch: x86_64
Build System: CMake using custom toolchain (which passes the -nostdlib, -target ... args, etc.)
You can try to use clang-cl to compile your code, using /c option to compile only: do not link yet. Use /Fo option to specify the output object file.
The clang-cl offers compatibility options from MSVC cl.exe. For further details, run clang-cl --help. The build target of clang-cl is default to windows, so you don't have to reset the build target in order to compile for EFI applications.
Be warned that clang-cl does not have full support to MSVC intrinsics. Intrinsics like __vmx_vmptrld, __svm_vmload, etc. are broken. clang-cl would generate a call instruction rather than the specific instruction. Define them in inline assembly in GCC's syntax, if you want to use these intrinsics.
After you compiled all source files into object files, run lld-link to link all output object files with /SUBSYSTEM:EFI_APPLICATION parameter into an EFI application.
I haven't used the header files from Zircon yet, but I tried compiling EDK II libraries with LLVM into .lib files on Windows.
With the help of these .lib files, I made some simple EFI applications. For instance, you can check this partition enumerator out.
The batch scripts might not work on MacOS, but, by reading them, you can definitely figure out the general ideas about how to specify the parameters.
If you want to use EDK II by virtue of its rich libraries, you might want to install Netwide Assembler as well, in that the assembly codes in EDK II libraries are NASM.

How to compile longjmp using emcc?

I'm trying to diagnose a linker issue with emcc. I've got it down to the following file:
#include <setjmp.h>
jmp_buf error;
int main(int argc, char *argv[]) {
int n = setjmp(error);
if (n)
return n;
longjmp(error, 33);
return 0;
}
When compiled with gcc, this file produces an a.out that exits with code 33 as expected. But when compiled with emcc, it fails at the linking step, with this error:
nr#homedog ~/s/c [1]> emcc -s LLD_REPORT_UNDEFINED longjmp.c
error: undefined symbol: __invoke_void_$struct___jmp_buf_tag*_i32 (referenced by top-level compiled C/C++ code)
warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
warning: ___invoke_void_$struct___jmp_buf_tag*_i32 may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
error: undefined symbol: emscripten_longjmp_jmpbuf (referenced by top-level compiled C/C++ code)
warning: _emscripten_longjmp_jmpbuf may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
Adding it to EXPORTED_FUNCTIONS results instead in this error:
wasm-ld: error: symbol exported via --export not found: emscripten_longjmp_jmpbuf
What do I need to do to compile this file?
I am running Debian stable (bullseye) with Emscripten version 2.0.12.
ETA: emcc reports versions as follows:
nr#homedog ~/s/c [1]> emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.12
Debian clang version 11.0.1-2
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /usr/bin
It looks like you have a mismatched llvm (clang) and emscripten versions. We recommend using emsdk to install all correct dependencies (how are you install them?). If you don't want use emsdk you will need to build llvm from source at the correct revision.
Your example works find with the latest version of emscripten:
$ emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.29-git (6e9e10d3f78eb249bf09922a23e19c3f81a86d0f)
...
$ emcc -s LLD_REPORT_UNDEFINED setjmp.c

`__heap_base` seems to be missing in clang 9.0.0, is there a replacement?

I'm trying to compile a C library of mine for WebAssembly, using clang (no emscripten), and it compiles fine with clang version 8.0.1, but fails with clang version 9.0.0. The reported error is wasm-ld: error: ….o: undefined symbol: __heap_base. Has __heap_base been replaced with some other symbol?
The library is open source and compilation instructions can be found here
Actually, I believe I found the culprit: the linker in 9.0.0 seems to require the --export=__heap_base (-Wl,--export=__heap_base for the clang). This works for my project.
This does seem to be bug in 9.0.0. It doesn't seem to occur with ToT or with 8.0.0.
Simple repro case:
extern void* __heap_base;
void* a = &__heap_base;
void _start() {
}
Build with:
$ clang --target=wasm32 test.c -nostdlib -Wl,-no-gc-sections
With 9.0.0:
wasm-ld: error: /tmp/test-551a5c.o: undefined symbol: __heap_base
clang-9: error: linker command failed with exit code 1 (use -v to see invocation)
This should be opened as bug in the llvm bug tracker.

Linking fails with gcc 4.8.2 / ld 2.24, succeeds with gcc 4.4.7 / ld 2.20

In a chroot based on CentOS 6.4 I'm working in, linking against ncurses with ld 2.20 succeeds, but linking with ld 2.24 fails. I don't directly invoke the linker, gcc is handling it -- gcc 4.4.7 is using ld 2.20, and gcc 4.8.2 is using ld 2.24.
Here is a minimal example that fails to link with gcc 4.8.2 / ld 2.24 in my particular environment.
#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
WINDOW* window = NULL;
if (!(window = initscr())) {
printf("Error initializing ncurses.");
exit(1);
}
halfdelay(50);
getch();
endwin();
}
Success (ld 2.20):
$ gcc main.c -lncurses -Wl,--verbose | grep "ncurses.*succeeded"
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/libncurses.so succeeded
$
Failure (ld 2.24):
$ /opt/gcc/4.8.2/bin/gcc48 main.c -lncurses -Wl,--verbose | grep "ncurses.*succeeded"
attempt to open /usr/lib/../lib64/libncurses.so succeeded
/opt/binutils/2.24/bin/ld24: /tmp/ccCxUFxl.o: undefined reference to symbol 'halfdelay'
/lib64/libtinfo.so.5: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
$
Note that both commands appear to link against the same libncurses.so.
For what it's worth, in a different chroot based on CentOS 5.4, there is a different libncurses version, and it links fine with ld 2.24, but unfortunately, building in that chroot is not an option. The nm utility shows that the (static) libncurses.a here does have the required symbols (nm lists no symbols for libncurses.so -- so I'm just assuming they are similar).
In the CentOS 6.4 chroot, however, nm shows that all of the ncurses symbols I'm getting "undefined reference" messages for are indeed undefined or not present in libncurses.a in the Centos 6.4 chroot, which is confusing, because linking with gcc 4.4.7 works. Something is not right.
Also, I tried producing an object with gcc 4.4.7, and then linking with gcc 4.8.2, but that did not help.
I'm confused as to why the one compiler / linker would succeed while the other would fail. Is this an ABI issue? Does anyone know what is happening here? Are there any flags I can pass to gcc to make the new linker work?
Your libncurses library is itself linked to libtinfo, which causes your older toolchain to also look for symbols in libtinfo.
But newer toolchains normally runs the linker with the --as-needed, and the --no-copy-dt-needed-entries, the latter which probably causes the difference you're seeing.
Basically you'll need to link to libtinfo as well, which is where the halfdelay function resides.
gcc main.c -lncurses -ltinfo

Winsock Program in c language is not working

I've started another program to run Winsock in C language on Windows7.
I found this help on msdn:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms737591%28v=vs.85%29.aspx
This program is not working and showing these errors:
$ gcc ak1.c -o ak1.exe -lwsock32 -lws2_32 -lAdvapi32 -lmswsock
C:\Users\rahul\AppData\Local\Temp\ccWqZC7C.o:ak1.c:(.text+0x109): undefined re
ference to `getaddrinfo'
C:\Users\rahul\AppData\Local\Temp\ccWqZC7C.o:ak1.c:(.text+0x1fa): undefined re
ference to `freeaddrinfo'
c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../mingw32/bin/ld.exe: C:\Users\a
mit\AppData\Local\Temp\ccWqZC7C.o: bad reloc address 0x20 in section `.eh_frame'
c:/mingw/bin/../lib/gcc/mingw32/4.7.2/../../../../mingw32/bin/ld.exe: final link
failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
Is this error related to MICROSOFT SDK for Windows7, means these libraries are not added on my system.
I checked "Advapi32" is not under my micrsoft SDK.
Help please !!!
You're using GCC (presumably MinGW) which doesn't use Microsoft's SDK. getaddrinfo() and freeaddrinfo() are declared in MinGW's ws2tcpip.h implementation, but only if WinXP or later is targeted.
Add -D_WIN32_WINNT=0x0501 to your compiler command line to target XP.
the solution is to add "-lws2_32" at the end of the command to compile with gcc ;-)

Resources