Skip to content

Commit ff8e506

Browse files
committed
Fix bugs in esp32 mkimage.erl script
Fixes an FD leak, the image file was never closed properly after writing. Fixes a misleading error message when a binary overlows its partiton. Closes #2084 Signed-off-by: Winford <winford@object.stream>
1 parent aa7ac0f commit ff8e506

1 file changed

Lines changed: 61 additions & 52 deletions

File tree

src/platforms/esp32/tools/mkimage.erl

Lines changed: 61 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -135,62 +135,71 @@ mkimage(RootDir, BootFile, OutputFile, Segments) ->
135135
io:format("=============================================~n"),
136136
case file:open(OutputFile, [write, binary]) of
137137
{ok, Fout} ->
138-
lists:foldl(
139-
fun(Segment, PrevOffset) ->
140-
SegmentOffset = from_hex(maps:get(offset, Segment)),
141-
case PrevOffset of
142-
undefined ->
143-
no_padding;
144-
_ ->
145-
case SegmentOffset > PrevOffset of
146-
true ->
147-
Padding = [
148-
16#FF
149-
|| _ <- lists:seq(1, SegmentOffset - PrevOffset)
150-
],
151-
io:format("Padding ~p bytes~n", [SegmentOffset - PrevOffset]),
152-
file:write(Fout, Padding);
153-
false ->
154-
throw(
155-
io_lib:format(
156-
"Error: insufficient space for segment ~p. Over by: ~p bytes~n",
157-
[
158-
maps:get(name, Segment), PrevOffset - SegmentOffset
159-
]
160-
)
161-
)
162-
end
163-
end,
164-
SegmentPaths = [
165-
replace(
166-
"BOOT_FILE", BootFile, replace("ROOT_DIR", RootDir, SegmentPath)
167-
)
168-
|| SegmentPath <- maps:get(path, Segment)
169-
],
170-
case try_read(SegmentPaths) of
171-
{ok, Data} ->
172-
file:write(Fout, Data),
173-
io:format("Wrote ~s (~p bytes) at offset ~s (~p)~n", [
174-
maps:get(name, Segment),
175-
byte_size(Data),
176-
maps:get(offset, Segment),
177-
SegmentOffset
178-
]),
179-
SegmentOffset + byte_size(Data);
180-
{error, Reason} ->
181-
Fmt =
182-
"Failed to read file ~p Reason: ~p."
183-
" Note that a full build is required before running this command.",
184-
throw(io_lib:format(Fmt, [SegmentPaths, Reason]))
185-
end
186-
end,
187-
undefined,
188-
Segments
189-
);
138+
write_segments(RootDir, BootFile, Fout, Segments);
190139
{error, Reason} ->
191140
throw(io_lib:format("Failed to open ~s for writing. Reason: ~p", [OutputFile, Reason]))
192141
end.
193142

143+
%% @private
144+
write_segments(RootDir, BootFile, Fout, []) ->
145+
file:close(Fout);
146+
write_segments(RootDir, BootFile, Fout, [Segment | Segments]) ->
147+
SegmentOffset = from_hex(maps:get(offset, Segment)),
148+
SegmentPaths = [
149+
replace(
150+
"BOOT_FILE", BootFile, replace("ROOT_DIR", RootDir, SegmentPath)
151+
)
152+
|| SegmentPath <- maps:get(path, Segment)
153+
],
154+
SegmentEnd =
155+
case try_read(SegmentPaths) of
156+
{ok, Data} ->
157+
file:write(Fout, Data),
158+
io:format("Wrote ~s (~p bytes) at offset ~s (~p)~n", [
159+
maps:get(name, Segment),
160+
byte_size(Data),
161+
maps:get(offset, Segment),
162+
SegmentOffset
163+
]),
164+
SegmentOffset + byte_size(Data);
165+
{error, Reason} ->
166+
Fmt =
167+
"Failed to read file ~p Reason: ~p."
168+
" Note that a full build is required before running this command.",
169+
throw(io_lib:format(Fmt, [SegmentPaths, Reason]))
170+
end,
171+
if
172+
Segments == [] ->
173+
ok;
174+
true ->
175+
[PeekNext | _] = Segments,
176+
NextOffset = from_hex(maps:get(offset, PeekNext)),
177+
case SegmentEnd > NextOffset of
178+
true ->
179+
throw(
180+
io_lib:format(
181+
"Error: insufficient space for segment ~p. Overflows partition by: ~p bytes~n",
182+
[maps:get(name, Segment), SegmentEnd - NextOffset]
183+
)
184+
);
185+
false ->
186+
PadSize = NextOffset - SegmentEnd,
187+
case PadSize of
188+
0 ->
189+
ok;
190+
PadSize ->
191+
Padding = [
192+
16#FF
193+
|| _ <- lists:seq(1, PadSize)
194+
],
195+
io:format("Padding ~p bytes~n", [PadSize]),
196+
file:write(Fout, Padding),
197+
ok
198+
end
199+
end
200+
end,
201+
write_segments(RootDir, BootFile, Fout, Segments).
202+
194203
%% @private
195204
try_read([]) ->
196205
{error, not_found};

0 commit comments

Comments
 (0)