From 1f8f01a0941495672cb270d588a5c1d074687d91 Mon Sep 17 00:00:00 2001 From: Chris Hooper Date: Fri, 8 Nov 2024 23:29:46 -0800 Subject: [PATCH] Build / release system - Made top level Makefile able to build lha and zip release images hostsmash - Fixed broken MacOS build -- should now support file service (untested) --- .gitignore | 3 ++ Makefile | 75 +++++++++++++++++++++++++++++++--- README.md | 2 + amiga/Makefile | 8 ++-- amiga/fs_hand.c | 2 +- amiga/smash.c | 2 +- amiga/smashftp.c | 2 +- doc/FAQ.txt | 54 ++++++++++++++++++++++++ doc/hw_build.txt | 2 +- doc/hw_install.txt | 6 ++- doc/hw_programming.txt | 14 ++++++- fw/Makefile | 18 ++++---- fw/Makefile.release | 93 ++++++++++++++++++++++++++++++++++++++++++ fw/version.c | 2 +- sw/Makefile | 57 ++++++++++++++++---------- sw/hostsmash.c | 72 ++++++++++++++++++++++++++++++-- 16 files changed, 363 insertions(+), 49 deletions(-) create mode 100644 doc/FAQ.txt create mode 100644 fw/Makefile.release diff --git a/.gitignore b/.gitignore index 6ea41c3..428fdbc 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,8 @@ generated.*.ld cscope.out .cscope_cmd.* objs/ +objs.x86_64/ +objs.mac/ objs.rom/ objs.rom_d/ objs.win32/ @@ -32,3 +34,4 @@ amiga/smashfsrom amiga/smashfsrom_d sw/hostsmash sw/crcit +kicksmash_* diff --git a/Makefile b/Makefile index 2842c99..402b7c1 100644 --- a/Makefile +++ b/Makefile @@ -2,20 +2,83 @@ # Makefile to build KickSmash firmware, host software, and Amiga software # +VER ?= 1.0+ MAKE ?= make MAKEFLAGS += --no-print-directory all: build-sw build-fw build-amiga clean: clean-sw clean-fw clean-amiga -build-sw build-fw build-amiga: +build-fw build-amiga build-sw: @echo - @echo Building in $(@:build-%=%) - @$(MAKE) -C $(@:build-%=%) + @echo "* Building in $(@:build-%=%)" + @$(MAKE) -C $(@:build-%=%) all clean-sw clean-fw clean-amiga: @echo - @echo Cleaning in $(@:clean-%=%) - @$(MAKE) -C $(@:clean-%=%) clean + @echo "* Cleaning in $(@:clean-%=%)" + @$(MAKE) -C $(@:clean-%=%) clean-all -.PHONY: build-sw build-fw build-amiga clean-sw clean-fw clean-amiga all clean +# --------------------------------------------------------------- + +RELEASE_DIR := kicksmash_$(VER) +RELEASE_LHA := kicksmash_$(VER).lha +RELEASE_ZIP := kicksmash_$(VER).zip + +RELEASE_TARGETS := +RELEASE_DIRS := +define RELEASE_IT +ifneq (,$(wildcard $(1))) +RELEASE_TARGETS += $(RELEASE_DIR)/$(2) +RELEASE_DIRS += $(dir $(RELEASE_DIR)/$(2)) +$(RELEASE_DIR)/$(2): $(1) +endif +endef +$(eval $(call RELEASE_IT,sw/objs.x86_64/hostsmash,sw/hostsmash.linux_x86_64)) +$(eval $(call RELEASE_IT,sw/objs.mac/hostsmash,sw/hostsmash.mac)) +$(eval $(call RELEASE_IT,sw/objs.win32/hostsmash.exe,sw/hostsmash_win32.exe)) +$(eval $(call RELEASE_IT,sw/objs.win64/hostsmash.exe,sw/hostsmash_win64.exe)) +$(eval $(call RELEASE_IT,fw/objs/fw.bin,fw/fw.bin)) +$(eval $(call RELEASE_IT,fw/objs/fw.elf,fw/fw.elf)) +$(eval $(call RELEASE_IT,fw/Makefile.release,fw/Makefile)) +$(eval $(call RELEASE_IT,fw/.gdbinit,fw/.gdbinit)) +$(eval $(call RELEASE_IT,amiga/smash,amiga/smash)) +$(eval $(call RELEASE_IT,amiga/smashftp,amiga/smashftp)) +$(eval $(call RELEASE_IT,amiga/smashfs,amiga/smashfs)) +$(eval $(call RELEASE_IT,amiga/smashfsrom,amiga/smashfsrom)) +$(eval $(call RELEASE_IT,amiga/smashfsrom_d,amiga/smashfsrom_d)) +$(eval $(call RELEASE_IT,README.md,README.md)) +$(eval $(call RELEASE_IT,LICENSE.md,LICENSE.md)) +$(foreach DOC,$(wildcard doc/*),$(eval $(call RELEASE_IT,$(DOC),$(DOC)))) + +RELEASE_DIRS := $(sort $(RELEASE_DIR) $(RELEASE_DIRS)) + +ifneq (,$(wildcard $(RELEASE_LHA))$(wildcard $(RELEASE_ZIP))) +release: + @echo $(RELEASE_LHA) or $(RELEASE_ZIP) already exists +else +release: all + @$(MAKE) do_release + +do_release: populating $(RELEASE_TARGETS) $(RELEASE_LHA) $(RELEASE_ZIP) + +$(RELEASE_LHA): all populating $(RELEASE_TARGETS) + @echo "* Building $@" + @rm -f $@ + @lha -aq2 $@ $(RELEASE_DIR) + +$(RELEASE_ZIP): all populating $(RELEASE_TARGETS) + @echo "* Building $@" + @rm -f $@ + @zip -rq $@ $(RELEASE_DIR) + +populating: + @echo "* Populating $(RELEASE_DIR)" + +$(RELEASE_TARGETS): | $(RELEASE_DIRS) + cp -p $^ $@ +endif +$(RELEASE_DIRS): + mkdir -p $@ + +.PHONY: build-sw build-fw build-amiga clean-sw clean-fw clean-amiga all clean release populating diff --git a/README.md b/README.md index fd3f24b..7689822 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,5 @@ and Amiga 4000 computer systems. Features include: ![Alt text](photos/2024_11_07_kicksmash32_rev5_profile_view_2.jpg?raw=true "Kicksmash32") All hardware, firmware, and software is open source. + +View files in the doc directory for complete documentation. diff --git a/amiga/Makefile b/amiga/Makefile index 1b0beba..2c58bd7 100644 --- a/amiga/Makefile +++ b/amiga/Makefile @@ -79,6 +79,7 @@ $(error "No $(CC) in PATH: maybe do PATH=$$PATH:/opt/amiga13/bin") endif all: $(SMASH_PROG) $(FS_PROG) $(FTP_PROG) $(FSROM_PROG) $(FSROM_PROG_D) + @: gdb: m68k-amigaos-gdb $(SMASH_PROG) @@ -149,14 +150,15 @@ zip: lha: @echo Building $(PROGVER).lha - $(QUIET)rm -rf $(SMASH_PROG).zip $(PROGVER) + $(QUIET)rm -rf $(SMASH_PROG).lha $(PROGVER) $(QUIET)mkdir $(PROGVER) $(QUIET)cp -p $(SMASH_PROG) $(PROGVER)/ $(QUIET)lha -aq2 $(PROGVER).lha $(PROGVER) $(QUIET)rm -rf $(PROGVER) -clean: - rm -rf $(OBJS) $(OBJDIR) $(ROM_OBJDIR) $(ROM_OBJDIR_D) +clean clean-all: + @echo Cleaning + @rm -rf $(OBJS) $(OBJDIR) $(ROM_OBJDIR) $(ROM_OBJDIR_D) FLINT_FILE=flexelint.lnt flint: diff --git a/amiga/fs_hand.c b/amiga/fs_hand.c index 1f1412f..8899c42 100644 --- a/amiga/fs_hand.c +++ b/amiga/fs_hand.c @@ -30,7 +30,7 @@ #define DIRBUF_SIZE 2000 -const char *version = "\0$VER: smashfs 0.1 ("__DATE__") � Chris Hooper"; +const char *version = "\0$VER: smashfs 0.2 ("__DATE__") � Chris Hooper"; BOOL __check_abort_enabled = 0; // Disable gcc clib2 ^C break handling diff --git a/amiga/smash.c b/amiga/smash.c index 6d85b93..a1ff5bf 100644 --- a/amiga/smash.c +++ b/amiga/smash.c @@ -14,7 +14,7 @@ * THE AUTHOR ASSUMES NO LIABILITY FOR ANY DAMAGE ARISING OUT OF THE USE * OR MISUSE OF THIS UTILITY OR INFORMATION REPORTED BY THIS UTILITY. */ -const char *version = "\0$VER: smash 0.2 ("__DATE__") © Chris Hooper"; +const char *version = "\0$VER: smash 1.0 ("__DATE__") © Chris Hooper"; #include #include diff --git a/amiga/smashftp.c b/amiga/smashftp.c index f5a7d37..834820c 100644 --- a/amiga/smashftp.c +++ b/amiga/smashftp.c @@ -14,7 +14,7 @@ * THE AUTHOR ASSUMES NO LIABILITY FOR ANY DAMAGE ARISING OUT OF THE USE * OR MISUSE OF THIS UTILITY OR INFORMATION REPORTED BY THIS UTILITY. */ -const char *version = "\0$VER: smashftp 0.4 ("__DATE__") © Chris Hooper"; +const char *version = "\0$VER: smashftp 1.0 ("__DATE__") © Chris Hooper"; #include #include diff --git a/doc/FAQ.txt b/doc/FAQ.txt new file mode 100644 index 0000000..0f75562 --- /dev/null +++ b/doc/FAQ.txt @@ -0,0 +1,54 @@ +* What problem does KickSmash32 solve? + +If you need to occasionally change ROMs in your Amiga, this can be a +tedious process with most Amiga systems. It often involves opening the +case, removing the drives and drive tray, and may also include removing +the CPU or removing all expansion cards. + +ROM images can be programmed by KickSmash32 in system by running a +program on the Amiga. Up to eight 512 KB ROM images may be stored and +switched between using either an Amiga command or by performing a long +(Control-Amiga-Amiga) reset. + +In addition, the USB port on KickSmash32 maybe connected permanently +to an external host so that ROM images can be programmed even when the +Amiga is not able to boot. The Amiga must be held in reset in this case. + +======================================================================== + +* Which Amiga models are supported by KickSmash32? + +KickSmash32 is currently only tested in Amiga 3000 rev 9 and +Amiga 4000 rev B motherboards. It will likely work in Amiga 3000T and +Amiga 4000T systems, but has not been tested. It will not work in +Amiga 3000 rev 7 and below motherboards, as those require a ROM Tower. +An Amiga 3000 ROM tower replacement with spacing identical to the +rev 9 motherboard is in development, but is not available yet. + +KickSmash32 might also work in the Amiga 1200, but this has not been +tested. With further software development, it can probably be made to +support the Amiga 500 and 2000. A lower cost version could be made +which supports those Amiga models. + +======================================================================== + +* How do I install KickSmash32? + +It's recommended to connect KickSmash by USB to your PC first before +installing it in the Amiga. This will allow you to update KickSmash +firmware, if necessary, and program an initial Kickstart ROM image. +See doc/sw_install.txt for instructions. Read doc/sw_hostsmash.txt for +further information on programming Kickstart images. + +KickSmash requires a connection to the Amiga's KBRST signal. You will +need to attach a jumper from a spot on the board to the KBRST pin on +KickSmash. See doc/hw_install.txt for details on this. + +Download the latest software release from the KickSmash github repository: + https://github.com/cdhooper/kicksmash32 + +Install files in the amiga directory on your Amiga. The sw directory +contains hostsmash executables for Linux, Windows, and MacOS. This +utility is used to program firmware images on KickSmash over USB. + +======================================================================== diff --git a/doc/hw_build.txt b/doc/hw_build.txt index 1605ce2..efd22ea 100644 --- a/doc/hw_build.txt +++ b/doc/hw_build.txt @@ -1,7 +1,7 @@ KickSmash Hardware Build ------------------------ -Use files in the rev4 directory to have a fab house build a PCB. +Use files in the rev5 directory to have a fab house build a PCB. HASL is fine. I use JLCPCB for most of my builds. My general order for building these boards is: diff --git a/doc/hw_install.txt b/doc/hw_install.txt index ae7b919..2540c0b 100644 --- a/doc/hw_install.txt +++ b/doc/hw_install.txt @@ -23,6 +23,8 @@ that system enough to confirm. screwdriver, be very careful to not damage traces on your motherboard. 4. Install KickSmash in place of the ROMs + The USB connector of KickSmash should face the same side of the ROM + sockets as the notch of the ROMs you've removed. In the Amiga 3000, KickSmash will be oriented with the USB-C connector facing Gary. In the Amiga 4000, KickSmash will be oriented with the USB-C @@ -34,8 +36,8 @@ that system enough to confirm. 5. Attach your KBRST wire to the KBRST pin on KickSmash 6. Optionally attach your ST-Link - You can do this if you plan to do firmware programming. Ensure the - cable is oriented correctly. + It's not necessary unless you plan to do firmware programming. Ensure + the cable is oriented correctly. 7. Optionally attach a USB-C cable to your KickSmash This cable would be routed out the back of your Amiga and then diff --git a/doc/hw_programming.txt b/doc/hw_programming.txt index 2f191a0..3343ea6 100644 --- a/doc/hw_programming.txt +++ b/doc/hw_programming.txt @@ -8,7 +8,15 @@ There are two ways to program firmware on your KickSmash. I prefer using the ST-Link for rapid programming cycles because it's fast and requires less manual intervention to get new firmware loaded. An advantage of using USB DFU mode is that it does not require any -programmer hardware. You just need a computer which has a DFU downloader. +programmer hardware. You just need a computer which has a DFU updater. +On Linux, dfu-util is the recommended DFU updater. Depending on your +Linux distribution, you might use one of the following commands to +install it: + dnf install dfu-util + yum install dfu-util + apt-get install dfu-util +On MacOS, you can install dfu-util using brew: + brew install dfu-util In either case, you will need a computer that you can connect by USB-C to your KickSmash. You will also need to build firmware for @@ -63,6 +71,10 @@ Get all the source code from here: shows up on your computer, type: make dfu + if you are on MacOS, you might need to first build the firmware and + then type: + make just-dfu + When programming in DFU mode, you should see output including the following: Erase [=========================] 100% 87036 bytes diff --git a/fw/Makefile b/fw/Makefile index 990763c..e667d70 100644 --- a/fw/Makefile +++ b/fw/Makefile @@ -29,17 +29,17 @@ LDSCRIPT = stm32f1.ld # Also works for STM32F4 BOARD_TYPE := STM32F107 ifeq ($(BOARD_TYPE), STM32F4) -$(info Building for STM32F4) +#$(info Building for STM32F4) LIBNAME := opencm3_stm32f4 ARCH_FLAGS := -mthumb -mcpu=cortex-m4 -mhard-float DEFS += -DSTM32F4 -DSTM32F407xx else ifeq ($(BOARD_TYPE), STM32F103) -$(info Building for STM32F103) +#$(info Building for STM32F103) LIBNAME := opencm3_stm32f1 ARCH_FLAGS := -mthumb -mcpu=cortex-m3 -msoft-float DEFS += -DSTM32F1 -DSTM32F103xE else -$(info Building for STM32F107) +#$(info Building for STM32F107) LIBNAME := opencm3_stm32f1 ARCH_FLAGS := -mthumb -mcpu=cortex-m3 -msoft-float DEFS += -DSTM32F1 -DSTM32F107xC @@ -204,7 +204,7 @@ $(OPENCM3_LIB): | $(OPENCM3_DIR) -x bmp_flash.scr \ $(OBJDIR)/$*.elf -clean: +clean clean-all: @echo Cleaning $(QUIET)$(RM) $(GENERATED_BINARIES) generated.* $(OBJS) $(OBJS:%.o=%.d) @@ -214,12 +214,16 @@ clean: UDEV_DIR := /etc/udev/rules.d UDEV_FILENAMES := 70-st-link.rules 70-ttymxprog.rules UDEV_FILE_PATHS := $(UDEV_FILENAMES:%=$(UDEV_DIR)/%) +ifneq (,$(wildcard $(UDEV_FILE_PATHS))) $(UDEV_FILE_PATHS) &: sudo cp -np udev/* $(UDEV_DIR) sudo udevadm control --reload +else +$(UDEV_FILE_PATHS) &: +endif # Write STM32 flash using DFU mode -just-dfu: $(UDEV_FILE_PATHS) +just-dfu: $(DFU_UTIL) --device 0483:df11 --alt 0 --download $(BINARY).bin --dfuse-address 0x08000000:leave dfu-unprotect: $(UDEV_FILE_PATHS) @@ -260,7 +264,7 @@ just-protect: $(ST_TOOLS_PATH)/st-flash | $(UDEV_FILE_PATHS) just-clobber: $(ST_TOOLS_PATH)/st-flash | $(UDEV_FILE_PATHS) $(ST_TOOLS_PATH)/st-flash $(ST_ARGS) --reset write flash_clobber.bin 0x1ffff800 -dfu: all just-dfu +dfu: all $(UDEV_FILE_PATHS) just-dfu flash: all just-flash # Connect to remote STM32 via ST-Link (follow with "make gdb") @@ -282,4 +286,4 @@ $(ST_TOOLS_PATH)/st-flash build-stutils: | $(ST_BUILD_DIR) gdb: gdb -q -x .gdbinit $(BINARY).elf -.PHONY: images clean get-stutils build_stutils stlink dfu flash just-dfu just-flash just-unprotect just-dfu dfu-unprotect clean size elf bin hex srec list udev-files +.PHONY: images clean get-stutils build_stutils stlink dfu flash just-dfu just-flash just-unprotect just-dfu dfu-unprotect size elf bin hex srec list udev-files diff --git a/fw/Makefile.release b/fw/Makefile.release new file mode 100644 index 0000000..ddfc400 --- /dev/null +++ b/fw/Makefile.release @@ -0,0 +1,93 @@ +# Kicksmash installer +# +# Program using dfu: make dfu +# Program using st-link: make flash + +# Firmware name +BINARY = fw + +DFU_UTIL=dfu-util +ST_BUILD_DIR=stutils +ST_TOOLS_PATH=$(ST_BUILD_DIR)/build/Release/bin + +all: + @echo Use \"make dfu\" to program via USB DFU + @echo Use \"make flash\" to program via ST-Link + @echo Other options: just-dfu stinfo stlink stinfo gdb + +UDEV_DIR := /etc/udev/rules.d +UDEV_FILENAMES := 70-st-link.rules 70-ttymxprog.rules +UDEV_FILE_PATHS := $(UDEV_FILENAMES:%=$(UDEV_DIR)/%) +ifneq (,$(wildcard $(UDEV_FILE_PATHS))) +$(UDEV_FILE_PATHS) &: + sudo cp -np udev/* $(UDEV_DIR) + sudo udevadm control --reload +else +$(UDEV_FILE_PATHS) &: +endif + +# Write STM32 flash using DFU mode +just-dfu: + $(DFU_UTIL) --device 0483:df11 --alt 0 --download $(BINARY).bin --dfuse-address 0x08000000:leave + +dfu-unprotect: $(UDEV_FILE_PATHS) + $(DFU_UTIL) -s 0:force:unprotect -a 0 --device 0483:df11 --alt 0 --download $(BINARY).bin + +dfu-clobber: $(UDEV_FILE_PATHS) + $(DFU_UTIL) -s 0:force:unprotect --alt 1 --download flash_clobber.bin -Z 0x10 --dfuse-address 0x1ffff800:leave + +#dfu-clobber: $(UDEV_FILE_PATHS) +# $(DFU_UTIL) -s 0:force:unprotect --alt 1 --download flash_clobber.bin -Z 0xd --dfuse-address 0x1ffff800:leave + +# Write STM32 flash using ST-Link +just-flash: $(ST_TOOLS_PATH)/st-flash | $(BINARY).bin $(UDEV_FILE_PATHS) + $(ST_TOOLS_PATH)/st-flash $(ST_ARGS) --reset write $(BINARY).bin 0x08000000 + +# Erase STM32 flash using ST-Link +just-erase: $(ST_TOOLS_PATH)/st-flash | $(UDEV_FILE_PATHS) + $(ST_TOOLS_PATH)/st-flash $(ST_ARGS) --flash=0x100000 erase 0x08000000 0x3c000 + +just-mxprog: + ./mxprog -d /dev/ttyACM0 -e -a 0x000000 -l 0x80000 + ./mxprog -d /dev/ttyACM0 -wv A3000.47.111.rom -a 0x000000 -s 3210 + +# Protect/unprotect/clobber flash by writing the option byte area +# The following can also be done by the STM32CubeProgrammer. +# F105 unlocked 1ffff800: a5 5a 07 f8 00 ff 00 ff ff 00 ff 00 ff 00 ff 00 +# F105 protect 1ffff800: 00 ff 07 f8 ff 00 ff 00 00 ff 00 ff 00 ff 00 ff +# F105 clobber 1ffff800: 00 00 00 00 00 03 00 03 00 ff 00 ff 00 ff 00 ff + +# Select specific programmer ("make stinfo" to get serial) +# export ST_ARGS="--serial 57FF6E064975545225502187" # amiga1 +# export ST_ARGS="--serial 303030303030303030303031" # amiga2 + +just-unprotect: $(ST_TOOLS_PATH)/st-flash | $(UDEV_FILE_PATHS) + $(ST_TOOLS_PATH)/st-flash $(ST_ARGS) --reset write flash_unprotect.bin 0x1ffff800 +just-protect: $(ST_TOOLS_PATH)/st-flash | $(UDEV_FILE_PATHS) + $(ST_TOOLS_PATH)/st-flash $(ST_ARGS) --reset write flash_protect.bin 0x1ffff800 +just-clobber: $(ST_TOOLS_PATH)/st-flash | $(UDEV_FILE_PATHS) + $(ST_TOOLS_PATH)/st-flash $(ST_ARGS) --reset write flash_clobber.bin 0x1ffff800 + +dfu: all $(UDEV_FILE_PATHS) just-dfu +flash: all just-flash + +# Connect to remote STM32 via ST-Link (follow with "make gdb") +stlink: $(ST_TOOLS_PATH)/st-flash | $(UDEV_FILE_PATHS) + $(ST_TOOLS_PATH)/st-util $(ST_ARGS) --no-reset + +stinfo reset: $(ST_TOOLS_PATH)/st-flash | $(UDEV_FILE_PATHS) + $(ST_TOOLS_PATH)/st-info --probe + +# Get ST-TOOLS +$(ST_BUILD_DIR) get-stutils: + git clone https://github.com/texane/stlink.git stutils + +# Build ST-TOOLS +$(ST_TOOLS_PATH)/st-flash build-stutils: | $(ST_BUILD_DIR) + make -C $(ST_BUILD_DIR) CMAKEFLAGS=-DCMAKE_INSTALL_PREFIX=. + ln -s ../../config $(ST_BUILD_DIR)/build/Release/stlink + +gdb: + gdb -q -x .gdbinit $(BINARY).elf + +.PHONY: get-stutils build_stutils stlink dfu flash just-dfu just-flash just-unprotect just-dfu dfu-unprotect size elf bin hex srec list udev-files diff --git a/fw/version.c b/fw/version.c index 1f6a3f3..7794d52 100644 --- a/fw/version.c +++ b/fw/version.c @@ -12,4 +12,4 @@ #include "version.h" const char * const version_str = - "Version 0.2 built "BUILD_DATE" "BUILD_TIME; + "Version 1.1 built "BUILD_DATE" "BUILD_TIME; diff --git a/sw/Makefile b/sw/Makefile index 6c24805..5e05c28 100644 --- a/sw/Makefile +++ b/sw/Makefile @@ -1,12 +1,12 @@ -PROG=hostsmash -SRCS=hostsmash.c crc32.c version.c +PROG1=hostsmash +SRCS1=hostsmash.c crc32.c version.c PROG2=crcit SRCS2=crcit.c crc32.c CC := gcc #CFLAGS := -O2 -g -pthread -Wall -Wpedantic #LDFLAGS := -O2 -g -lpthread -CFLAGS := -O0 -g -pthread -Wall -Wpedantic -Wno-variadic-macros -LDFLAGS := -O0 -g -lpthread +CFLAGS := -O2 -pthread -Wall -Wpedantic -Wno-variadic-macros +LDFLAGS := -O2 -lpthread UNAME_S := $(shell uname -s) # @@ -39,7 +39,7 @@ ifneq (,$(filter $(TARGET_OS),Windows_NT Windows win win32 win64)) # -static works for Vista+, but doesn't work for XP LDFLAGS += -lws2_32 -static OBJDIR := objs.win64 - SRCS += mingw-realpath.c + SRCS1 += mingw-realpath.c CC := x86_64-w64-mingw32-gcc endif ifneq (,$(filter $(TARGET_OS),win32)) @@ -49,8 +49,8 @@ ifneq (,$(filter $(TARGET_OS),win32)) CC := i686-w64-mingw32-gcc endif ifneq (,$(filter $(TARGET_OS),Windows_NT Windows win win32 win64)) - PROG := $(OBJDIR)/$(PROG).exe - PROG2 := $(OBJDIR)/$(PROG2).exe + PROG1 := $(PROG1).exe + PROG2 := $(PROG2).exe endif # Linux @@ -67,9 +67,12 @@ ifeq ($(TARGET_OS),Darwin) OBJDIR := objs.mac endif -ifneq ($(TARGET_OS),$(OS)) - $(info HOST=$(OS) TARGET=$(TARGET_OS)) -endif +OPROG1 := $(OBJDIR)/$(PROG1) +OPROG2 := $(OBJDIR)/$(PROG2) + +#ifneq ($(TARGET_OS),$(OS)) +# $(info HOST=$(OS) TARGET=$(TARGET_OS)) +#endif # If verbose is specified with no other targets, then build everything ifeq ($(MAKECMDGOALS),verbose) @@ -81,12 +84,14 @@ else QUIET := endif -OBJS := $(SRCS:%.c=$(OBJDIR)/%.o) +OBJS1 := $(SRCS1:%.c=$(OBJDIR)/%.o) OBJS2 := $(SRCS2:%.c=$(OBJDIR)/%.o) -nativeprog: $(PROG) $(PROG2) +nativeprog: $(OPROG1) $(OPROG2) + @: -all: $(PROG) $(PROG2) win32 win64 +all: $(OPROG1) $(OPROG2) win32 win64 + @: win32: $(MAKE) TARGET_OS=win32 @@ -98,23 +103,27 @@ define DEPEND_SRC # given source file. $(patsubst %,$(OBJDIR)/%,$(filter-out $(OBJDIR)/%,$(basename $(1)).o)) $(filter $(OBJDIR)/%,$(basename $(1)).o): $(1) endef -$(foreach SRCFILE,$(SRCS),$(eval $(call DEPEND_SRC,$(SRCFILE)))) +$(foreach SRCFILE,$(SRCS1),$(eval $(call DEPEND_SRC,$(SRCFILE)))) $(foreach SRCFILE,$(SRCS2),$(eval $(call DEPEND_SRC,$(SRCFILE)))) -$(OBJS) $(OBJS2): Makefile smash_cmd.h version.h crc32.h host_cmd.h +$(OBJS1) $(OBJS2): Makefile smash_cmd.h version.h crc32.h host_cmd.h $(OBJDIR)/hostsmash.o: | $(USB_HDR) -$(OBJDIR)/version.o: $(filter-out $(OBJDIR)/version.o,$(OBJS)) Makefile +$(OBJDIR)/version.o: $(filter-out $(OBJDIR)/version.o,$(OBJS1)) Makefile -$(PROG): $(OBJS) +$(OPROG1): $(OBJS1) @echo Building $@ - $(QUIET)$(CC) -o $@ $(OBJS) $(LDFLAGS) + $(QUIET)$(CC) -o $@ $(OBJS1) $(LDFLAGS) + @rm -f $(PROG1) + @ln -s $@ -$(PROG2): $(OBJS2) +$(OPROG2): $(OBJS2) @echo Building $@ $(QUIET)$(CC) -o $@ $(OBJS2) $(LDFLAGS) + @rm -f $(PROG2) + @ln -s $@ -$(sort $(OBJS) $(OBJS2)): Makefile | $(OBJDIR) +$(sort $(OBJS1) $(OBJS2)): Makefile | $(OBJDIR) @echo Building $@ $(QUIET)$(CC) $(CFLAGS) -c $(filter %.c,$^) -o $@ @@ -130,6 +139,12 @@ $(USB_HDR): clean: @echo Cleaning - $(QUIET)rm -rf $(PROG) $(OBJDIR) + $(QUIET)rm -rf $(OPROG1) $(OPROG2) $(OBJDIR) + +clean-all: clean + @$(MAKE) TARGET_OS=win32 clean + @$(MAKE) TARGET_OS=win64 clean verbose: + +.PHONY: all clean clean-all verbose nativeprog diff --git a/sw/hostsmash.c b/sw/hostsmash.c index 35177d4..3961b85 100644 --- a/sw/hostsmash.c +++ b/sw/hostsmash.c @@ -15,6 +15,9 @@ #include #include #include +#ifdef OSX +#include +#endif #ifdef __MINGW32__ #include #define handle_t winhandle_t @@ -52,6 +55,17 @@ typedef unsigned int uint; #include "host_cmd.h" #include "version.h" +#ifdef __clang__ +#define ATTRIBUTE_PRINTF __attribute__((format(printf, 1, 2))) +#else +#define ATTRIBUTE_PRINTF __attribute__((format(__gnu_printf__, 1, 2))) +#endif + +#ifdef OSX +#define lseek64 lseek +#define off64_t off_t +#endif + #define FILE_DEBUG #ifndef FILE_DEBUG #define fsprintf(args...) do { } while (0) @@ -157,11 +171,11 @@ static uint debug_fs = 0; static uint debug_msg = 0; #ifdef FILE_DEBUG -__attribute__((format(__gnu_printf__, 1, 2))) +ATTRIBUTE_PRINTF int fsprintf(const char *fmt, ...) { - int rc; + int rc = 0; va_list args; if (debug_fs) { @@ -175,11 +189,11 @@ fsprintf(const char *fmt, ...) #endif #ifdef MSG_DEBUG -__attribute__((format(__printf__, 1, 2))) +ATTRIBUTE_PRINTF int msgprintf(const char *fmt, ...) { - int rc; + int rc = 0; va_list args; if (debug_msg) { @@ -192,6 +206,15 @@ msgprintf(const char *fmt, ...) } #endif +#ifdef OSX +static void +timespec_to_timeval(struct timeval *tv, struct timespec *ts) +{ + tv->tv_sec = ts->tv_sec; + tv->tv_usec = ts->tv_nsec / 1000; +} +#endif + /* Command line modes which may be specified by the user */ #define MODE_UNKNOWN 0x00 #define MODE_ERASE 0x01 @@ -5525,7 +5548,48 @@ sm_fsetdate(hm_fsetdate_t *hm, uint *status) hm->hm_hdr.km_status = errno_to_km_status(); goto reply_setdate_fail; } +#elif defined (OSX) + /* MacOS */ + struct timeval times[2]; + timespec_to_timeval(×[0], &statbuf.st_atimespec); // last access time + timespec_to_timeval(×[1], &statbuf.st_ctimespec); // last modify time + + switch (which) { + case 0: // Set the modify date/time + times[1].tv_sec = utcsec; + times[1].tv_usec = nsec / 1000; + break; + case 1: // Get the modify date/time + hm->hm_time = SWAP32(statbuf.st_ctimespec.tv_sec); + hm->hm_time_ns = SWAP32(statbuf.st_ctimespec.tv_nsec); + goto reply_setdate_good; + case 2: // Set the change date/time + /* Not sure how to set this one */ + hm->hm_hdr.km_status = KM_STATUS_INVALID; + goto reply_setdate_fail; + case 3: // Get the change date/time + hm->hm_time = SWAP32(statbuf.st_ctimespec.tv_sec); + hm->hm_time_ns = SWAP32(statbuf.st_ctimespec.tv_nsec); + goto reply_setdate_good; + case 4: // Set the access date/time + times[0].tv_sec = utcsec; + times[0].tv_usec = nsec / 1000; + break; + case 5: // Get the access date/time + hm->hm_time = SWAP32(statbuf.st_atimespec.tv_sec); + hm->hm_time_ns = SWAP32(statbuf.st_atimespec.tv_nsec); + goto reply_setdate_good; + default: + hm->hm_hdr.km_status = KM_STATUS_INVALID; + goto reply_setdate_fail; + } + if (utimes(path, times)) { + fsprintf("utimes fail: %d\n", errno); + hm->hm_hdr.km_status = errno_to_km_status(); + goto reply_setdate_fail; + } #else + /* Linux */ struct timespec times[2]; times[0] = statbuf.st_atim; // last access time times[1] = statbuf.st_ctim; // last modification time